2 * This file is part of Libav.
4 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "hwcontext.h"
24 #include "hwcontext_internal.h"
31 static const HWContextType
* const hw_table
[] = {
33 &ff_hwcontext_type_cuda
,
36 &ff_hwcontext_type_dxva2
,
39 &ff_hwcontext_type_qsv
,
42 &ff_hwcontext_type_vaapi
,
45 &ff_hwcontext_type_vdpau
,
50 const char *hw_type_names
[] = {
51 [AV_HWDEVICE_TYPE_CUDA
] = "cuda",
52 [AV_HWDEVICE_TYPE_DXVA2
] = "dxva2",
53 [AV_HWDEVICE_TYPE_QSV
] = "qsv",
54 [AV_HWDEVICE_TYPE_VAAPI
] = "vaapi",
55 [AV_HWDEVICE_TYPE_VDPAU
] = "vdpau",
58 enum AVHWDeviceType
av_hwdevice_find_type_by_name(const char *name
)
61 for (type
= 0; type
< FF_ARRAY_ELEMS(hw_type_names
); type
++) {
62 if (hw_type_names
[type
] && !strcmp(hw_type_names
[type
], name
))
65 return AV_HWDEVICE_TYPE_NONE
;
68 const char *av_hwdevice_get_type_name(enum AVHWDeviceType type
)
70 if (type
>= 0 && type
< FF_ARRAY_ELEMS(hw_type_names
))
71 return hw_type_names
[type
];
76 enum AVHWDeviceType
av_hwdevice_iterate_types(enum AVHWDeviceType prev
)
78 enum AVHWDeviceType next
;
80 for (i
= 0; hw_table
[i
]; i
++) {
81 if (prev
!= AV_HWDEVICE_TYPE_NONE
&& hw_table
[i
]->type
<= prev
)
83 if (!set
|| hw_table
[i
]->type
< next
) {
84 next
= hw_table
[i
]->type
;
88 return set ? next
: AV_HWDEVICE_TYPE_NONE
;
91 static const AVClass hwdevice_ctx_class
= {
92 .class_name
= "AVHWDeviceContext",
93 .item_name
= av_default_item_name
,
94 .version
= LIBAVUTIL_VERSION_INT
,
97 static void hwdevice_ctx_free(void *opaque
, uint8_t *data
)
99 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)data
;
101 /* uninit might still want access the hw context and the user
102 * free() callback might destroy it, so uninit has to be called first */
103 if (ctx
->internal
->hw_type
->device_uninit
)
104 ctx
->internal
->hw_type
->device_uninit(ctx
);
109 av_buffer_unref(&ctx
->internal
->source_device
);
111 av_freep(&ctx
->hwctx
);
112 av_freep(&ctx
->internal
->priv
);
113 av_freep(&ctx
->internal
);
117 AVBufferRef
*av_hwdevice_ctx_alloc(enum AVHWDeviceType type
)
119 AVHWDeviceContext
*ctx
;
121 const HWContextType
*hw_type
= NULL
;
124 for (i
= 0; hw_table
[i
]; i
++) {
125 if (hw_table
[i
]->type
== type
) {
126 hw_type
= hw_table
[i
];
133 ctx
= av_mallocz(sizeof(*ctx
));
137 ctx
->internal
= av_mallocz(sizeof(*ctx
->internal
));
141 if (hw_type
->device_priv_size
) {
142 ctx
->internal
->priv
= av_mallocz(hw_type
->device_priv_size
);
143 if (!ctx
->internal
->priv
)
147 if (hw_type
->device_hwctx_size
) {
148 ctx
->hwctx
= av_mallocz(hw_type
->device_hwctx_size
);
153 buf
= av_buffer_create((uint8_t*)ctx
, sizeof(*ctx
),
154 hwdevice_ctx_free
, NULL
,
155 AV_BUFFER_FLAG_READONLY
);
160 ctx
->av_class
= &hwdevice_ctx_class
;
162 ctx
->internal
->hw_type
= hw_type
;
168 av_freep(&ctx
->internal
->priv
);
169 av_freep(&ctx
->internal
);
170 av_freep(&ctx
->hwctx
);
175 int av_hwdevice_ctx_init(AVBufferRef
*ref
)
177 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)ref
->data
;
180 if (ctx
->internal
->hw_type
->device_init
) {
181 ret
= ctx
->internal
->hw_type
->device_init(ctx
);
188 if (ctx
->internal
->hw_type
->device_uninit
)
189 ctx
->internal
->hw_type
->device_uninit(ctx
);
193 static const AVClass hwframe_ctx_class
= {
194 .class_name
= "AVHWFramesContext",
195 .item_name
= av_default_item_name
,
196 .version
= LIBAVUTIL_VERSION_INT
,
199 static void hwframe_ctx_free(void *opaque
, uint8_t *data
)
201 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)data
;
203 if (ctx
->internal
->source_frames
) {
204 av_buffer_unref(&ctx
->internal
->source_frames
);
207 if (ctx
->internal
->pool_internal
)
208 av_buffer_pool_uninit(&ctx
->internal
->pool_internal
);
210 if (ctx
->internal
->hw_type
->frames_uninit
)
211 ctx
->internal
->hw_type
->frames_uninit(ctx
);
217 av_buffer_unref(&ctx
->device_ref
);
219 av_freep(&ctx
->hwctx
);
220 av_freep(&ctx
->internal
->priv
);
221 av_freep(&ctx
->internal
);
225 AVBufferRef
*av_hwframe_ctx_alloc(AVBufferRef
*device_ref_in
)
227 AVHWDeviceContext
*device_ctx
= (AVHWDeviceContext
*)device_ref_in
->data
;
228 const HWContextType
*hw_type
= device_ctx
->internal
->hw_type
;
229 AVHWFramesContext
*ctx
;
230 AVBufferRef
*buf
, *device_ref
= NULL
;;
232 ctx
= av_mallocz(sizeof(*ctx
));
236 ctx
->internal
= av_mallocz(sizeof(*ctx
->internal
));
240 if (hw_type
->frames_priv_size
) {
241 ctx
->internal
->priv
= av_mallocz(hw_type
->frames_priv_size
);
242 if (!ctx
->internal
->priv
)
246 if (hw_type
->frames_hwctx_size
) {
247 ctx
->hwctx
= av_mallocz(hw_type
->frames_hwctx_size
);
252 device_ref
= av_buffer_ref(device_ref_in
);
256 buf
= av_buffer_create((uint8_t*)ctx
, sizeof(*ctx
),
257 hwframe_ctx_free
, NULL
,
258 AV_BUFFER_FLAG_READONLY
);
262 ctx
->av_class
= &hwframe_ctx_class
;
263 ctx
->device_ref
= device_ref
;
264 ctx
->device_ctx
= device_ctx
;
265 ctx
->format
= AV_PIX_FMT_NONE
;
266 ctx
->sw_format
= AV_PIX_FMT_NONE
;
268 ctx
->internal
->hw_type
= hw_type
;
274 av_buffer_unref(&device_ref
);
276 av_freep(&ctx
->internal
->priv
);
277 av_freep(&ctx
->internal
);
278 av_freep(&ctx
->hwctx
);
283 static int hwframe_pool_prealloc(AVBufferRef
*ref
)
285 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)ref
->data
;
289 frames
= av_mallocz_array(ctx
->initial_pool_size
, sizeof(*frames
));
291 return AVERROR(ENOMEM
);
293 for (i
= 0; i
< ctx
->initial_pool_size
; i
++) {
294 frames
[i
] = av_frame_alloc();
298 ret
= av_hwframe_get_buffer(ref
, frames
[i
], 0);
304 for (i
= 0; i
< ctx
->initial_pool_size
; i
++)
305 av_frame_free(&frames
[i
]);
311 int av_hwframe_ctx_init(AVBufferRef
*ref
)
313 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)ref
->data
;
314 const enum AVPixelFormat
*pix_fmt
;
317 if (ctx
->internal
->source_frames
) {
318 /* A derived frame context is already initialised. */
322 /* validate the pixel format */
323 for (pix_fmt
= ctx
->internal
->hw_type
->pix_fmts
; *pix_fmt
!= AV_PIX_FMT_NONE
; pix_fmt
++) {
324 if (*pix_fmt
== ctx
->format
)
327 if (*pix_fmt
== AV_PIX_FMT_NONE
) {
328 av_log(ctx
, AV_LOG_ERROR
,
329 "The hardware pixel format '%s' is not supported by the device type '%s'\n",
330 av_get_pix_fmt_name(ctx
->format
), ctx
->internal
->hw_type
->name
);
331 return AVERROR(ENOSYS
);
334 /* validate the dimensions */
335 ret
= av_image_check_size(ctx
->width
, ctx
->height
, 0, ctx
);
339 /* format-specific init */
340 if (ctx
->internal
->hw_type
->frames_init
) {
341 ret
= ctx
->internal
->hw_type
->frames_init(ctx
);
346 if (ctx
->internal
->pool_internal
&& !ctx
->pool
)
347 ctx
->pool
= ctx
->internal
->pool_internal
;
349 /* preallocate the frames in the pool, if requested */
350 if (ctx
->initial_pool_size
> 0) {
351 ret
= hwframe_pool_prealloc(ref
);
358 if (ctx
->internal
->hw_type
->frames_uninit
)
359 ctx
->internal
->hw_type
->frames_uninit(ctx
);
363 int av_hwframe_transfer_get_formats(AVBufferRef
*hwframe_ref
,
364 enum AVHWFrameTransferDirection dir
,
365 enum AVPixelFormat
**formats
, int flags
)
367 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)hwframe_ref
->data
;
369 if (!ctx
->internal
->hw_type
->transfer_get_formats
)
370 return AVERROR(ENOSYS
);
372 return ctx
->internal
->hw_type
->transfer_get_formats(ctx
, dir
, formats
);
375 static int transfer_data_alloc(AVFrame
*dst
, const AVFrame
*src
, int flags
)
377 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
381 frame_tmp
= av_frame_alloc();
383 return AVERROR(ENOMEM
);
385 /* if the format is set, use that
386 * otherwise pick the first supported one */
387 if (dst
->format
>= 0) {
388 frame_tmp
->format
= dst
->format
;
390 enum AVPixelFormat
*formats
;
392 ret
= av_hwframe_transfer_get_formats(src
->hw_frames_ctx
,
393 AV_HWFRAME_TRANSFER_DIRECTION_FROM
,
397 frame_tmp
->format
= formats
[0];
400 frame_tmp
->width
= ctx
->width
;
401 frame_tmp
->height
= ctx
->height
;
403 ret
= av_frame_get_buffer(frame_tmp
, 32);
407 ret
= av_hwframe_transfer_data(frame_tmp
, src
, flags
);
411 frame_tmp
->width
= src
->width
;
412 frame_tmp
->height
= src
->height
;
414 av_frame_move_ref(dst
, frame_tmp
);
417 av_frame_free(&frame_tmp
);
421 int av_hwframe_transfer_data(AVFrame
*dst
, const AVFrame
*src
, int flags
)
423 AVHWFramesContext
*ctx
;
427 return transfer_data_alloc(dst
, src
, flags
);
429 if (src
->hw_frames_ctx
) {
430 ctx
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
432 ret
= ctx
->internal
->hw_type
->transfer_data_from(ctx
, dst
, src
);
435 } else if (dst
->hw_frames_ctx
) {
436 ctx
= (AVHWFramesContext
*)dst
->hw_frames_ctx
->data
;
438 ret
= ctx
->internal
->hw_type
->transfer_data_to(ctx
, dst
, src
);
442 return AVERROR(ENOSYS
);
447 int av_hwframe_get_buffer(AVBufferRef
*hwframe_ref
, AVFrame
*frame
, int flags
)
449 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)hwframe_ref
->data
;
452 if (ctx
->internal
->source_frames
) {
453 // This is a derived frame context, so we allocate in the source
454 // and map the frame immediately.
457 src_frame
= av_frame_alloc();
459 return AVERROR(ENOMEM
);
461 ret
= av_hwframe_get_buffer(ctx
->internal
->source_frames
,
466 ret
= av_hwframe_map(frame
, src_frame
, 0);
468 av_log(ctx
, AV_LOG_ERROR
, "Failed to map frame into derived "
469 "frame context: %d.\n", ret
);
470 av_frame_free(&src_frame
);
474 // Free the source frame immediately - the mapped frame still
475 // contains a reference to it.
476 av_frame_free(&src_frame
);
481 if (!ctx
->internal
->hw_type
->frames_get_buffer
)
482 return AVERROR(ENOSYS
);
485 return AVERROR(EINVAL
);
487 frame
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
488 if (!frame
->hw_frames_ctx
)
489 return AVERROR(ENOMEM
);
491 ret
= ctx
->internal
->hw_type
->frames_get_buffer(ctx
, frame
);
493 av_buffer_unref(&frame
->hw_frames_ctx
);
500 void *av_hwdevice_hwconfig_alloc(AVBufferRef
*ref
)
502 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)ref
->data
;
503 const HWContextType
*hw_type
= ctx
->internal
->hw_type
;
505 if (hw_type
->device_hwconfig_size
== 0)
508 return av_mallocz(hw_type
->device_hwconfig_size
);
511 AVHWFramesConstraints
*av_hwdevice_get_hwframe_constraints(AVBufferRef
*ref
,
512 const void *hwconfig
)
514 AVHWDeviceContext
*ctx
= (AVHWDeviceContext
*)ref
->data
;
515 const HWContextType
*hw_type
= ctx
->internal
->hw_type
;
516 AVHWFramesConstraints
*constraints
;
518 if (!hw_type
->frames_get_constraints
)
521 constraints
= av_mallocz(sizeof(*constraints
));
525 constraints
->min_width
= constraints
->min_height
= 0;
526 constraints
->max_width
= constraints
->max_height
= INT_MAX
;
528 if (hw_type
->frames_get_constraints(ctx
, hwconfig
, constraints
) >= 0) {
531 av_hwframe_constraints_free(&constraints
);
536 void av_hwframe_constraints_free(AVHWFramesConstraints
**constraints
)
539 av_freep(&(*constraints
)->valid_hw_formats
);
540 av_freep(&(*constraints
)->valid_sw_formats
);
542 av_freep(constraints
);
545 int av_hwdevice_ctx_create(AVBufferRef
**pdevice_ref
, enum AVHWDeviceType type
,
546 const char *device
, AVDictionary
*opts
, int flags
)
548 AVBufferRef
*device_ref
= NULL
;
549 AVHWDeviceContext
*device_ctx
;
552 device_ref
= av_hwdevice_ctx_alloc(type
);
554 ret
= AVERROR(ENOMEM
);
557 device_ctx
= (AVHWDeviceContext
*)device_ref
->data
;
559 if (!device_ctx
->internal
->hw_type
->device_create
) {
560 ret
= AVERROR(ENOSYS
);
564 ret
= device_ctx
->internal
->hw_type
->device_create(device_ctx
, device
,
569 ret
= av_hwdevice_ctx_init(device_ref
);
573 *pdevice_ref
= device_ref
;
576 av_buffer_unref(&device_ref
);
581 int av_hwdevice_ctx_create_derived(AVBufferRef
**dst_ref_ptr
,
582 enum AVHWDeviceType type
,
583 AVBufferRef
*src_ref
, int flags
)
585 AVBufferRef
*dst_ref
= NULL
, *tmp_ref
;
586 AVHWDeviceContext
*dst_ctx
, *tmp_ctx
;
591 tmp_ctx
= (AVHWDeviceContext
*)tmp_ref
->data
;
592 if (tmp_ctx
->type
== type
) {
593 dst_ref
= av_buffer_ref(tmp_ref
);
595 ret
= AVERROR(ENOMEM
);
600 tmp_ref
= tmp_ctx
->internal
->source_device
;
603 dst_ref
= av_hwdevice_ctx_alloc(type
);
605 ret
= AVERROR(ENOMEM
);
608 dst_ctx
= (AVHWDeviceContext
*)dst_ref
->data
;
612 tmp_ctx
= (AVHWDeviceContext
*)tmp_ref
->data
;
613 if (dst_ctx
->internal
->hw_type
->device_derive
) {
614 ret
= dst_ctx
->internal
->hw_type
->device_derive(dst_ctx
,
618 dst_ctx
->internal
->source_device
= av_buffer_ref(src_ref
);
619 if (!dst_ctx
->internal
->source_device
) {
620 ret
= AVERROR(ENOMEM
);
625 if (ret
!= AVERROR(ENOSYS
))
628 tmp_ref
= tmp_ctx
->internal
->source_device
;
631 ret
= AVERROR(ENOSYS
);
635 *dst_ref_ptr
= dst_ref
;
639 av_buffer_unref(&dst_ref
);
644 static void ff_hwframe_unmap(void *opaque
, uint8_t *data
)
646 HWMapDescriptor
*hwmap
= (HWMapDescriptor
*)data
;
647 AVHWFramesContext
*ctx
= opaque
;
650 hwmap
->unmap(ctx
, hwmap
);
652 av_frame_free(&hwmap
->source
);
654 av_buffer_unref(&hwmap
->hw_frames_ctx
);
659 int ff_hwframe_map_create(AVBufferRef
*hwframe_ref
,
660 AVFrame
*dst
, const AVFrame
*src
,
661 void (*unmap
)(AVHWFramesContext
*ctx
,
662 HWMapDescriptor
*hwmap
),
665 AVHWFramesContext
*ctx
= (AVHWFramesContext
*)hwframe_ref
->data
;
666 HWMapDescriptor
*hwmap
;
669 hwmap
= av_mallocz(sizeof(*hwmap
));
671 ret
= AVERROR(ENOMEM
);
675 hwmap
->source
= av_frame_alloc();
676 if (!hwmap
->source
) {
677 ret
= AVERROR(ENOMEM
);
680 ret
= av_frame_ref(hwmap
->source
, src
);
684 hwmap
->hw_frames_ctx
= av_buffer_ref(hwframe_ref
);
685 if (!hwmap
->hw_frames_ctx
) {
686 ret
= AVERROR(ENOMEM
);
690 hwmap
->unmap
= unmap
;
693 dst
->buf
[0] = av_buffer_create((uint8_t*)hwmap
, sizeof(*hwmap
),
694 &ff_hwframe_unmap
, ctx
, 0);
696 ret
= AVERROR(ENOMEM
);
704 av_buffer_unref(&hwmap
->hw_frames_ctx
);
705 av_frame_free(&hwmap
->source
);
711 int av_hwframe_map(AVFrame
*dst
, const AVFrame
*src
, int flags
)
713 AVHWFramesContext
*src_frames
, *dst_frames
;
714 HWMapDescriptor
*hwmap
;
717 if (src
->hw_frames_ctx
&& dst
->hw_frames_ctx
) {
718 src_frames
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
719 dst_frames
= (AVHWFramesContext
*)dst
->hw_frames_ctx
->data
;
721 if ((src_frames
== dst_frames
&&
722 src
->format
== dst_frames
->sw_format
&&
723 dst
->format
== dst_frames
->format
) ||
724 (src_frames
->internal
->source_frames
&&
725 src_frames
->internal
->source_frames
->data
==
726 (uint8_t*)dst_frames
)) {
727 // This is an unmap operation. We don't need to directly
728 // do anything here other than fill in the original frame,
729 // because the real unmap will be invoked when the last
730 // reference to the mapped frame disappears.
732 av_log(src_frames
, AV_LOG_ERROR
, "Invalid mapping "
733 "found when attempting unmap.\n");
734 return AVERROR(EINVAL
);
736 hwmap
= (HWMapDescriptor
*)src
->buf
[0]->data
;
738 return av_frame_ref(dst
, hwmap
->source
);
742 if (src
->hw_frames_ctx
) {
743 src_frames
= (AVHWFramesContext
*)src
->hw_frames_ctx
->data
;
745 if (src_frames
->format
== src
->format
&&
746 src_frames
->internal
->hw_type
->map_from
) {
747 ret
= src_frames
->internal
->hw_type
->map_from(src_frames
,
749 if (ret
!= AVERROR(ENOSYS
))
754 if (dst
->hw_frames_ctx
) {
755 dst_frames
= (AVHWFramesContext
*)dst
->hw_frames_ctx
->data
;
757 if (dst_frames
->format
== dst
->format
&&
758 dst_frames
->internal
->hw_type
->map_to
) {
759 ret
= dst_frames
->internal
->hw_type
->map_to(dst_frames
,
761 if (ret
!= AVERROR(ENOSYS
))
766 return AVERROR(ENOSYS
);
769 int av_hwframe_ctx_create_derived(AVBufferRef
**derived_frame_ctx
,
770 enum AVPixelFormat format
,
771 AVBufferRef
*derived_device_ctx
,
772 AVBufferRef
*source_frame_ctx
,
775 AVBufferRef
*dst_ref
= NULL
;
776 AVHWFramesContext
*dst
= NULL
;
777 AVHWFramesContext
*src
= (AVHWFramesContext
*)source_frame_ctx
->data
;
780 if (src
->internal
->source_frames
) {
781 AVHWFramesContext
*src_src
=
782 (AVHWFramesContext
*)src
->internal
->source_frames
->data
;
783 AVHWDeviceContext
*dst_dev
=
784 (AVHWDeviceContext
*)derived_device_ctx
->data
;
786 if (src_src
->device_ctx
== dst_dev
) {
787 // This is actually an unmapping, so we just return a
788 // reference to the source frame context.
790 av_buffer_ref(src
->internal
->source_frames
);
791 if (!*derived_frame_ctx
) {
792 ret
= AVERROR(ENOMEM
);
799 dst_ref
= av_hwframe_ctx_alloc(derived_device_ctx
);
801 ret
= AVERROR(ENOMEM
);
805 dst
= (AVHWFramesContext
*)dst_ref
->data
;
807 dst
->format
= format
;
808 dst
->sw_format
= src
->sw_format
;
809 dst
->width
= src
->width
;
810 dst
->height
= src
->height
;
812 dst
->internal
->source_frames
= av_buffer_ref(source_frame_ctx
);
813 if (!dst
->internal
->source_frames
) {
814 ret
= AVERROR(ENOMEM
);
818 ret
= av_hwframe_ctx_init(dst_ref
);
822 *derived_frame_ctx
= dst_ref
;
827 av_buffer_unref(&dst
->internal
->source_frames
);
828 av_buffer_unref(&dst_ref
);