FFmpeg
Loading...
Searching...
No Matches
hwcontext.c
Go to the documentation of this file.
1/*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#include "config.h"
20
21#include "avassert.h"
22#include "buffer.h"
23#include "common.h"
24#include "frame_internal.h"
25#include "hwcontext.h"
26#include "hwcontext_internal.h"
27#include "imgutils.h"
28#include "log.h"
29#include "mem.h"
30#include "pixdesc.h"
31#include "pixfmt.h"
32
33static const HWContextType * const hw_table[] = {
34#if CONFIG_CUDA
36#endif
37#if CONFIG_D3D11VA
39#endif
40#if CONFIG_D3D12VA
42#endif
43#if CONFIG_LIBDRM
45#endif
46#if CONFIG_DXVA2
48#endif
49#if CONFIG_OPENCL
51#endif
52#if CONFIG_QSV
54#endif
55#if CONFIG_VAAPI
57#endif
58#if CONFIG_VDPAU
60#endif
61#if CONFIG_VIDEOTOOLBOX
63#endif
64#if CONFIG_MEDIACODEC
66#endif
67#if CONFIG_VULKAN
69#endif
70#if CONFIG_AMF
72#endif
73#if CONFIG_OHCODEC
75#endif
76 NULL,
77};
78
79static const char *const hw_type_names[] = {
80 [AV_HWDEVICE_TYPE_CUDA] = "cuda",
81 [AV_HWDEVICE_TYPE_DRM] = "drm",
82 [AV_HWDEVICE_TYPE_DXVA2] = "dxva2",
83 [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va",
84 [AV_HWDEVICE_TYPE_D3D12VA] = "d3d12va",
85 [AV_HWDEVICE_TYPE_OPENCL] = "opencl",
86 [AV_HWDEVICE_TYPE_QSV] = "qsv",
87 [AV_HWDEVICE_TYPE_VAAPI] = "vaapi",
88 [AV_HWDEVICE_TYPE_VDPAU] = "vdpau",
89 [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox",
90 [AV_HWDEVICE_TYPE_MEDIACODEC] = "mediacodec",
91 [AV_HWDEVICE_TYPE_VULKAN] = "vulkan",
92 [AV_HWDEVICE_TYPE_AMF] = "amf",
93 [AV_HWDEVICE_TYPE_OHCODEC] = "ohcodec",
94};
95
96typedef struct FFHWDeviceContext {
97 /**
98 * The public AVHWDeviceContext. See hwcontext.h for it.
99 */
101
103
104 /**
105 * For a derived device, a reference to the original device
106 * context it was derived from.
107 */
110
112{
113 int type;
114 for (type = 0; type < FF_ARRAY_ELEMS(hw_type_names); type++) {
115 if (hw_type_names[type] && !strcmp(hw_type_names[type], name))
116 return type;
117 }
119}
120
122{
125 return hw_type_names[type];
126 else
127 return NULL;
128}
129
131{
132 enum AVHWDeviceType next;
133 int i, set = 0;
134 for (i = 0; hw_table[i]; i++) {
135 if (prev != AV_HWDEVICE_TYPE_NONE && hw_table[i]->type <= prev)
136 continue;
137 if (!set || hw_table[i]->type < next) {
138 next = hw_table[i]->type;
139 set = 1;
140 }
141 }
142 return set ? next : AV_HWDEVICE_TYPE_NONE;
143}
144
145static const char *hwdevice_ctx_get_name(void *ptr)
146{
147 FFHWDeviceContext *ctx = ptr;
148 return ctx->hw_type->name;
149}
150
152 .class_name = "AVHWDeviceContext",
153 .item_name = hwdevice_ctx_get_name,
154 .category = AV_CLASS_CATEGORY_HWDEVICE,
155 .version = LIBAVUTIL_VERSION_INT,
156};
157
158static void hwdevice_ctx_free(void *opaque, uint8_t *data)
159{
161 AVHWDeviceContext *ctx = &ctxi->p;
162
163 /* uninit might still want access the hw context and the user
164 * free() callback might destroy it, so uninit has to be called first */
165 if (ctxi->hw_type->device_uninit)
166 ctxi->hw_type->device_uninit(ctx);
167
168 if (ctx->free)
169 ctx->free(ctx);
170
172
173 av_freep(&ctx->hwctx);
174 av_freep(&ctx);
175}
176
178{
179 FFHWDeviceContext *ctxi;
181 AVBufferRef *buf;
182 const HWContextType *hw_type = NULL;
183 int i;
184
185 for (i = 0; hw_table[i]; i++) {
186 if (hw_table[i]->type == type) {
187 hw_type = hw_table[i];
188 break;
189 }
190 }
191 if (!hw_type)
192 return NULL;
193
194 ctxi = av_mallocz(sizeof(*ctxi));
195 if (!ctxi)
196 return NULL;
197 ctx = &ctxi->p;
198
199 if (hw_type->device_hwctx_size) {
200 ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
201 if (!ctx->hwctx)
202 goto fail;
203 }
204
205 buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
208 if (!buf)
209 goto fail;
210
211 ctx->type = type;
212 ctx->av_class = &hwdevice_ctx_class;
213
214 ctxi->hw_type = hw_type;
215
216 return buf;
217
218fail:
219 av_freep(&ctx->hwctx);
220 av_freep(&ctx);
221 return NULL;
222}
223
225{
227 AVHWDeviceContext *ctx = &ctxi->p;
228 int ret = 0;
229
230 if (ctxi->hw_type->device_init)
231 ret = ctxi->hw_type->device_init(ctx);
232
233 return ret;
234}
235
237 .class_name = "AVHWFramesContext",
238 .item_name = av_default_item_name,
239 .version = LIBAVUTIL_VERSION_INT,
240};
241
242static void hwframe_ctx_free(void *opaque, uint8_t *data)
243{
245 AVHWFramesContext *ctx = &ctxi->p;
246
247 if (ctxi->pool_internal)
249
252
253 if (ctxi->hw_type->frames_uninit)
254 ctxi->hw_type->frames_uninit(ctx);
255
256 if (ctx->free)
257 ctx->free(ctx);
258
260
261 av_buffer_unref(&ctx->device_ref);
262
263 av_freep(&ctx->hwctx);
264 av_freep(&ctx);
265}
266
268{
269 FFHWDeviceContext *device_ctx = (FFHWDeviceContext*)device_ref_in->data;
270 const HWContextType *hw_type = device_ctx->hw_type;
271 FFHWFramesContext *ctxi;
273 AVBufferRef *buf, *device_ref = NULL;
274
275 ctxi = av_mallocz(sizeof(*ctxi));
276 if (!ctxi)
277 return NULL;
278 ctx = &ctxi->p;
279
281 av_free(ctxi);
282 return NULL;
283 }
284
285 if (hw_type->frames_hwctx_size) {
286 ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
287 if (!ctx->hwctx)
288 goto fail;
289 }
290
291 device_ref = av_buffer_ref(device_ref_in);
292 if (!device_ref)
293 goto fail;
294
295 buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
298 if (!buf)
299 goto fail;
300
301 ctx->av_class = &hwframe_ctx_class;
302 ctx->device_ref = device_ref;
303 ctx->device_ctx = &device_ctx->p;
304 ctx->format = AV_PIX_FMT_NONE;
305 ctx->sw_format = AV_PIX_FMT_NONE;
306
307 ctxi->hw_type = hw_type;
308
309 return buf;
310
311fail:
312 av_buffer_unref(&device_ref);
314 av_freep(&ctx->hwctx);
315 av_freep(&ctx);
316 return NULL;
317}
318
320{
322 AVFrame **frames;
323 int i, ret = 0;
324
325 frames = av_calloc(ctx->initial_pool_size, sizeof(*frames));
326 if (!frames)
327 return AVERROR(ENOMEM);
328
329 for (i = 0; i < ctx->initial_pool_size; i++) {
331 if (!frames[i])
332 goto fail;
333
335 if (ret < 0)
336 goto fail;
337 }
338
339fail:
340 for (i = 0; i < ctx->initial_pool_size; i++)
343
344 return ret;
345}
346
348{
350 AVHWFramesContext *ctx = &ctxi->p;
351 const enum AVPixelFormat *pix_fmt;
352 int ret;
353
354 if (ctxi->source_frames) {
355 /* A derived frame context is already initialised. */
356 return 0;
357 }
358
359 /* validate the pixel format */
360 for (pix_fmt = ctxi->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
361 if (*pix_fmt == ctx->format)
362 break;
363 }
364 if (*pix_fmt == AV_PIX_FMT_NONE) {
366 "The hardware pixel format '%s' is not supported by the device type '%s'\n",
367 av_get_pix_fmt_name(ctx->format), ctxi->hw_type->name);
368 return AVERROR(ENOSYS);
369 }
370
371 /* validate the dimensions */
372 ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
373 if (ret < 0)
374 return ret;
375
376 /* format-specific init */
377 if (ctxi->hw_type->frames_init) {
378 ret = ctxi->hw_type->frames_init(ctx);
379 if (ret < 0)
380 return ret;
381 }
382
383 if (ctxi->pool_internal && !ctx->pool)
384 ctx->pool = ctxi->pool_internal;
385
386 /* preallocate the frames in the pool, if requested */
387 if (ctx->initial_pool_size > 0) {
389 if (ret < 0)
390 return ret;
391 }
392
393 return 0;
394}
395
398 enum AVPixelFormat **formats, int flags)
399{
400 FFHWFramesContext *ctxi = (FFHWFramesContext*)hwframe_ref->data;
401
402 if (!ctxi->hw_type->transfer_get_formats)
403 return AVERROR(ENOSYS);
404
405 return ctxi->hw_type->transfer_get_formats(&ctxi->p, dir, formats);
406}
407
408static void transfer_pool_free(void *opaque)
409{
410 AVBufferRef *device_ref = opaque;
411 av_buffer_unref(&device_ref);
412}
413
414static AVBufferRef *transfer_buffer_alloc(void *opaque, size_t size)
415{
416 FFHWFramesContext *ctxi = opaque;
417 AVBufferRef *buf = NULL;
418
420 if (ctxi->transfer_pool_size != size) {
421 /* buffers of the hardware context type need the device to be freed */
422 AVBufferRef *device_ref = ctxi->hw_type->transfer_buffer_alloc ?
424
426 ctxi->transfer_pool = device_ref ?
427 av_buffer_pool_init2(size, device_ref,
431 ctxi->transfer_pool_size = ctxi->transfer_pool ? size : 0;
432 if (!ctxi->transfer_pool)
433 av_buffer_unref(&device_ref);
434 }
435 if (ctxi->transfer_pool)
438
439 return buf ? buf : av_buffer_alloc(size);
440}
441
447
449{
451 AVFrame *frame_tmp;
452 int ret = 0;
453
454 if (!src->hw_frames_ctx)
455 return AVERROR(EINVAL);
456 ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
457
458 frame_tmp = av_frame_alloc();
459 if (!frame_tmp)
460 return AVERROR(ENOMEM);
461
462 /* if the format is set, use that
463 * otherwise pick the first supported one */
464 if (dst->format >= 0) {
465 frame_tmp->format = dst->format;
466 } else {
468
469 ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
471 &formats, 0);
472 if (ret < 0)
473 goto fail;
474 frame_tmp->format = formats[0];
476 }
477 frame_tmp->width = ctx->width;
478 frame_tmp->height = ctx->height;
479
480 ret = av_hwframe_get_transfer_buffer(src->hw_frames_ctx, frame_tmp);
481 if (ret < 0)
482 goto fail;
483
484 ret = av_hwframe_transfer_data(frame_tmp, src, flags);
485 if (ret < 0)
486 goto fail;
487
488 frame_tmp->width = src->width;
489 frame_tmp->height = src->height;
490
491 av_frame_move_ref(dst, frame_tmp);
492
493fail:
494 av_frame_free(&frame_tmp);
495 return ret;
496}
497
499{
500 int ret;
501
502 if (!dst->buf[0])
504
505 /*
506 * Hardware -> Hardware Transfer.
507 * Unlike Software -> Hardware or Hardware -> Software, the transfer
508 * function could be provided by either the src or dst, depending on
509 * the specific combination of hardware.
510 */
511 if (src->hw_frames_ctx && dst->hw_frames_ctx) {
512 FFHWFramesContext *src_ctx =
513 (FFHWFramesContext*)src->hw_frames_ctx->data;
514 FFHWFramesContext *dst_ctx =
515 (FFHWFramesContext*)dst->hw_frames_ctx->data;
516
517 if (src_ctx->source_frames) {
518 av_log(src_ctx, AV_LOG_ERROR,
519 "A device with a derived frame context cannot be used as "
520 "the source of a HW -> HW transfer.");
521 return AVERROR(ENOSYS);
522 }
523
524 if (dst_ctx->source_frames) {
525 av_log(src_ctx, AV_LOG_ERROR,
526 "A device with a derived frame context cannot be used as "
527 "the destination of a HW -> HW transfer.");
528 return AVERROR(ENOSYS);
529 }
530
531 ret = AVERROR(ENOSYS);
532 if (src_ctx->hw_type->transfer_data_from)
533 ret = src_ctx->hw_type->transfer_data_from(&src_ctx->p, dst, src);
534 if (ret == AVERROR(ENOSYS) && dst_ctx->hw_type->transfer_data_to)
535 ret = dst_ctx->hw_type->transfer_data_to(&dst_ctx->p, dst, src);
536 if (ret < 0)
537 return ret;
538 } else {
539 if (src->hw_frames_ctx) {
540 FFHWFramesContext *ctx = (FFHWFramesContext*)src->hw_frames_ctx->data;
541
542 if (!ctx->hw_type->transfer_data_from)
543 return AVERROR(ENOSYS);
544
545 ret = ctx->hw_type->transfer_data_from(&ctx->p, dst, src);
546 if (ret < 0)
547 return ret;
548 } else if (dst->hw_frames_ctx) {
549 FFHWFramesContext *ctx = (FFHWFramesContext*)dst->hw_frames_ctx->data;
550
551 if (!ctx->hw_type->transfer_data_to)
552 return AVERROR(ENOSYS);
553
554 ret = ctx->hw_type->transfer_data_to(&ctx->p, dst, src);
555 if (ret < 0)
556 return ret;
557 } else {
558 return AVERROR(ENOSYS);
559 }
560 }
561 return 0;
562}
563
565{
566 FFHWFramesContext *ctxi = (FFHWFramesContext*)hwframe_ref->data;
567 AVHWFramesContext *ctx = &ctxi->p;
568 int ret;
569
570 if (ctxi->source_frames) {
571 // This is a derived frame context, so we allocate in the source
572 // and map the frame immediately.
573 AVFrame *src_frame;
574
575 frame->format = ctx->format;
576 frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
577 if (!frame->hw_frames_ctx)
578 return AVERROR(ENOMEM);
579
580 src_frame = av_frame_alloc();
581 if (!src_frame)
582 return AVERROR(ENOMEM);
583
585 src_frame, 0);
586 if (ret < 0) {
587 av_frame_free(&src_frame);
588 return ret;
589 }
590
591 ret = av_hwframe_map(frame, src_frame,
593 if (ret) {
594 av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived "
595 "frame context: %d.\n", ret);
596 av_frame_free(&src_frame);
597 return ret;
598 }
599
600 // Free the source frame immediately - the mapped frame still
601 // contains a reference to it.
602 av_frame_free(&src_frame);
603
604 return 0;
605 }
606
607 if (!ctxi->hw_type->frames_get_buffer)
608 return AVERROR(ENOSYS);
609
610 if (!ctx->pool)
611 return AVERROR(EINVAL);
612
613 frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
614 if (!frame->hw_frames_ctx)
615 return AVERROR(ENOMEM);
616
618 if (ret < 0) {
619 av_buffer_unref(&frame->hw_frames_ctx);
620 return ret;
621 }
622
623 frame->extended_data = frame->data;
624
625 return 0;
626}
627
629{
631 const HWContextType *hw_type = ctx->hw_type;
632
633 if (hw_type->device_hwconfig_size == 0)
634 return NULL;
635
636 return av_mallocz(hw_type->device_hwconfig_size);
637}
638
640 const void *hwconfig)
641{
643 const HWContextType *hw_type = ctx->hw_type;
644 AVHWFramesConstraints *constraints;
645
646 if (!hw_type->frames_get_constraints)
647 return NULL;
648
649 constraints = av_mallocz(sizeof(*constraints));
650 if (!constraints)
651 return NULL;
652
653 constraints->min_width = constraints->min_height = 0;
654 constraints->max_width = constraints->max_height = INT_MAX;
655
656 if (hw_type->frames_get_constraints(&ctx->p, hwconfig, constraints) >= 0) {
657 return constraints;
658 } else {
659 av_hwframe_constraints_free(&constraints);
660 return NULL;
661 }
662}
663
665{
666 if (*constraints) {
667 av_freep(&(*constraints)->valid_hw_formats);
668 av_freep(&(*constraints)->valid_sw_formats);
669 }
670 av_freep(constraints);
671}
672
674 const char *device, AVDictionary *opts, int flags)
675{
676 AVBufferRef *device_ref = NULL;
677 FFHWDeviceContext *device_ctx;
678 int ret = 0;
679
680 device_ref = av_hwdevice_ctx_alloc(type);
681 if (!device_ref) {
682 ret = AVERROR(ENOMEM);
683 goto fail;
684 }
685 device_ctx = (FFHWDeviceContext*)device_ref->data;
686
687 if (!device_ctx->hw_type->device_create) {
688 ret = AVERROR(ENOSYS);
689 goto fail;
690 }
691
692 ret = device_ctx->hw_type->device_create(&device_ctx->p, device,
693 opts, flags);
694 if (ret < 0)
695 goto fail;
696
697 ret = av_hwdevice_ctx_init(device_ref);
698 if (ret < 0)
699 goto fail;
700
701 *pdevice_ref = device_ref;
702 return 0;
703fail:
704 av_buffer_unref(&device_ref);
705 *pdevice_ref = NULL;
706 return ret;
707}
708
710 enum AVHWDeviceType type,
711 AVBufferRef *src_ref,
713{
714 AVBufferRef *dst_ref = NULL, *tmp_ref;
715 FFHWDeviceContext *dst_ctx;
716 int ret = 0;
717
718 tmp_ref = src_ref;
719 while (tmp_ref) {
720 FFHWDeviceContext *tmp_ctx = (FFHWDeviceContext*)tmp_ref->data;
721 if (tmp_ctx->p.type == type) {
722 dst_ref = av_buffer_ref(tmp_ref);
723 if (!dst_ref) {
724 ret = AVERROR(ENOMEM);
725 goto fail;
726 }
727 goto done;
728 }
729 tmp_ref = tmp_ctx->source_device;
730 }
731
732 dst_ref = av_hwdevice_ctx_alloc(type);
733 if (!dst_ref) {
734 ret = AVERROR(ENOMEM);
735 goto fail;
736 }
737 dst_ctx = (FFHWDeviceContext*)dst_ref->data;
738
739 tmp_ref = src_ref;
740 while (tmp_ref) {
741 FFHWDeviceContext *tmp_ctx = (FFHWDeviceContext*)tmp_ref->data;
742 if (dst_ctx->hw_type->device_derive) {
743 ret = dst_ctx->hw_type->device_derive(&dst_ctx->p,
744 &tmp_ctx->p,
745 options, flags);
746 if (ret == 0) {
747 dst_ctx->source_device = av_buffer_ref(src_ref);
748 if (!dst_ctx->source_device) {
749 ret = AVERROR(ENOMEM);
750 goto fail;
751 }
752 ret = av_hwdevice_ctx_init(dst_ref);
753 if (ret < 0)
754 goto fail;
755 goto done;
756 }
757 if (ret != AVERROR(ENOSYS))
758 goto fail;
759 }
760 tmp_ref = tmp_ctx->source_device;
761 }
762
763 ret = AVERROR(ENOSYS);
764 goto fail;
765
766done:
767 *dst_ref_ptr = dst_ref;
768 return 0;
769
770fail:
771 av_buffer_unref(&dst_ref);
772 *dst_ref_ptr = NULL;
773 return ret;
774}
775
777 enum AVHWDeviceType type,
778 AVBufferRef *src_ref, int flags)
779{
780 return av_hwdevice_ctx_create_derived_opts(dst_ref_ptr, type, src_ref,
781 NULL, flags);
782}
783
784static void ff_hwframe_unmap(void *opaque, uint8_t *data)
785{
787 AVHWFramesContext *ctx = opaque;
788
789 if (hwmap->unmap)
790 hwmap->unmap(ctx, hwmap);
791
792 av_frame_free(&hwmap->source);
793
795
796 av_free(hwmap);
797}
798
800 AVFrame *dst, const AVFrame *src,
801 void (*unmap)(AVHWFramesContext *ctx,
802 HWMapDescriptor *hwmap),
803 void *priv)
804{
806 HWMapDescriptor *hwmap;
807 int ret;
808
809 hwmap = av_mallocz(sizeof(*hwmap));
810 if (!hwmap) {
811 ret = AVERROR(ENOMEM);
812 goto fail;
813 }
814
815 hwmap->source = av_frame_alloc();
816 if (!hwmap->source) {
817 ret = AVERROR(ENOMEM);
818 goto fail;
819 }
820 ret = av_frame_ref(hwmap->source, src);
821 if (ret < 0)
822 goto fail;
823
824 hwmap->hw_frames_ctx = av_buffer_ref(hwframe_ref);
825 if (!hwmap->hw_frames_ctx) {
826 ret = AVERROR(ENOMEM);
827 goto fail;
828 }
829
830 hwmap->unmap = unmap;
831 hwmap->priv = priv;
832
833 dst->buf[0] = av_buffer_create((uint8_t*)hwmap, sizeof(*hwmap),
834 &ff_hwframe_unmap, ctx, 0);
835 if (!dst->buf[0]) {
836 ret = AVERROR(ENOMEM);
837 goto fail;
838 }
839
840 return 0;
841
842fail:
843 if (hwmap) {
845 av_frame_free(&hwmap->source);
846 }
847 av_free(hwmap);
848 return ret;
849}
850
852{
853 AVBufferRef *orig_dst_frames = dst->hw_frames_ctx;
854 enum AVPixelFormat orig_dst_fmt = dst->format;
855 HWMapDescriptor *hwmap;
856 int ret;
857
858 if (src->hw_frames_ctx && dst->hw_frames_ctx) {
859 FFHWFramesContext *src_frames = (FFHWFramesContext*)src->hw_frames_ctx->data;
860 FFHWFramesContext *dst_frames = (FFHWFramesContext*)dst->hw_frames_ctx->data;
861
862 if ((src_frames == dst_frames &&
863 src->format == dst_frames->p.sw_format &&
864 dst->format == dst_frames->p.format) ||
865 (src_frames->source_frames &&
866 src_frames->source_frames->data ==
867 (uint8_t*)dst_frames)) {
868 // This is an unmap operation. We don't need to directly
869 // do anything here other than fill in the original frame,
870 // because the real unmap will be invoked when the last
871 // reference to the mapped frame disappears.
872 if (!src->buf[0]) {
873 av_log(src_frames, AV_LOG_ERROR, "Invalid mapping "
874 "found when attempting unmap.\n");
875 return AVERROR(EINVAL);
876 }
877 hwmap = (HWMapDescriptor*)src->buf[0]->data;
878 return av_frame_replace(dst, hwmap->source);
879 }
880 }
881
882 if (src->hw_frames_ctx) {
883 FFHWFramesContext *src_frames = (FFHWFramesContext*)src->hw_frames_ctx->data;
884
885 if (src_frames->p.format == src->format &&
886 src_frames->hw_type->map_from) {
887 ret = src_frames->hw_type->map_from(&src_frames->p,
888 dst, src, flags);
889 if (ret >= 0)
890 return ret;
891 else if (ret != AVERROR(ENOSYS))
892 goto fail;
893 }
894 }
895
896 if (dst->hw_frames_ctx) {
897 FFHWFramesContext *dst_frames = (FFHWFramesContext*)dst->hw_frames_ctx->data;
898
899 if (dst_frames->p.format == dst->format &&
900 dst_frames->hw_type->map_to) {
901 ret = dst_frames->hw_type->map_to(&dst_frames->p,
902 dst, src, flags);
903 if (ret >= 0)
904 return ret;
905 else if (ret != AVERROR(ENOSYS))
906 goto fail;
907 }
908 }
909
910 return AVERROR(ENOSYS);
911
912fail:
913 // if the caller provided dst frames context, it should be preserved
914 // by this function
915 av_assert0(orig_dst_frames == NULL ||
916 orig_dst_frames == dst->hw_frames_ctx);
917
918 // preserve user-provided dst frame fields, but clean
919 // anything we might have set
920 dst->hw_frames_ctx = NULL;
922
923 dst->hw_frames_ctx = orig_dst_frames;
924 dst->format = orig_dst_fmt;
925
926 return ret;
927}
928
931 AVBufferRef *derived_device_ctx,
932 AVBufferRef *source_frame_ctx,
933 int flags)
934{
935 AVBufferRef *dst_ref = NULL;
936 FFHWFramesContext *dsti = NULL;
937 FFHWFramesContext *srci = (FFHWFramesContext*)source_frame_ctx->data;
938 AVHWFramesContext *dst, *src = &srci->p;
939 int ret;
940
941 if (srci->source_frames) {
942 AVHWFramesContext *src_src =
944 AVHWDeviceContext *dst_dev =
945 (AVHWDeviceContext*)derived_device_ctx->data;
946
947 if (src_src->device_ctx == dst_dev) {
948 // This is actually an unmapping, so we just return a
949 // reference to the source frame context.
950 *derived_frame_ctx = av_buffer_ref(srci->source_frames);
951 if (!*derived_frame_ctx) {
952 ret = AVERROR(ENOMEM);
953 goto fail;
954 }
955 return 0;
956 }
957 }
958
959 dst_ref = av_hwframe_ctx_alloc(derived_device_ctx);
960 if (!dst_ref) {
961 ret = AVERROR(ENOMEM);
962 goto fail;
963 }
964
965 dsti = (FFHWFramesContext*)dst_ref->data;
966 dst = &dsti->p;
967
968 dst->format = format;
969 dst->sw_format = src->sw_format;
970 dst->width = src->width;
971 dst->height = src->height;
972
973 dsti->source_frames = av_buffer_ref(source_frame_ctx);
974 if (!dsti->source_frames) {
975 ret = AVERROR(ENOMEM);
976 goto fail;
977 }
978
984
985 ret = AVERROR(ENOSYS);
986 if (srci->hw_type->frames_derive_from)
988 if (ret == AVERROR(ENOSYS) &&
991 if (ret == AVERROR(ENOSYS))
992 ret = 0;
993 if (ret)
994 goto fail;
995
996 *derived_frame_ctx = dst_ref;
997 return 0;
998
999fail:
1000 if (dsti)
1002 av_buffer_unref(&dst_ref);
1003 return ret;
1004}
1005
1007{
1008 HWMapDescriptor *hwmap = (HWMapDescriptor*)dst->buf[0]->data;
1009 return av_frame_replace(hwmap->source, src);
1010}
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:97
static const char *const format[]
Definition af_aiir.c:445
static int frames
static AVFormatContext * ctx
static AVDictionary * opts
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition avassert.h:42
refcounted data buffer API
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
common internal and external API header
#define NULL
Definition coverity.c:32
static enum AVPixelFormat pix_fmt
static AVFrame * frame
int ret
Definition ffplay.c:391
SDL_atomic_t done
Definition ffplay.c:392
int ff_frame_get_video_buffer(AVFrame *frame, int align, AVBufferRef *(*alloc)(void *opaque, size_t size), void *opaque)
Allocate the buffer of a video frame like av_frame_get_buffer().
Definition frame.c:76
#define fail
Definition test.h:479
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:140
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition buffer.c:104
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition buffer.h:114
AVBufferRef * av_buffer_alloc(size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition buffer.c:78
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition buffer.c:56
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition buffer.c:331
AVBufferPool * av_buffer_pool_init(size_t size, AVBufferRef *(*alloc)(size_t size))
Allocate and initialize a buffer pool.
Definition buffer.c:284
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition buffer.c:396
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition buffer.c:260
#define AVERROR(e)
Definition error.h:45
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition frame.c:499
int av_frame_replace(AVFrame *dst, const AVFrame *src)
Ensure the destination frame refers to the same data described by the source frame,...
Definition frame.c:379
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition frame.c:526
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition frame.c:281
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:65
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition frame.c:53
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
const char * av_default_item_name(void *ptr)
Return the context name.
Definition log.c:247
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition imgutils.c:318
#define LIBAVUTIL_VERSION_INT
Definition version.h:85
enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev)
Iterate over supported device types.
Definition hwcontext.c:130
int av_hwdevice_ctx_init(AVBufferRef *ref)
Finalize the device context before use.
Definition hwcontext.c:224
static void ff_hwframe_unmap(void *opaque, uint8_t *data)
Definition hwcontext.c:784
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition hwcontext.c:673
int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats, int flags)
Get a list of possible source or target formats usable in av_hwframe_transfer_data().
Definition hwcontext.c:396
static int hwframe_pool_prealloc(AVBufferRef *ref)
Definition hwcontext.c:319
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition hwcontext.c:664
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition hwcontext.c:121
static AVBufferRef * transfer_buffer_alloc(void *opaque, size_t size)
Definition hwcontext.c:414
static const char *const hw_type_names[]
Definition hwcontext.c:79
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, int flags)
Create a new device of the specified type from an existing device.
Definition hwcontext.c:776
int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx, enum AVPixelFormat format, AVBufferRef *derived_device_ctx, AVBufferRef *source_frame_ctx, int flags)
Create and initialise an AVHWFramesContext as a mapping of another existing AVHWFramesContext on a di...
Definition hwcontext.c:929
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition hwcontext.c:111
static const HWContextType *const hw_table[]
Definition hwcontext.c:33
int av_hwframe_get_transfer_buffer(AVBufferRef *hwframe_ctx, AVFrame *frame)
Allocate the buffers of a software frame that data is transferred to or from frames of the given AVHW...
Definition hwcontext.c:442
AVBufferRef * av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
Allocate an AVHWDeviceContext for a given hardware type.
Definition hwcontext.c:177
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition hwcontext.c:347
static const AVClass hwframe_ctx_class
Definition hwcontext.c:236
static void hwframe_ctx_free(void *opaque, uint8_t *data)
Definition hwcontext.c:242
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition hwcontext.c:799
static void hwdevice_ctx_free(void *opaque, uint8_t *data)
Definition hwcontext.c:158
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition hwcontext.c:267
static void transfer_pool_free(void *opaque)
Definition hwcontext.c:408
static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
Definition hwcontext.c:448
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition hwcontext.c:851
static const char * hwdevice_ctx_get_name(void *ptr)
Definition hwcontext.c:145
static const AVClass hwdevice_ctx_class
Definition hwcontext.c:151
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition hwcontext.c:498
AVHWFramesConstraints * av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, const void *hwconfig)
Get the constraints on HW frames given a device and the HW-specific configuration to be used with tha...
Definition hwcontext.c:639
void * av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
Allocate a HW-specific configuration structure for a given HW device.
Definition hwcontext.c:628
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition hwcontext.c:564
int av_hwdevice_ctx_create_derived_opts(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, AVDictionary *options, int flags)
Create a new device of the specified type from an existing device.
Definition hwcontext.c:709
int ff_hwframe_map_replace(AVFrame *dst, const AVFrame *src)
Replace the current hwmap of dst with the one from src, used for indirect mappings like VAAPI->(DRM)-...
Definition hwcontext.c:1006
@ AV_HWFRAME_MAP_READ
The mapping must be readable.
Definition hwcontext.h:530
@ AV_HWFRAME_MAP_DIRECT
The mapping must be direct.
Definition hwcontext.h:546
@ AV_HWFRAME_MAP_WRITE
The mapping must be writeable.
Definition hwcontext.h:534
@ AV_HWFRAME_MAP_OVERWRITE
The mapped frame will be overwritten completely in subsequent operations, so the current frame data n...
Definition hwcontext.h:540
AVHWFrameTransferDirection
Definition hwcontext.h:421
@ AV_HWFRAME_TRANSFER_DIRECTION_FROM
Transfer the data from the queried hw frame.
Definition hwcontext.h:425
AVHWDeviceType
Definition hwcontext.h:27
@ AV_HWDEVICE_TYPE_OHCODEC
Definition hwcontext.h:43
@ AV_HWDEVICE_TYPE_D3D11VA
Definition hwcontext.h:35
@ AV_HWDEVICE_TYPE_NONE
Definition hwcontext.h:28
@ AV_HWDEVICE_TYPE_AMF
Definition hwcontext.h:41
@ AV_HWDEVICE_TYPE_VDPAU
Definition hwcontext.h:29
@ AV_HWDEVICE_TYPE_OPENCL
Definition hwcontext.h:37
@ AV_HWDEVICE_TYPE_VULKAN
Definition hwcontext.h:39
@ AV_HWDEVICE_TYPE_MEDIACODEC
Definition hwcontext.h:38
@ AV_HWDEVICE_TYPE_QSV
Definition hwcontext.h:33
@ AV_HWDEVICE_TYPE_VIDEOTOOLBOX
Definition hwcontext.h:34
@ AV_HWDEVICE_TYPE_CUDA
Definition hwcontext.h:30
@ AV_HWDEVICE_TYPE_DRM
Definition hwcontext.h:36
@ AV_HWDEVICE_TYPE_D3D12VA
Definition hwcontext.h:40
@ AV_HWDEVICE_TYPE_DXVA2
Definition hwcontext.h:32
@ AV_HWDEVICE_TYPE_VAAPI
Definition hwcontext.h:31
const HWContextType ff_hwcontext_type_amf
const HWContextType ff_hwcontext_type_cuda
const HWContextType ff_hwcontext_type_d3d11va
const HWContextType ff_hwcontext_type_d3d12va
const HWContextType ff_hwcontext_type_drm
const HWContextType ff_hwcontext_type_dxva2
const HWContextType ff_hwcontext_type_opencl
const HWContextType ff_hwcontext_type_vaapi
const HWContextType ff_hwcontext_type_vdpau
const HWContextType ff_hwcontext_type_qsv
const HWContextType ff_hwcontext_type_oh
const HWContextType ff_hwcontext_type_videotoolbox
const HWContextType ff_hwcontext_type_vulkan
const HWContextType ff_hwcontext_type_mediacodec
misc image utilities
enum MPFType type
Definition jpegmpfenc.c:55
static int ff_mutex_unlock(AVMutex *mutex)
Definition thread.h:189
static int ff_mutex_lock(AVMutex *mutex)
Definition thread.h:188
static int ff_mutex_destroy(AVMutex *mutex)
Definition thread.h:190
static int ff_mutex_init(AVMutex *mutex, const void *attr)
Definition thread.h:187
@ AV_CLASS_CATEGORY_HWDEVICE
Definition log.h:40
void * av_calloc(size_t nmemb, size_t size)
Definition mem.c:370
Memory handling functions.
const char data[16]
Definition mxf.c:149
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition pixdesc.c:3404
pixel format definitions
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
const char * name
Definition qsvenc.c:142
formats
Definition signature.h:47
#define FF_ARRAY_ELEMS(a)
A reference to a data buffer.
Definition buffer.h:82
uint8_t * data
The data buffer.
Definition buffer.h:90
Describe the class of an AVClass context structure.
Definition log.h:76
This structure describes decoded (raw) audio or video data.
Definition frame.h:479
int width
Definition frame.h:551
int height
Definition frame.h:551
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition frame.h:566
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition hwcontext.h:63
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition hwcontext.h:75
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition hwcontext.h:459
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition hwcontext.h:484
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition hwcontext.h:477
This struct describes a set or pool of "hardware" frames (i.e.
Definition hwcontext.h:118
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition hwcontext.h:200
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition hwcontext.h:129
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition hwcontext.h:213
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition hwcontext.h:137
const HWContextType * hw_type
Definition hwcontext.c:102
AVBufferRef * source_device
For a derived device, a reference to the original device context it was derived from.
Definition hwcontext.c:108
AVHWDeviceContext p
The public AVHWDeviceContext.
Definition hwcontext.c:100
const HWContextType * hw_type
AVBufferPool * transfer_pool
Buffers of transfer_pool_size bytes for av_hwframe_get_transfer_buffer(), both guarded by transfer_po...
int source_allocation_map_flags
Flags to apply to the mapping from the source to the derived frame context when trying to allocate in...
AVHWFramesContext p
The public AVHWFramesContext.
AVBufferPool * pool_internal
AVBufferRef * source_frames
For a derived context, a reference to the original frames context it was derived from.
size_t frames_hwctx_size
size of the public frame pool hardware-specific context, i.e.
int(* transfer_data_from)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
int(* map_from)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags)
int(* frames_get_constraints)(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
int(* device_create)(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
int(* transfer_data_to)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
int(* transfer_get_formats)(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
int(* map_to)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags)
int(* frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame)
size_t device_hwctx_size
size of the public hardware-specific context, i.e.
int(* device_init)(AVHWDeviceContext *ctx)
int(* frames_derive_to)(AVHWFramesContext *dst_ctx, AVHWFramesContext *src_ctx, int flags)
void(* frames_uninit)(AVHWFramesContext *ctx)
int(* frames_derive_from)(AVHWFramesContext *dst_ctx, AVHWFramesContext *src_ctx, int flags)
size_t device_hwconfig_size
Size of the hardware-specific device configuration.
const char * name
void(* device_uninit)(AVHWDeviceContext *ctx)
int(* device_derive)(AVHWDeviceContext *dst_ctx, AVHWDeviceContext *src_ctx, AVDictionary *opts, int flags)
AVBufferRef *(* transfer_buffer_alloc)(void *device_ref, size_t size)
Allocate a buffer of size bytes for av_hwframe_get_transfer_buffer(), av_buffer_alloc() is used if th...
int(* frames_init)(AVHWFramesContext *ctx)
enum AVPixelFormat * pix_fmts
An array of pixel formats supported by the AVHWFramesContext instances Terminated by AV_PIX_FMT_NONE.
void * priv
Hardware-specific private data associated with the mapping.
void(* unmap)(AVHWFramesContext *ctx, struct HWMapDescriptor *hwmap)
Unmap function.
AVFrame * source
A reference to the original source of the mapping.
AVBufferRef * hw_frames_ctx
A reference to the hardware frames context in which this mapping was made.
#define av_free(p)
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248
static int ref[MAX_W *MAX_W]
static void set(uint8_t *a[], int ch, int index, int ch_count, enum AVSampleFormat f, double v)
Definition swresample.c:56
int size