2 * This file is part of FFmpeg.
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.
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.
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
24 #include "hwcontext.h"
25 #include "hwcontext_internal.h"
32 static const HWContextType
* const hw_table
[] = {
34 &ff_hwcontext_type_cuda
,
37 &ff_hwcontext_type_d3d11va
,
40 &ff_hwcontext_type_d3d12va
,
43 &ff_hwcontext_type_drm
,
46 &ff_hwcontext_type_dxva2
,
49 &ff_hwcontext_type_opencl
,
52 &ff_hwcontext_type_qsv
,
55 &ff_hwcontext_type_vaapi
,
58 &ff_hwcontext_type_vdpau
,
60 #if CONFIG_VIDEOTOOLBOX
61 &ff_hwcontext_type_videotoolbox
,
64 &ff_hwcontext_type_mediacodec
,
67 &ff_hwcontext_type_vulkan
,
70 &ff_hwcontext_type_amf
,
73 &ff_hwcontext_type_oh
,
78 static const char *const hw_type_names
[] = {
79 [AV_HWDEVICE_TYPE_CUDA
] = "cuda",
80 [AV_HWDEVICE_TYPE_DRM
] = "drm",
81 [AV_HWDEVICE_TYPE_DXVA2
] = "dxva2",
82 [AV_HWDEVICE_TYPE_D3D11VA
] = "d3d11va",
83 [AV_HWDEVICE_TYPE_D3D12VA
] = "d3d12va",
84 [AV_HWDEVICE_TYPE_OPENCL
] = "opencl",
85 [AV_HWDEVICE_TYPE_QSV
] = "qsv",
86 [AV_HWDEVICE_TYPE_VAAPI
] = "vaapi",
87 [AV_HWDEVICE_TYPE_VDPAU
] = "vdpau",
88 [AV_HWDEVICE_TYPE_VIDEOTOOLBOX
] = "videotoolbox",
89 [AV_HWDEVICE_TYPE_MEDIACODEC
] = "mediacodec",
90 [AV_HWDEVICE_TYPE_VULKAN
] = "vulkan",
91 [AV_HWDEVICE_TYPE_AMF
] = "amf",
92 [AV_HWDEVICE_TYPE_OHCODEC
] = "ohcodec",
95 typedef struct FFHWDeviceContext
{
97 * The public AVHWDeviceContext. See hwcontext.h for it.
101 const HWContextType
*hw_type
;
104 * For a derived device, a reference to the original device
105 * context it was derived from.
107 AVBufferRef
*source_device
;
110 enum AVHWDeviceType
av_hwdevice_find_type_by_name(const char *name
)
113 for (type
= 0; type
< FF_ARRAY_ELEMS(hw_type_names
); type
++) {
114 if (hw_type_names
[type
] && !strcmp(hw_type_names
[type
], name
))
117 return AV_HWDEVICE_TYPE_NONE
;
120 const char *av_hwdevice_get_type_name(enum AVHWDeviceType type
)
122 if (type
> AV_HWDEVICE_TYPE_NONE
&&
123 type
< FF_ARRAY_ELEMS(hw_type_names
))
124 return hw_type_names
[type
];
129 enum AVHWDeviceType
av_hwdevice_iterate_types(enum AVHWDeviceType prev
)
131 enum AVHWDeviceType next
;
133 for (i
= 0; hw_table
[i
]; i
++) {
134 if (prev
!= AV_HWDEVICE_TYPE_NONE
&& hw_table
[i
]->type
<= prev
)
136 if (!set
|| hw_table
[i
]->type
< next
) {
137 next
= hw_table
[i
]->type
;
141 return set
? next
: AV_HWDEVICE_TYPE_NONE
;
144 static const char *hwdevice_ctx_get_name(void *ptr
)
146 FFHWDeviceContext
*ctx
= ptr
;
147 return ctx
->hw_type
->name
;
150 static const AVClass hwdevice_ctx_class
= {
151 .class_name
= "AVHWDeviceContext",
152 .item_name
= hwdevice_ctx_get_name
,
153 .category
= AV_CLASS_CATEGORY_HWDEVICE
,
154 .version
= LIBAVUTIL_VERSION_INT
,
157 static void hwdevice_ctx_free(void *opaque
, uint8_t *data
)
159 FFHWDeviceContext
*ctxi
= (FFHWDeviceContext
*)data
;
160 AVHWDeviceContext
*ctx
= &ctxi
->p
;
162 /* uninit might still want access the hw context and the user
163 * free() callback might destroy it, so uninit has to be called first */
164 if (ctxi
->hw_type
->device_uninit
)
165 ctxi
->hw_type
->device_uninit(ctx
);
170 av_buffer_unref(&ctxi
->source_device
);
172 av_freep(&ctx
->hwctx
);
176 AVBufferRef
*av_hwdevice_ctx_alloc(enum AVHWDeviceType type
)
178 FFHWDeviceContext
*ctxi
;
179 AVHWDeviceContext
*ctx
;
181 const HWContextType
*hw_type
= NULL
;
184 for (i
= 0; hw_table
[i
]; i
++) {
185 if (hw_table
[i
]->type
== type
) {
186 hw_type
= hw_table
[i
];
193 ctxi
= av_mallocz(sizeof(*ctxi
));
198 if (hw_type
->device_hwctx_size
) {
199 ctx
->hwctx
= av_mallocz(hw_type
->device_hwctx_size
);
204 buf
= av_buffer_create((uint8_t*)ctx
, sizeof(*ctx
),
205 hwdevice_ctx_free
, NULL
,
206 AV_BUFFER_FLAG_READONLY
);
211 ctx
->av_class
= &hwdevice_ctx_class
;
213 ctxi
->hw_type
= hw_type
;
218 av_freep(&ctx
->hwctx
);
223 int av_hwdevice_ctx_init(AVBufferRef
*ref
)
225 FFHWDeviceContext
*ctxi
= (FFHWDeviceContext
*)ref
->data
;
226 AVHWDeviceContext
*ctx
= &ctxi
->p
;
229 if (ctxi
->hw_type
->device_init
)
230 ret
= ctxi
->hw_type
->device_init(ctx
);
235 static const AVClass hwframe_ctx_class
= {
236 .class_name
= "AVHWFramesContext",
237 .item_name
= av_default_item_name
,
238 .version
= LIBAVUTIL_VERSION_INT
,
241 static void hwframe_ctx_free(void *opaque
, uint8_t *data
)
243 FFHWFramesContext
*ctxi
= (FFHWFramesContext
*)data
;
244 AVHWFramesContext
*ctx
= &ctxi
->p
;
246 if (ctxi
->pool_internal
)
247 av_buffer_pool_uninit(&ctxi
->pool_internal
);
249 if (ctxi
->hw_type
->frames_uninit
)
250 ctxi
->hw_type
->frames_uninit(ctx
);
255 av_buffer_unref(&ctxi
->source_frames
);
257 av_buffer_unref(&ctx
->device_ref
);
259 av_freep(&ctx
->hwctx
);
263 AVBufferRef
*av_hwframe_ctx_alloc(AVBufferRef
*device_ref_in
)
265 FFHWDeviceContext
*device_ctx
= (FFHWDeviceContext
*)device_ref_in
->data
;
266 const HWContextType
*hw_type
= device_ctx
->hw_type
;
267 FFHWFramesContext
*ctxi
;
268 AVHWFramesContext
*ctx
;
269 AVBufferRef
*buf
, *device_ref
= NULL
;
271 ctxi
= av_mallocz(sizeof(*ctxi
));
276 if (hw_type
->frames_hwctx_size
) {
277 ctx
->hwctx
= av_mallocz(hw_type
->frames_hwctx_size
);
282 device_ref
= av_buffer_ref(device_ref_in
);
286 buf
= av_buffer_create((uint8_t*)ctx
, sizeof(*ctx
),
287 hwframe_ctx_free
, NULL
,
288 AV_BUFFER_FLAG_READONLY
);
292 ctx
->av_class
= &hwframe_ctx_class
;
293 ctx
->device_ref
= device_ref
;
294 ctx
->device_ctx
= &device_ctx
->p
;
295 ctx
->format
= AV_PIX_FMT_NONE
;
296 ctx
->sw_format
= AV_PIX_FMT_NONE
;
298 ctxi
->hw_type
= hw_type
;
303 av_buffer_unref(&device_ref
);
304 av_freep(&ctx
->hwctx
);
309 static int hwframe_pool_prealloc(AVBufferRef
*ref
)
311 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)ref
->data
;
315 frames
= av_calloc(ctx
->initial_pool_size
, sizeof(*frames
));
317 return AVERROR(ENOMEM
);
319 for (i
= 0; i
< ctx
->initial_pool_size
; i
++) {
320 frames
[i
] = av_frame_alloc();
324 ret
= av_hwframe_get_buffer(ref
, frames
[i
], 0);
330 for (i
= 0; i
< ctx
->initial_pool_size
; i
++)
331 av_frame_free(&frames
[i
]);
337 int av_hwframe_ctx_init(AVBufferRef
*ref
)
339 FFHWFramesContext
*ctxi
= (FFHWFramesContext
*)ref
->data
;
340 AVHWFramesContext
*ctx
= &ctxi
->p
;
341 const enum AVPixelFormat
*pix_fmt
;
344 if (ctxi
->source_frames
) {
345 /* A derived frame context is already initialised. */
349 /* validate the pixel format */
350 for (pix_fmt
= ctxi
->hw_type
->pix_fmts
; *pix_fmt
!= AV_PIX_FMT_NONE
; pix_fmt
++) {
351 if (*pix_fmt
== ctx
->format
)
354 if (*pix_fmt
== AV_PIX_FMT_NONE
) {
355 av_log(ctx
, AV_LOG_ERROR
,
356 "The hardware pixel format '%s' is not supported by the device type '%s'\n",
357 av_get_pix_fmt_name(ctx
->format
), ctxi
->hw_type
->name
);
358 return AVERROR(ENOSYS
);
361 /* validate the dimensions */
362 ret
= av_image_check_size(ctx
->width
, ctx
->height
, 0, ctx
);
366 /* format-specific init */
367 if (ctxi
->hw_type
->frames_init
) {
368 ret
= ctxi
->hw_type
->frames_init(ctx
);
373 if (ctxi
->pool_internal
&& !ctx
->pool
)
374 ctx
->pool
= ctxi
->pool_internal
;
376 /* preallocate the frames in the pool, if requested */
377 if (ctx
->initial_pool_size
> 0) {
378 ret
= hwframe_pool_prealloc(ref
);
386 int av_hwframe_transfer_get_formats(AVBufferRef
*hwframe_ref
,
387 enum AVHWFrameTransferDirection dir
,
388 enum AVPixelFormat
**formats
, int flags
)
390 FFHWFramesContext
*ctxi
= (FFHWFramesContext
*)hwframe_ref
->data
;
392 if (!ctxi
->hw_type
->transfer_get_formats
)
393 return AVERROR(ENOSYS
);
395 return ctxi
->hw_type
->transfer_get_formats(&ctxi
->p
, dir
, formats
);
398 static int transfer_data_alloc(AVFrame
*dst
, const AVFrame
*src
, int flags
)
400 AVHWFramesContext
*ctx
;
404 if (!src
->hw_frames_ctx
)
405 return AVERROR(EINVAL
);
406 ctx
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
408 frame_tmp
= av_frame_alloc();
410 return AVERROR(ENOMEM
);
412 /* if the format is set, use that
413 * otherwise pick the first supported one */
414 if (dst
->format
>= 0) {
415 frame_tmp
->format
= dst
->format
;
417 enum AVPixelFormat
*formats
;
419 ret
= av_hwframe_transfer_get_formats(src
->hw_frames_ctx
,
420 AV_HWFRAME_TRANSFER_DIRECTION_FROM
,
424 frame_tmp
->format
= formats
[0];
427 frame_tmp
->width
= ctx
->width
;
428 frame_tmp
->height
= ctx
->height
;
430 ret
= av_frame_get_buffer(frame_tmp
, 0);
434 ret
= av_hwframe_transfer_data(frame_tmp
, src
, flags
);
438 frame_tmp
->width
= src
->width
;
439 frame_tmp
->height
= src
->height
;
441 av_frame_move_ref(dst
, frame_tmp
);
444 av_frame_free(&frame_tmp
);
448 int av_hwframe_transfer_data(AVFrame
*dst
, const AVFrame
*src
, int flags
)
453 return transfer_data_alloc(dst
, src
, flags
);
456 * Hardware -> Hardware Transfer.
457 * Unlike Software -> Hardware or Hardware -> Software, the transfer
458 * function could be provided by either the src or dst, depending on
459 * the specific combination of hardware.
461 if (src
->hw_frames_ctx
&& dst
->hw_frames_ctx
) {
462 FFHWFramesContext
*src_ctx
=
463 (FFHWFramesContext
*)src
->hw_frames_ctx
->data
;
464 FFHWFramesContext
*dst_ctx
=
465 (FFHWFramesContext
*)dst
->hw_frames_ctx
->data
;
467 if (src_ctx
->source_frames
) {
468 av_log(src_ctx
, AV_LOG_ERROR
,
469 "A device with a derived frame context cannot be used as "
470 "the source of a HW -> HW transfer.");
471 return AVERROR(ENOSYS
);
474 if (dst_ctx
->source_frames
) {
475 av_log(src_ctx
, AV_LOG_ERROR
,
476 "A device with a derived frame context cannot be used as "
477 "the destination of a HW -> HW transfer.");
478 return AVERROR(ENOSYS
);
481 ret
= src_ctx
->hw_type
->transfer_data_from(&src_ctx
->p
, dst
, src
);
482 if (ret
== AVERROR(ENOSYS
))
483 ret
= dst_ctx
->hw_type
->transfer_data_to(&dst_ctx
->p
, dst
, src
);
487 if (src
->hw_frames_ctx
) {
488 FFHWFramesContext
*ctx
= (FFHWFramesContext
*)src
->hw_frames_ctx
->data
;
490 ret
= ctx
->hw_type
->transfer_data_from(&ctx
->p
, dst
, src
);
493 } else if (dst
->hw_frames_ctx
) {
494 FFHWFramesContext
*ctx
= (FFHWFramesContext
*)dst
->hw_frames_ctx
->data
;
496 ret
= ctx
->hw_type
->transfer_data_to(&ctx
->p
, dst
, src
);
500 return AVERROR(ENOSYS
);
506 int av_hwframe_get_buffer(AVBufferRef
*hwframe_ref
, AVFrame
*frame
, int flags
)
508 FFHWFramesContext
*ctxi
= (FFHWFramesContext
*)hwframe_ref
->data
;
509 AVHWFramesContext
*ctx
= &ctxi
->p
;
512 if (ctxi
->source_frames
) {
513 // This is a derived frame context, so we allocate in the source
514 // and map the frame immediately.
517 frame
->format
= ctx
->format
;
518 frame
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
519 if (!frame
->hw_frames_ctx
)
520 return AVERROR(ENOMEM
);
522 src_frame
= av_frame_alloc();
524 return AVERROR(ENOMEM
);
526 ret
= av_hwframe_get_buffer(ctxi
->source_frames
,
529 av_frame_free(&src_frame
);
533 ret
= av_hwframe_map(frame
, src_frame
,
534 ctxi
->source_allocation_map_flags
);
536 av_log(ctx
, AV_LOG_ERROR
, "Failed to map frame into derived "
537 "frame context: %d.\n", ret
);
538 av_frame_free(&src_frame
);
542 // Free the source frame immediately - the mapped frame still
543 // contains a reference to it.
544 av_frame_free(&src_frame
);
549 if (!ctxi
->hw_type
->frames_get_buffer
)
550 return AVERROR(ENOSYS
);
553 return AVERROR(EINVAL
);
555 frame
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
556 if (!frame
->hw_frames_ctx
)
557 return AVERROR(ENOMEM
);
559 ret
= ctxi
->hw_type
->frames_get_buffer(ctx
, frame
);
561 av_buffer_unref(&frame
->hw_frames_ctx
);
565 frame
->extended_data
= frame
->data
;
570 void *av_hwdevice_hwconfig_alloc(AVBufferRef
*ref
)
572 FFHWDeviceContext
*ctx
= (FFHWDeviceContext
*)ref
->data
;
573 const HWContextType
*hw_type
= ctx
->hw_type
;
575 if (hw_type
->device_hwconfig_size
== 0)
578 return av_mallocz(hw_type
->device_hwconfig_size
);
581 AVHWFramesConstraints
*av_hwdevice_get_hwframe_constraints(AVBufferRef
*ref
,
582 const void *hwconfig
)
584 FFHWDeviceContext
*ctx
= (FFHWDeviceContext
*)ref
->data
;
585 const HWContextType
*hw_type
= ctx
->hw_type
;
586 AVHWFramesConstraints
*constraints
;
588 if (!hw_type
->frames_get_constraints
)
591 constraints
= av_mallocz(sizeof(*constraints
));
595 constraints
->min_width
= constraints
->min_height
= 0;
596 constraints
->max_width
= constraints
->max_height
= INT_MAX
;
598 if (hw_type
->frames_get_constraints(&ctx
->p
, hwconfig
, constraints
) >= 0) {
601 av_hwframe_constraints_free(&constraints
);
606 void av_hwframe_constraints_free(AVHWFramesConstraints
**constraints
)
609 av_freep(&(*constraints
)->valid_hw_formats
);
610 av_freep(&(*constraints
)->valid_sw_formats
);
612 av_freep(constraints
);
615 int av_hwdevice_ctx_create(AVBufferRef
**pdevice_ref
, enum AVHWDeviceType type
,
616 const char *device
, AVDictionary
*opts
, int flags
)
618 AVBufferRef
*device_ref
= NULL
;
619 FFHWDeviceContext
*device_ctx
;
622 device_ref
= av_hwdevice_ctx_alloc(type
);
624 ret
= AVERROR(ENOMEM
);
627 device_ctx
= (FFHWDeviceContext
*)device_ref
->data
;
629 if (!device_ctx
->hw_type
->device_create
) {
630 ret
= AVERROR(ENOSYS
);
634 ret
= device_ctx
->hw_type
->device_create(&device_ctx
->p
, device
,
639 ret
= av_hwdevice_ctx_init(device_ref
);
643 *pdevice_ref
= device_ref
;
646 av_buffer_unref(&device_ref
);
651 int av_hwdevice_ctx_create_derived_opts(AVBufferRef
**dst_ref_ptr
,
652 enum AVHWDeviceType type
,
653 AVBufferRef
*src_ref
,
654 AVDictionary
*options
, int flags
)
656 AVBufferRef
*dst_ref
= NULL
, *tmp_ref
;
657 FFHWDeviceContext
*dst_ctx
;
662 FFHWDeviceContext
*tmp_ctx
= (FFHWDeviceContext
*)tmp_ref
->data
;
663 if (tmp_ctx
->p
.type
== type
) {
664 dst_ref
= av_buffer_ref(tmp_ref
);
666 ret
= AVERROR(ENOMEM
);
671 tmp_ref
= tmp_ctx
->source_device
;
674 dst_ref
= av_hwdevice_ctx_alloc(type
);
676 ret
= AVERROR(ENOMEM
);
679 dst_ctx
= (FFHWDeviceContext
*)dst_ref
->data
;
683 FFHWDeviceContext
*tmp_ctx
= (FFHWDeviceContext
*)tmp_ref
->data
;
684 if (dst_ctx
->hw_type
->device_derive
) {
685 ret
= dst_ctx
->hw_type
->device_derive(&dst_ctx
->p
,
689 dst_ctx
->source_device
= av_buffer_ref(src_ref
);
690 if (!dst_ctx
->source_device
) {
691 ret
= AVERROR(ENOMEM
);
694 ret
= av_hwdevice_ctx_init(dst_ref
);
699 if (ret
!= AVERROR(ENOSYS
))
702 tmp_ref
= tmp_ctx
->source_device
;
705 ret
= AVERROR(ENOSYS
);
709 *dst_ref_ptr
= dst_ref
;
713 av_buffer_unref(&dst_ref
);
718 int av_hwdevice_ctx_create_derived(AVBufferRef
**dst_ref_ptr
,
719 enum AVHWDeviceType type
,
720 AVBufferRef
*src_ref
, int flags
)
722 return av_hwdevice_ctx_create_derived_opts(dst_ref_ptr
, type
, src_ref
,
726 static void ff_hwframe_unmap(void *opaque
, uint8_t *data
)
728 HWMapDescriptor
*hwmap
= (HWMapDescriptor
*)data
;
729 AVHWFramesContext
*ctx
= opaque
;
732 hwmap
->unmap(ctx
, hwmap
);
734 av_frame_free(&hwmap
->source
);
736 av_buffer_unref(&hwmap
->hw_frames_ctx
);
741 int ff_hwframe_map_create(AVBufferRef
*hwframe_ref
,
742 AVFrame
*dst
, const AVFrame
*src
,
743 void (*unmap
)(AVHWFramesContext
*ctx
,
744 HWMapDescriptor
*hwmap
),
747 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)hwframe_ref
->data
;
748 HWMapDescriptor
*hwmap
;
751 hwmap
= av_mallocz(sizeof(*hwmap
));
753 ret
= AVERROR(ENOMEM
);
757 hwmap
->source
= av_frame_alloc();
758 if (!hwmap
->source
) {
759 ret
= AVERROR(ENOMEM
);
762 ret
= av_frame_ref(hwmap
->source
, src
);
766 hwmap
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
767 if (!hwmap
->hw_frames_ctx
) {
768 ret
= AVERROR(ENOMEM
);
772 hwmap
->unmap
= unmap
;
775 dst
->buf
[0] = av_buffer_create((uint8_t*)hwmap
, sizeof(*hwmap
),
776 &ff_hwframe_unmap
, ctx
, 0);
778 ret
= AVERROR(ENOMEM
);
786 av_buffer_unref(&hwmap
->hw_frames_ctx
);
787 av_frame_free(&hwmap
->source
);
793 int av_hwframe_map(AVFrame
*dst
, const AVFrame
*src
, int flags
)
795 AVBufferRef
*orig_dst_frames
= dst
->hw_frames_ctx
;
796 enum AVPixelFormat orig_dst_fmt
= dst
->format
;
797 HWMapDescriptor
*hwmap
;
800 if (src
->hw_frames_ctx
&& dst
->hw_frames_ctx
) {
801 FFHWFramesContext
*src_frames
= (FFHWFramesContext
*)src
->hw_frames_ctx
->data
;
802 FFHWFramesContext
*dst_frames
= (FFHWFramesContext
*)dst
->hw_frames_ctx
->data
;
804 if ((src_frames
== dst_frames
&&
805 src
->format
== dst_frames
->p
.sw_format
&&
806 dst
->format
== dst_frames
->p
.format
) ||
807 (src_frames
->source_frames
&&
808 src_frames
->source_frames
->data
==
809 (uint8_t*)dst_frames
)) {
810 // This is an unmap operation. We don't need to directly
811 // do anything here other than fill in the original frame,
812 // because the real unmap will be invoked when the last
813 // reference to the mapped frame disappears.
815 av_log(src_frames
, AV_LOG_ERROR
, "Invalid mapping "
816 "found when attempting unmap.\n");
817 return AVERROR(EINVAL
);
819 hwmap
= (HWMapDescriptor
*)src
->buf
[0]->data
;
820 return av_frame_replace(dst
, hwmap
->source
);
824 if (src
->hw_frames_ctx
) {
825 FFHWFramesContext
*src_frames
= (FFHWFramesContext
*)src
->hw_frames_ctx
->data
;
827 if (src_frames
->p
.format
== src
->format
&&
828 src_frames
->hw_type
->map_from
) {
829 ret
= src_frames
->hw_type
->map_from(&src_frames
->p
,
833 else if (ret
!= AVERROR(ENOSYS
))
838 if (dst
->hw_frames_ctx
) {
839 FFHWFramesContext
*dst_frames
= (FFHWFramesContext
*)dst
->hw_frames_ctx
->data
;
841 if (dst_frames
->p
.format
== dst
->format
&&
842 dst_frames
->hw_type
->map_to
) {
843 ret
= dst_frames
->hw_type
->map_to(&dst_frames
->p
,
847 else if (ret
!= AVERROR(ENOSYS
))
852 return AVERROR(ENOSYS
);
855 // if the caller provided dst frames context, it should be preserved
857 av_assert0(orig_dst_frames
== NULL
||
858 orig_dst_frames
== dst
->hw_frames_ctx
);
860 // preserve user-provided dst frame fields, but clean
861 // anything we might have set
862 dst
->hw_frames_ctx
= NULL
;
865 dst
->hw_frames_ctx
= orig_dst_frames
;
866 dst
->format
= orig_dst_fmt
;
871 int av_hwframe_ctx_create_derived(AVBufferRef
**derived_frame_ctx
,
872 enum AVPixelFormat format
,
873 AVBufferRef
*derived_device_ctx
,
874 AVBufferRef
*source_frame_ctx
,
877 AVBufferRef
*dst_ref
= NULL
;
878 FFHWFramesContext
*dsti
= NULL
;
879 FFHWFramesContext
*srci
= (FFHWFramesContext
*)source_frame_ctx
->data
;
880 AVHWFramesContext
*dst
, *src
= &srci
->p
;
883 if (srci
->source_frames
) {
884 AVHWFramesContext
*src_src
=
885 (AVHWFramesContext
*)srci
->source_frames
->data
;
886 AVHWDeviceContext
*dst_dev
=
887 (AVHWDeviceContext
*)derived_device_ctx
->data
;
889 if (src_src
->device_ctx
== dst_dev
) {
890 // This is actually an unmapping, so we just return a
891 // reference to the source frame context.
892 *derived_frame_ctx
= av_buffer_ref(srci
->source_frames
);
893 if (!*derived_frame_ctx
) {
894 ret
= AVERROR(ENOMEM
);
901 dst_ref
= av_hwframe_ctx_alloc(derived_device_ctx
);
903 ret
= AVERROR(ENOMEM
);
907 dsti
= (FFHWFramesContext
*)dst_ref
->data
;
910 dst
->format
= format
;
911 dst
->sw_format
= src
->sw_format
;
912 dst
->width
= src
->width
;
913 dst
->height
= src
->height
;
915 dsti
->source_frames
= av_buffer_ref(source_frame_ctx
);
916 if (!dsti
->source_frames
) {
917 ret
= AVERROR(ENOMEM
);
921 dsti
->source_allocation_map_flags
=
922 flags
& (AV_HWFRAME_MAP_READ
|
923 AV_HWFRAME_MAP_WRITE
|
924 AV_HWFRAME_MAP_OVERWRITE
|
925 AV_HWFRAME_MAP_DIRECT
);
927 ret
= AVERROR(ENOSYS
);
928 if (srci
->hw_type
->frames_derive_from
)
929 ret
= srci
->hw_type
->frames_derive_from(dst
, src
, flags
);
930 if (ret
== AVERROR(ENOSYS
) &&
931 dsti
->hw_type
->frames_derive_to
)
932 ret
= dsti
->hw_type
->frames_derive_to(dst
, src
, flags
);
933 if (ret
== AVERROR(ENOSYS
))
938 *derived_frame_ctx
= dst_ref
;
943 av_buffer_unref(&dsti
->source_frames
);
944 av_buffer_unref(&dst_ref
);
948 int ff_hwframe_map_replace(AVFrame
*dst
, const AVFrame
*src
)
950 HWMapDescriptor
*hwmap
= (HWMapDescriptor
*)dst
->buf
[0]->data
;
951 return av_frame_replace(hwmap
->source
, src
);