Browse code

HWAccel: adds Video Decoder Acceleration (VDA) module for Mac OS X.

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Sebastien Zwickert authored on 2011/11/02 08:55:09
Showing 15 changed files
... ...
@@ -70,6 +70,7 @@ easier to use. The changes are:
70 70
 - 4:2:2 H.264 decoding support
71 71
 - Pulseaudio input device
72 72
 - Prores encoder
73
+- Video Decoder Acceleration (VDA) HWAccel module.
73 74
 
74 75
 version 0.8:
75 76
 
... ...
@@ -237,6 +237,7 @@ Hardware acceleration:
237 237
   dxva2*                                Laurent Aimar
238 238
   libstagefright.cpp                    Mohamed Naufal
239 239
   vaapi*                                Gwenole Beauchesne
240
+  vda*                                  Sebastien Zwickert
240 241
   vdpau*                                Carl Eugen Hoyos
241 242
 
242 243
 
... ...
@@ -111,6 +111,7 @@ Configuration options:
111 111
   --enable-vaapi           enable VAAPI code [autodetect]
112 112
   --enable-vdpau           enable VDPAU code [autodetect]
113 113
   --disable-dxva2          disable DXVA2 code
114
+  --disable-vda            disable VDA code
114 115
   --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
115 116
   --enable-hardcoded-tables use hardcoded tables instead of runtime generation
116 117
   --enable-memalign-hack   emulate memalign, interferes with memory debuggers
... ...
@@ -1052,6 +1053,7 @@ CONFIG_LIST="
1052 1052
     swscale_alpha
1053 1053
     thumb
1054 1054
     vaapi
1055
+    vda
1055 1056
     vdpau
1056 1057
     version3
1057 1058
     x11grab
... ...
@@ -1377,6 +1379,8 @@ h264_crystalhd_decoder_select="crystalhd h264_mp4toannexb_bsf h264_parser"
1377 1377
 h264_dxva2_hwaccel_deps="dxva2api_h"
1378 1378
 h264_dxva2_hwaccel_select="dxva2 h264_decoder"
1379 1379
 h264_vaapi_hwaccel_select="vaapi"
1380
+h264_vda_hwaccel_deps="VideoDecodeAcceleration_VDADecoder_h"
1381
+h264_vda_hwaccel_select="vda"
1380 1382
 h264_vdpau_decoder_select="vdpau h264_decoder"
1381 1383
 imc_decoder_select="fft mdct sinewin"
1382 1384
 jpegls_decoder_select="golomb"
... ...
@@ -2955,6 +2959,7 @@ check_func_headers windows.h MapViewOfFile
2955 2955
 check_func_headers windows.h VirtualAlloc
2956 2956
 
2957 2957
 check_header dlfcn.h
2958
+check_header VideoDecodeAcceleration/VDADecoder.h
2958 2959
 check_header dxva2api.h -D_WIN32_WINNT=0x0600
2959 2960
 check_header libcrystalhd/libcrystalhd_if.h
2960 2961
 check_header malloc.h
... ...
@@ -2970,6 +2975,11 @@ check_header X11/extensions/XvMClib.h
2970 2970
 disabled  zlib || check_lib   zlib.h      zlibVersion -lz   || disable  zlib
2971 2971
 disabled bzlib || check_lib2 bzlib.h BZ2_bzlibVersion -lbz2 || disable bzlib
2972 2972
 
2973
+# adds ldflags for VDA module
2974
+if enabled vda; then
2975
+    add_ldflags -framework CoreFoundation -framework VideoDecodeAcceleration -framework QuartzCore
2976
+fi
2977
+
2973 2978
 # check for some common methods of building with pthread support
2974 2979
 # do this before the optional library checks as some of them require pthreads
2975 2980
 if ! disabled pthreads && ! enabled w32threads; then
... ...
@@ -3,7 +3,7 @@ include $(SUBDIR)../config.mak
3 3
 NAME = avcodec
4 4
 FFLIBS = avutil
5 5
 
6
-HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vdpau.h version.h xvmc.h
6
+HEADERS = avcodec.h avfft.h dxva2.h opt.h vaapi.h vda.h vdpau.h version.h xvmc.h
7 7
 
8 8
 OBJS = allcodecs.o                                                      \
9 9
        audioconvert.o                                                   \
... ...
@@ -49,6 +49,7 @@ RDFT-OBJS-$(CONFIG_HARDCODED_TABLES)   += sin_tables.o
49 49
 OBJS-$(CONFIG_RDFT)                    += rdft.o $(RDFT-OBJS-yes)
50 50
 OBJS-$(CONFIG_SINEWIN)                 += sinewin.o
51 51
 OBJS-$(CONFIG_VAAPI)                   += vaapi.o
52
+OBJS-$(CONFIG_VDA)                     += vda.o
52 53
 OBJS-$(CONFIG_VDPAU)                   += vdpau.o
53 54
 
54 55
 # decoders/encoders/hardware accelerators
... ...
@@ -192,6 +193,7 @@ OBJS-$(CONFIG_H264_DECODER)            += h264.o                               \
192 192
                                           mpegvideo.o error_resilience.o
193 193
 OBJS-$(CONFIG_H264_DXVA2_HWACCEL)      += dxva2_h264.o
194 194
 OBJS-$(CONFIG_H264_VAAPI_HWACCEL)      += vaapi_h264.o
195
+OBJS-$(CONFIG_H264_VDA_HWACCEL)        += vda_h264.o
195 196
 OBJS-$(CONFIG_HUFFYUV_DECODER)         += huffyuv.o
196 197
 OBJS-$(CONFIG_HUFFYUV_ENCODER)         += huffyuv.o
197 198
 OBJS-$(CONFIG_IDCIN_DECODER)           += idcinvideo.o
... ...
@@ -703,6 +705,7 @@ SKIPHEADERS-$(CONFIG_DXVA2)            += dxva2.h dxva2_internal.h
703 703
 SKIPHEADERS-$(CONFIG_LIBDIRAC)         += libdirac.h
704 704
 SKIPHEADERS-$(CONFIG_LIBSCHROEDINGER)  += libschroedinger.h
705 705
 SKIPHEADERS-$(CONFIG_VAAPI)            += vaapi_internal.h
706
+SKIPHEADERS-$(CONFIG_VDA)              += vda_internal.h
706 707
 SKIPHEADERS-$(CONFIG_VDPAU)            += vdpau.h
707 708
 SKIPHEADERS-$(CONFIG_XVMC)             += xvmc.h
708 709
 SKIPHEADERS-$(HAVE_W32THREADS)         += w32pthreads.h
... ...
@@ -57,6 +57,7 @@ void avcodec_register_all(void)
57 57
     REGISTER_HWACCEL (H263_VAAPI, h263_vaapi);
58 58
     REGISTER_HWACCEL (H264_DXVA2, h264_dxva2);
59 59
     REGISTER_HWACCEL (H264_VAAPI, h264_vaapi);
60
+    REGISTER_HWACCEL (H264_VDA, h264_vda);
60 61
     REGISTER_HWACCEL (MPEG1_VDPAU, mpeg1_vdpau);
61 62
     REGISTER_HWACCEL (MPEG2_DXVA2, mpeg2_dxva2);
62 63
     REGISTER_HWACCEL (MPEG2_VAAPI, mpeg2_vaapi);
... ...
@@ -56,6 +56,7 @@ static const uint8_t div6[QP_MAX_NUM+1]={
56 56
 static const enum PixelFormat hwaccel_pixfmt_list_h264_jpeg_420[] = {
57 57
     PIX_FMT_DXVA2_VLD,
58 58
     PIX_FMT_VAAPI_VLD,
59
+    PIX_FMT_VDA_VLD,
59 60
     PIX_FMT_YUVJ420P,
60 61
     PIX_FMT_NONE
61 62
 };
... ...
@@ -118,6 +118,7 @@ const enum PixelFormat ff_pixfmt_list_420[] = {
118 118
 const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = {
119 119
     PIX_FMT_DXVA2_VLD,
120 120
     PIX_FMT_VAAPI_VLD,
121
+    PIX_FMT_VDA_VLD,
121 122
     PIX_FMT_YUV420P,
122 123
     PIX_FMT_NONE
123 124
 };
124 125
new file mode 100644
... ...
@@ -0,0 +1,271 @@
0
+/*
1
+ * VDA HW acceleration.
2
+ *
3
+ * copyright (c) 2011 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 "vda_internal.h"
23
+
24
+/**
25
+ * \addtogroup VDA_Decoding
26
+ *
27
+ * @{
28
+ */
29
+
30
+/* Mutex manager callback. */
31
+static int vda_lock_operation(void **mtx, enum AVLockOp op)
32
+{
33
+    switch(op)
34
+    {
35
+        case AV_LOCK_CREATE:
36
+            *mtx = av_malloc(sizeof(pthread_mutex_t));
37
+            if(!*mtx)
38
+                return 1;
39
+            return !!pthread_mutex_init(*mtx, NULL);
40
+        case AV_LOCK_OBTAIN:
41
+            return !!pthread_mutex_lock(*mtx);
42
+        case AV_LOCK_RELEASE:
43
+            return !!pthread_mutex_unlock(*mtx);
44
+        case AV_LOCK_DESTROY:
45
+            pthread_mutex_destroy(*mtx);
46
+            av_freep(mtx);
47
+            return 0;
48
+    }
49
+    return 1;
50
+}
51
+
52
+/* Helper to create a dictionary according to the given pts. */
53
+static CFDictionaryRef vda_dictionary_with_pts(int64_t i_pts)
54
+{
55
+    CFStringRef key = CFSTR("FF_VDA_DECODER_PTS_KEY");
56
+    CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &i_pts);
57
+    CFDictionaryRef user_info = CFDictionaryCreate( kCFAllocatorDefault,
58
+                                                    (const void **)&key,
59
+                                                    (const void **)&value,
60
+                                                    1,
61
+                                                    &kCFTypeDictionaryKeyCallBacks,
62
+                                                    &kCFTypeDictionaryValueCallBacks);
63
+    CFRelease(value);
64
+    return user_info;
65
+}
66
+
67
+/* Helper to retrieve the pts from the given dictionary. */
68
+static int64_t vda_pts_from_dictionary(CFDictionaryRef user_info)
69
+{
70
+    CFNumberRef pts;
71
+    int64_t outValue = 0;
72
+
73
+    if (NULL == user_info)
74
+        return 0;
75
+
76
+    pts = CFDictionaryGetValue(user_info, CFSTR("FF_VDA_DECODER_PTS_KEY"));
77
+
78
+    if (pts)
79
+        CFNumberGetValue(pts, kCFNumberSInt64Type, &outValue);
80
+
81
+    return outValue;
82
+}
83
+
84
+/* Removes and releases all frames from the queue. */
85
+static void vda_clear_queue(struct vda_context *vda_ctx)
86
+{
87
+    vda_frame *top_frame;
88
+
89
+    vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN);
90
+
91
+    while (vda_ctx->queue != NULL)
92
+    {
93
+        top_frame = vda_ctx->queue;
94
+        vda_ctx->queue = top_frame->next_frame;
95
+        ff_vda_release_vda_frame(top_frame);
96
+    }
97
+
98
+    vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_RELEASE);
99
+}
100
+
101
+
102
+/* Decoder callback that adds the vda frame to the queue in display order. */
103
+static void vda_decoder_callback (void *vda_hw_ctx,
104
+                                  CFDictionaryRef user_info,
105
+                                  OSStatus status,
106
+                                  uint32_t infoFlags,
107
+                                  CVImageBufferRef image_buffer)
108
+{
109
+    struct vda_context *vda_ctx = (struct vda_context*)vda_hw_ctx;
110
+    vda_frame *new_frame;
111
+    vda_frame *queue_walker;
112
+
113
+    if (NULL == image_buffer)
114
+        return;
115
+
116
+    if (kCVPixelFormatType_422YpCbCr8 != CVPixelBufferGetPixelFormatType(image_buffer))
117
+        return;
118
+
119
+    new_frame = (vda_frame *)av_mallocz(sizeof(vda_frame));
120
+    new_frame->next_frame = NULL;
121
+    new_frame->cv_buffer = CVPixelBufferRetain(image_buffer);
122
+    new_frame->pts = vda_pts_from_dictionary(user_info);
123
+
124
+    vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN);
125
+
126
+    queue_walker = vda_ctx->queue;
127
+
128
+    if (!queue_walker || (new_frame->pts < queue_walker->pts))
129
+    {
130
+        /* we have an empty queue, or this frame earlier than the current queue head */
131
+        new_frame->next_frame = queue_walker;
132
+        vda_ctx->queue = new_frame;
133
+    }
134
+    else
135
+    {
136
+        /* walk the queue and insert this frame where it belongs in display order */
137
+        vda_frame *next_frame;
138
+
139
+        while (1)
140
+        {
141
+            next_frame = queue_walker->next_frame;
142
+
143
+            if (!next_frame || (new_frame->pts < next_frame->pts))
144
+            {
145
+                new_frame->next_frame = next_frame;
146
+                queue_walker->next_frame = new_frame;
147
+                break;
148
+            }
149
+            queue_walker = next_frame;
150
+        }
151
+    }
152
+
153
+    vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_RELEASE);
154
+}
155
+
156
+int ff_vda_create_decoder(struct vda_context *vda_ctx,
157
+                          uint8_t *extradata,
158
+                          int extradata_size)
159
+{
160
+    OSStatus status = kVDADecoderNoErr;
161
+    CFNumberRef height;
162
+    CFNumberRef width;
163
+    CFNumberRef format;
164
+    CFDataRef avc_data;
165
+    CFMutableDictionaryRef config_info;
166
+
167
+    if (av_lockmgr_register(vda_lock_operation))
168
+        return -1;
169
+
170
+    vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_CREATE);
171
+
172
+    config_info = (CFDictionaryCreateMutable(kCFAllocatorDefault,
173
+                                             4,
174
+                                             &kCFTypeDictionaryKeyCallBacks,
175
+                                             &kCFTypeDictionaryValueCallBacks));
176
+
177
+    height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->height);
178
+    width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->width);
179
+    format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->format);
180
+    avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
181
+
182
+    CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
183
+    CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
184
+    CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
185
+    CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
186
+
187
+    status = VDADecoderCreate( config_info,
188
+                               NULL,
189
+                               (VDADecoderOutputCallback *)vda_decoder_callback,
190
+                               (void *)vda_ctx,
191
+                               &vda_ctx->decoder );
192
+
193
+    CFRelease(height);
194
+    CFRelease(width);
195
+    CFRelease(format);
196
+    CFRelease(avc_data);
197
+    CFRelease(config_info);
198
+
199
+    if (kVDADecoderNoErr != status)
200
+        return status;
201
+
202
+    return 0;
203
+}
204
+
205
+int ff_vda_destroy_decoder(struct vda_context *vda_ctx)
206
+{
207
+    OSStatus status = kVDADecoderNoErr;
208
+
209
+    if (vda_ctx->decoder)
210
+        status = VDADecoderDestroy(vda_ctx->decoder);
211
+
212
+    vda_clear_queue(vda_ctx);
213
+
214
+    if (vda_ctx->queue_mutex != NULL)
215
+        vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_DESTROY);
216
+
217
+    if (kVDADecoderNoErr != status)
218
+        return status;
219
+
220
+    return 0;
221
+}
222
+
223
+vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx)
224
+{
225
+    vda_frame *top_frame;
226
+
227
+    if (!vda_ctx->queue)
228
+        return NULL;
229
+
230
+    vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_OBTAIN);
231
+    top_frame = vda_ctx->queue;
232
+    vda_ctx->queue = top_frame->next_frame;
233
+    vda_lock_operation(&vda_ctx->queue_mutex, AV_LOCK_RELEASE);
234
+
235
+    return top_frame;
236
+}
237
+
238
+void ff_vda_release_vda_frame(vda_frame *frame)
239
+{
240
+    if (frame != NULL)
241
+    {
242
+        CVPixelBufferRelease(frame->cv_buffer);
243
+        av_freep(&frame);
244
+    }
245
+}
246
+
247
+int ff_vda_decoder_decode(struct vda_context *vda_ctx,
248
+                          uint8_t *bitstream,
249
+                          int bitstream_size,
250
+                          int64_t frame_pts)
251
+{
252
+    OSStatus status = kVDADecoderNoErr;
253
+    CFDictionaryRef user_info;
254
+    CFDataRef coded_frame;
255
+
256
+    coded_frame = CFDataCreate(kCFAllocatorDefault, bitstream, bitstream_size);
257
+    user_info = vda_dictionary_with_pts(frame_pts);
258
+
259
+    status = VDADecoderDecode(vda_ctx->decoder, 0, coded_frame, user_info);
260
+
261
+    CFRelease(user_info);
262
+    CFRelease(coded_frame);
263
+
264
+    if (kVDADecoderNoErr != status)
265
+        return status;
266
+
267
+    return 0;
268
+}
269
+
270
+/* @} */
0 271
new file mode 100644
... ...
@@ -0,0 +1,140 @@
0
+/*
1
+ * VDA HW acceleration
2
+ *
3
+ * copyright (c) 2011 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_VDA_H
23
+#define AVCODEC_VDA_H
24
+
25
+#include <stdint.h>
26
+
27
+// emmintrin.h is unable to compile with -std=c99 -Werror=missing-prototypes
28
+// http://openradar.appspot.com/8026390
29
+#undef __GNUC_STDC_INLINE__
30
+
31
+#define Picture QuickdrawPicture
32
+
33
+#include <pthread.h>
34
+#include "avcodec.h"
35
+#include <VideoDecodeAcceleration/VDADecoder.h>
36
+
37
+/**
38
+ *  This structure is used to store a decoded frame information and data.
39
+ */
40
+typedef struct
41
+{
42
+    /**
43
+    * The PTS of the frame.
44
+    *
45
+    * - encoding: unused
46
+    * - decoding: Set/Unset by libavcodec.
47
+    */
48
+    int64_t             pts;
49
+
50
+    /**
51
+    * The CoreVideo buffer that contains the decoded data.
52
+    *
53
+    * - encoding: unused
54
+    * - decoding: Set/Unset by libavcodec.
55
+    */
56
+    CVPixelBufferRef    cv_buffer;
57
+
58
+    /**
59
+    * A pointer to the next frame.
60
+    *
61
+    * - encoding: unused
62
+    * - decoding: Set/Unset by libavcodec.
63
+    */
64
+    struct vda_frame    *next_frame;
65
+
66
+} vda_frame;
67
+
68
+/**
69
+ * This structure is used to provide the necessary configurations and data
70
+ * to the VDA FFmpeg HWAccel implementation.
71
+ *
72
+ * The application must make it available as AVCodecContext.hwaccel_context.
73
+ */
74
+struct vda_context {
75
+
76
+    /**
77
+    * VDA decoder object.
78
+    *
79
+    * - encoding: unused
80
+    * - decoding: Set/Unset by libavcodec.
81
+    */
82
+    VDADecoder          decoder;
83
+
84
+    /**
85
+    * VDA frames queue ordered by presentation timestamp.
86
+    *
87
+    * - encoding: unused
88
+    * - decoding: Set/Unset by libavcodec.
89
+    */
90
+    vda_frame           *queue;
91
+
92
+    /**
93
+    * Mutex for locking queue operations.
94
+    *
95
+    * - encoding: unused
96
+    * - decoding: Set/Unset by libavcodec.
97
+    */
98
+    void                *queue_mutex;
99
+
100
+    /**
101
+    * The frame width.
102
+    *
103
+    * - encoding: unused
104
+    * - decoding: Set/Unset by user.
105
+    */
106
+    int                 width;
107
+
108
+    /**
109
+    * The frame height.
110
+    *
111
+    * - encoding: unused
112
+    * - decoding: Set/Unset by user.
113
+    */
114
+    int                 height;
115
+
116
+    /**
117
+    * The frame format.
118
+    *
119
+    * - encoding: unused
120
+    * - decoding: Set/Unset by user.
121
+    */
122
+    int                 format;
123
+};
124
+
125
+/** Creates the video decoder. */
126
+int ff_vda_create_decoder(struct vda_context *vda_ctx,
127
+                          uint8_t *extradata,
128
+                          int extradata_size);
129
+
130
+/** Destroys the video decoder. */
131
+int ff_vda_destroy_decoder(struct vda_context *vda_ctx);
132
+
133
+/** Returns the top frame of the queue. */
134
+vda_frame *ff_vda_queue_pop(struct vda_context *vda_ctx);
135
+
136
+/** Releases the given frame. */
137
+void ff_vda_release_vda_frame(vda_frame *frame);
138
+
139
+#endif /* AVCODEC_VDA_H */
0 140
new file mode 100644
... ...
@@ -0,0 +1,107 @@
0
+/*
1
+ * VDA H264 HW acceleration.
2
+ *
3
+ * copyright (c) 2011 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 "vda_internal.h"
23
+
24
+/* This structure is used to store the bitstream of the current frame. */
25
+struct vda_picture_context {
26
+    uint8_t         *bitstream;
27
+    int              bitstream_size;
28
+};
29
+
30
+static int start_frame(AVCodecContext *avctx,
31
+                       av_unused const uint8_t *buffer,
32
+                       av_unused uint32_t size)
33
+{
34
+    const H264Context *h = avctx->priv_data;
35
+    struct vda_context *vda_ctx = avctx->hwaccel_context;
36
+    struct vda_picture_context *pic_ctx = h->s.current_picture_ptr->f.hwaccel_picture_private;
37
+
38
+    if (!vda_ctx->decoder)
39
+        return -1;
40
+
41
+    pic_ctx->bitstream = NULL;
42
+    pic_ctx->bitstream_size = 0;
43
+
44
+    return 0;
45
+}
46
+
47
+static int decode_slice(AVCodecContext *avctx,
48
+                        const uint8_t *buffer,
49
+                        uint32_t size)
50
+{
51
+    H264Context *h = avctx->priv_data;
52
+    struct vda_context *vda_ctx = avctx->hwaccel_context;
53
+    struct vda_picture_context *pic_ctx = h->s.current_picture_ptr->f.hwaccel_picture_private;
54
+    void *tmp;
55
+
56
+    if (!vda_ctx->decoder)
57
+        return -1;
58
+
59
+    tmp = av_realloc(pic_ctx->bitstream, pic_ctx->bitstream_size+size+4);
60
+    if (!tmp)
61
+        return AVERROR(ENOMEM);
62
+
63
+    pic_ctx->bitstream = tmp;
64
+
65
+    AV_WB32(pic_ctx->bitstream+pic_ctx->bitstream_size, size);
66
+    memcpy(pic_ctx->bitstream+pic_ctx->bitstream_size+4, buffer, size);
67
+
68
+    pic_ctx->bitstream_size += size + 4;
69
+
70
+    return 0;
71
+}
72
+
73
+static int end_frame(AVCodecContext *avctx)
74
+{
75
+    H264Context *h = avctx->priv_data;
76
+    struct vda_context *vda_ctx = avctx->hwaccel_context;
77
+    struct vda_picture_context *pic_ctx = h->s.current_picture_ptr->f.hwaccel_picture_private;
78
+    AVFrame *frame = (AVFrame*)h->s.current_picture_ptr;
79
+    int status;
80
+
81
+    if (!vda_ctx->decoder || !pic_ctx->bitstream)
82
+        return -1;
83
+
84
+    status = ff_vda_decoder_decode(vda_ctx, pic_ctx->bitstream,
85
+                                   pic_ctx->bitstream_size,
86
+                                   frame->reordered_opaque);
87
+
88
+    if (status)
89
+        av_log(avctx, AV_LOG_ERROR, "Failed to decode frame (%d)\n", status);
90
+
91
+    av_freep(&pic_ctx->bitstream);
92
+
93
+    return status;
94
+}
95
+
96
+AVHWAccel ff_h264_vda_hwaccel = {
97
+    .name           = "h264_vda",
98
+    .type           = AVMEDIA_TYPE_VIDEO,
99
+    .id             = CODEC_ID_H264,
100
+    .pix_fmt        = PIX_FMT_VDA_VLD,
101
+    .capabilities   = 0,
102
+    .start_frame    = start_frame,
103
+    .decode_slice   = decode_slice,
104
+    .end_frame      = end_frame,
105
+    .priv_data_size = sizeof(struct vda_picture_context),
106
+};
0 107
new file mode 100644
... ...
@@ -0,0 +1,50 @@
0
+/*
1
+ * VDA HW acceleration
2
+ *
3
+ * copyright (c) 2011 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_VDA_INTERNAL_H
23
+#define AVCODEC_VDA_INTERNAL_H
24
+
25
+#include "h264.h"
26
+#include "h264data.h"
27
+
28
+#include "vda.h"
29
+
30
+#include <CoreFoundation/CFDictionary.h>
31
+#include <CoreFoundation/CFNumber.h>
32
+#include <CoreFoundation/CFData.h>
33
+#include <CoreFoundation/CFString.h>
34
+
35
+/**
36
+ * \addtogroup VDA_Decoding
37
+ *
38
+ * @{
39
+ */
40
+
41
+/** Send a frame data to the hardware decoder. */
42
+int ff_vda_decoder_decode(struct vda_context *vda_ctx,
43
+                          uint8_t *bitstream,
44
+                          int bitstream_size,
45
+                          int64_t frame_pts);
46
+
47
+/* @} */
48
+
49
+#endif /* AVCODEC_VDA_INTERNAL_H */
... ...
@@ -21,7 +21,7 @@
21 21
 #define AVCODEC_VERSION_H
22 22
 
23 23
 #define LIBAVCODEC_VERSION_MAJOR 53
24
-#define LIBAVCODEC_VERSION_MINOR 26
24
+#define LIBAVCODEC_VERSION_MINOR 27
25 25
 #define LIBAVCODEC_VERSION_MICRO  0
26 26
 
27 27
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
... ...
@@ -40,7 +40,7 @@
40 40
 #define AV_VERSION(a, b, c) AV_VERSION_DOT(a, b, c)
41 41
 
42 42
 #define LIBAVUTIL_VERSION_MAJOR 51
43
-#define LIBAVUTIL_VERSION_MINOR 22
43
+#define LIBAVUTIL_VERSION_MINOR 23
44 44
 #define LIBAVUTIL_VERSION_MICRO  0
45 45
 
46 46
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
... ...
@@ -1003,6 +1003,12 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = {
1003 1003
         .log2_chroma_h = 1,
1004 1004
         .flags = PIX_FMT_HWACCEL,
1005 1005
     },
1006
+    [PIX_FMT_VDA_VLD] = {
1007
+        .name = "vda_vld",
1008
+        .log2_chroma_w = 1,
1009
+        .log2_chroma_h = 1,
1010
+        .flags = PIX_FMT_HWACCEL,
1011
+    },
1006 1012
     [PIX_FMT_GRAY8A] = {
1007 1013
         .name = "gray8a",
1008 1014
         .nb_components= 2,
... ...
@@ -158,6 +158,8 @@ enum PixelFormat {
158 158
     PIX_FMT_BGRA64LE,  ///< packed RGBA 16:16:16:16, 64bpp, 16B, 16G, 16R, 16A, the 2-byte value for each R/G/B/A component is stored as little-endian
159 159
     PIX_FMT_GBR24P,    ///< planar GBR, 24bpp, 8G, 8B, 8R.
160 160
 
161
+    PIX_FMT_VDA_VLD,   ///< HW decoding through VDA.
162
+
161 163
     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
162 164
 };
163 165