1 /*
2 * VDA H264 HW acceleration.
3 *
4 * copyright (c) 2011 Sebastien Zwickert
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #include <CoreFoundation/CFDictionary.h>
24 #include <CoreFoundation/CFNumber.h>
25 #include <CoreFoundation/CFData.h>
26
30
33 };
36
38 // The current bitstream buffer.
40
41 // The current size of the bitstream.
43
44 // The reference size used for fast reallocation.
46
49
50 /* Decoder callback that adds the vda frame to the queue in display order. */
52 CFDictionaryRef user_info,
53 OSStatus status,
54 uint32_t infoFlags,
55 CVImageBufferRef image_buffer)
56 {
58
61
62 if (!image_buffer)
63 return;
64
65 if (vda_ctx->
cv_pix_fmt_type != CVPixelBufferGetPixelFormatType(image_buffer))
66 return;
67
68 vda_ctx->
cv_buffer = CVPixelBufferRetain(image_buffer);
69 }
70
72 {
73 OSStatus status;
74 CFDataRef coded_frame;
75 uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
76
77 coded_frame = CFDataCreate(kCFAllocatorDefault,
80
81 status = VDADecoderDecode(vda_ctx->
decoder, 0, coded_frame,
NULL);
82
83 if (kVDADecoderNoErr == status)
84 status = VDADecoderFlush(vda_ctx->
decoder, flush_flags);
85
86 CFRelease(coded_frame);
87
88 return status;
89 }
90
91
95 {
98
100 return -1;
101
103
104 return 0;
105 }
106
110 {
113 void *tmp;
114
116 return -1;
117
121 if (!tmp)
123
125
128
130
131 return 0;
132 }
133
135 {
137 CVPixelBufferRelease(context->
cv_buffer);
139 }
140
142 {
149 int status;
150
152 return -1;
153
156
159
161 return status;
162
165 if (!context || !buffer) {
166 CVPixelBufferRelease(vda_ctx->
cv_buffer);
168 return -1;
169 }
170
173
174 return status;
175 }
176
179 int extradata_size)
180 {
181 OSStatus status;
184 CFNumberRef format;
185 CFDataRef avc_data;
186 CFMutableDictionaryRef config_info;
187 CFMutableDictionaryRef buffer_attributes;
188 CFMutableDictionaryRef io_surface_properties;
189 CFNumberRef cv_pix_fmt;
190
193
194 /* Each VCL NAL in the bitstream sent to the decoder
195 * is preceded by a 4 bytes length header.
196 * Change the avcC atom header if needed, to signal headers of 4 bytes. */
197 if (extradata_size >= 4 && (extradata[4] & 0x03) != 0x03) {
199
200 if (!(rw_extradata =
av_malloc(extradata_size)))
202
203 memcpy(rw_extradata, extradata, extradata_size);
204
205 rw_extradata[4] |= 0x03;
206
207 avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, extradata_size);
208
210 } else {
211 avc_data = CFDataCreate(kCFAllocatorDefault, extradata, extradata_size);
212 }
213
214 config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
215 4,
216 &kCFTypeDictionaryKeyCallBacks,
217 &kCFTypeDictionaryValueCallBacks);
218
219 height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->
height);
220 width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->
width);
221 format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &vda_ctx->
format);
222
223 CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
224 CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
225 CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
226 CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
227
228 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
229 2,
230 &kCFTypeDictionaryKeyCallBacks,
231 &kCFTypeDictionaryValueCallBacks);
232 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
233 0,
234 &kCFTypeDictionaryKeyCallBacks,
235 &kCFTypeDictionaryValueCallBacks);
236 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault,
237 kCFNumberSInt32Type,
239 CFDictionarySetValue(buffer_attributes,
240 kCVPixelBufferPixelFormatTypeKey,
241 cv_pix_fmt);
242 CFDictionarySetValue(buffer_attributes,
243 kCVPixelBufferIOSurfacePropertiesKey,
244 io_surface_properties);
245
246 status = VDADecoderCreate(config_info,
247 buffer_attributes,
249 vda_ctx,
251
252 CFRelease(height);
253 CFRelease(width);
254 CFRelease(format);
255 CFRelease(avc_data);
256 CFRelease(config_info);
257 CFRelease(io_surface_properties);
258 CFRelease(cv_pix_fmt);
259 CFRelease(buffer_attributes);
260
261 return status;
262 }
263
265 {
266 OSStatus status = kVDADecoderNoErr;
267
269 status = VDADecoderDestroy(vda_ctx->
decoder);
270
271 return status;
272 }
273
275 {
277 if (vda) {
280 CVPixelBufferRelease(vda->
frame);
281 }
282 return 0;
283 }
284
295 };
296
298 CFDictionaryRef user_info,
299 OSStatus status,
300 uint32_t infoFlags,
301 CVImageBufferRef image_buffer)
302 {
305
306
308 CVPixelBufferRelease(vda->
frame);
310 }
311
312 if (!image_buffer)
313 return;
314
315 vda->
frame = CVPixelBufferRetain(image_buffer);
316 }
317
321 {
323
325
326 return 0;
327 }
328
332 {
334 void *tmp;
335
339 if (!tmp)
341
343
346
348
349 return 0;
350 }
351
353 {
354 CVImageBufferRef
frame = (CVImageBufferRef)data;
355 CVPixelBufferRelease(frame);
356 }
357
359 {
364 uint32_t flush_flags = 1 << 0; ///< kVDADecoderFlush_emitFrames
365 CFDataRef coded_frame;
366 OSStatus status;
367
370
371
372 coded_frame = CFDataCreate(kCFAllocatorDefault,
375
376 status = VDADecoderDecode(vda_ctx->
decoder, 0, coded_frame,
NULL);
377
378 if (status == kVDADecoderNoErr)
379 status = VDADecoderFlush(vda_ctx->
decoder, flush_flags);
380
381 CFRelease(coded_frame);
382
385
386 if (status != kVDADecoderNoErr) {
389 }
390
392
399
402
403 return 0;
404 }
405
407 {
409 OSStatus status = kVDADecoderNoErr;
412 CFNumberRef format;
413 CFDataRef avc_data;
414 CFMutableDictionaryRef config_info;
415 CFMutableDictionaryRef buffer_attributes;
416 CFMutableDictionaryRef io_surface_properties;
417 CFNumberRef cv_pix_fmt;
419
420 // kCVPixelFormatType_420YpCbCr8Planar;
421
422 /* Each VCL NAL in the bitstream sent to the decoder
423 * is preceded by a 4 bytes length header.
424 * Change the avcC atom header if needed, to signal headers of 4 bytes. */
427
430
432
433 rw_extradata[4] |= 0x03;
434
435 avc_data = CFDataCreate(kCFAllocatorDefault, rw_extradata, avctx->
extradata_size);
436
438 } else {
439 avc_data = CFDataCreate(kCFAllocatorDefault,
441 }
442
443 config_info = CFDictionaryCreateMutable(kCFAllocatorDefault,
444 4,
445 &kCFTypeDictionaryKeyCallBacks,
446 &kCFTypeDictionaryValueCallBacks);
447
448 height = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->
height);
449 width = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &avctx->
width);
450 format = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &fmt);
451 CFDictionarySetValue(config_info, kVDADecoderConfiguration_Height, height);
452 CFDictionarySetValue(config_info, kVDADecoderConfiguration_Width, width);
453 CFDictionarySetValue(config_info, kVDADecoderConfiguration_avcCData, avc_data);
454 CFDictionarySetValue(config_info, kVDADecoderConfiguration_SourceFormat, format);
455
456 buffer_attributes = CFDictionaryCreateMutable(kCFAllocatorDefault,
457 2,
458 &kCFTypeDictionaryKeyCallBacks,
459 &kCFTypeDictionaryValueCallBacks);
460 io_surface_properties = CFDictionaryCreateMutable(kCFAllocatorDefault,
461 0,
462 &kCFTypeDictionaryKeyCallBacks,
463 &kCFTypeDictionaryValueCallBacks);
464 cv_pix_fmt = CFNumberCreate(kCFAllocatorDefault,
465 kCFNumberSInt32Type,
467
468 CFDictionarySetValue(buffer_attributes,
469 kCVPixelBufferPixelFormatTypeKey,
470 cv_pix_fmt);
471 CFDictionarySetValue(buffer_attributes,
472 kCVPixelBufferIOSurfacePropertiesKey,
473 io_surface_properties);
474
475 status = VDADecoderCreate(config_info,
476 buffer_attributes,
478 avctx,
480
481 CFRelease(format);
482 CFRelease(height);
483 CFRelease(width);
484 CFRelease(avc_data);
485 CFRelease(config_info);
486 CFRelease(cv_pix_fmt);
487 CFRelease(io_surface_properties);
488 CFRelease(buffer_attributes);
489
490 if (status != kVDADecoderNoErr) {
492 }
493
494 switch (status) {
495 case kVDADecoderHardwareNotSupportedErr:
496 case kVDADecoderFormatNotSupportedErr:
498 case kVDADecoderConfigurationError:
500 case kVDADecoderDecoderFailedErr:
502 case kVDADecoderNoErr:
503 return 0;
504 default:
506 }
507 }
508
510 {
515
518 return 0;
519 }
520
532 };