2 * VDA H264 HW acceleration.
4 * copyright (c) 2011 Sebastien Zwickert
6 * This file is part of FFmpeg.
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.
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.
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
23 #include <CoreFoundation/CFDictionary.h>
24 #include <CoreFoundation/CFNumber.h>
25 #include <CoreFoundation/CFData.h>
28 #include "libavutil/avutil.h"
32 CVPixelBufferRef cv_buffer
;
35 #include "vda_internal.h"
37 typedef struct VDAContext
{
38 // The current bitstream buffer.
41 // The current size of the bitstream.
44 // The reference size used for fast reallocation.
47 CVImageBufferRef frame
;
50 /* Decoder callback that adds the vda frame to the queue in display order. */
51 static void vda_decoder_callback(void *vda_hw_ctx
,
52 CFDictionaryRef user_info
,
55 CVImageBufferRef image_buffer
)
57 struct vda_context
*vda_ctx
= vda_hw_ctx
;
59 if (infoFlags
& kVDADecodeInfo_FrameDropped
)
60 vda_ctx
->cv_buffer
= NULL
;
65 if (vda_ctx
->cv_pix_fmt_type
!= CVPixelBufferGetPixelFormatType(image_buffer
))
68 vda_ctx
->cv_buffer
= CVPixelBufferRetain(image_buffer
);
71 static int vda_sync_decode(VDAContext
*ctx
, struct vda_context
*vda_ctx
)
74 CFDataRef coded_frame
;
75 uint32_t flush_flags
= 1 << 0; ///< kVDADecoderFlush_emitFrames
77 coded_frame
= CFDataCreate(kCFAllocatorDefault
,
81 status
= VDADecoderDecode(vda_ctx
->decoder
, 0, coded_frame
, NULL
);
83 if (kVDADecoderNoErr
== status
)
84 status
= VDADecoderFlush(vda_ctx
->decoder
, flush_flags
);
86 CFRelease(coded_frame
);
92 static int vda_old_h264_start_frame(AVCodecContext
*avctx
,
93 av_unused
const uint8_t *buffer
,
94 av_unused
uint32_t size
)
96 VDAContext
*vda
= avctx
->internal
->hwaccel_priv_data
;
97 struct vda_context
*vda_ctx
= avctx
->hwaccel_context
;
99 if (!vda_ctx
->decoder
)
102 vda
->bitstream_size
= 0;
107 static int vda_old_h264_decode_slice(AVCodecContext
*avctx
,
108 const uint8_t *buffer
,
111 VDAContext
*vda
= avctx
->internal
->hwaccel_priv_data
;
112 struct vda_context
*vda_ctx
= avctx
->hwaccel_context
;
115 if (!vda_ctx
->decoder
)
118 tmp
= av_fast_realloc(vda
->bitstream
,
119 &vda
->allocated_size
,
120 vda
->bitstream_size
+ size
+ 4);
122 return AVERROR(ENOMEM
);
124 vda
->bitstream
= tmp
;
126 AV_WB32(vda
->bitstream
+ vda
->bitstream_size
, size
);
127 memcpy(vda
->bitstream
+ vda
->bitstream_size
+ 4, buffer
, size
);
129 vda
->bitstream_size
+= size
+ 4;
134 static void vda_h264_release_buffer(void *opaque
, uint8_t *data
)
136 struct vda_buffer
*context
= opaque
;
137 CVPixelBufferRelease(context
->cv_buffer
);
141 static int vda_old_h264_end_frame(AVCodecContext
*avctx
)
143 H264Context
*h
= avctx
->priv_data
;
144 VDAContext
*vda
= avctx
->internal
->hwaccel_priv_data
;
145 struct vda_context
*vda_ctx
= avctx
->hwaccel_context
;
146 AVFrame
*frame
= &h
->cur_pic_ptr
->f
;
147 struct vda_buffer
*context
;
151 if (!vda_ctx
->decoder
|| !vda
->bitstream
)
154 status
= vda_sync_decode(vda
, vda_ctx
);
155 frame
->data
[3] = (void*)vda_ctx
->cv_buffer
;
158 av_log(avctx
, AV_LOG_ERROR
, "Failed to decode frame (%d)\n", status
);
160 if (!vda_ctx
->use_ref_buffer
|| status
)
163 context
= av_mallocz(sizeof(*context
));
164 buffer
= av_buffer_create(NULL
, 0, vda_h264_release_buffer
, context
, 0);
165 if (!context
|| !buffer
) {
166 CVPixelBufferRelease(vda_ctx
->cv_buffer
);
171 context
->cv_buffer
= vda_ctx
->cv_buffer
;
172 frame
->buf
[3] = buffer
;
177 int ff_vda_create_decoder(struct vda_context
*vda_ctx
,
186 CFMutableDictionaryRef config_info
;
187 CFMutableDictionaryRef buffer_attributes
;
188 CFMutableDictionaryRef io_surface_properties
;
189 CFNumberRef cv_pix_fmt
;
191 vda_ctx
->priv_bitstream
= NULL
;
192 vda_ctx
->priv_allocated_size
= 0;
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) {
198 uint8_t *rw_extradata
;
200 if (!(rw_extradata
= av_malloc(extradata_size
)))
201 return AVERROR(ENOMEM
);
203 memcpy(rw_extradata
, extradata
, extradata_size
);
205 rw_extradata
[4] |= 0x03;
207 avc_data
= CFDataCreate(kCFAllocatorDefault
, rw_extradata
, extradata_size
);
209 av_freep(&rw_extradata
);
211 avc_data
= CFDataCreate(kCFAllocatorDefault
, extradata
, extradata_size
);
214 config_info
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
216 &kCFTypeDictionaryKeyCallBacks
,
217 &kCFTypeDictionaryValueCallBacks
);
219 height
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &vda_ctx
->height
);
220 width
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &vda_ctx
->width
);
221 format
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &vda_ctx
->format
);
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
);
228 buffer_attributes
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
230 &kCFTypeDictionaryKeyCallBacks
,
231 &kCFTypeDictionaryValueCallBacks
);
232 io_surface_properties
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
234 &kCFTypeDictionaryKeyCallBacks
,
235 &kCFTypeDictionaryValueCallBacks
);
236 cv_pix_fmt
= CFNumberCreate(kCFAllocatorDefault
,
238 &vda_ctx
->cv_pix_fmt_type
);
239 CFDictionarySetValue(buffer_attributes
,
240 kCVPixelBufferPixelFormatTypeKey
,
242 CFDictionarySetValue(buffer_attributes
,
243 kCVPixelBufferIOSurfacePropertiesKey
,
244 io_surface_properties
);
246 status
= VDADecoderCreate(config_info
,
248 (VDADecoderOutputCallback
*)vda_decoder_callback
,
256 CFRelease(config_info
);
257 CFRelease(io_surface_properties
);
258 CFRelease(cv_pix_fmt
);
259 CFRelease(buffer_attributes
);
264 int ff_vda_destroy_decoder(struct vda_context
*vda_ctx
)
266 OSStatus status
= kVDADecoderNoErr
;
268 if (vda_ctx
->decoder
)
269 status
= VDADecoderDestroy(vda_ctx
->decoder
);
274 static int vda_h264_uninit(AVCodecContext
*avctx
)
276 VDAContext
*vda
= avctx
->internal
->hwaccel_priv_data
;
278 av_freep(&vda
->bitstream
);
280 CVPixelBufferRelease(vda
->frame
);
285 AVHWAccel ff_h264_vda_old_hwaccel
= {
287 .type
= AVMEDIA_TYPE_VIDEO
,
288 .id
= AV_CODEC_ID_H264
,
289 .pix_fmt
= AV_PIX_FMT_VDA_VLD
,
290 .start_frame
= vda_old_h264_start_frame
,
291 .decode_slice
= vda_old_h264_decode_slice
,
292 .end_frame
= vda_old_h264_end_frame
,
293 .uninit
= vda_h264_uninit
,
294 .priv_data_size
= sizeof(VDAContext
),
297 void ff_vda_output_callback(void *opaque
,
298 CFDictionaryRef user_info
,
301 CVImageBufferRef image_buffer
)
303 AVCodecContext
*ctx
= opaque
;
304 VDAContext
*vda
= ctx
->internal
->hwaccel_priv_data
;
308 CVPixelBufferRelease(vda
->frame
);
315 vda
->frame
= CVPixelBufferRetain(image_buffer
);
318 static int vda_h264_start_frame(AVCodecContext
*avctx
,
319 const uint8_t *buffer
,
322 VDAContext
*vda
= avctx
->internal
->hwaccel_priv_data
;
324 vda
->bitstream_size
= 0;
329 static int vda_h264_decode_slice(AVCodecContext
*avctx
,
330 const uint8_t *buffer
,
333 VDAContext
*vda
= avctx
->internal
->hwaccel_priv_data
;
336 tmp
= av_fast_realloc(vda
->bitstream
,
337 &vda
->allocated_size
,
338 vda
->bitstream_size
+ size
+ 4);
340 return AVERROR(ENOMEM
);
342 vda
->bitstream
= tmp
;
344 AV_WB32(vda
->bitstream
+ vda
->bitstream_size
, size
);
345 memcpy(vda
->bitstream
+ vda
->bitstream_size
+ 4, buffer
, size
);
347 vda
->bitstream_size
+= size
+ 4;
352 static void release_buffer(void *opaque
, uint8_t *data
)
354 CVImageBufferRef frame
= (CVImageBufferRef
)data
;
355 CVPixelBufferRelease(frame
);
358 static int vda_h264_end_frame(AVCodecContext
*avctx
)
360 H264Context
*h
= avctx
->priv_data
;
361 VDAContext
*vda
= avctx
->internal
->hwaccel_priv_data
;
362 AVVDAContext
*vda_ctx
= avctx
->hwaccel_context
;
363 AVFrame
*frame
= &h
->cur_pic_ptr
->f
;
364 uint32_t flush_flags
= 1 << 0; ///< kVDADecoderFlush_emitFrames
365 CFDataRef coded_frame
;
368 if (!vda
->bitstream_size
)
369 return AVERROR_INVALIDDATA
;
372 coded_frame
= CFDataCreate(kCFAllocatorDefault
,
374 vda
->bitstream_size
);
376 status
= VDADecoderDecode(vda_ctx
->decoder
, 0, coded_frame
, NULL
);
378 if (status
== kVDADecoderNoErr
)
379 status
= VDADecoderFlush(vda_ctx
->decoder
, flush_flags
);
381 CFRelease(coded_frame
);
383 if (status
!= kVDADecoderNoErr
) {
384 av_log(avctx
, AV_LOG_ERROR
, "Failed to decode frame (%d)\n", status
);
385 return AVERROR_UNKNOWN
;
389 av_buffer_unref(&frame
->buf
[0]);
391 frame
->buf
[0] = av_buffer_create((uint8_t*)vda
->frame
,
393 release_buffer
, NULL
,
394 AV_BUFFER_FLAG_READONLY
);
396 return AVERROR(ENOMEM
);
398 frame
->data
[3] = (uint8_t*)vda
->frame
;
405 int ff_vda_default_init(AVCodecContext
*avctx
)
407 AVVDAContext
*vda_ctx
= avctx
->hwaccel_context
;
408 OSStatus status
= kVDADecoderNoErr
;
413 CFMutableDictionaryRef config_info
;
414 CFMutableDictionaryRef buffer_attributes
;
415 CFMutableDictionaryRef io_surface_properties
;
416 CFNumberRef cv_pix_fmt
;
417 int32_t fmt
= 'avc1', pix_fmt
= kCVPixelFormatType_422YpCbCr8
;
419 // kCVPixelFormatType_420YpCbCr8Planar;
421 /* Each VCL NAL in the bitstream sent to the decoder
422 * is preceded by a 4 bytes length header.
423 * Change the avcC atom header if needed, to signal headers of 4 bytes. */
424 if (avctx
->extradata_size
>= 4 && (avctx
->extradata
[4] & 0x03) != 0x03) {
425 uint8_t *rw_extradata
;
427 if (!(rw_extradata
= av_malloc(avctx
->extradata_size
)))
428 return AVERROR(ENOMEM
);
430 memcpy(rw_extradata
, avctx
->extradata
, avctx
->extradata_size
);
432 rw_extradata
[4] |= 0x03;
434 avc_data
= CFDataCreate(kCFAllocatorDefault
, rw_extradata
, avctx
->extradata_size
);
436 av_freep(&rw_extradata
);
438 avc_data
= CFDataCreate(kCFAllocatorDefault
,
439 avctx
->extradata
, avctx
->extradata_size
);
442 config_info
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
444 &kCFTypeDictionaryKeyCallBacks
,
445 &kCFTypeDictionaryValueCallBacks
);
447 height
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &avctx
->height
);
448 width
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &avctx
->width
);
449 format
= CFNumberCreate(kCFAllocatorDefault
, kCFNumberSInt32Type
, &fmt
);
450 CFDictionarySetValue(config_info
, kVDADecoderConfiguration_Height
, height
);
451 CFDictionarySetValue(config_info
, kVDADecoderConfiguration_Width
, width
);
452 CFDictionarySetValue(config_info
, kVDADecoderConfiguration_avcCData
, avc_data
);
453 CFDictionarySetValue(config_info
, kVDADecoderConfiguration_SourceFormat
, format
);
455 buffer_attributes
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
457 &kCFTypeDictionaryKeyCallBacks
,
458 &kCFTypeDictionaryValueCallBacks
);
459 io_surface_properties
= CFDictionaryCreateMutable(kCFAllocatorDefault
,
461 &kCFTypeDictionaryKeyCallBacks
,
462 &kCFTypeDictionaryValueCallBacks
);
463 cv_pix_fmt
= CFNumberCreate(kCFAllocatorDefault
,
467 CFDictionarySetValue(buffer_attributes
,
468 kCVPixelBufferPixelFormatTypeKey
,
470 CFDictionarySetValue(buffer_attributes
,
471 kCVPixelBufferIOSurfacePropertiesKey
,
472 io_surface_properties
);
474 status
= VDADecoderCreate(config_info
,
476 (VDADecoderOutputCallback
*)ff_vda_output_callback
,
484 CFRelease(config_info
);
485 CFRelease(cv_pix_fmt
);
486 CFRelease(io_surface_properties
);
487 CFRelease(buffer_attributes
);
489 if (status
!= kVDADecoderNoErr
) {
490 av_log(avctx
, AV_LOG_ERROR
, "Cannot initialize VDA %d\n", status
);
494 case kVDADecoderHardwareNotSupportedErr
:
495 case kVDADecoderFormatNotSupportedErr
:
496 return AVERROR(ENOSYS
);
497 case kVDADecoderConfigurationError
:
498 return AVERROR(EINVAL
);
499 case kVDADecoderDecoderFailedErr
:
500 return AVERROR_INVALIDDATA
;
501 case kVDADecoderNoErr
:
504 return AVERROR_UNKNOWN
;
508 static int vda_h264_alloc_frame(AVCodecContext
*avctx
, AVFrame
*frame
)
510 frame
->width
= avctx
->width
;
511 frame
->height
= avctx
->height
;
512 frame
->format
= avctx
->pix_fmt
;
513 frame
->buf
[0] = av_buffer_alloc(1);
516 return AVERROR(ENOMEM
);
520 AVHWAccel ff_h264_vda_hwaccel
= {
522 .type
= AVMEDIA_TYPE_VIDEO
,
523 .id
= AV_CODEC_ID_H264
,
524 .pix_fmt
= AV_PIX_FMT_VDA
,
525 .alloc_frame
= vda_h264_alloc_frame
,
526 .start_frame
= vda_h264_start_frame
,
527 .decode_slice
= vda_h264_decode_slice
,
528 .end_frame
= vda_h264_end_frame
,
529 .uninit
= vda_h264_uninit
,
530 .priv_data_size
= sizeof(VDAContext
),