Browse code

avcodec: add new Videotoolbox hwaccel.

Sebastien Zwickert authored on 2015/07/11 20:23:21
Showing 22 changed files
... ...
@@ -29,6 +29,7 @@ version <next>:
29 29
 - acrossfade audio filter
30 30
 - allyuv video source
31 31
 - atadenoise video filter
32
+- OS X VideoToolbox support
32 33
 
33 34
 
34 35
 version 2.7:
... ...
@@ -305,6 +305,7 @@ Hardware acceleration:
305 305
   vaapi*                                Gwenole Beauchesne
306 306
   vda*                                  Sebastien Zwickert
307 307
   vdpau*                                Carl Eugen Hoyos
308
+  videotoolbox*                         Sebastien Zwickert
308 309
 
309 310
 
310 311
 libavdevice
... ...
@@ -31,7 +31,10 @@ $(foreach prog,$(AVBASENAMES),$(eval OBJS-$(prog)-$(CONFIG_OPENCL) += cmdutils_o
31 31
 OBJS-ffmpeg                   += ffmpeg_opt.o ffmpeg_filter.o
32 32
 OBJS-ffmpeg-$(HAVE_VDPAU_X11) += ffmpeg_vdpau.o
33 33
 OBJS-ffmpeg-$(HAVE_DXVA2_LIB) += ffmpeg_dxva2.o
34
-OBJS-ffmpeg-$(CONFIG_VDA)     += ffmpeg_vda.o
34
+ifndef CONFIG_VIDEOTOOLBOX
35
+OBJS-ffmpeg-$(CONFIG_VDA)     += ffmpeg_videotoolbox.o
36
+endif
37
+OBJS-ffmpeg-$(CONFIG_VIDEOTOOLBOX) += ffmpeg_videotoolbox.o
35 38
 OBJS-ffserver                 += ffserver_config.o
36 39
 
37 40
 TESTTOOLS   = audiogen videogen rotozoom tiny_psnr tiny_ssim base64
... ...
@@ -155,6 +155,7 @@ Hardware accelerators:
155 155
   --disable-vaapi          disable VAAPI code [autodetect]
156 156
   --disable-vda            disable VDA code [autodetect]
157 157
   --disable-vdpau          disable VDPAU code [autodetect]
158
+  --enable-videotoolbox    enable VideoToolbox code [autodetect]
158 159
 
159 160
 Individual component options:
160 161
   --disable-everything     disable all components listed below
... ...
@@ -1470,6 +1471,7 @@ HWACCEL_LIST="
1470 1470
     vaapi
1471 1471
     vda
1472 1472
     vdpau
1473
+    videotoolbox
1473 1474
     xvmc
1474 1475
 "
1475 1476
 
... ...
@@ -2380,14 +2382,18 @@ d3d11va_deps="d3d11_h dxva_h ID3D11VideoDecoder"
2380 2380
 dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode"
2381 2381
 vaapi_deps="va_va_h"
2382 2382
 vda_deps="VideoDecodeAcceleration_VDADecoder_h pthreads"
2383
-vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore"
2383
+vda_extralibs="-framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore -framework CoreServices"
2384 2384
 vdpau_deps="vdpau_vdpau_h vdpau_vdpau_x11_h"
2385
+videotoolbox_deps="VideoToolbox_VideoToolbox_h pthreads"
2386
+videotoolbox_extralibs="-framework CoreFoundation -framework VideoToolbox -framework CoreMedia -framework QuartzCore -framework CoreServices"
2385 2387
 xvmc_deps="X11_extensions_XvMClib_h"
2386 2388
 
2387 2389
 h263_vaapi_hwaccel_deps="vaapi"
2388 2390
 h263_vaapi_hwaccel_select="h263_decoder"
2389 2391
 h263_vdpau_hwaccel_deps="vdpau"
2390 2392
 h263_vdpau_hwaccel_select="h263_decoder"
2393
+h263_videotoolbox_hwaccel_deps="videotoolbox"
2394
+h263_videotoolbox_hwaccel_select="h263_decoder"
2391 2395
 h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
2392 2396
 h264_d3d11va_hwaccel_deps="d3d11va"
2393 2397
 h264_d3d11va_hwaccel_select="h264_decoder"
... ...
@@ -2410,6 +2416,8 @@ h264_vdpau_decoder_deps="vdpau"
2410 2410
 h264_vdpau_decoder_select="h264_decoder"
2411 2411
 h264_vdpau_hwaccel_deps="vdpau"
2412 2412
 h264_vdpau_hwaccel_select="h264_decoder"
2413
+h264_videotoolbox_hwaccel_deps="videotoolbox"
2414
+h264_videotoolbox_hwaccel_select="h264_decoder"
2413 2415
 hevc_d3d11va_hwaccel_deps="d3d11va DXVA_PicParams_HEVC"
2414 2416
 hevc_d3d11va_hwaccel_select="hevc_decoder"
2415 2417
 hevc_dxva2_hwaccel_deps="dxva2 DXVA_PicParams_HEVC"
... ...
@@ -2425,6 +2433,8 @@ mpeg1_vdpau_decoder_deps="vdpau"
2425 2425
 mpeg1_vdpau_decoder_select="mpeg1video_decoder"
2426 2426
 mpeg1_vdpau_hwaccel_deps="vdpau"
2427 2427
 mpeg1_vdpau_hwaccel_select="mpeg1video_decoder"
2428
+mpeg1_videotoolbox_hwaccel_deps="videotoolbox"
2429
+mpeg1_videotoolbox_hwaccel_select="mpeg1video_decoder"
2428 2430
 mpeg1_xvmc_hwaccel_deps="xvmc"
2429 2431
 mpeg1_xvmc_hwaccel_select="mpeg1video_decoder"
2430 2432
 mpeg2_crystalhd_decoder_select="crystalhd"
... ...
@@ -2438,6 +2448,8 @@ mpeg2_vaapi_hwaccel_deps="vaapi"
2438 2438
 mpeg2_vaapi_hwaccel_select="mpeg2video_decoder"
2439 2439
 mpeg2_vdpau_hwaccel_deps="vdpau"
2440 2440
 mpeg2_vdpau_hwaccel_select="mpeg2video_decoder"
2441
+mpeg2_videotoolbox_hwaccel_deps="videotoolbox"
2442
+mpeg2_videotoolbox_hwaccel_select="mpeg2video_decoder"
2441 2443
 mpeg2_xvmc_hwaccel_deps="xvmc"
2442 2444
 mpeg2_xvmc_hwaccel_select="mpeg2video_decoder"
2443 2445
 mpeg4_crystalhd_decoder_select="crystalhd"
... ...
@@ -2447,6 +2459,8 @@ mpeg4_vdpau_decoder_deps="vdpau"
2447 2447
 mpeg4_vdpau_decoder_select="mpeg4_decoder"
2448 2448
 mpeg4_vdpau_hwaccel_deps="vdpau"
2449 2449
 mpeg4_vdpau_hwaccel_select="mpeg4_decoder"
2450
+mpeg4_videotoolbox_hwaccel_deps="videotoolbox"
2451
+mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder"
2450 2452
 msmpeg4_crystalhd_decoder_select="crystalhd"
2451 2453
 vc1_crystalhd_decoder_select="crystalhd"
2452 2454
 vc1_d3d11va_hwaccel_deps="d3d11va"
... ...
@@ -2902,7 +2916,7 @@ sws_max_filter_size_default=256
2902 2902
 set_default sws_max_filter_size
2903 2903
 
2904 2904
 # Enable hwaccels by default.
2905
-enable d3d11va dxva2 vaapi vda vdpau xvmc
2905
+enable d3d11va dxva2 vaapi vda vdpau videotoolbox xvmc
2906 2906
 enable xlib
2907 2907
 
2908 2908
 # build settings
... ...
@@ -5108,6 +5122,7 @@ check_header valgrind/valgrind.h
5108 5108
 check_header vdpau/vdpau.h
5109 5109
 check_header vdpau/vdpau_x11.h
5110 5110
 check_header VideoDecodeAcceleration/VDADecoder.h
5111
+check_header VideoToolbox/VideoToolbox.h
5111 5112
 check_header windows.h
5112 5113
 check_header X11/extensions/XvMClib.h
5113 5114
 check_header asm/types.h
... ...
@@ -63,6 +63,7 @@ enum HWAccelID {
63 63
     HWACCEL_VDPAU,
64 64
     HWACCEL_DXVA2,
65 65
     HWACCEL_VDA,
66
+    HWACCEL_VIDEOTOOLBOX,
66 67
 };
67 68
 
68 69
 typedef struct HWAccel {
... ...
@@ -520,6 +521,7 @@ extern int frame_bits_per_raw_sample;
520 520
 extern AVIOContext *progress_avio;
521 521
 extern float max_error_rate;
522 522
 extern int vdpau_api_ver;
523
+extern char *videotoolbox_pixfmt;
523 524
 
524 525
 extern const AVIOInterruptCB int_cb;
525 526
 
... ...
@@ -554,5 +556,6 @@ int ffmpeg_parse_options(int argc, char **argv);
554 554
 int vdpau_init(AVCodecContext *s);
555 555
 int dxva2_init(AVCodecContext *s);
556 556
 int vda_init(AVCodecContext *s);
557
+int videotoolbox_init(AVCodecContext *s);
557 558
 
558 559
 #endif /* FFMPEG_H */
... ...
@@ -74,7 +74,10 @@ const HWAccel hwaccels[] = {
74 74
     { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD },
75 75
 #endif
76 76
 #if CONFIG_VDA
77
-    { "vda",   vda_init,   HWACCEL_VDA,   AV_PIX_FMT_VDA },
77
+    { "vda",   videotoolbox_init,   HWACCEL_VDA,   AV_PIX_FMT_VDA },
78
+#endif
79
+#if CONFIG_VIDEOTOOLBOX
80
+    { "videotoolbox",   videotoolbox_init,   HWACCEL_VIDEOTOOLBOX,   AV_PIX_FMT_VIDEOTOOLBOX },
78 81
 #endif
79 82
     { 0 },
80 83
 };
... ...
@@ -3233,6 +3236,9 @@ const OptionDef options[] = {
3233 3233
 #if HAVE_VDPAU_X11
3234 3234
     { "vdpau_api_ver", HAS_ARG | OPT_INT | OPT_EXPERT, { &vdpau_api_ver }, "" },
3235 3235
 #endif
3236
+#if CONFIG_VDA || CONFIG_VIDEOTOOLBOX
3237
+    { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" },
3238
+#endif
3236 3239
     { "autorotate",       HAS_ARG | OPT_BOOL | OPT_SPEC |
3237 3240
                           OPT_EXPERT | OPT_INPUT,                                { .off = OFFSET(autorotate) },
3238 3241
         "automatically insert correct rotate filters" },
3239 3242
deleted file mode 100644
... ...
@@ -1,137 +0,0 @@
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 "libavcodec/avcodec.h"
20
-#include "libavcodec/vda.h"
21
-#include "libavutil/imgutils.h"
22
-
23
-#include "ffmpeg.h"
24
-
25
-typedef struct VDAContext {
26
-    AVFrame *tmp_frame;
27
-} VDAContext;
28
-
29
-static int vda_retrieve_data(AVCodecContext *s, AVFrame *frame)
30
-{
31
-    InputStream *ist = s->opaque;
32
-    VDAContext  *vda = ist->hwaccel_ctx;
33
-    CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3];
34
-    OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
35
-    CVReturn err;
36
-    uint8_t *data[4] = { 0 };
37
-    int linesize[4] = { 0 };
38
-    int planes, ret, i;
39
-
40
-    av_frame_unref(vda->tmp_frame);
41
-
42
-    switch (pixel_format) {
43
-    case kCVPixelFormatType_420YpCbCr8Planar: vda->tmp_frame->format = AV_PIX_FMT_YUV420P; break;
44
-    case kCVPixelFormatType_422YpCbCr8:       vda->tmp_frame->format = AV_PIX_FMT_UYVY422; break;
45
-    default:
46
-        av_log(NULL, AV_LOG_ERROR,
47
-               "Unsupported pixel format: %u\n", pixel_format);
48
-        return AVERROR(ENOSYS);
49
-    }
50
-
51
-    vda->tmp_frame->width  = frame->width;
52
-    vda->tmp_frame->height = frame->height;
53
-    ret = av_frame_get_buffer(vda->tmp_frame, 32);
54
-    if (ret < 0)
55
-        return ret;
56
-
57
-    err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
58
-    if (err != kCVReturnSuccess) {
59
-        av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
60
-        return AVERROR_UNKNOWN;
61
-    }
62
-
63
-    if (CVPixelBufferIsPlanar(pixbuf)) {
64
-
65
-        planes = CVPixelBufferGetPlaneCount(pixbuf);
66
-        for (i = 0; i < planes; i++) {
67
-            data[i]     = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
68
-            linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
69
-        }
70
-    } else {
71
-        data[0] = CVPixelBufferGetBaseAddress(pixbuf);
72
-        linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
73
-    }
74
-
75
-    av_image_copy(vda->tmp_frame->data, vda->tmp_frame->linesize,
76
-                  (const uint8_t **)data, linesize, vda->tmp_frame->format,
77
-                  frame->width, frame->height);
78
-
79
-    CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
80
-
81
-    ret = av_frame_copy_props(vda->tmp_frame, frame);
82
-
83
-    if (ret < 0)
84
-        return ret;
85
-
86
-    av_frame_unref(frame);
87
-    av_frame_move_ref(frame, vda->tmp_frame);
88
-
89
-    return 0;
90
-}
91
-
92
-static void vda_uninit(AVCodecContext *s)
93
-{
94
-    InputStream *ist = s->opaque;
95
-    VDAContext  *vda = ist->hwaccel_ctx;
96
-
97
-    ist->hwaccel_uninit        = NULL;
98
-    ist->hwaccel_retrieve_data = NULL;
99
-
100
-    av_frame_free(&vda->tmp_frame);
101
-
102
-    av_vda_default_free(s);
103
-    av_freep(&ist->hwaccel_ctx);
104
-}
105
-
106
-int vda_init(AVCodecContext *s)
107
-{
108
-    InputStream *ist = s->opaque;
109
-    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
110
-    VDAContext *vda;
111
-    int ret;
112
-
113
-    vda = av_mallocz(sizeof(*vda));
114
-    if (!vda)
115
-        return AVERROR(ENOMEM);
116
-
117
-    ist->hwaccel_ctx           = vda;
118
-    ist->hwaccel_uninit        = vda_uninit;
119
-    ist->hwaccel_retrieve_data = vda_retrieve_data;
120
-
121
-    vda->tmp_frame = av_frame_alloc();
122
-    if (!vda->tmp_frame) {
123
-        ret = AVERROR(ENOMEM);
124
-        goto fail;
125
-    }
126
-
127
-    ret = av_vda_default_init(s);
128
-    if (ret < 0) {
129
-        av_log(NULL, loglevel, "Error creating VDA decoder.\n");
130
-        goto fail;
131
-    }
132
-
133
-    return 0;
134
-fail:
135
-    vda_uninit(s);
136
-    return ret;
137
-}
138 1
new file mode 100644
... ...
@@ -0,0 +1,187 @@
0
+/*
1
+ * This file is part of FFmpeg.
2
+ *
3
+ * FFmpeg is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * FFmpeg is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with FFmpeg; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#include <CoreServices/CoreServices.h>
19
+
20
+#include "config.h"
21
+#include "libavcodec/avcodec.h"
22
+#if CONFIG_VDA
23
+#  include "libavcodec/vda.h"
24
+#endif
25
+#if CONFIG_VIDEOTOOLBOX
26
+#  include "libavcodec/videotoolbox.h"
27
+#endif
28
+#include "libavutil/imgutils.h"
29
+#include "ffmpeg.h"
30
+
31
+typedef struct VTContext {
32
+    AVFrame *tmp_frame;
33
+} VTContext;
34
+
35
+char *videotoolbox_pixfmt;
36
+
37
+static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame)
38
+{
39
+    InputStream *ist = s->opaque;
40
+    VTContext  *vt = ist->hwaccel_ctx;
41
+    CVPixelBufferRef pixbuf = (CVPixelBufferRef)frame->data[3];
42
+    OSType pixel_format = CVPixelBufferGetPixelFormatType(pixbuf);
43
+    CVReturn err;
44
+    uint8_t *data[4] = { 0 };
45
+    int linesize[4] = { 0 };
46
+    int planes, ret, i;
47
+    char codec_str[32];
48
+
49
+    av_frame_unref(vt->tmp_frame);
50
+
51
+    switch (pixel_format) {
52
+    case kCVPixelFormatType_420YpCbCr8Planar: vt->tmp_frame->format = AV_PIX_FMT_YUV420P; break;
53
+    case kCVPixelFormatType_422YpCbCr8:       vt->tmp_frame->format = AV_PIX_FMT_UYVY422; break;
54
+    case kCVPixelFormatType_32BGRA:           vt->tmp_frame->format = AV_PIX_FMT_BGRA; break;
55
+#ifdef kCFCoreFoundationVersionNumber10_7
56
+    case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break;
57
+#endif
58
+    default:
59
+        av_get_codec_tag_string(codec_str, sizeof(codec_str), s->codec_tag);
60
+        av_log(NULL, AV_LOG_ERROR,
61
+               "%s: Unsupported pixel format: %s\n", codec_str, videotoolbox_pixfmt);
62
+        return AVERROR(ENOSYS);
63
+    }
64
+
65
+    vt->tmp_frame->width  = frame->width;
66
+    vt->tmp_frame->height = frame->height;
67
+    ret = av_frame_get_buffer(vt->tmp_frame, 32);
68
+    if (ret < 0)
69
+        return ret;
70
+
71
+    err = CVPixelBufferLockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
72
+    if (err != kCVReturnSuccess) {
73
+        av_log(NULL, AV_LOG_ERROR, "Error locking the pixel buffer.\n");
74
+        return AVERROR_UNKNOWN;
75
+    }
76
+
77
+    if (CVPixelBufferIsPlanar(pixbuf)) {
78
+
79
+        planes = CVPixelBufferGetPlaneCount(pixbuf);
80
+        for (i = 0; i < planes; i++) {
81
+            data[i]     = CVPixelBufferGetBaseAddressOfPlane(pixbuf, i);
82
+            linesize[i] = CVPixelBufferGetBytesPerRowOfPlane(pixbuf, i);
83
+        }
84
+    } else {
85
+        data[0] = CVPixelBufferGetBaseAddress(pixbuf);
86
+        linesize[0] = CVPixelBufferGetBytesPerRow(pixbuf);
87
+    }
88
+
89
+    av_image_copy(vt->tmp_frame->data, vt->tmp_frame->linesize,
90
+                  (const uint8_t **)data, linesize, vt->tmp_frame->format,
91
+                  frame->width, frame->height);
92
+
93
+    ret = av_frame_copy_props(vt->tmp_frame, frame);
94
+    CVPixelBufferUnlockBaseAddress(pixbuf, kCVPixelBufferLock_ReadOnly);
95
+    if (ret < 0)
96
+        return ret;
97
+
98
+    av_frame_unref(frame);
99
+    av_frame_move_ref(frame, vt->tmp_frame);
100
+
101
+    return 0;
102
+}
103
+
104
+static void videotoolbox_uninit(AVCodecContext *s)
105
+{
106
+    InputStream *ist = s->opaque;
107
+    VTContext  *vt = ist->hwaccel_ctx;
108
+
109
+    ist->hwaccel_uninit        = NULL;
110
+    ist->hwaccel_retrieve_data = NULL;
111
+
112
+    av_frame_free(&vt->tmp_frame);
113
+
114
+    if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
115
+#if CONFIG_VIDEOTOOLBOX
116
+        av_videotoolbox_default_free(s);
117
+#endif
118
+    } else {
119
+#if CONFIG_VDA
120
+        av_vda_default_free(s);
121
+#endif
122
+    }
123
+    av_freep(&ist->hwaccel_ctx);
124
+}
125
+
126
+int videotoolbox_init(AVCodecContext *s)
127
+{
128
+    InputStream *ist = s->opaque;
129
+    int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
130
+    int ret = 0;
131
+    VTContext *vt;
132
+
133
+    vt = av_mallocz(sizeof(*vt));
134
+    if (!vt)
135
+        return AVERROR(ENOMEM);
136
+
137
+    ist->hwaccel_ctx           = vt;
138
+    ist->hwaccel_uninit        = videotoolbox_uninit;
139
+    ist->hwaccel_retrieve_data = videotoolbox_retrieve_data;
140
+
141
+    vt->tmp_frame = av_frame_alloc();
142
+    if (!vt->tmp_frame) {
143
+        ret = AVERROR(ENOMEM);
144
+        goto fail;
145
+    }
146
+
147
+    if (ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX) {
148
+#if CONFIG_VIDEOTOOLBOX
149
+        if (!videotoolbox_pixfmt) {
150
+            ret = av_videotoolbox_default_init(s);
151
+        } else {
152
+            AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context();
153
+            CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
154
+                                                               videotoolbox_pixfmt,
155
+                                                               kCFStringEncodingUTF8);
156
+            vtctx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
157
+            ret = av_videotoolbox_default_init2(s, vtctx);
158
+            CFRelease(pixfmt_str);
159
+        }
160
+#endif
161
+    } else {
162
+#if CONFIG_VDA
163
+        if (!videotoolbox_pixfmt) {
164
+            ret = av_vda_default_init(s);
165
+        } else {
166
+            AVVDAContext *vdactx = av_vda_alloc_context();
167
+            CFStringRef pixfmt_str = CFStringCreateWithCString(kCFAllocatorDefault,
168
+                                                               videotoolbox_pixfmt,
169
+                                                               kCFStringEncodingUTF8);
170
+            vdactx->cv_pix_fmt_type = UTGetOSTypeFromString(pixfmt_str);
171
+            ret = av_vda_default_init2(s, vdactx);
172
+            CFRelease(pixfmt_str);
173
+        }
174
+#endif
175
+    }
176
+    if (ret < 0) {
177
+        av_log(NULL, loglevel,
178
+               "Error creating %s decoder.\n", ist->hwaccel_id == HWACCEL_VIDEOTOOLBOX ? "Videotoolbox" : "VDA");
179
+        goto fail;
180
+    }
181
+
182
+    return 0;
183
+fail:
184
+    videotoolbox_uninit(s);
185
+    return ret;
186
+}
... ...
@@ -13,6 +13,7 @@ HEADERS = avcodec.h                                                     \
13 13
           vda.h                                                         \
14 14
           vdpau.h                                                       \
15 15
           version.h                                                     \
16
+          videotoolbox.h                                                \
16 17
           vorbis_parser.h                                               \
17 18
           xvmc.h                                                        \
18 19
 
... ...
@@ -696,28 +697,34 @@ OBJS-$(CONFIG_VIMA_DECODER)               += vima.o adpcm_data.o
696 696
 OBJS-$(CONFIG_D3D11VA)                    += dxva2.o
697 697
 OBJS-$(CONFIG_DXVA2)                      += dxva2.o
698 698
 OBJS-$(CONFIG_VAAPI)                      += vaapi.o
699
-OBJS-$(CONFIG_VDA)                        += vda.o
699
+OBJS-$(CONFIG_VDA)                        += vda.o videotoolbox.o
700
+OBJS-$(CONFIG_VIDEOTOOLBOX)               += videotoolbox.o
700 701
 OBJS-$(CONFIG_VDPAU)                      += vdpau.o
701 702
 
702 703
 OBJS-$(CONFIG_H263_VAAPI_HWACCEL)         += vaapi_mpeg4.o
703 704
 OBJS-$(CONFIG_H263_VDPAU_HWACCEL)         += vdpau_mpeg4.o
705
+OBJS-$(CONFIG_H263_VIDEOTOOLBOX_HWACCEL)  += videotoolbox.o
704 706
 OBJS-$(CONFIG_H264_D3D11VA_HWACCEL)       += dxva2_h264.o
705 707
 OBJS-$(CONFIG_H264_DXVA2_HWACCEL)         += dxva2_h264.o
706 708
 OBJS-$(CONFIG_H264_VAAPI_HWACCEL)         += vaapi_h264.o
707 709
 OBJS-$(CONFIG_H264_VDA_HWACCEL)           += vda_h264.o
708 710
 OBJS-$(CONFIG_H264_VDPAU_HWACCEL)         += vdpau_h264.o
711
+OBJS-$(CONFIG_H264_VIDEOTOOLBOX_HWACCEL)  += videotoolbox.o
709 712
 OBJS-$(CONFIG_HEVC_D3D11VA_HWACCEL)       += dxva2_hevc.o
710 713
 OBJS-$(CONFIG_HEVC_DXVA2_HWACCEL)         += dxva2_hevc.o
711 714
 OBJS-$(CONFIG_HEVC_VDPAU_HWACCEL)         += vdpau_hevc.o
712 715
 OBJS-$(CONFIG_MPEG1_VDPAU_HWACCEL)        += vdpau_mpeg12.o
716
+OBJS-$(CONFIG_MPEG1_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
713 717
 OBJS-$(CONFIG_MPEG1_XVMC_HWACCEL)         += mpegvideo_xvmc.o
714 718
 OBJS-$(CONFIG_MPEG2_D3D11VA_HWACCEL)      += dxva2_mpeg2.o
715 719
 OBJS-$(CONFIG_MPEG2_DXVA2_HWACCEL)        += dxva2_mpeg2.o
716 720
 OBJS-$(CONFIG_MPEG2_VAAPI_HWACCEL)        += vaapi_mpeg2.o
717 721
 OBJS-$(CONFIG_MPEG2_VDPAU_HWACCEL)        += vdpau_mpeg12.o
722
+OBJS-$(CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
718 723
 OBJS-$(CONFIG_MPEG2_XVMC_HWACCEL)         += mpegvideo_xvmc.o
719 724
 OBJS-$(CONFIG_MPEG4_VAAPI_HWACCEL)        += vaapi_mpeg4.o
720 725
 OBJS-$(CONFIG_MPEG4_VDPAU_HWACCEL)        += vdpau_mpeg4.o
726
+OBJS-$(CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL) += videotoolbox.o
721 727
 OBJS-$(CONFIG_VC1_D3D11VA_HWACCEL)        += dxva2_vc1.o
722 728
 OBJS-$(CONFIG_VC1_DXVA2_HWACCEL)          += dxva2_vc1.o
723 729
 OBJS-$(CONFIG_VC1_VAAPI_HWACCEL)          += vaapi_vc1.o
... ...
@@ -912,8 +919,9 @@ SKIPHEADERS-$(CONFIG_QSVDEC)           += qsvdec.h
912 912
 SKIPHEADERS-$(CONFIG_QSVENC)           += qsvenc.h
913 913
 SKIPHEADERS-$(CONFIG_XVMC)             += xvmc.h
914 914
 SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_internal.h
915
-SKIPHEADERS-$(CONFIG_VDA)              += vda.h vda_internal.h
915
+SKIPHEADERS-$(CONFIG_VDA)              += vda.h vda_vt_internal.h
916 916
 SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h vdpau_internal.h
917
+SKIPHEADERS-$(CONFIG_VIDEOTOOLBOX)     += videotoolbox.h vda_vt_internal.h
917 918
 
918 919
 TESTPROGS = imgconvert                                                  \
919 920
             jpeg2000dwt                                                 \
... ...
@@ -76,6 +76,7 @@ void avcodec_register_all(void)
76 76
     /* hardware accelerators */
77 77
     REGISTER_HWACCEL(H263_VAAPI,        h263_vaapi);
78 78
     REGISTER_HWACCEL(H263_VDPAU,        h263_vdpau);
79
+    REGISTER_HWACCEL(H263_VIDEOTOOLBOX, h263_videotoolbox);
79 80
     REGISTER_HWACCEL(H264_D3D11VA,      h264_d3d11va);
80 81
     REGISTER_HWACCEL(H264_DXVA2,        h264_dxva2);
81 82
     REGISTER_HWACCEL(H264_MMAL,         h264_mmal);
... ...
@@ -84,20 +85,24 @@ void avcodec_register_all(void)
84 84
     REGISTER_HWACCEL(H264_VDA,          h264_vda);
85 85
     REGISTER_HWACCEL(H264_VDA_OLD,      h264_vda_old);
86 86
     REGISTER_HWACCEL(H264_VDPAU,        h264_vdpau);
87
+    REGISTER_HWACCEL(H264_VIDEOTOOLBOX, h264_videotoolbox);
87 88
     REGISTER_HWACCEL(HEVC_D3D11VA,      hevc_d3d11va);
88 89
     REGISTER_HWACCEL(HEVC_DXVA2,        hevc_dxva2);
89 90
     REGISTER_HWACCEL(HEVC_QSV,          hevc_qsv);
90 91
     REGISTER_HWACCEL(HEVC_VDPAU,        hevc_vdpau);
91 92
     REGISTER_HWACCEL(MPEG1_XVMC,        mpeg1_xvmc);
92 93
     REGISTER_HWACCEL(MPEG1_VDPAU,       mpeg1_vdpau);
94
+    REGISTER_HWACCEL(MPEG1_VIDEOTOOLBOX, mpeg1_videotoolbox);
93 95
     REGISTER_HWACCEL(MPEG2_XVMC,        mpeg2_xvmc);
94 96
     REGISTER_HWACCEL(MPEG2_D3D11VA,     mpeg2_d3d11va);
95 97
     REGISTER_HWACCEL(MPEG2_DXVA2,       mpeg2_dxva2);
96 98
     REGISTER_HWACCEL(MPEG2_QSV,         mpeg2_qsv);
97 99
     REGISTER_HWACCEL(MPEG2_VAAPI,       mpeg2_vaapi);
98 100
     REGISTER_HWACCEL(MPEG2_VDPAU,       mpeg2_vdpau);
101
+    REGISTER_HWACCEL(MPEG2_VIDEOTOOLBOX, mpeg2_videotoolbox);
99 102
     REGISTER_HWACCEL(MPEG4_VAAPI,       mpeg4_vaapi);
100 103
     REGISTER_HWACCEL(MPEG4_VDPAU,       mpeg4_vdpau);
104
+    REGISTER_HWACCEL(MPEG4_VIDEOTOOLBOX, mpeg4_videotoolbox);
101 105
     REGISTER_HWACCEL(VC1_D3D11VA,       vc1_d3d11va);
102 106
     REGISTER_HWACCEL(VC1_DXVA2,         vc1_dxva2);
103 107
     REGISTER_HWACCEL(VC1_VAAPI,         vc1_vaapi);
... ...
@@ -723,6 +723,9 @@ const enum AVPixelFormat ff_h263_hwaccel_pixfmt_list_420[] = {
723 723
 #if CONFIG_H263_VDPAU_HWACCEL || CONFIG_MPEG4_VDPAU_HWACCEL
724 724
     AV_PIX_FMT_VDPAU,
725 725
 #endif
726
+#if CONFIG_H263_VIDEOTOOLBOX_HWACCEL || CONFIG_MPEG4_VIDEOTOOLBOX_HWACCEL
727
+    AV_PIX_FMT_VIDEOTOOLBOX,
728
+#endif
726 729
     AV_PIX_FMT_YUV420P,
727 730
     AV_PIX_FMT_NONE
728 731
 };
... ...
@@ -868,6 +868,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
868 868
                      CONFIG_H264_D3D11VA_HWACCEL + \
869 869
                      CONFIG_H264_VAAPI_HWACCEL + \
870 870
                      (CONFIG_H264_VDA_HWACCEL * 2) + \
871
+                     CONFIG_H264_VIDEOTOOLBOX_HWACCEL + \
871 872
                      CONFIG_H264_VDPAU_HWACCEL)
872 873
     enum AVPixelFormat pix_fmts[HWACCEL_MAX + 2], *fmt = pix_fmts;
873 874
     const enum AVPixelFormat *choices = pix_fmts;
... ...
@@ -948,6 +949,9 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback)
948 948
             *fmt++ = AV_PIX_FMT_VDA_VLD;
949 949
             *fmt++ = AV_PIX_FMT_VDA;
950 950
 #endif
951
+#if CONFIG_H264_VIDEOTOOLBOX_HWACCEL
952
+            *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX;
953
+#endif
951 954
             if (h->avctx->codec->pix_fmts)
952 955
                 choices = h->avctx->codec->pix_fmts;
953 956
             else if (h->avctx->color_range == AVCOL_RANGE_JPEG)
... ...
@@ -1211,6 +1211,9 @@ static const enum AVPixelFormat mpeg2_hwaccel_pixfmt_list_420[] = {
1211 1211
 #if CONFIG_MPEG2_VAAPI_HWACCEL
1212 1212
     AV_PIX_FMT_VAAPI_VLD,
1213 1213
 #endif
1214
+#if CONFIG_MPEG2_VIDEOTOOLBOX_HWACCEL
1215
+    AV_PIX_FMT_VIDEOTOOLBOX,
1216
+#endif
1214 1217
     AV_PIX_FMT_YUV420P,
1215 1218
     AV_PIX_FMT_NONE
1216 1219
 };
... ...
@@ -21,7 +21,7 @@
21 21
 #include "libavutil/mem.h"
22 22
 
23 23
 #include "vda.h"
24
-#include "vda_internal.h"
24
+#include "vda_vt_internal.h"
25 25
 
26 26
 #if CONFIG_H264_VDA_HWACCEL
27 27
 AVVDAContext *av_vda_alloc_context(void)
... ...
@@ -32,20 +32,7 @@ struct vda_buffer {
32 32
     CVPixelBufferRef cv_buffer;
33 33
 };
34 34
 #include "internal.h"
35
-#include "vda_internal.h"
36
-
37
-typedef struct VDAContext {
38
-    // The current bitstream buffer.
39
-    uint8_t             *bitstream;
40
-
41
-    // The current size of the bitstream.
42
-    int                  bitstream_size;
43
-
44
-    // The reference size used for fast reallocation.
45
-    int                  allocated_size;
46
-
47
-    CVImageBufferRef frame;
48
-} VDAContext;
35
+#include "vda_vt_internal.h"
49 36
 
50 37
 /* Decoder callback that adds the vda frame to the queue in display order. */
51 38
 static void vda_decoder_callback(void *vda_hw_ctx,
... ...
@@ -68,7 +55,7 @@ static void vda_decoder_callback(void *vda_hw_ctx,
68 68
     vda_ctx->cv_buffer = CVPixelBufferRetain(image_buffer);
69 69
 }
70 70
 
71
-static int vda_sync_decode(VDAContext *ctx, struct vda_context *vda_ctx)
71
+static int vda_sync_decode(VTContext *ctx, struct vda_context *vda_ctx)
72 72
 {
73 73
     OSStatus status;
74 74
     CFDataRef coded_frame;
... ...
@@ -93,7 +80,7 @@ static int vda_old_h264_start_frame(AVCodecContext *avctx,
93 93
                                 av_unused const uint8_t *buffer,
94 94
                                 av_unused uint32_t size)
95 95
 {
96
-    VDAContext *vda = avctx->internal->hwaccel_priv_data;
96
+    VTContext *vda = avctx->internal->hwaccel_priv_data;
97 97
     struct vda_context *vda_ctx = avctx->hwaccel_context;
98 98
 
99 99
     if (!vda_ctx->decoder)
... ...
@@ -108,7 +95,7 @@ static int vda_old_h264_decode_slice(AVCodecContext *avctx,
108 108
                                  const uint8_t *buffer,
109 109
                                  uint32_t size)
110 110
 {
111
-    VDAContext *vda             = avctx->internal->hwaccel_priv_data;
111
+    VTContext *vda              = avctx->internal->hwaccel_priv_data;
112 112
     struct vda_context *vda_ctx = avctx->hwaccel_context;
113 113
     void *tmp;
114 114
 
... ...
@@ -141,7 +128,7 @@ static void vda_h264_release_buffer(void *opaque, uint8_t *data)
141 141
 static int vda_old_h264_end_frame(AVCodecContext *avctx)
142 142
 {
143 143
     H264Context *h                      = avctx->priv_data;
144
-    VDAContext *vda                     = avctx->internal->hwaccel_priv_data;
144
+    VTContext *vda                      = avctx->internal->hwaccel_priv_data;
145 145
     struct vda_context *vda_ctx         = avctx->hwaccel_context;
146 146
     AVFrame *frame                      = h->cur_pic_ptr->f;
147 147
     struct vda_buffer *context;
... ...
@@ -271,17 +258,6 @@ int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
271 271
     return status;
272 272
 }
273 273
 
274
-static int vda_h264_uninit(AVCodecContext *avctx)
275
-{
276
-    VDAContext *vda = avctx->internal->hwaccel_priv_data;
277
-    if (vda) {
278
-        av_freep(&vda->bitstream);
279
-        if (vda->frame)
280
-            CVPixelBufferRelease(vda->frame);
281
-    }
282
-    return 0;
283
-}
284
-
285 274
 AVHWAccel ff_h264_vda_old_hwaccel = {
286 275
     .name           = "h264_vda",
287 276
     .type           = AVMEDIA_TYPE_VIDEO,
... ...
@@ -290,8 +266,8 @@ AVHWAccel ff_h264_vda_old_hwaccel = {
290 290
     .start_frame    = vda_old_h264_start_frame,
291 291
     .decode_slice   = vda_old_h264_decode_slice,
292 292
     .end_frame      = vda_old_h264_end_frame,
293
-    .uninit         = vda_h264_uninit,
294
-    .priv_data_size = sizeof(VDAContext),
293
+    .uninit         = ff_videotoolbox_uninit,
294
+    .priv_data_size = sizeof(VTContext),
295 295
 };
296 296
 
297 297
 void ff_vda_output_callback(void *opaque,
... ...
@@ -301,7 +277,7 @@ void ff_vda_output_callback(void *opaque,
301 301
                             CVImageBufferRef image_buffer)
302 302
 {
303 303
     AVCodecContext *ctx = opaque;
304
-    VDAContext *vda = ctx->internal->hwaccel_priv_data;
304
+    VTContext *vda = ctx->internal->hwaccel_priv_data;
305 305
 
306 306
 
307 307
     if (vda->frame) {
... ...
@@ -315,65 +291,10 @@ void ff_vda_output_callback(void *opaque,
315 315
     vda->frame = CVPixelBufferRetain(image_buffer);
316 316
 }
317 317
 
318
-static int vda_h264_start_frame(AVCodecContext *avctx,
319
-                                const uint8_t *buffer,
320
-                                uint32_t size)
321
-{
322
-    VDAContext *vda = avctx->internal->hwaccel_priv_data;
323
-    H264Context *h  = avctx->priv_data;
324
-
325
-    if (h->is_avc == 1) {
326
-        void *tmp;
327
-        vda->bitstream_size = 0;
328
-        tmp = av_fast_realloc(vda->bitstream,
329
-                              &vda->allocated_size,
330
-                              size);
331
-        vda->bitstream = tmp;
332
-        memcpy(vda->bitstream, buffer, size);
333
-        vda->bitstream_size = size;
334
-    } else {
335
-        vda->bitstream_size = 0;
336
-    }
337
-    return 0;
338
-}
339
-
340
-static int vda_h264_decode_slice(AVCodecContext *avctx,
341
-                                 const uint8_t *buffer,
342
-                                 uint32_t size)
343
-{
344
-    VDAContext *vda       = avctx->internal->hwaccel_priv_data;
345
-    H264Context *h  = avctx->priv_data;
346
-    void *tmp;
347
-
348
-    if (h->is_avc == 1)
349
-        return 0;
350
-
351
-    tmp = av_fast_realloc(vda->bitstream,
352
-                          &vda->allocated_size,
353
-                          vda->bitstream_size + size + 4);
354
-    if (!tmp)
355
-        return AVERROR(ENOMEM);
356
-
357
-    vda->bitstream = tmp;
358
-
359
-    AV_WB32(vda->bitstream + vda->bitstream_size, size);
360
-    memcpy(vda->bitstream + vda->bitstream_size + 4, buffer, size);
361
-
362
-    vda->bitstream_size += size + 4;
363
-
364
-    return 0;
365
-}
366
-
367
-static void release_buffer(void *opaque, uint8_t *data)
368
-{
369
-    CVImageBufferRef frame = (CVImageBufferRef)data;
370
-    CVPixelBufferRelease(frame);
371
-}
372
-
373 318
 static int vda_h264_end_frame(AVCodecContext *avctx)
374 319
 {
375 320
     H264Context *h        = avctx->priv_data;
376
-    VDAContext *vda       = avctx->internal->hwaccel_priv_data;
321
+    VTContext *vda        = avctx->internal->hwaccel_priv_data;
377 322
     AVVDAContext *vda_ctx = avctx->hwaccel_context;
378 323
     AVFrame *frame        = h->cur_pic_ptr->f;
379 324
     uint32_t flush_flags  = 1 << 0; ///< kVDADecoderFlush_emitFrames
... ...
@@ -403,19 +324,7 @@ static int vda_h264_end_frame(AVCodecContext *avctx)
403 403
         return AVERROR_UNKNOWN;
404 404
     }
405 405
 
406
-    av_buffer_unref(&frame->buf[0]);
407
-
408
-    frame->buf[0] = av_buffer_create((uint8_t*)vda->frame,
409
-                                     sizeof(vda->frame),
410
-                                     release_buffer, NULL,
411
-                                     AV_BUFFER_FLAG_READONLY);
412
-    if (!frame->buf[0])
413
-        return AVERROR(ENOMEM);
414
-
415
-    frame->data[3] = (uint8_t*)vda->frame;
416
-    vda->frame = NULL;
417
-
418
-    return 0;
406
+    return ff_videotoolbox_buffer_create(vda, frame);
419 407
 }
420 408
 
421 409
 int ff_vda_default_init(AVCodecContext *avctx)
... ...
@@ -434,26 +343,7 @@ int ff_vda_default_init(AVCodecContext *avctx)
434 434
 
435 435
     // kCVPixelFormatType_420YpCbCr8Planar;
436 436
 
437
-    /* Each VCL NAL in the bitstream sent to the decoder
438
-     * is preceded by a 4 bytes length header.
439
-     * Change the avcC atom header if needed, to signal headers of 4 bytes. */
440
-    if (avctx->extradata_size >= 4 && (avctx->extradata[4] & 0x03) != 0x03) {
441
-        uint8_t *rw_extradata;
442
-
443
-        if (!(rw_extradata = av_malloc(avctx->extradata_size)))
444
-            return AVERROR(ENOMEM);
445
-
446
-        memcpy(rw_extradata, avctx->extradata, avctx->extradata_size);
447
-
448
-        rw_extradata[4] |= 0x03;
449
-
450
-        avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->extradata_size);
451
-
452
-        av_freep(&rw_extradata);
453
-    } else {
454
-        avc_data = CFDataCreate(kCFAllocatorDefault,
455
-                                avctx->extradata, avctx->extradata_size);
456
-    }
437
+    avc_data = ff_videotoolbox_avcc_extradata_create(avctx);
457 438
 
458 439
     config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
459 440
                                             4,
... ...
@@ -521,27 +411,15 @@ int ff_vda_default_init(AVCodecContext *avctx)
521 521
     }
522 522
 }
523 523
 
524
-static int vda_h264_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
525
-{
526
-    frame->width  = avctx->width;
527
-    frame->height = avctx->height;
528
-    frame->format = avctx->pix_fmt;
529
-    frame->buf[0] = av_buffer_alloc(1);
530
-
531
-    if (!frame->buf[0])
532
-        return AVERROR(ENOMEM);
533
-    return 0;
534
-}
535
-
536 524
 AVHWAccel ff_h264_vda_hwaccel = {
537 525
     .name           = "h264_vda",
538 526
     .type           = AVMEDIA_TYPE_VIDEO,
539 527
     .id             = AV_CODEC_ID_H264,
540 528
     .pix_fmt        = AV_PIX_FMT_VDA,
541
-    .alloc_frame    = vda_h264_alloc_frame,
542
-    .start_frame    = vda_h264_start_frame,
543
-    .decode_slice   = vda_h264_decode_slice,
529
+    .alloc_frame    = ff_videotoolbox_alloc_frame,
530
+    .start_frame    = ff_videotoolbox_h264_start_frame,
531
+    .decode_slice   = ff_videotoolbox_h264_decode_slice,
544 532
     .end_frame      = vda_h264_end_frame,
545
-    .uninit         = vda_h264_uninit,
546
-    .priv_data_size = sizeof(VDAContext),
533
+    .uninit         = ff_videotoolbox_uninit,
534
+    .priv_data_size = sizeof(VTContext),
547 535
 };
548 536
deleted file mode 100644
... ...
@@ -1,33 +0,0 @@
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
-#ifndef AVCODEC_VDA_INTERNAL_H
20
-#define AVCODEC_VDA_INTERNAL_H
21
-
22
-#include "vda.h"
23
-
24
-void ff_vda_output_callback(void *vda_hw_ctx,
25
-                            CFDictionaryRef user_info,
26
-                            OSStatus status,
27
-                            uint32_t infoFlags,
28
-                            CVImageBufferRef image_buffer);
29
-
30
-int ff_vda_default_init(AVCodecContext *avctx);
31
-void ff_vda_default_free(AVCodecContext *avctx);
32
-
33
-#endif /* AVCODEC_VDA_INTERNAL_H */
34 1
new file mode 100644
... ...
@@ -0,0 +1,55 @@
0
+/*
1
+ * This file is part of FFmpeg.
2
+ *
3
+ * FFmpeg is free software; you can redistribute it and/or
4
+ * modify it under the terms of the GNU Lesser General Public
5
+ * License as published by the Free Software Foundation; either
6
+ * version 2.1 of the License, or (at your option) any later version.
7
+ *
8
+ * FFmpeg is distributed in the hope that it will be useful,
9
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
+ * Lesser General Public License for more details.
12
+ *
13
+ * You should have received a copy of the GNU Lesser General Public
14
+ * License along with FFmpeg; if not, write to the Free Software
15
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16
+ */
17
+
18
+#ifndef AVCODEC_VDA_VT_INTERNAL_H
19
+#define AVCODEC_VDA_VT_INTERNAL_H
20
+
21
+void ff_vda_output_callback(void *vda_hw_ctx,
22
+                            CFDictionaryRef user_info,
23
+                            OSStatus status,
24
+                            uint32_t infoFlags,
25
+                            CVImageBufferRef image_buffer);
26
+
27
+int ff_vda_default_init(AVCodecContext *avctx);
28
+void ff_vda_default_free(AVCodecContext *avctx);
29
+
30
+typedef struct VTContext {
31
+    // The current bitstream buffer.
32
+    uint8_t                     *bitstream;
33
+
34
+    // The current size of the bitstream.
35
+    int                         bitstream_size;
36
+
37
+    // The reference size used for fast reallocation.
38
+    int                         allocated_size;
39
+
40
+    // The core video buffer
41
+    CVImageBufferRef            frame;
42
+} VTContext;
43
+
44
+int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame);
45
+int ff_videotoolbox_uninit(AVCodecContext *avctx);
46
+int ff_videotoolbox_buffer_create(VTContext *vtctx, AVFrame *frame);
47
+int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx,
48
+                                     const uint8_t *buffer,
49
+                                     uint32_t size);
50
+int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
51
+                                      const uint8_t *buffer,
52
+                                      uint32_t size);
53
+CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx);
54
+#endif /* AVCODEC_VDA_VT_INTERNAL_H */
... ...
@@ -29,8 +29,8 @@
29 29
 #include "libavutil/version.h"
30 30
 
31 31
 #define LIBAVCODEC_VERSION_MAJOR 56
32
-#define LIBAVCODEC_VERSION_MINOR  56
33
-#define LIBAVCODEC_VERSION_MICRO 101
32
+#define LIBAVCODEC_VERSION_MINOR  57
33
+#define LIBAVCODEC_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
36 36
                                                LIBAVCODEC_VERSION_MINOR, \
37 37
new file mode 100644
... ...
@@ -0,0 +1,690 @@
0
+/*
1
+ * Videotoolbox hardware acceleration
2
+ *
3
+ * copyright (c) 2012 Sebastien Zwickert
4
+ *
5
+ * This file is part of FFmpeg.
6
+ *
7
+ * FFmpeg is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * FFmpeg is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with FFmpeg; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ */
21
+
22
+#include "config.h"
23
+#if CONFIG_VIDEOTOOLBOX
24
+#  include "videotoolbox.h"
25
+#else
26
+#  include "vda.h"
27
+#endif
28
+#include "vda_vt_internal.h"
29
+#include "libavutil/avutil.h"
30
+#include "bytestream.h"
31
+#include "h264.h"
32
+#include "mpegvideo.h"
33
+
34
+#ifndef kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder
35
+#  define kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder CFSTR("EnableHardwareAcceleratedVideoDecoder")
36
+#endif
37
+
38
+#define VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING  12
39
+
40
+static void videotoolbox_buffer_release(void *opaque, uint8_t *data)
41
+{
42
+    CVPixelBufferRef cv_buffer = (CVImageBufferRef)data;
43
+    CVPixelBufferRelease(cv_buffer);
44
+}
45
+
46
+static int videotoolbox_buffer_copy(VTContext *vtctx,
47
+                                    const uint8_t *buffer,
48
+                                    uint32_t size)
49
+{
50
+    void *tmp;
51
+
52
+    tmp = av_fast_realloc(vtctx->bitstream,
53
+                         &vtctx->allocated_size,
54
+                         size);
55
+
56
+    if (!tmp)
57
+        return AVERROR(ENOMEM);
58
+
59
+    vtctx->bitstream = tmp;
60
+    memcpy(vtctx->bitstream, buffer, size);
61
+    vtctx->bitstream_size = size;
62
+
63
+    return 0;
64
+}
65
+
66
+int ff_videotoolbox_alloc_frame(AVCodecContext *avctx, AVFrame *frame)
67
+{
68
+    frame->width  = avctx->width;
69
+    frame->height = avctx->height;
70
+    frame->format = avctx->pix_fmt;
71
+    frame->buf[0] = av_buffer_alloc(1);
72
+
73
+    if (!frame->buf[0])
74
+        return AVERROR(ENOMEM);
75
+
76
+    return 0;
77
+}
78
+
79
+CFDataRef ff_videotoolbox_avcc_extradata_create(AVCodecContext *avctx)
80
+{
81
+    CFDataRef data = NULL;
82
+
83
+    /* Each VCL NAL in the bistream sent to the decoder
84
+     * is preceded by a 4 bytes length header.
85
+     * Change the avcC atom header if needed, to signal headers of 4 bytes. */
86
+    if (avctx->extradata_size >= 4 && (avctx->extradata[4] & 0x03) != 0x03) {
87
+        uint8_t *rw_extradata = av_memdup(avctx->extradata, avctx->extradata_size);
88
+
89
+        if (!rw_extradata)
90
+            return NULL;
91
+
92
+        rw_extradata[4] |= 0x03;
93
+
94
+        data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->extradata_size);
95
+
96
+        av_freep(&rw_extradata);
97
+    } else {
98
+        data = CFDataCreate(kCFAllocatorDefault, avctx->extradata, avctx->extradata_size);
99
+    }
100
+
101
+    return data;
102
+}
103
+
104
+int ff_videotoolbox_buffer_create(VTContext *vtctx, AVFrame *frame)
105
+{
106
+    av_buffer_unref(&frame->buf[0]);
107
+
108
+    frame->buf[0] = av_buffer_create((uint8_t*)vtctx->frame,
109
+                                     sizeof(vtctx->frame),
110
+                                     videotoolbox_buffer_release,
111
+                                     NULL,
112
+                                     AV_BUFFER_FLAG_READONLY);
113
+    if (!frame->buf[0]) {
114
+        return AVERROR(ENOMEM);
115
+    }
116
+
117
+    frame->data[3] = (uint8_t*)vtctx->frame;
118
+    vtctx->frame = NULL;
119
+
120
+    return 0;
121
+}
122
+
123
+int ff_videotoolbox_h264_start_frame(AVCodecContext *avctx,
124
+                                     const uint8_t *buffer,
125
+                                     uint32_t size)
126
+{
127
+    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
128
+    H264Context *h  = avctx->priv_data;
129
+
130
+    vtctx->bitstream_size = 0;
131
+
132
+    if (h->is_avc == 1) {
133
+        return videotoolbox_buffer_copy(vtctx, buffer, size);
134
+    }
135
+
136
+    return 0;
137
+}
138
+
139
+int ff_videotoolbox_h264_decode_slice(AVCodecContext *avctx,
140
+                                      const uint8_t *buffer,
141
+                                      uint32_t size)
142
+{
143
+    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
144
+    H264Context *h  = avctx->priv_data;
145
+    void *tmp;
146
+
147
+    if (h->is_avc == 1)
148
+        return 0;
149
+
150
+    tmp = av_fast_realloc(vtctx->bitstream,
151
+                          &vtctx->allocated_size,
152
+                          vtctx->bitstream_size+size+4);
153
+    if (!tmp)
154
+        return AVERROR(ENOMEM);
155
+
156
+    vtctx->bitstream = tmp;
157
+
158
+    AV_WB32(vtctx->bitstream + vtctx->bitstream_size, size);
159
+    memcpy(vtctx->bitstream + vtctx->bitstream_size + 4, buffer, size);
160
+
161
+    vtctx->bitstream_size += size + 4;
162
+
163
+    return 0;
164
+}
165
+
166
+int ff_videotoolbox_uninit(AVCodecContext *avctx)
167
+{
168
+    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
169
+    if (vtctx) {
170
+        av_freep(&vtctx->bitstream);
171
+        if (vtctx->frame)
172
+            CVPixelBufferRelease(vtctx->frame);
173
+    }
174
+
175
+    return 0;
176
+}
177
+
178
+#if CONFIG_VIDEOTOOLBOX
179
+static void videotoolbox_write_mp4_descr_length(PutByteContext *pb, int length)
180
+{
181
+    int i;
182
+    uint8_t b;
183
+
184
+    for (i = 3; i >= 0; i--) {
185
+        b = (length >> (i * 7)) & 0x7F;
186
+        if (i != 0)
187
+            b |= 0x80;
188
+
189
+        bytestream2_put_byteu(pb, b);
190
+    }
191
+}
192
+
193
+static CFDataRef videotoolbox_esds_extradata_create(AVCodecContext *avctx)
194
+{
195
+    CFDataRef data;
196
+    uint8_t *rw_extradata;
197
+    PutByteContext pb;
198
+    int full_size = 3 + 5 + 13 + 5 + avctx->extradata_size + 3;
199
+    // ES_DescrTag data + DecoderConfigDescrTag + data + DecSpecificInfoTag + size + SLConfigDescriptor
200
+    int config_size = 13 + 5 + avctx->extradata_size;
201
+    int s;
202
+
203
+    if (!(rw_extradata = av_mallocz(full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING)))
204
+        return NULL;
205
+
206
+    bytestream2_init_writer(&pb, rw_extradata, full_size + VIDEOTOOLBOX_ESDS_EXTRADATA_PADDING);
207
+    bytestream2_put_byteu(&pb, 0);        // version
208
+    bytestream2_put_ne24(&pb, 0);         // flags
209
+
210
+    // elementary stream descriptor
211
+    bytestream2_put_byteu(&pb, 0x03);     // ES_DescrTag
212
+    videotoolbox_write_mp4_descr_length(&pb, full_size);
213
+    bytestream2_put_ne16(&pb, 0);         // esid
214
+    bytestream2_put_byteu(&pb, 0);        // stream priority (0-32)
215
+
216
+    // decoder configuration descriptor
217
+    bytestream2_put_byteu(&pb, 0x04);     // DecoderConfigDescrTag
218
+    videotoolbox_write_mp4_descr_length(&pb, config_size);
219
+    bytestream2_put_byteu(&pb, 32);       // object type indication. 32 = CODEC_ID_MPEG4
220
+    bytestream2_put_byteu(&pb, 0x11);     // stream type
221
+    bytestream2_put_ne24(&pb, 0);         // buffer size
222
+    bytestream2_put_ne32(&pb, 0);         // max bitrate
223
+    bytestream2_put_ne32(&pb, 0);         // avg bitrate
224
+
225
+    // decoder specific descriptor
226
+    bytestream2_put_byteu(&pb, 0x05);     ///< DecSpecificInfoTag
227
+    videotoolbox_write_mp4_descr_length(&pb, avctx->extradata_size);
228
+
229
+    bytestream2_put_buffer(&pb, avctx->extradata, avctx->extradata_size);
230
+
231
+    // SLConfigDescriptor
232
+    bytestream2_put_byteu(&pb, 0x06);     // SLConfigDescrTag
233
+    bytestream2_put_byteu(&pb, 0x01);     // length
234
+    bytestream2_put_byteu(&pb, 0x02);     //
235
+
236
+    s = bytestream2_size_p(&pb);
237
+
238
+    data = CFDataCreate(kCFAllocatorDefault, rw_extradata, s);
239
+
240
+    av_freep(&rw_extradata);
241
+    return data;
242
+}
243
+
244
+static CMSampleBufferRef videotoolbox_sample_buffer_create(CMFormatDescriptionRef fmt_desc,
245
+                                                           void *buffer,
246
+                                                           int size)
247
+{
248
+    OSStatus status;
249
+    CMBlockBufferRef  block_buf;
250
+    CMSampleBufferRef sample_buf;
251
+
252
+    block_buf  = NULL;
253
+    sample_buf = NULL;
254
+
255
+    status = CMBlockBufferCreateWithMemoryBlock(kCFAllocatorDefault,// structureAllocator
256
+                                                buffer,             // memoryBlock
257
+                                                size,               // blockLength
258
+                                                kCFAllocatorNull,   // blockAllocator
259
+                                                NULL,               // customBlockSource
260
+                                                0,                  // offsetToData
261
+                                                size,               // dataLength
262
+                                                0,                  // flags
263
+                                                &block_buf);
264
+
265
+    if (!status) {
266
+        status = CMSampleBufferCreate(kCFAllocatorDefault,  // allocator
267
+                                      block_buf,            // dataBuffer
268
+                                      TRUE,                 // dataReady
269
+                                      0,                    // makeDataReadyCallback
270
+                                      0,                    // makeDataReadyRefcon
271
+                                      fmt_desc,             // formatDescription
272
+                                      1,                    // numSamples
273
+                                      0,                    // numSampleTimingEntries
274
+                                      NULL,                 // sampleTimingArray
275
+                                      0,                    // numSampleSizeEntries
276
+                                      NULL,                 // sampleSizeArray
277
+                                      &sample_buf);
278
+    }
279
+
280
+    if (block_buf)
281
+        CFRelease(block_buf);
282
+
283
+    return sample_buf;
284
+}
285
+
286
+static void videotoolbox_decoder_callback(void *opaque,
287
+                                          void *sourceFrameRefCon,
288
+                                          OSStatus status,
289
+                                          VTDecodeInfoFlags flags,
290
+                                          CVImageBufferRef image_buffer,
291
+                                          CMTime pts,
292
+                                          CMTime duration)
293
+{
294
+    AVCodecContext *avctx = opaque;
295
+    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
296
+
297
+    if (vtctx->frame) {
298
+        CVPixelBufferRelease(vtctx->frame);
299
+        vtctx->frame = NULL;
300
+    }
301
+
302
+    if (!image_buffer) {
303
+        av_log(NULL, AV_LOG_DEBUG, "vt decoder cb: output image buffer is null\n");
304
+        return;
305
+    }
306
+
307
+    vtctx->frame = CVPixelBufferRetain(image_buffer);
308
+}
309
+
310
+static OSStatus videotoolbox_session_decode_frame(AVCodecContext *avctx)
311
+{
312
+    OSStatus status;
313
+    CMSampleBufferRef sample_buf;
314
+    AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
315
+    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
316
+
317
+    sample_buf = videotoolbox_sample_buffer_create(videotoolbox->cm_fmt_desc,
318
+                                                   vtctx->bitstream,
319
+                                                   vtctx->bitstream_size);
320
+
321
+    if (!sample_buf)
322
+        return -1;
323
+
324
+    status = VTDecompressionSessionDecodeFrame(videotoolbox->session,
325
+                                               sample_buf,
326
+                                               0,       // decodeFlags
327
+                                               NULL,    // sourceFrameRefCon
328
+                                               0);      // infoFlagsOut
329
+    if (status == noErr)
330
+        status = VTDecompressionSessionWaitForAsynchronousFrames(videotoolbox->session);
331
+
332
+    CFRelease(sample_buf);
333
+
334
+    return status;
335
+}
336
+
337
+static int videotoolbox_common_end_frame(AVCodecContext *avctx, AVFrame *frame)
338
+{
339
+    int status;
340
+    AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
341
+    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
342
+
343
+    if (!videotoolbox->session || !vtctx->bitstream)
344
+        return AVERROR_INVALIDDATA;
345
+
346
+    status = videotoolbox_session_decode_frame(avctx);
347
+
348
+    if (status) {
349
+        av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
350
+        return AVERROR_UNKNOWN;
351
+    }
352
+
353
+    if (!vtctx->frame)
354
+        return AVERROR_UNKNOWN;
355
+
356
+    return ff_videotoolbox_buffer_create(vtctx, frame);
357
+}
358
+
359
+static int videotoolbox_h264_end_frame(AVCodecContext *avctx)
360
+{
361
+    H264Context *h = avctx->priv_data;
362
+    AVFrame *frame = h->cur_pic_ptr->f;
363
+
364
+    return videotoolbox_common_end_frame(avctx, frame);
365
+}
366
+
367
+static int videotoolbox_mpeg_start_frame(AVCodecContext *avctx,
368
+                                         const uint8_t *buffer,
369
+                                         uint32_t size)
370
+{
371
+    VTContext *vtctx = avctx->internal->hwaccel_priv_data;
372
+
373
+    return videotoolbox_buffer_copy(vtctx, buffer, size);
374
+}
375
+
376
+static int videotoolbox_mpeg_decode_slice(AVCodecContext *avctx,
377
+                                          const uint8_t *buffer,
378
+                                          uint32_t size)
379
+{
380
+    return 0;
381
+}
382
+
383
+static int videotoolbox_mpeg_end_frame(AVCodecContext *avctx)
384
+{
385
+    MpegEncContext *s = avctx->priv_data;
386
+    AVFrame *frame = s->current_picture_ptr->f;
387
+
388
+    return videotoolbox_common_end_frame(avctx, frame);
389
+}
390
+
391
+static CFDictionaryRef videotoolbox_decoder_config_create(CMVideoCodecType codec_type,
392
+                                                          AVCodecContext *avctx)
393
+{
394
+    CFMutableDictionaryRef config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
395
+                                                                   1,
396
+                                                                   &kCFTypeDictionaryKeyCallBacks,
397
+                                                                   &kCFTypeDictionaryValueCallBacks);
398
+
399
+    CFDictionarySetValue(config_info,
400
+                         kVTVideoDecoderSpecification_EnableHardwareAcceleratedVideoDecoder,
401
+                         kCFBooleanTrue);
402
+
403
+    if (avctx->extradata_size) {
404
+        CFMutableDictionaryRef avc_info;
405
+        CFDataRef data = NULL;
406
+
407
+        avc_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
408
+                                             1,
409
+                                             &kCFTypeDictionaryKeyCallBacks,
410
+                                             &kCFTypeDictionaryValueCallBacks);
411
+
412
+        switch (codec_type) {
413
+        case kCMVideoCodecType_MPEG4Video :
414
+            data = videotoolbox_esds_extradata_create(avctx);
415
+            if (data)
416
+                CFDictionarySetValue(avc_info, CFSTR("esds"), data);
417
+            break;
418
+        case kCMVideoCodecType_H264 :
419
+            data = ff_videotoolbox_avcc_extradata_create(avctx);
420
+            if (data)
421
+                CFDictionarySetValue(avc_info, CFSTR("avcC"), data);
422
+            break;
423
+        default:
424
+            break;
425
+        }
426
+
427
+        CFDictionarySetValue(config_info,
428
+                kCMFormatDescriptionExtension_SampleDescriptionExtensionAtoms,
429
+                avc_info);
430
+
431
+        if (data)
432
+            CFRelease(data);
433
+
434
+        CFRelease(avc_info);
435
+    }
436
+    return config_info;
437
+}
438
+
439
+static CFDictionaryRef videotoolbox_buffer_attributes_create(int width,
440
+                                                             int height,
441
+                                                             OSType pix_fmt)
442
+{
443
+    CFMutableDictionaryRef buffer_attributes;
444
+    CFMutableDictionaryRef io_surface_properties;
445
+    CFNumberRef cv_pix_fmt;
446
+    CFNumberRef w;
447
+    CFNumberRef h;
448
+
449
+    w = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
450
+    h = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
451
+    cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pix_fmt);
452
+
453
+    buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
454
+                                                  4,
455
+                                                  &kCFTypeDictionaryKeyCallBacks,
456
+                                                  &kCFTypeDictionaryValueCallBacks);
457
+    io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
458
+                                                      0,
459
+                                                      &kCFTypeDictionaryKeyCallBacks,
460
+                                                      &kCFTypeDictionaryValueCallBacks);
461
+
462
+    CFDictionarySetValue(buffer_attributes, kCVPixelBufferPixelFormatTypeKey, cv_pix_fmt);
463
+    CFDictionarySetValue(buffer_attributes, kCVPixelBufferIOSurfacePropertiesKey, io_surface_properties);
464
+    CFDictionarySetValue(buffer_attributes, kCVPixelBufferWidthKey, w);
465
+    CFDictionarySetValue(buffer_attributes, kCVPixelBufferHeightKey, h);
466
+
467
+    CFRelease(io_surface_properties);
468
+    CFRelease(cv_pix_fmt);
469
+    CFRelease(w);
470
+    CFRelease(h);
471
+
472
+    return buffer_attributes;
473
+}
474
+
475
+static CMVideoFormatDescriptionRef videotoolbox_format_desc_create(CMVideoCodecType codec_type,
476
+                                                                   CFDictionaryRef decoder_spec,
477
+                                                                   int width,
478
+                                                                   int height)
479
+{
480
+    CMFormatDescriptionRef cm_fmt_desc;
481
+    OSStatus status;
482
+
483
+    status = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
484
+                                            codec_type,
485
+                                            width,
486
+                                            height,
487
+                                            decoder_spec, // Dictionary of extension
488
+                                            &cm_fmt_desc);
489
+
490
+    if (status)
491
+        return NULL;
492
+
493
+    return cm_fmt_desc;
494
+}
495
+
496
+static int videotoolbox_default_init(AVCodecContext *avctx)
497
+{
498
+    AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
499
+    OSStatus status;
500
+    VTDecompressionOutputCallbackRecord decoder_cb;
501
+    CFDictionaryRef decoder_spec;
502
+    CFDictionaryRef buf_attr;
503
+    int32_t pix_fmt;
504
+
505
+    if (!videotoolbox) {
506
+        av_log(avctx, AV_LOG_ERROR, "hwaccel context is not set\n");
507
+        return -1;
508
+    }
509
+
510
+    switch( avctx->codec_id ) {
511
+    case AV_CODEC_ID_H263 :
512
+        videotoolbox->cm_codec_type = kCMVideoCodecType_H263;
513
+        break;
514
+    case AV_CODEC_ID_H264 :
515
+        videotoolbox->cm_codec_type = kCMVideoCodecType_H264;
516
+        break;
517
+    case AV_CODEC_ID_MPEG1VIDEO :
518
+        videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG1Video;
519
+        break;
520
+    case AV_CODEC_ID_MPEG2VIDEO :
521
+        videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG2Video;
522
+        break;
523
+    case AV_CODEC_ID_MPEG4 :
524
+        videotoolbox->cm_codec_type = kCMVideoCodecType_MPEG4Video;
525
+        break;
526
+    default :
527
+        break;
528
+    }
529
+
530
+    pix_fmt = videotoolbox->cv_pix_fmt_type;
531
+
532
+    decoder_spec = videotoolbox_decoder_config_create(videotoolbox->cm_codec_type, avctx);
533
+
534
+    videotoolbox->cm_fmt_desc = videotoolbox_format_desc_create(videotoolbox->cm_codec_type,
535
+                                                                decoder_spec,
536
+                                                                avctx->width,
537
+                                                                avctx->height);
538
+    if (!videotoolbox->cm_fmt_desc) {
539
+        if (decoder_spec)
540
+            CFRelease(decoder_spec);
541
+
542
+        av_log(avctx, AV_LOG_ERROR, "format description creation failed\n");
543
+        return -1;
544
+    }
545
+
546
+    buf_attr = videotoolbox_buffer_attributes_create(avctx->width,
547
+                                                     avctx->height,
548
+                                                     videotoolbox->cv_pix_fmt_type);
549
+
550
+    decoder_cb.decompressionOutputCallback = videotoolbox_decoder_callback;
551
+    decoder_cb.decompressionOutputRefCon   = avctx;
552
+
553
+    status = VTDecompressionSessionCreate(NULL,                      // allocator
554
+                                          videotoolbox->cm_fmt_desc, // videoFormatDescription
555
+                                          decoder_spec,              // videoDecoderSpecification
556
+                                          buf_attr,                  // destinationImageBufferAttributes
557
+                                          &decoder_cb,               // outputCallback
558
+                                          &videotoolbox->session);   // decompressionSessionOut
559
+
560
+    if (decoder_spec)
561
+        CFRelease(decoder_spec);
562
+    if (buf_attr)
563
+        CFRelease(buf_attr);
564
+
565
+    switch (status) {
566
+    case kVTVideoDecoderNotAvailableNowErr:
567
+    case kVTVideoDecoderUnsupportedDataFormatErr:
568
+        return AVERROR(ENOSYS);
569
+    case kVTVideoDecoderMalfunctionErr:
570
+        return AVERROR(EINVAL);
571
+    case kVTVideoDecoderBadDataErr :
572
+        return AVERROR_INVALIDDATA;
573
+    case 0:
574
+        return 0;
575
+    default:
576
+        return AVERROR_UNKNOWN;
577
+    }
578
+}
579
+
580
+static void videotoolbox_default_free(AVCodecContext *avctx)
581
+{
582
+    AVVideotoolboxContext *videotoolbox = avctx->hwaccel_context;
583
+
584
+    if (videotoolbox) {
585
+        if (videotoolbox->cm_fmt_desc)
586
+            CFRelease(videotoolbox->cm_fmt_desc);
587
+
588
+        if (videotoolbox->session)
589
+            VTDecompressionSessionInvalidate(videotoolbox->session);
590
+    }
591
+}
592
+
593
+AVHWAccel ff_h263_videotoolbox_hwaccel = {
594
+    .name           = "h263_videotoolbox",
595
+    .type           = AVMEDIA_TYPE_VIDEO,
596
+    .id             = AV_CODEC_ID_H263,
597
+    .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
598
+    .alloc_frame    = ff_videotoolbox_alloc_frame,
599
+    .start_frame    = videotoolbox_mpeg_start_frame,
600
+    .decode_slice   = videotoolbox_mpeg_decode_slice,
601
+    .end_frame      = videotoolbox_mpeg_end_frame,
602
+    .uninit         = ff_videotoolbox_uninit,
603
+    .priv_data_size = sizeof(VTContext),
604
+};
605
+
606
+AVHWAccel ff_h264_videotoolbox_hwaccel = {
607
+    .name           = "h264_videotoolbox",
608
+    .type           = AVMEDIA_TYPE_VIDEO,
609
+    .id             = AV_CODEC_ID_H264,
610
+    .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
611
+    .alloc_frame    = ff_videotoolbox_alloc_frame,
612
+    .start_frame    = ff_videotoolbox_h264_start_frame,
613
+    .decode_slice   = ff_videotoolbox_h264_decode_slice,
614
+    .end_frame      = videotoolbox_h264_end_frame,
615
+    .uninit         = ff_videotoolbox_uninit,
616
+    .priv_data_size = sizeof(VTContext),
617
+};
618
+
619
+AVHWAccel ff_mpeg1_videotoolbox_hwaccel = {
620
+    .name           = "mpeg1_videotoolbox",
621
+    .type           = AVMEDIA_TYPE_VIDEO,
622
+    .id             = AV_CODEC_ID_MPEG1VIDEO,
623
+    .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
624
+    .alloc_frame    = ff_videotoolbox_alloc_frame,
625
+    .start_frame    = videotoolbox_mpeg_start_frame,
626
+    .decode_slice   = videotoolbox_mpeg_decode_slice,
627
+    .end_frame      = videotoolbox_mpeg_end_frame,
628
+    .uninit         = ff_videotoolbox_uninit,
629
+    .priv_data_size = sizeof(VTContext),
630
+};
631
+
632
+AVHWAccel ff_mpeg2_videotoolbox_hwaccel = {
633
+    .name           = "mpeg2_videotoolbox",
634
+    .type           = AVMEDIA_TYPE_VIDEO,
635
+    .id             = AV_CODEC_ID_MPEG2VIDEO,
636
+    .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
637
+    .alloc_frame    = ff_videotoolbox_alloc_frame,
638
+    .start_frame    = videotoolbox_mpeg_start_frame,
639
+    .decode_slice   = videotoolbox_mpeg_decode_slice,
640
+    .end_frame      = videotoolbox_mpeg_end_frame,
641
+    .uninit         = ff_videotoolbox_uninit,
642
+    .priv_data_size = sizeof(VTContext),
643
+};
644
+
645
+AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
646
+    .name           = "mpeg4_videotoolbox",
647
+    .type           = AVMEDIA_TYPE_VIDEO,
648
+    .id             = AV_CODEC_ID_MPEG4,
649
+    .pix_fmt        = AV_PIX_FMT_VIDEOTOOLBOX,
650
+    .alloc_frame    = ff_videotoolbox_alloc_frame,
651
+    .start_frame    = videotoolbox_mpeg_start_frame,
652
+    .decode_slice   = videotoolbox_mpeg_decode_slice,
653
+    .end_frame      = videotoolbox_mpeg_end_frame,
654
+    .uninit         = ff_videotoolbox_uninit,
655
+    .priv_data_size = sizeof(VTContext),
656
+};
657
+
658
+AVVideotoolboxContext *av_videotoolbox_alloc_context(void)
659
+{
660
+    AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret));
661
+
662
+    if (ret) {
663
+        ret->output_callback = videotoolbox_decoder_callback;
664
+        ret->cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
665
+    }
666
+
667
+    return ret;
668
+}
669
+
670
+int av_videotoolbox_default_init(AVCodecContext *avctx)
671
+{
672
+    return av_videotoolbox_default_init2(avctx, NULL);
673
+}
674
+
675
+int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx)
676
+{
677
+    avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context();
678
+    if (!avctx->hwaccel_context)
679
+        return AVERROR(ENOMEM);
680
+    return videotoolbox_default_init(avctx);
681
+}
682
+
683
+void av_videotoolbox_default_free(AVCodecContext *avctx)
684
+{
685
+
686
+    videotoolbox_default_free(avctx);
687
+    av_freep(&avctx->hwaccel_context);
688
+}
689
+#endif /* CONFIG_VIDEOTOOLBOX */
0 690
new file mode 100644
... ...
@@ -0,0 +1,126 @@
0
+/*
1
+ * Videotoolbox hardware acceleration
2
+ *
3
+ * copyright (c) 2012 Sebastien Zwickert
4
+ *
5
+ * This file is part of FFmpeg.
6
+ *
7
+ * FFmpeg is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * FFmpeg is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with FFmpeg; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ */
21
+
22
+#ifndef AVCODEC_VIDEOTOOLBOX_H
23
+#define AVCODEC_VIDEOTOOLBOX_H
24
+
25
+/**
26
+ * @file
27
+ * @ingroup lavc_codec_hwaccel_videotoolbox
28
+ * Public libavcodec Videotoolbox header.
29
+ */
30
+
31
+#include <stdint.h>
32
+
33
+#define Picture QuickdrawPicture
34
+#include <VideoToolbox/VideoToolbox.h>
35
+#undef Picture
36
+
37
+#include "libavcodec/avcodec.h"
38
+
39
+/**
40
+ * This struct holds all the information that needs to be passed
41
+ * between the caller and libavcodec for initializing Videotoolbox decoding.
42
+ * Its size is not a part of the public ABI, it must be allocated with
43
+ * av_videotoolbox_alloc_context() and freed with av_free().
44
+ */
45
+typedef struct AVVideotoolboxContext {
46
+    /**
47
+     * Videotoolbox decompression session object.
48
+     * Created and freed the caller.
49
+     */
50
+    VTDecompressionSessionRef session;
51
+
52
+    /**
53
+     * The output callback that must be passed to the session.
54
+     * Set by av_videottoolbox_default_init()
55
+     */
56
+    VTDecompressionOutputCallback output_callback;
57
+
58
+    /**
59
+     * CVPixelBuffer Format Type that Videotoolbox will use for decoded frames.
60
+     * set by the caller.
61
+     */
62
+    OSType cv_pix_fmt_type;
63
+
64
+    /**
65
+     * CoreMedia Format Description that Videotoolbox will use to create the decompression session.
66
+     * Set by the caller.
67
+     */
68
+    CMVideoFormatDescriptionRef cm_fmt_desc;
69
+
70
+    /**
71
+     * CoreMedia codec type that Videotoolbox will use to create the decompression session.
72
+     * Set by the caller.
73
+     */
74
+    int cm_codec_type;
75
+} AVVideotoolboxContext;
76
+
77
+/**
78
+ * Allocate and initialize a Videotoolbox context.
79
+ *
80
+ * This function should be called from the get_format() callback when the caller
81
+ * selects the AV_PIX_FMT_VIDETOOLBOX format. The caller must then create
82
+ * the decoder object (using the output callback provided by libavcodec) that
83
+ * will be used for Videotoolbox-accelerated decoding.
84
+ *
85
+ * When decoding with Videotoolbox is finished, the caller must destroy the decoder
86
+ * object and free the Videotoolbox context using av_free().
87
+ *
88
+ * @return the newly allocated context or NULL on failure
89
+ */
90
+AVVideotoolboxContext *av_videotoolbox_alloc_context(void);
91
+
92
+/**
93
+ * This is a convenience function that creates and sets up the Videotoolbox context using
94
+ * an internal implementation.
95
+ *
96
+ * @param avctx the corresponding codec context
97
+ *
98
+ * @return >= 0 on success, a negative AVERROR code on failure
99
+ */
100
+int av_videotoolbox_default_init(AVCodecContext *avctx);
101
+
102
+/**
103
+ * This is a convenience function that creates and sets up the Videotoolbox context using
104
+ * an internal implementation.
105
+ *
106
+ * @param avctx the corresponding codec context
107
+ * @param vtctx the Videotoolbox context to use
108
+ *
109
+ * @return >= 0 on success, a negative AVERROR code on failure
110
+ */
111
+int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx);
112
+
113
+/**
114
+ * This function must be called to free the Videotoolbox context initialized with
115
+ * av_videotoolbox_default_init().
116
+ *
117
+ * @param avctx the corresponding codec context
118
+ */
119
+void av_videotoolbox_default_free(AVCodecContext *avctx);
120
+
121
+/**
122
+ * @}
123
+ */
124
+
125
+#endif /* AVCODEC_VIDEOTOOLBOX_H */
... ...
@@ -1632,6 +1632,10 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = {
1632 1632
         },
1633 1633
         .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_ALPHA,
1634 1634
     },
1635
+    [AV_PIX_FMT_VIDEOTOOLBOX] = {
1636
+        .name = "videotoolbox_vld",
1637
+        .flags = AV_PIX_FMT_FLAG_HWACCEL,
1638
+    },
1635 1639
     [AV_PIX_FMT_GBRP] = {
1636 1640
         .name = "gbrp",
1637 1641
         .nb_components = 3,
... ...
@@ -311,6 +311,8 @@ enum AVPixelFormat {
311 311
     AV_PIX_FMT_AYUV64LE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), little-endian
312 312
     AV_PIX_FMT_AYUV64BE,    ///< packed AYUV 4:4:4,64bpp (1 Cr & Cb sample per 1x1 Y & A samples), big-endian
313 313
 
314
+    AV_PIX_FMT_VIDEOTOOLBOX, ///< hardware decoding through Videotoolbox
315
+
314 316
     AV_PIX_FMT_NB,        ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
315 317
 
316 318
 #if FF_API_PIX_FMT