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
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_d3d11va,
39 &ff_hwcontext_type_drm,
42 &ff_hwcontext_type_dxva2,
45 &ff_hwcontext_type_qsv,
48 &ff_hwcontext_type_vaapi,
51 &ff_hwcontext_type_vdpau,
53 #if CONFIG_VIDEOTOOLBOX
54 &ff_hwcontext_type_videotoolbox,
59 static const char *const hw_type_names[] = {
60 [AV_HWDEVICE_TYPE_CUDA] = "cuda",
61 [AV_HWDEVICE_TYPE_DRM] = "drm",
62 [AV_HWDEVICE_TYPE_DXVA2] = "dxva2",
63 [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va",
64 [AV_HWDEVICE_TYPE_QSV] = "qsv",
65 [AV_HWDEVICE_TYPE_VAAPI] = "vaapi",
66 [AV_HWDEVICE_TYPE_VDPAU] = "vdpau",
67 [AV_HWDEVICE_TYPE_VIDEOTOOLBOX] = "videotoolbox",
70 enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
73 for (type = 0; type < FF_ARRAY_ELEMS(hw_type_names); type++) {
74 if (hw_type_names[type] && !strcmp(hw_type_names[type], name))
77 return AV_HWDEVICE_TYPE_NONE;
80 const char *av_hwdevice_get_type_name(enum AVHWDeviceType type)
82 if (type > AV_HWDEVICE_TYPE_NONE &&
83 type < FF_ARRAY_ELEMS(hw_type_names))
84 return hw_type_names[type];
89 enum AVHWDeviceType av_hwdevice_iterate_types(enum AVHWDeviceType prev)
91 enum AVHWDeviceType next;
93 for (i = 0; hw_table[i]; i++) {
94 if (prev != AV_HWDEVICE_TYPE_NONE && hw_table[i]->type <= prev)
96 if (!set || hw_table[i]->type < next) {
97 next = hw_table[i]->type;
101 return set ? next : AV_HWDEVICE_TYPE_NONE;
104 static const AVClass hwdevice_ctx_class = {
105 .class_name = "AVHWDeviceContext",
106 .item_name = av_default_item_name,
107 .version = LIBAVUTIL_VERSION_INT,
110 static void hwdevice_ctx_free(void *opaque, uint8_t *data)
112 AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
114 /* uninit might still want access the hw context and the user
115 * free() callback might destroy it, so uninit has to be called first */
116 if (ctx->internal->hw_type->device_uninit)
117 ctx->internal->hw_type->device_uninit(ctx);
122 av_buffer_unref(&ctx->internal->source_device);
124 av_freep(&ctx->hwctx);
125 av_freep(&ctx->internal->priv);
126 av_freep(&ctx->internal);
130 AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
132 AVHWDeviceContext *ctx;
134 const HWContextType *hw_type = NULL;
137 for (i = 0; hw_table[i]; i++) {
138 if (hw_table[i]->type == type) {
139 hw_type = hw_table[i];
146 ctx = av_mallocz(sizeof(*ctx));
150 ctx->internal = av_mallocz(sizeof(*ctx->internal));
154 if (hw_type->device_priv_size) {
155 ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
156 if (!ctx->internal->priv)
160 if (hw_type->device_hwctx_size) {
161 ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
166 buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
167 hwdevice_ctx_free, NULL,
168 AV_BUFFER_FLAG_READONLY);
173 ctx->av_class = &hwdevice_ctx_class;
175 ctx->internal->hw_type = hw_type;
181 av_freep(&ctx->internal->priv);
182 av_freep(&ctx->internal);
183 av_freep(&ctx->hwctx);
188 int av_hwdevice_ctx_init(AVBufferRef *ref)
190 AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
193 if (ctx->internal->hw_type->device_init) {
194 ret = ctx->internal->hw_type->device_init(ctx);
201 if (ctx->internal->hw_type->device_uninit)
202 ctx->internal->hw_type->device_uninit(ctx);
206 static const AVClass hwframe_ctx_class = {
207 .class_name = "AVHWFramesContext",
208 .item_name = av_default_item_name,
209 .version = LIBAVUTIL_VERSION_INT,
212 static void hwframe_ctx_free(void *opaque, uint8_t *data)
214 AVHWFramesContext *ctx = (AVHWFramesContext*)data;
216 if (ctx->internal->source_frames) {
217 av_buffer_unref(&ctx->internal->source_frames);
220 if (ctx->internal->pool_internal)
221 av_buffer_pool_uninit(&ctx->internal->pool_internal);
223 if (ctx->internal->hw_type->frames_uninit)
224 ctx->internal->hw_type->frames_uninit(ctx);
230 av_buffer_unref(&ctx->device_ref);
232 av_freep(&ctx->hwctx);
233 av_freep(&ctx->internal->priv);
234 av_freep(&ctx->internal);
238 AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
240 AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
241 const HWContextType *hw_type = device_ctx->internal->hw_type;
242 AVHWFramesContext *ctx;
243 AVBufferRef *buf, *device_ref = NULL;
245 ctx = av_mallocz(sizeof(*ctx));
249 ctx->internal = av_mallocz(sizeof(*ctx->internal));
253 if (hw_type->frames_priv_size) {
254 ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
255 if (!ctx->internal->priv)
259 if (hw_type->frames_hwctx_size) {
260 ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
265 device_ref = av_buffer_ref(device_ref_in);
269 buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
270 hwframe_ctx_free, NULL,
271 AV_BUFFER_FLAG_READONLY);
275 ctx->av_class = &hwframe_ctx_class;
276 ctx->device_ref = device_ref;
277 ctx->device_ctx = device_ctx;
278 ctx->format = AV_PIX_FMT_NONE;
279 ctx->sw_format = AV_PIX_FMT_NONE;
281 ctx->internal->hw_type = hw_type;
287 av_buffer_unref(&device_ref);
289 av_freep(&ctx->internal->priv);
290 av_freep(&ctx->internal);
291 av_freep(&ctx->hwctx);
296 static int hwframe_pool_prealloc(AVBufferRef *ref)
298 AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
302 frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames));
304 return AVERROR(ENOMEM);
306 for (i = 0; i < ctx->initial_pool_size; i++) {
307 frames[i] = av_frame_alloc();
311 ret = av_hwframe_get_buffer(ref, frames[i], 0);
317 for (i = 0; i < ctx->initial_pool_size; i++)
318 av_frame_free(&frames[i]);
324 int av_hwframe_ctx_init(AVBufferRef *ref)
326 AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
327 const enum AVPixelFormat *pix_fmt;
330 if (ctx->internal->source_frames) {
331 /* A derived frame context is already initialised. */
335 /* validate the pixel format */
336 for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
337 if (*pix_fmt == ctx->format)
340 if (*pix_fmt == AV_PIX_FMT_NONE) {
341 av_log(ctx, AV_LOG_ERROR,
342 "The hardware pixel format '%s' is not supported by the device type '%s'\n",
343 av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name);
344 return AVERROR(ENOSYS);
347 /* validate the dimensions */
348 ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
352 /* format-specific init */
353 if (ctx->internal->hw_type->frames_init) {
354 ret = ctx->internal->hw_type->frames_init(ctx);
359 if (ctx->internal->pool_internal && !ctx->pool)
360 ctx->pool = ctx->internal->pool_internal;
362 /* preallocate the frames in the pool, if requested */
363 if (ctx->initial_pool_size > 0) {
364 ret = hwframe_pool_prealloc(ref);
371 if (ctx->internal->hw_type->frames_uninit)
372 ctx->internal->hw_type->frames_uninit(ctx);
376 int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
377 enum AVHWFrameTransferDirection dir,
378 enum AVPixelFormat **formats, int flags)
380 AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
382 if (!ctx->internal->hw_type->transfer_get_formats)
383 return AVERROR(ENOSYS);
385 return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
388 static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
390 AVHWFramesContext *ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
394 frame_tmp = av_frame_alloc();
396 return AVERROR(ENOMEM);
398 /* if the format is set, use that
399 * otherwise pick the first supported one */
400 if (dst->format >= 0) {
401 frame_tmp->format = dst->format;
403 enum AVPixelFormat *formats;
405 ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
406 AV_HWFRAME_TRANSFER_DIRECTION_FROM,
410 frame_tmp->format = formats[0];
413 frame_tmp->width = ctx->width;
414 frame_tmp->height = ctx->height;
416 ret = av_frame_get_buffer(frame_tmp, 32);
420 ret = av_hwframe_transfer_data(frame_tmp, src, flags);
424 frame_tmp->width = src->width;
425 frame_tmp->height = src->height;
427 av_frame_move_ref(dst, frame_tmp);
430 av_frame_free(&frame_tmp);
434 int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
436 AVHWFramesContext *ctx;
440 return transfer_data_alloc(dst, src, flags);
442 if (src->hw_frames_ctx) {
443 ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
445 ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
448 } else if (dst->hw_frames_ctx) {
449 ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
451 ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
455 return AVERROR(ENOSYS);
460 int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
462 AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
465 if (ctx->internal->source_frames) {
466 // This is a derived frame context, so we allocate in the source
467 // and map the frame immediately.
470 frame->format = ctx->format;
471 frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
472 if (!frame->hw_frames_ctx)
473 return AVERROR(ENOMEM);
475 src_frame = av_frame_alloc();
477 return AVERROR(ENOMEM);
479 ret = av_hwframe_get_buffer(ctx->internal->source_frames,
484 ret = av_hwframe_map(frame, src_frame,
485 ctx->internal->source_allocation_map_flags);
487 av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived "
488 "frame context: %d.\n", ret);
489 av_frame_free(&src_frame);
493 // Free the source frame immediately - the mapped frame still
494 // contains a reference to it.
495 av_frame_free(&src_frame);
500 if (!ctx->internal->hw_type->frames_get_buffer)
501 return AVERROR(ENOSYS);
504 return AVERROR(EINVAL);
506 frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
507 if (!frame->hw_frames_ctx)
508 return AVERROR(ENOMEM);
510 ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
512 av_buffer_unref(&frame->hw_frames_ctx);
519 void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
521 AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
522 const HWContextType *hw_type = ctx->internal->hw_type;
524 if (hw_type->device_hwconfig_size == 0)
527 return av_mallocz(hw_type->device_hwconfig_size);
530 AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
531 const void *hwconfig)
533 AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
534 const HWContextType *hw_type = ctx->internal->hw_type;
535 AVHWFramesConstraints *constraints;
537 if (!hw_type->frames_get_constraints)
540 constraints = av_mallocz(sizeof(*constraints));
544 constraints->min_width = constraints->min_height = 0;
545 constraints->max_width = constraints->max_height = INT_MAX;
547 if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) {
550 av_hwframe_constraints_free(&constraints);
555 void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
558 av_freep(&(*constraints)->valid_hw_formats);
559 av_freep(&(*constraints)->valid_sw_formats);
561 av_freep(constraints);
564 int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
565 const char *device, AVDictionary *opts, int flags)
567 AVBufferRef *device_ref = NULL;
568 AVHWDeviceContext *device_ctx;
571 device_ref = av_hwdevice_ctx_alloc(type);
573 ret = AVERROR(ENOMEM);
576 device_ctx = (AVHWDeviceContext*)device_ref->data;
578 if (!device_ctx->internal->hw_type->device_create) {
579 ret = AVERROR(ENOSYS);
583 ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
588 ret = av_hwdevice_ctx_init(device_ref);
592 *pdevice_ref = device_ref;
595 av_buffer_unref(&device_ref);
600 int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr,
601 enum AVHWDeviceType type,
602 AVBufferRef *src_ref, int flags)
604 AVBufferRef *dst_ref = NULL, *tmp_ref;
605 AVHWDeviceContext *dst_ctx, *tmp_ctx;
610 tmp_ctx = (AVHWDeviceContext*)tmp_ref->data;
611 if (tmp_ctx->type == type) {
612 dst_ref = av_buffer_ref(tmp_ref);
614 ret = AVERROR(ENOMEM);
619 tmp_ref = tmp_ctx->internal->source_device;
622 dst_ref = av_hwdevice_ctx_alloc(type);
624 ret = AVERROR(ENOMEM);
627 dst_ctx = (AVHWDeviceContext*)dst_ref->data;
631 tmp_ctx = (AVHWDeviceContext*)tmp_ref->data;
632 if (dst_ctx->internal->hw_type->device_derive) {
633 ret = dst_ctx->internal->hw_type->device_derive(dst_ctx,
637 dst_ctx->internal->source_device = av_buffer_ref(src_ref);
638 if (!dst_ctx->internal->source_device) {
639 ret = AVERROR(ENOMEM);
644 if (ret != AVERROR(ENOSYS))
647 tmp_ref = tmp_ctx->internal->source_device;
650 ret = AVERROR(ENOSYS);
654 ret = av_hwdevice_ctx_init(dst_ref);
658 *dst_ref_ptr = dst_ref;
662 av_buffer_unref(&dst_ref);
667 static void ff_hwframe_unmap(void *opaque, uint8_t *data)
669 HWMapDescriptor *hwmap = (HWMapDescriptor*)data;
670 AVHWFramesContext *ctx = opaque;
673 hwmap->unmap(ctx, hwmap);
675 av_frame_free(&hwmap->source);
677 av_buffer_unref(&hwmap->hw_frames_ctx);
682 int ff_hwframe_map_create(AVBufferRef *hwframe_ref,
683 AVFrame *dst, const AVFrame *src,
684 void (*unmap)(AVHWFramesContext *ctx,
685 HWMapDescriptor *hwmap),
688 AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
689 HWMapDescriptor *hwmap;
692 hwmap = av_mallocz(sizeof(*hwmap));
694 ret = AVERROR(ENOMEM);
698 hwmap->source = av_frame_alloc();
699 if (!hwmap->source) {
700 ret = AVERROR(ENOMEM);
703 ret = av_frame_ref(hwmap->source, src);
707 hwmap->hw_frames_ctx = av_buffer_ref(hwframe_ref);
708 if (!hwmap->hw_frames_ctx) {
709 ret = AVERROR(ENOMEM);
713 hwmap->unmap = unmap;
716 dst->buf[0] = av_buffer_create((uint8_t*)hwmap, sizeof(*hwmap),
717 &ff_hwframe_unmap, ctx, 0);
719 ret = AVERROR(ENOMEM);
727 av_buffer_unref(&hwmap->hw_frames_ctx);
728 av_frame_free(&hwmap->source);
734 int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
736 AVHWFramesContext *src_frames, *dst_frames;
737 HWMapDescriptor *hwmap;
740 if (src->hw_frames_ctx && dst->hw_frames_ctx) {
741 src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data;
742 dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data;
744 if ((src_frames == dst_frames &&
745 src->format == dst_frames->sw_format &&
746 dst->format == dst_frames->format) ||
747 (src_frames->internal->source_frames &&
748 src_frames->internal->source_frames->data ==
749 (uint8_t*)dst_frames)) {
750 // This is an unmap operation. We don't need to directly
751 // do anything here other than fill in the original frame,
752 // because the real unmap will be invoked when the last
753 // reference to the mapped frame disappears.
755 av_log(src_frames, AV_LOG_ERROR, "Invalid mapping "
756 "found when attempting unmap.\n");
757 return AVERROR(EINVAL);
759 hwmap = (HWMapDescriptor*)src->buf[0]->data;
761 return av_frame_ref(dst, hwmap->source);
765 if (src->hw_frames_ctx) {
766 src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data;
768 if (src_frames->format == src->format &&
769 src_frames->internal->hw_type->map_from) {
770 ret = src_frames->internal->hw_type->map_from(src_frames,
772 if (ret != AVERROR(ENOSYS))
777 if (dst->hw_frames_ctx) {
778 dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data;
780 if (dst_frames->format == dst->format &&
781 dst_frames->internal->hw_type->map_to) {
782 ret = dst_frames->internal->hw_type->map_to(dst_frames,
784 if (ret != AVERROR(ENOSYS))
789 return AVERROR(ENOSYS);
792 int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,
793 enum AVPixelFormat format,
794 AVBufferRef *derived_device_ctx,
795 AVBufferRef *source_frame_ctx,
798 AVBufferRef *dst_ref = NULL;
799 AVHWFramesContext *dst = NULL;
800 AVHWFramesContext *src = (AVHWFramesContext*)source_frame_ctx->data;
803 if (src->internal->source_frames) {
804 AVHWFramesContext *src_src =
805 (AVHWFramesContext*)src->internal->source_frames->data;
806 AVHWDeviceContext *dst_dev =
807 (AVHWDeviceContext*)derived_device_ctx->data;
809 if (src_src->device_ctx == dst_dev) {
810 // This is actually an unmapping, so we just return a
811 // reference to the source frame context.
813 av_buffer_ref(src->internal->source_frames);
814 if (!*derived_frame_ctx) {
815 ret = AVERROR(ENOMEM);
822 dst_ref = av_hwframe_ctx_alloc(derived_device_ctx);
824 ret = AVERROR(ENOMEM);
828 dst = (AVHWFramesContext*)dst_ref->data;
830 dst->format = format;
831 dst->sw_format = src->sw_format;
832 dst->width = src->width;
833 dst->height = src->height;
835 dst->internal->source_frames = av_buffer_ref(source_frame_ctx);
836 if (!dst->internal->source_frames) {
837 ret = AVERROR(ENOMEM);
841 dst->internal->source_allocation_map_flags =
842 flags & (AV_HWFRAME_MAP_READ |
843 AV_HWFRAME_MAP_WRITE |
844 AV_HWFRAME_MAP_OVERWRITE |
845 AV_HWFRAME_MAP_DIRECT);
847 ret = AVERROR(ENOSYS);
848 if (src->internal->hw_type->frames_derive_from)
849 ret = src->internal->hw_type->frames_derive_from(dst, src, flags);
850 if (ret == AVERROR(ENOSYS) &&
851 dst->internal->hw_type->frames_derive_to)
852 ret = dst->internal->hw_type->frames_derive_to(dst, src, flags);
853 if (ret == AVERROR(ENOSYS))
858 *derived_frame_ctx = dst_ref;
863 av_buffer_unref(&dst->internal->source_frames);
864 av_buffer_unref(&dst_ref);