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_drm
,
43 &ff_hwcontext_type_dxva2
,
46 &ff_hwcontext_type_opencl
,
49 &ff_hwcontext_type_qsv
,
52 &ff_hwcontext_type_vaapi
,
55 &ff_hwcontext_type_vdpau
,
57 #if CONFIG_VIDEOTOOLBOX
58 &ff_hwcontext_type_videotoolbox
,
61 &ff_hwcontext_type_mediacodec
,
64 &ff_hwcontext_type_vulkan
,
69 static const char *const hw_type_names
[] = {
70 [AV_HWDEVICE_TYPE_CUDA
] = "cuda",
71 [AV_HWDEVICE_TYPE_DRM
] = "drm",
72 [AV_HWDEVICE_TYPE_DXVA2
] = "dxva2",
73 [AV_HWDEVICE_TYPE_D3D11VA
] = "d3d11va",
74 [AV_HWDEVICE_TYPE_OPENCL
] = "opencl",
75 [AV_HWDEVICE_TYPE_QSV
] = "qsv",
76 [AV_HWDEVICE_TYPE_VAAPI
] = "vaapi",
77 [AV_HWDEVICE_TYPE_VDPAU
] = "vdpau",
78 [AV_HWDEVICE_TYPE_VIDEOTOOLBOX
] = "videotoolbox",
79 [AV_HWDEVICE_TYPE_MEDIACODEC
] = "mediacodec",
80 [AV_HWDEVICE_TYPE_VULKAN
] = "vulkan",
83 enum AVHWDeviceType
av_hwdevice_find_type_by_name(const char *name
)
86 for (type
= 0; type
< FF_ARRAY_ELEMS(hw_type_names
); type
++) {
87 if (hw_type_names
[type
] && !strcmp(hw_type_names
[type
], name
))
90 return AV_HWDEVICE_TYPE_NONE
;
93 const char *av_hwdevice_get_type_name(enum AVHWDeviceType type
)
95 if (type
> AV_HWDEVICE_TYPE_NONE
&&
96 type
< FF_ARRAY_ELEMS(hw_type_names
))
97 return hw_type_names
[type
];
102 enum AVHWDeviceType
av_hwdevice_iterate_types(enum AVHWDeviceType prev
)
104 enum AVHWDeviceType next
;
106 for (i
= 0; hw_table
[i
]; i
++) {
107 if (prev
!= AV_HWDEVICE_TYPE_NONE
&& hw_table
[i
]->type
<= prev
)
109 if (!set
|| hw_table
[i
]->type
< next
) {
110 next
= hw_table
[i
]->type
;
114 return set
? next
: AV_HWDEVICE_TYPE_NONE
;
117 static const AVClass hwdevice_ctx_class
= {
118 .class_name
= "AVHWDeviceContext",
119 .item_name
= av_default_item_name
,
120 .version
= LIBAVUTIL_VERSION_INT
,
123 static void hwdevice_ctx_free(void *opaque
, uint8_t *data
)
125 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)data
;
127 /* uninit might still want access the hw context and the user
128 * free() callback might destroy it, so uninit has to be called first */
129 if (ctx
->internal
->hw_type
->device_uninit
)
130 ctx
->internal
->hw_type
->device_uninit(ctx
);
135 av_buffer_unref(&ctx
->internal
->source_device
);
137 av_freep(&ctx
->hwctx
);
138 av_freep(&ctx
->internal
->priv
);
139 av_freep(&ctx
->internal
);
143 AVBufferRef
*av_hwdevice_ctx_alloc(enum AVHWDeviceType type
)
145 AVHWDeviceContext
*ctx
;
147 const HWContextType
*hw_type
= NULL
;
150 for (i
= 0; hw_table
[i
]; i
++) {
151 if (hw_table
[i
]->type
== type
) {
152 hw_type
= hw_table
[i
];
159 ctx
= av_mallocz(sizeof(*ctx
));
163 ctx
->internal
= av_mallocz(sizeof(*ctx
->internal
));
167 if (hw_type
->device_priv_size
) {
168 ctx
->internal
->priv
= av_mallocz(hw_type
->device_priv_size
);
169 if (!ctx
->internal
->priv
)
173 if (hw_type
->device_hwctx_size
) {
174 ctx
->hwctx
= av_mallocz(hw_type
->device_hwctx_size
);
179 buf
= av_buffer_create((uint8_t*)ctx
, sizeof(*ctx
),
180 hwdevice_ctx_free
, NULL
,
181 AV_BUFFER_FLAG_READONLY
);
186 ctx
->av_class
= &hwdevice_ctx_class
;
188 ctx
->internal
->hw_type
= hw_type
;
194 av_freep(&ctx
->internal
->priv
);
195 av_freep(&ctx
->internal
);
196 av_freep(&ctx
->hwctx
);
201 int av_hwdevice_ctx_init(AVBufferRef
*ref
)
203 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)ref
->data
;
206 if (ctx
->internal
->hw_type
->device_init
) {
207 ret
= ctx
->internal
->hw_type
->device_init(ctx
);
214 if (ctx
->internal
->hw_type
->device_uninit
)
215 ctx
->internal
->hw_type
->device_uninit(ctx
);
219 static const AVClass hwframe_ctx_class
= {
220 .class_name
= "AVHWFramesContext",
221 .item_name
= av_default_item_name
,
222 .version
= LIBAVUTIL_VERSION_INT
,
225 static void hwframe_ctx_free(void *opaque
, uint8_t *data
)
227 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)data
;
229 if (ctx
->internal
->pool_internal
)
230 av_buffer_pool_uninit(&ctx
->internal
->pool_internal
);
232 if (ctx
->internal
->hw_type
->frames_uninit
)
233 ctx
->internal
->hw_type
->frames_uninit(ctx
);
238 av_buffer_unref(&ctx
->internal
->source_frames
);
240 av_buffer_unref(&ctx
->device_ref
);
242 av_freep(&ctx
->hwctx
);
243 av_freep(&ctx
->internal
->priv
);
244 av_freep(&ctx
->internal
);
248 AVBufferRef
*av_hwframe_ctx_alloc(AVBufferRef
*device_ref_in
)
250 AVHWDeviceContext
*device_ctx
= (AVHWDeviceContext
*)device_ref_in
->data
;
251 const HWContextType
*hw_type
= device_ctx
->internal
->hw_type
;
252 AVHWFramesContext
*ctx
;
253 AVBufferRef
*buf
, *device_ref
= NULL
;
255 ctx
= av_mallocz(sizeof(*ctx
));
259 ctx
->internal
= av_mallocz(sizeof(*ctx
->internal
));
263 if (hw_type
->frames_priv_size
) {
264 ctx
->internal
->priv
= av_mallocz(hw_type
->frames_priv_size
);
265 if (!ctx
->internal
->priv
)
269 if (hw_type
->frames_hwctx_size
) {
270 ctx
->hwctx
= av_mallocz(hw_type
->frames_hwctx_size
);
275 device_ref
= av_buffer_ref(device_ref_in
);
279 buf
= av_buffer_create((uint8_t*)ctx
, sizeof(*ctx
),
280 hwframe_ctx_free
, NULL
,
281 AV_BUFFER_FLAG_READONLY
);
285 ctx
->av_class
= &hwframe_ctx_class
;
286 ctx
->device_ref
= device_ref
;
287 ctx
->device_ctx
= device_ctx
;
288 ctx
->format
= AV_PIX_FMT_NONE
;
289 ctx
->sw_format
= AV_PIX_FMT_NONE
;
291 ctx
->internal
->hw_type
= hw_type
;
297 av_buffer_unref(&device_ref
);
299 av_freep(&ctx
->internal
->priv
);
300 av_freep(&ctx
->internal
);
301 av_freep(&ctx
->hwctx
);
306 static int hwframe_pool_prealloc(AVBufferRef
*ref
)
308 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)ref
->data
;
312 frames
= av_calloc(ctx
->initial_pool_size
, sizeof(*frames
));
314 return AVERROR(ENOMEM
);
316 for (i
= 0; i
< ctx
->initial_pool_size
; i
++) {
317 frames
[i
] = av_frame_alloc();
321 ret
= av_hwframe_get_buffer(ref
, frames
[i
], 0);
327 for (i
= 0; i
< ctx
->initial_pool_size
; i
++)
328 av_frame_free(&frames
[i
]);
334 int av_hwframe_ctx_init(AVBufferRef
*ref
)
336 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)ref
->data
;
337 const enum AVPixelFormat
*pix_fmt
;
340 if (ctx
->internal
->source_frames
) {
341 /* A derived frame context is already initialised. */
345 /* validate the pixel format */
346 for (pix_fmt
= ctx
->internal
->hw_type
->pix_fmts
; *pix_fmt
!= AV_PIX_FMT_NONE
; pix_fmt
++) {
347 if (*pix_fmt
== ctx
->format
)
350 if (*pix_fmt
== AV_PIX_FMT_NONE
) {
351 av_log(ctx
, AV_LOG_ERROR
,
352 "The hardware pixel format '%s' is not supported by the device type '%s'\n",
353 av_get_pix_fmt_name(ctx
->format
), ctx
->internal
->hw_type
->name
);
354 return AVERROR(ENOSYS
);
357 /* validate the dimensions */
358 ret
= av_image_check_size(ctx
->width
, ctx
->height
, 0, ctx
);
362 /* format-specific init */
363 if (ctx
->internal
->hw_type
->frames_init
) {
364 ret
= ctx
->internal
->hw_type
->frames_init(ctx
);
369 if (ctx
->internal
->pool_internal
&& !ctx
->pool
)
370 ctx
->pool
= ctx
->internal
->pool_internal
;
372 /* preallocate the frames in the pool, if requested */
373 if (ctx
->initial_pool_size
> 0) {
374 ret
= hwframe_pool_prealloc(ref
);
381 if (ctx
->internal
->hw_type
->frames_uninit
)
382 ctx
->internal
->hw_type
->frames_uninit(ctx
);
386 int av_hwframe_transfer_get_formats(AVBufferRef
*hwframe_ref
,
387 enum AVHWFrameTransferDirection dir
,
388 enum AVPixelFormat
**formats
, int flags
)
390 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)hwframe_ref
->data
;
392 if (!ctx
->internal
->hw_type
->transfer_get_formats
)
393 return AVERROR(ENOSYS
);
395 return ctx
->internal
->hw_type
->transfer_get_formats(ctx
, dir
, formats
);
398 static int transfer_data_alloc(AVFrame
*dst
, const AVFrame
*src
, int flags
)
400 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
404 frame_tmp
= av_frame_alloc();
406 return AVERROR(ENOMEM
);
408 /* if the format is set, use that
409 * otherwise pick the first supported one */
410 if (dst
->format
>= 0) {
411 frame_tmp
->format
= dst
->format
;
413 enum AVPixelFormat
*formats
;
415 ret
= av_hwframe_transfer_get_formats(src
->hw_frames_ctx
,
416 AV_HWFRAME_TRANSFER_DIRECTION_FROM
,
420 frame_tmp
->format
= formats
[0];
423 frame_tmp
->width
= ctx
->width
;
424 frame_tmp
->height
= ctx
->height
;
426 ret
= av_frame_get_buffer(frame_tmp
, 0);
430 ret
= av_hwframe_transfer_data(frame_tmp
, src
, flags
);
434 frame_tmp
->width
= src
->width
;
435 frame_tmp
->height
= src
->height
;
437 av_frame_move_ref(dst
, frame_tmp
);
440 av_frame_free(&frame_tmp
);
444 int av_hwframe_transfer_data(AVFrame
*dst
, const AVFrame
*src
, int flags
)
446 AVHWFramesContext
*ctx
;
450 return transfer_data_alloc(dst
, src
, flags
);
453 * Hardware -> Hardware Transfer.
454 * Unlike Software -> Hardware or Hardware -> Software, the transfer
455 * function could be provided by either the src or dst, depending on
456 * the specific combination of hardware.
458 if (src
->hw_frames_ctx
&& dst
->hw_frames_ctx
) {
459 AVHWFramesContext
*src_ctx
=
460 (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
461 AVHWFramesContext
*dst_ctx
=
462 (AVHWFramesContext
*)dst
->hw_frames_ctx
->data
;
464 if (src_ctx
->internal
->source_frames
) {
465 av_log(src_ctx
, AV_LOG_ERROR
,
466 "A device with a derived frame context cannot be used as "
467 "the source of a HW -> HW transfer.");
468 return AVERROR(ENOSYS
);
471 if (dst_ctx
->internal
->source_frames
) {
472 av_log(src_ctx
, AV_LOG_ERROR
,
473 "A device with a derived frame context cannot be used as "
474 "the destination of a HW -> HW transfer.");
475 return AVERROR(ENOSYS
);
478 ret
= src_ctx
->internal
->hw_type
->transfer_data_from(src_ctx
, dst
, src
);
479 if (ret
== AVERROR(ENOSYS
))
480 ret
= dst_ctx
->internal
->hw_type
->transfer_data_to(dst_ctx
, dst
, src
);
484 if (src
->hw_frames_ctx
) {
485 ctx
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
487 ret
= ctx
->internal
->hw_type
->transfer_data_from(ctx
, dst
, src
);
490 } else if (dst
->hw_frames_ctx
) {
491 ctx
= (AVHWFramesContext
*)dst
->hw_frames_ctx
->data
;
493 ret
= ctx
->internal
->hw_type
->transfer_data_to(ctx
, dst
, src
);
497 return AVERROR(ENOSYS
);
503 int av_hwframe_get_buffer(AVBufferRef
*hwframe_ref
, AVFrame
*frame
, int flags
)
505 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)hwframe_ref
->data
;
508 if (ctx
->internal
->source_frames
) {
509 // This is a derived frame context, so we allocate in the source
510 // and map the frame immediately.
513 frame
->format
= ctx
->format
;
514 frame
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
515 if (!frame
->hw_frames_ctx
)
516 return AVERROR(ENOMEM
);
518 src_frame
= av_frame_alloc();
520 return AVERROR(ENOMEM
);
522 ret
= av_hwframe_get_buffer(ctx
->internal
->source_frames
,
525 av_frame_free(&src_frame
);
529 ret
= av_hwframe_map(frame
, src_frame
,
530 ctx
->internal
->source_allocation_map_flags
);
532 av_log(ctx
, AV_LOG_ERROR
, "Failed to map frame into derived "
533 "frame context: %d.\n", ret
);
534 av_frame_free(&src_frame
);
538 // Free the source frame immediately - the mapped frame still
539 // contains a reference to it.
540 av_frame_free(&src_frame
);
545 if (!ctx
->internal
->hw_type
->frames_get_buffer
)
546 return AVERROR(ENOSYS
);
549 return AVERROR(EINVAL
);
551 frame
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
552 if (!frame
->hw_frames_ctx
)
553 return AVERROR(ENOMEM
);
555 ret
= ctx
->internal
->hw_type
->frames_get_buffer(ctx
, frame
);
557 av_buffer_unref(&frame
->hw_frames_ctx
);
561 frame
->extended_data
= frame
->data
;
566 void *av_hwdevice_hwconfig_alloc(AVBufferRef
*ref
)
568 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)ref
->data
;
569 const HWContextType
*hw_type
= ctx
->internal
->hw_type
;
571 if (hw_type
->device_hwconfig_size
== 0)
574 return av_mallocz(hw_type
->device_hwconfig_size
);
577 AVHWFramesConstraints
*av_hwdevice_get_hwframe_constraints(AVBufferRef
*ref
,
578 const void *hwconfig
)
580 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)ref
->data
;
581 const HWContextType
*hw_type
= ctx
->internal
->hw_type
;
582 AVHWFramesConstraints
*constraints
;
584 if (!hw_type
->frames_get_constraints
)
587 constraints
= av_mallocz(sizeof(*constraints
));
591 constraints
->min_width
= constraints
->min_height
= 0;
592 constraints
->max_width
= constraints
->max_height
= INT_MAX
;
594 if (hw_type
->frames_get_constraints(ctx
, hwconfig
, constraints
) >= 0) {
597 av_hwframe_constraints_free(&constraints
);
602 void av_hwframe_constraints_free(AVHWFramesConstraints
**constraints
)
605 av_freep(&(*constraints
)->valid_hw_formats
);
606 av_freep(&(*constraints
)->valid_sw_formats
);
608 av_freep(constraints
);
611 int av_hwdevice_ctx_create(AVBufferRef
**pdevice_ref
, enum AVHWDeviceType type
,
612 const char *device
, AVDictionary
*opts
, int flags
)
614 AVBufferRef
*device_ref
= NULL
;
615 AVHWDeviceContext
*device_ctx
;
618 device_ref
= av_hwdevice_ctx_alloc(type
);
620 ret
= AVERROR(ENOMEM
);
623 device_ctx
= (AVHWDeviceContext
*)device_ref
->data
;
625 if (!device_ctx
->internal
->hw_type
->device_create
) {
626 ret
= AVERROR(ENOSYS
);
630 ret
= device_ctx
->internal
->hw_type
->device_create(device_ctx
, device
,
635 ret
= av_hwdevice_ctx_init(device_ref
);
639 *pdevice_ref
= device_ref
;
642 av_buffer_unref(&device_ref
);
647 int av_hwdevice_ctx_create_derived_opts(AVBufferRef
**dst_ref_ptr
,
648 enum AVHWDeviceType type
,
649 AVBufferRef
*src_ref
,
650 AVDictionary
*options
, int flags
)
652 AVBufferRef
*dst_ref
= NULL
, *tmp_ref
;
653 AVHWDeviceContext
*dst_ctx
, *tmp_ctx
;
658 tmp_ctx
= (AVHWDeviceContext
*)tmp_ref
->data
;
659 if (tmp_ctx
->type
== type
) {
660 dst_ref
= av_buffer_ref(tmp_ref
);
662 ret
= AVERROR(ENOMEM
);
667 tmp_ref
= tmp_ctx
->internal
->source_device
;
670 dst_ref
= av_hwdevice_ctx_alloc(type
);
672 ret
= AVERROR(ENOMEM
);
675 dst_ctx
= (AVHWDeviceContext
*)dst_ref
->data
;
679 tmp_ctx
= (AVHWDeviceContext
*)tmp_ref
->data
;
680 if (dst_ctx
->internal
->hw_type
->device_derive
) {
681 ret
= dst_ctx
->internal
->hw_type
->device_derive(dst_ctx
,
686 dst_ctx
->internal
->source_device
= av_buffer_ref(src_ref
);
687 if (!dst_ctx
->internal
->source_device
) {
688 ret
= AVERROR(ENOMEM
);
691 ret
= av_hwdevice_ctx_init(dst_ref
);
696 if (ret
!= AVERROR(ENOSYS
))
699 tmp_ref
= tmp_ctx
->internal
->source_device
;
702 ret
= AVERROR(ENOSYS
);
706 *dst_ref_ptr
= dst_ref
;
710 av_buffer_unref(&dst_ref
);
715 int av_hwdevice_ctx_create_derived(AVBufferRef
**dst_ref_ptr
,
716 enum AVHWDeviceType type
,
717 AVBufferRef
*src_ref
, int flags
)
719 return av_hwdevice_ctx_create_derived_opts(dst_ref_ptr
, type
, src_ref
,
723 static void ff_hwframe_unmap(void *opaque
, uint8_t *data
)
725 HWMapDescriptor
*hwmap
= (HWMapDescriptor
*)data
;
726 AVHWFramesContext
*ctx
= opaque
;
729 hwmap
->unmap(ctx
, hwmap
);
731 av_frame_free(&hwmap
->source
);
733 av_buffer_unref(&hwmap
->hw_frames_ctx
);
738 int ff_hwframe_map_create(AVBufferRef
*hwframe_ref
,
739 AVFrame
*dst
, const AVFrame
*src
,
740 void (*unmap
)(AVHWFramesContext
*ctx
,
741 HWMapDescriptor
*hwmap
),
744 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)hwframe_ref
->data
;
745 HWMapDescriptor
*hwmap
;
748 hwmap
= av_mallocz(sizeof(*hwmap
));
750 ret
= AVERROR(ENOMEM
);
754 hwmap
->source
= av_frame_alloc();
755 if (!hwmap
->source
) {
756 ret
= AVERROR(ENOMEM
);
759 ret
= av_frame_ref(hwmap
->source
, src
);
763 hwmap
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
764 if (!hwmap
->hw_frames_ctx
) {
765 ret
= AVERROR(ENOMEM
);
769 hwmap
->unmap
= unmap
;
772 dst
->buf
[0] = av_buffer_create((uint8_t*)hwmap
, sizeof(*hwmap
),
773 &ff_hwframe_unmap
, ctx
, 0);
775 ret
= AVERROR(ENOMEM
);
783 av_buffer_unref(&hwmap
->hw_frames_ctx
);
784 av_frame_free(&hwmap
->source
);
790 int av_hwframe_map(AVFrame
*dst
, const AVFrame
*src
, int flags
)
792 AVBufferRef
*orig_dst_frames
= dst
->hw_frames_ctx
;
793 enum AVPixelFormat orig_dst_fmt
= dst
->format
;
794 AVHWFramesContext
*src_frames
, *dst_frames
;
795 HWMapDescriptor
*hwmap
;
798 if (src
->hw_frames_ctx
&& dst
->hw_frames_ctx
) {
799 src_frames
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
800 dst_frames
= (AVHWFramesContext
*)dst
->hw_frames_ctx
->data
;
802 if ((src_frames
== dst_frames
&&
803 src
->format
== dst_frames
->sw_format
&&
804 dst
->format
== dst_frames
->format
) ||
805 (src_frames
->internal
->source_frames
&&
806 src_frames
->internal
->source_frames
->data
==
807 (uint8_t*)dst_frames
)) {
808 // This is an unmap operation. We don't need to directly
809 // do anything here other than fill in the original frame,
810 // because the real unmap will be invoked when the last
811 // reference to the mapped frame disappears.
813 av_log(src_frames
, AV_LOG_ERROR
, "Invalid mapping "
814 "found when attempting unmap.\n");
815 return AVERROR(EINVAL
);
817 hwmap
= (HWMapDescriptor
*)src
->buf
[0]->data
;
819 return av_frame_ref(dst
, hwmap
->source
);
823 if (src
->hw_frames_ctx
) {
824 src_frames
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
826 if (src_frames
->format
== src
->format
&&
827 src_frames
->internal
->hw_type
->map_from
) {
828 ret
= src_frames
->internal
->hw_type
->map_from(src_frames
,
832 else if (ret
!= AVERROR(ENOSYS
))
837 if (dst
->hw_frames_ctx
) {
838 dst_frames
= (AVHWFramesContext
*)dst
->hw_frames_ctx
->data
;
840 if (dst_frames
->format
== dst
->format
&&
841 dst_frames
->internal
->hw_type
->map_to
) {
842 ret
= dst_frames
->internal
->hw_type
->map_to(dst_frames
,
846 else if (ret
!= AVERROR(ENOSYS
))
851 return AVERROR(ENOSYS
);
854 // if the caller provided dst frames context, it should be preserved
856 av_assert0(orig_dst_frames
== NULL
||
857 orig_dst_frames
== dst
->hw_frames_ctx
);
859 // preserve user-provided dst frame fields, but clean
860 // anything we might have set
861 dst
->hw_frames_ctx
= NULL
;
864 dst
->hw_frames_ctx
= orig_dst_frames
;
865 dst
->format
= orig_dst_fmt
;
870 int av_hwframe_ctx_create_derived(AVBufferRef
**derived_frame_ctx
,
871 enum AVPixelFormat format
,
872 AVBufferRef
*derived_device_ctx
,
873 AVBufferRef
*source_frame_ctx
,
876 AVBufferRef
*dst_ref
= NULL
;
877 AVHWFramesContext
*dst
= NULL
;
878 AVHWFramesContext
*src
= (AVHWFramesContext
*)source_frame_ctx
->data
;
881 if (src
->internal
->source_frames
) {
882 AVHWFramesContext
*src_src
=
883 (AVHWFramesContext
*)src
->internal
->source_frames
->data
;
884 AVHWDeviceContext
*dst_dev
=
885 (AVHWDeviceContext
*)derived_device_ctx
->data
;
887 if (src_src
->device_ctx
== dst_dev
) {
888 // This is actually an unmapping, so we just return a
889 // reference to the source frame context.
891 av_buffer_ref(src
->internal
->source_frames
);
892 if (!*derived_frame_ctx
) {
893 ret
= AVERROR(ENOMEM
);
900 dst_ref
= av_hwframe_ctx_alloc(derived_device_ctx
);
902 ret
= AVERROR(ENOMEM
);
906 dst
= (AVHWFramesContext
*)dst_ref
->data
;
908 dst
->format
= format
;
909 dst
->sw_format
= src
->sw_format
;
910 dst
->width
= src
->width
;
911 dst
->height
= src
->height
;
913 dst
->internal
->source_frames
= av_buffer_ref(source_frame_ctx
);
914 if (!dst
->internal
->source_frames
) {
915 ret
= AVERROR(ENOMEM
);
919 dst
->internal
->source_allocation_map_flags
=
920 flags
& (AV_HWFRAME_MAP_READ
|
921 AV_HWFRAME_MAP_WRITE
|
922 AV_HWFRAME_MAP_OVERWRITE
|
923 AV_HWFRAME_MAP_DIRECT
);
925 ret
= AVERROR(ENOSYS
);
926 if (src
->internal
->hw_type
->frames_derive_from
)
927 ret
= src
->internal
->hw_type
->frames_derive_from(dst
, src
, flags
);
928 if (ret
== AVERROR(ENOSYS
) &&
929 dst
->internal
->hw_type
->frames_derive_to
)
930 ret
= dst
->internal
->hw_type
->frames_derive_to(dst
, src
, flags
);
931 if (ret
== AVERROR(ENOSYS
))
936 *derived_frame_ctx
= dst_ref
;
941 av_buffer_unref(&dst
->internal
->source_frames
);
942 av_buffer_unref(&dst_ref
);
946 int ff_hwframe_map_replace(AVFrame
*dst
, const AVFrame
*src
)
948 HWMapDescriptor
*hwmap
= (HWMapDescriptor
*)dst
->buf
[0]->data
;
949 av_frame_unref(hwmap
->source
);
950 return av_frame_ref(hwmap
->source
, src
);