]> git.sesse.net Git - ffmpeg/blob - libavutil/hwcontext.c
avcodec: add Gremlin Digital Video decoder
[ffmpeg] / libavutil / hwcontext.c
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 "buffer.h"
22 #include "common.h"
23 #include "hwcontext.h"
24 #include "hwcontext_internal.h"
25 #include "imgutils.h"
26 #include "log.h"
27 #include "mem.h"
28 #include "pixdesc.h"
29 #include "pixfmt.h"
30
31 static const HWContextType *hw_table[] = {
32 #if CONFIG_CUDA
33     &ff_hwcontext_type_cuda,
34 #endif
35 #if CONFIG_DXVA2
36     &ff_hwcontext_type_dxva2,
37 #endif
38 #if CONFIG_QSV
39     &ff_hwcontext_type_qsv,
40 #endif
41 #if CONFIG_VAAPI
42     &ff_hwcontext_type_vaapi,
43 #endif
44 #if CONFIG_VDPAU
45     &ff_hwcontext_type_vdpau,
46 #endif
47 #if CONFIG_VIDEOTOOLBOX
48     &ff_hwcontext_type_videotoolbox,
49 #endif
50     NULL,
51 };
52
53 static const AVClass hwdevice_ctx_class = {
54     .class_name = "AVHWDeviceContext",
55     .item_name  = av_default_item_name,
56     .version    = LIBAVUTIL_VERSION_INT,
57 };
58
59 static void hwdevice_ctx_free(void *opaque, uint8_t *data)
60 {
61     AVHWDeviceContext *ctx = (AVHWDeviceContext*)data;
62
63     /* uninit might still want access the hw context and the user
64      * free() callback might destroy it, so uninit has to be called first */
65     if (ctx->internal->hw_type->device_uninit)
66         ctx->internal->hw_type->device_uninit(ctx);
67
68     if (ctx->free)
69         ctx->free(ctx);
70
71     av_freep(&ctx->hwctx);
72     av_freep(&ctx->internal->priv);
73     av_freep(&ctx->internal);
74     av_freep(&ctx);
75 }
76
77 AVBufferRef *av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
78 {
79     AVHWDeviceContext *ctx;
80     AVBufferRef *buf;
81     const HWContextType *hw_type = NULL;
82     int i;
83
84     for (i = 0; hw_table[i]; i++) {
85         if (hw_table[i]->type == type) {
86             hw_type = hw_table[i];
87             break;
88         }
89     }
90     if (!hw_type)
91         return NULL;
92
93     ctx = av_mallocz(sizeof(*ctx));
94     if (!ctx)
95         return NULL;
96
97     ctx->internal = av_mallocz(sizeof(*ctx->internal));
98     if (!ctx->internal)
99         goto fail;
100
101     if (hw_type->device_priv_size) {
102         ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
103         if (!ctx->internal->priv)
104             goto fail;
105     }
106
107     if (hw_type->device_hwctx_size) {
108         ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
109         if (!ctx->hwctx)
110             goto fail;
111     }
112
113     buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
114                            hwdevice_ctx_free, NULL,
115                            AV_BUFFER_FLAG_READONLY);
116     if (!buf)
117         goto fail;
118
119     ctx->type     = type;
120     ctx->av_class = &hwdevice_ctx_class;
121
122     ctx->internal->hw_type = hw_type;
123
124     return buf;
125
126 fail:
127     if (ctx->internal)
128         av_freep(&ctx->internal->priv);
129     av_freep(&ctx->internal);
130     av_freep(&ctx->hwctx);
131     av_freep(&ctx);
132     return NULL;
133 }
134
135 int av_hwdevice_ctx_init(AVBufferRef *ref)
136 {
137     AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
138     int ret;
139
140     if (ctx->internal->hw_type->device_init) {
141         ret = ctx->internal->hw_type->device_init(ctx);
142         if (ret < 0)
143             goto fail;
144     }
145
146     return 0;
147 fail:
148     if (ctx->internal->hw_type->device_uninit)
149         ctx->internal->hw_type->device_uninit(ctx);
150     return ret;
151 }
152
153 static const AVClass hwframe_ctx_class = {
154     .class_name = "AVHWFramesContext",
155     .item_name  = av_default_item_name,
156     .version    = LIBAVUTIL_VERSION_INT,
157 };
158
159 static void hwframe_ctx_free(void *opaque, uint8_t *data)
160 {
161     AVHWFramesContext *ctx = (AVHWFramesContext*)data;
162
163     if (ctx->internal->source_frames) {
164         av_buffer_unref(&ctx->internal->source_frames);
165
166     } else {
167         if (ctx->internal->pool_internal)
168             av_buffer_pool_uninit(&ctx->internal->pool_internal);
169
170         if (ctx->internal->hw_type->frames_uninit)
171             ctx->internal->hw_type->frames_uninit(ctx);
172
173         if (ctx->free)
174             ctx->free(ctx);
175     }
176
177     av_buffer_unref(&ctx->device_ref);
178
179     av_freep(&ctx->hwctx);
180     av_freep(&ctx->internal->priv);
181     av_freep(&ctx->internal);
182     av_freep(&ctx);
183 }
184
185 AVBufferRef *av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
186 {
187     AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
188     const HWContextType  *hw_type = device_ctx->internal->hw_type;
189     AVHWFramesContext *ctx;
190     AVBufferRef *buf, *device_ref = NULL;
191
192     ctx = av_mallocz(sizeof(*ctx));
193     if (!ctx)
194         return NULL;
195
196     ctx->internal = av_mallocz(sizeof(*ctx->internal));
197     if (!ctx->internal)
198         goto fail;
199
200     if (hw_type->frames_priv_size) {
201         ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
202         if (!ctx->internal->priv)
203             goto fail;
204     }
205
206     if (hw_type->frames_hwctx_size) {
207         ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
208         if (!ctx->hwctx)
209             goto fail;
210     }
211
212     device_ref = av_buffer_ref(device_ref_in);
213     if (!device_ref)
214         goto fail;
215
216     buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
217                            hwframe_ctx_free, NULL,
218                            AV_BUFFER_FLAG_READONLY);
219     if (!buf)
220         goto fail;
221
222     ctx->av_class   = &hwframe_ctx_class;
223     ctx->device_ref = device_ref;
224     ctx->device_ctx = device_ctx;
225     ctx->format     = AV_PIX_FMT_NONE;
226     ctx->sw_format  = AV_PIX_FMT_NONE;
227
228     ctx->internal->hw_type = hw_type;
229
230     return buf;
231
232 fail:
233     if (device_ref)
234         av_buffer_unref(&device_ref);
235     if (ctx->internal)
236         av_freep(&ctx->internal->priv);
237     av_freep(&ctx->internal);
238     av_freep(&ctx->hwctx);
239     av_freep(&ctx);
240     return NULL;
241 }
242
243 static int hwframe_pool_prealloc(AVBufferRef *ref)
244 {
245     AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
246     AVFrame **frames;
247     int i, ret = 0;
248
249     frames = av_mallocz_array(ctx->initial_pool_size, sizeof(*frames));
250     if (!frames)
251         return AVERROR(ENOMEM);
252
253     for (i = 0; i < ctx->initial_pool_size; i++) {
254         frames[i] = av_frame_alloc();
255         if (!frames[i])
256             goto fail;
257
258         ret = av_hwframe_get_buffer(ref, frames[i], 0);
259         if (ret < 0)
260             goto fail;
261     }
262
263 fail:
264     for (i = 0; i < ctx->initial_pool_size; i++)
265         av_frame_free(&frames[i]);
266     av_freep(&frames);
267
268     return ret;
269 }
270
271 int av_hwframe_ctx_init(AVBufferRef *ref)
272 {
273     AVHWFramesContext *ctx = (AVHWFramesContext*)ref->data;
274     const enum AVPixelFormat *pix_fmt;
275     int ret;
276
277     if (ctx->internal->source_frames) {
278         /* A derived frame context is already initialised. */
279         return 0;
280     }
281
282     /* validate the pixel format */
283     for (pix_fmt = ctx->internal->hw_type->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++) {
284         if (*pix_fmt == ctx->format)
285             break;
286     }
287     if (*pix_fmt == AV_PIX_FMT_NONE) {
288         av_log(ctx, AV_LOG_ERROR,
289                "The hardware pixel format '%s' is not supported by the device type '%s'\n",
290                av_get_pix_fmt_name(ctx->format), ctx->internal->hw_type->name);
291         return AVERROR(ENOSYS);
292     }
293
294     /* validate the dimensions */
295     ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
296     if (ret < 0)
297         return ret;
298
299     /* format-specific init */
300     if (ctx->internal->hw_type->frames_init) {
301         ret = ctx->internal->hw_type->frames_init(ctx);
302         if (ret < 0)
303             goto fail;
304     }
305
306     if (ctx->internal->pool_internal && !ctx->pool)
307         ctx->pool = ctx->internal->pool_internal;
308
309     /* preallocate the frames in the pool, if requested */
310     if (ctx->initial_pool_size > 0) {
311         ret = hwframe_pool_prealloc(ref);
312         if (ret < 0)
313             goto fail;
314     }
315
316     return 0;
317 fail:
318     if (ctx->internal->hw_type->frames_uninit)
319         ctx->internal->hw_type->frames_uninit(ctx);
320     return ret;
321 }
322
323 int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref,
324                                     enum AVHWFrameTransferDirection dir,
325                                     enum AVPixelFormat **formats, int flags)
326 {
327     AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
328
329     if (!ctx->internal->hw_type->transfer_get_formats)
330         return AVERROR(ENOSYS);
331
332     return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
333 }
334
335 static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
336 {
337     AVHWFramesContext *ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
338     AVFrame *frame_tmp;
339     int ret = 0;
340
341     frame_tmp = av_frame_alloc();
342     if (!frame_tmp)
343         return AVERROR(ENOMEM);
344
345     /* if the format is set, use that
346      * otherwise pick the first supported one */
347     if (dst->format >= 0) {
348         frame_tmp->format = dst->format;
349     } else {
350         enum AVPixelFormat *formats;
351
352         ret = av_hwframe_transfer_get_formats(src->hw_frames_ctx,
353                                               AV_HWFRAME_TRANSFER_DIRECTION_FROM,
354                                               &formats, 0);
355         if (ret < 0)
356             goto fail;
357         frame_tmp->format = formats[0];
358         av_freep(&formats);
359     }
360     frame_tmp->width  = ctx->width;
361     frame_tmp->height = ctx->height;
362
363     ret = av_frame_get_buffer(frame_tmp, 32);
364     if (ret < 0)
365         goto fail;
366
367     ret = av_hwframe_transfer_data(frame_tmp, src, flags);
368     if (ret < 0)
369         goto fail;
370
371     frame_tmp->width  = src->width;
372     frame_tmp->height = src->height;
373
374     av_frame_move_ref(dst, frame_tmp);
375
376 fail:
377     av_frame_free(&frame_tmp);
378     return ret;
379 }
380
381 int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
382 {
383     AVHWFramesContext *ctx;
384     int ret;
385
386     if (!dst->buf[0])
387         return transfer_data_alloc(dst, src, flags);
388
389     if (src->hw_frames_ctx) {
390         ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
391
392         ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
393         if (ret < 0)
394             return ret;
395     } else if (dst->hw_frames_ctx) {
396         ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
397
398         ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
399         if (ret < 0)
400             return ret;
401     } else
402         return AVERROR(ENOSYS);
403
404     return 0;
405 }
406
407 int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
408 {
409     AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
410     int ret;
411
412     if (ctx->internal->source_frames) {
413         // This is a derived frame context, so we allocate in the source
414         // and map the frame immediately.
415         AVFrame *src_frame;
416
417         src_frame = av_frame_alloc();
418         if (!src_frame)
419             return AVERROR(ENOMEM);
420
421         ret = av_hwframe_get_buffer(ctx->internal->source_frames,
422                                     src_frame, 0);
423         if (ret < 0)
424             return ret;
425
426         ret = av_hwframe_map(frame, src_frame, 0);
427         if (ret) {
428             av_log(ctx, AV_LOG_ERROR, "Failed to map frame into derived "
429                    "frame context: %d.\n", ret);
430             av_frame_free(&src_frame);
431             return ret;
432         }
433
434         // Free the source frame immediately - the mapped frame still
435         // contains a reference to it.
436         av_frame_free(&src_frame);
437
438         return 0;
439     }
440
441     if (!ctx->internal->hw_type->frames_get_buffer)
442         return AVERROR(ENOSYS);
443
444     if (!ctx->pool)
445         return AVERROR(EINVAL);
446
447     frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
448     if (!frame->hw_frames_ctx)
449         return AVERROR(ENOMEM);
450
451     ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
452     if (ret < 0) {
453         av_buffer_unref(&frame->hw_frames_ctx);
454         return ret;
455     }
456
457     return 0;
458 }
459
460 void *av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
461 {
462     AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
463     const HWContextType  *hw_type = ctx->internal->hw_type;
464
465     if (hw_type->device_hwconfig_size == 0)
466         return NULL;
467
468     return av_mallocz(hw_type->device_hwconfig_size);
469 }
470
471 AVHWFramesConstraints *av_hwdevice_get_hwframe_constraints(AVBufferRef *ref,
472                                                            const void *hwconfig)
473 {
474     AVHWDeviceContext *ctx = (AVHWDeviceContext*)ref->data;
475     const HWContextType  *hw_type = ctx->internal->hw_type;
476     AVHWFramesConstraints *constraints;
477
478     if (!hw_type->frames_get_constraints)
479         return NULL;
480
481     constraints = av_mallocz(sizeof(*constraints));
482     if (!constraints)
483         return NULL;
484
485     constraints->min_width = constraints->min_height = 0;
486     constraints->max_width = constraints->max_height = INT_MAX;
487
488     if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) {
489         return constraints;
490     } else {
491         av_hwframe_constraints_free(&constraints);
492         return NULL;
493     }
494 }
495
496 void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
497 {
498     if (*constraints) {
499         av_freep(&(*constraints)->valid_hw_formats);
500         av_freep(&(*constraints)->valid_sw_formats);
501     }
502     av_freep(constraints);
503 }
504
505 int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
506                            const char *device, AVDictionary *opts, int flags)
507 {
508     AVBufferRef *device_ref = NULL;
509     AVHWDeviceContext *device_ctx;
510     int ret = 0;
511
512     device_ref = av_hwdevice_ctx_alloc(type);
513     if (!device_ref) {
514         ret = AVERROR(ENOMEM);
515         goto fail;
516     }
517     device_ctx = (AVHWDeviceContext*)device_ref->data;
518
519     if (!device_ctx->internal->hw_type->device_create) {
520         ret = AVERROR(ENOSYS);
521         goto fail;
522     }
523
524     ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
525                                                        opts, flags);
526     if (ret < 0)
527         goto fail;
528
529     ret = av_hwdevice_ctx_init(device_ref);
530     if (ret < 0)
531         goto fail;
532
533     *pdevice_ref = device_ref;
534     return 0;
535 fail:
536     av_buffer_unref(&device_ref);
537     *pdevice_ref = NULL;
538     return ret;
539 }
540
541 static void ff_hwframe_unmap(void *opaque, uint8_t *data)
542 {
543     HWMapDescriptor *hwmap = (HWMapDescriptor*)data;
544     AVHWFramesContext *ctx = opaque;
545
546     if (hwmap->unmap)
547         hwmap->unmap(ctx, hwmap);
548
549     av_frame_free(&hwmap->source);
550
551     av_buffer_unref(&hwmap->hw_frames_ctx);
552
553     av_free(hwmap);
554 }
555
556 int ff_hwframe_map_create(AVBufferRef *hwframe_ref,
557                           AVFrame *dst, const AVFrame *src,
558                           void (*unmap)(AVHWFramesContext *ctx,
559                                         HWMapDescriptor *hwmap),
560                           void *priv)
561 {
562     AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
563     HWMapDescriptor *hwmap;
564     int ret;
565
566     hwmap = av_mallocz(sizeof(*hwmap));
567     if (!hwmap) {
568         ret = AVERROR(ENOMEM);
569         goto fail;
570     }
571
572     hwmap->source = av_frame_alloc();
573     if (!hwmap->source) {
574         ret = AVERROR(ENOMEM);
575         goto fail;
576     }
577     ret = av_frame_ref(hwmap->source, src);
578     if (ret < 0)
579         goto fail;
580
581     hwmap->hw_frames_ctx = av_buffer_ref(hwframe_ref);
582     if (!hwmap->hw_frames_ctx) {
583         ret = AVERROR(ENOMEM);
584         goto fail;
585     }
586
587     hwmap->unmap = unmap;
588     hwmap->priv  = priv;
589
590     dst->buf[0] = av_buffer_create((uint8_t*)hwmap, sizeof(*hwmap),
591                                    &ff_hwframe_unmap, ctx, 0);
592     if (!dst->buf[0]) {
593         ret = AVERROR(ENOMEM);
594         goto fail;
595     }
596
597     return 0;
598
599 fail:
600     if (hwmap) {
601         av_buffer_unref(&hwmap->hw_frames_ctx);
602         av_frame_free(&hwmap->source);
603     }
604     av_free(hwmap);
605     return ret;
606 }
607
608 int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
609 {
610     AVHWFramesContext *src_frames, *dst_frames;
611     HWMapDescriptor *hwmap;
612     int ret;
613
614     if (src->hw_frames_ctx && dst->hw_frames_ctx) {
615         src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data;
616         dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data;
617
618         if ((src_frames == dst_frames &&
619              src->format == dst_frames->sw_format &&
620              dst->format == dst_frames->format) ||
621             (src_frames->internal->source_frames &&
622              src_frames->internal->source_frames->data ==
623              (uint8_t*)dst_frames)) {
624             // This is an unmap operation.  We don't need to directly
625             // do anything here other than fill in the original frame,
626             // because the real unmap will be invoked when the last
627             // reference to the mapped frame disappears.
628             if (!src->buf[0]) {
629                 av_log(src_frames, AV_LOG_ERROR, "Invalid mapping "
630                        "found when attempting unmap.\n");
631                 return AVERROR(EINVAL);
632             }
633             hwmap = (HWMapDescriptor*)src->buf[0]->data;
634             av_frame_unref(dst);
635             return av_frame_ref(dst, hwmap->source);
636         }
637     }
638
639     if (src->hw_frames_ctx) {
640         src_frames = (AVHWFramesContext*)src->hw_frames_ctx->data;
641
642         if (src_frames->format == src->format &&
643             src_frames->internal->hw_type->map_from) {
644             ret = src_frames->internal->hw_type->map_from(src_frames,
645                                                           dst, src, flags);
646             if (ret != AVERROR(ENOSYS))
647                 return ret;
648         }
649     }
650
651     if (dst->hw_frames_ctx) {
652         dst_frames = (AVHWFramesContext*)dst->hw_frames_ctx->data;
653
654         if (dst_frames->format == dst->format &&
655             dst_frames->internal->hw_type->map_to) {
656             ret = dst_frames->internal->hw_type->map_to(dst_frames,
657                                                         dst, src, flags);
658             if (ret != AVERROR(ENOSYS))
659                 return ret;
660         }
661     }
662
663     return AVERROR(ENOSYS);
664 }
665
666 int av_hwframe_ctx_create_derived(AVBufferRef **derived_frame_ctx,
667                                   enum AVPixelFormat format,
668                                   AVBufferRef *derived_device_ctx,
669                                   AVBufferRef *source_frame_ctx,
670                                   int flags)
671 {
672     AVBufferRef   *dst_ref = NULL;
673     AVHWFramesContext *dst = NULL;
674     AVHWFramesContext *src = (AVHWFramesContext*)source_frame_ctx->data;
675     int ret;
676
677     if (src->internal->source_frames) {
678         AVHWFramesContext *src_src =
679             (AVHWFramesContext*)src->internal->source_frames->data;
680         AVHWDeviceContext *dst_dev =
681             (AVHWDeviceContext*)derived_device_ctx->data;
682
683         if (src_src->device_ctx == dst_dev) {
684             // This is actually an unmapping, so we just return a
685             // reference to the source frame context.
686             *derived_frame_ctx =
687                 av_buffer_ref(src->internal->source_frames);
688             if (!*derived_frame_ctx) {
689                 ret = AVERROR(ENOMEM);
690                 goto fail;
691             }
692             return 0;
693         }
694     }
695
696     dst_ref = av_hwframe_ctx_alloc(derived_device_ctx);
697     if (!dst_ref) {
698         ret = AVERROR(ENOMEM);
699         goto fail;
700     }
701
702     dst = (AVHWFramesContext*)dst_ref->data;
703
704     dst->format    = format;
705     dst->sw_format = src->sw_format;
706     dst->width     = src->width;
707     dst->height    = src->height;
708
709     dst->internal->source_frames = av_buffer_ref(source_frame_ctx);
710     if (!dst->internal->source_frames) {
711         ret = AVERROR(ENOMEM);
712         goto fail;
713     }
714
715     ret = av_hwframe_ctx_init(dst_ref);
716     if (ret)
717         goto fail;
718
719     *derived_frame_ctx = dst_ref;
720     return 0;
721
722 fail:
723     if (dst)
724         av_buffer_unref(&dst->internal->source_frames);
725     av_buffer_unref(&dst_ref);
726     return ret;
727 }