2 * Copyright (C) 2005-2010 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #if (defined HAVE_CONFIG_H) && (!defined WIN32)
26 #if defined(HAVE_LIBVDADECODER)
27 #include "DynamicDll.h"
28 #include "settings/GUISettings.h"
30 #include "DVDStreamInfo.h"
31 #include "cores/dvdplayer/DVDCodecs/DVDCodecUtils.h"
32 #include "DVDVideoCodecVDA.h"
33 #include "DllAvFormat.h"
34 #include "DllSwScale.h"
35 #include "utils/log.h"
36 #include "utils/TimeUtils.h"
37 #include "osx/CocoaInterface.h"
38 #include <CoreFoundation/CoreFoundation.h>
41 * if extradata size is greater than 7, then have a valid quicktime
44 * -: avcC atom header :-
45 * -----------------------------------
47 * 1 byte - h.264 stream profile
48 * 1 byte - h.264 compatible profiles
49 * 1 byte - h.264 stream level
50 * 6 bits - reserved set to 63
52 * ( 0 - 1 byte; 1 - 2 bytes; 3 - 4 bytes)
54 * 5 bits - number of SPS
55 * for (i=0; i < number of SPS; i++) {
56 * 2 bytes - SPS length
57 * SPS length bytes - SPS NAL unit
59 * 1 byte - number of PPS
60 * for (i=0; i < number of PPS; i++) {
61 * 2 bytes - PPS length
62 * PPS length bytes - PPS NAL unit
65 how to detect the interlacing used on an existing stream:
66 - progressive is signalled by setting
67 frame_mbs_only_flag: 1 in the SPS.
68 - interlaced is signalled by setting
69 frame_mbs_only_flag: 0 in the SPS and
70 field_pic_flag: 1 on all frames.
71 - paff is signalled by setting
72 frame_mbs_only_flag: 0 in the SPS and
73 field_pic_flag: 1 on all frames that get interlaced and
74 field_pic_flag: 0 on all frames that get progressive.
75 - mbaff is signalled by setting
76 frame_mbs_only_flag: 0 in the SPS and
77 mb_adaptive_frame_field_flag: 1 in the SPS and
78 field_pic_flag: 0 on the frames,
79 (field_pic_flag: 1 would indicate a normal interlaced frame).
82 // missing in 10.4/10.5 SDKs.
83 #if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060)
86 // component Y'CbCr 8-bit 4:2:2, ordered Cb Y'0 Cr Y'1 .
87 kCVPixelFormatType_422YpCbCr8 = FourCharCode('2vuy'),
88 kCVPixelFormatType_32BGRA = FourCharCode('BGRA')
92 ////////////////////////////////////////////////////////////////////////////////////////////
93 // http://developer.apple.com/mac/library/technotes/tn2010/tn2267.html
94 // VDADecoder API (keep this until VDADecoder.h is public).
95 // #include <VideoDecodeAcceleration/VDADecoder.h>
98 kVDADecoderHardwareNotSupportedErr = -12470,
99 kVDADecoderFormatNotSupportedErr = -12471,
100 kVDADecoderConfigurationError = -12472,
101 kVDADecoderDecoderFailedErr = -12473,
104 kVDADecodeInfo_Asynchronous = 1UL << 0,
105 kVDADecodeInfo_FrameDropped = 1UL << 1
108 // tells the decoder not to bother returning a CVPixelBuffer
109 // in the outputCallback. The output callback will still be called.
110 kVDADecoderDecodeFlags_DontEmitFrame = 1 << 0
113 // decode and return buffers for all frames currently in flight.
114 kVDADecoderFlush_EmitFrames = 1 << 0
117 typedef struct OpaqueVDADecoder* VDADecoder;
119 typedef void (*VDADecoderOutputCallback)(
120 void *decompressionOutputRefCon,
121 CFDictionaryRef frameInfo,
124 CVImageBufferRef imageBuffer);
126 ////////////////////////////////////////////////////////////////////////////////////////////
127 class DllLibVDADecoderInterface
130 virtual ~DllLibVDADecoderInterface() {}
131 virtual OSStatus VDADecoderCreate(
132 CFDictionaryRef decoderConfiguration, CFDictionaryRef destinationImageBufferAttributes,
133 VDADecoderOutputCallback *outputCallback, void *decoderOutputCallbackRefcon, VDADecoder *decoderOut) = 0;
134 virtual OSStatus VDADecoderDecode(
135 VDADecoder decoder, uint32_t decodeFlags, CFTypeRef compressedBuffer, CFDictionaryRef frameInfo) = 0;
136 virtual OSStatus VDADecoderFlush(VDADecoder decoder, uint32_t flushFlags) = 0;
137 virtual OSStatus VDADecoderDestroy(VDADecoder decoder) = 0;
138 virtual CFStringRef Get_kVDADecoderConfiguration_Height() = 0;
139 virtual CFStringRef Get_kVDADecoderConfiguration_Width() = 0;
140 virtual CFStringRef Get_kVDADecoderConfiguration_SourceFormat() = 0;
141 virtual CFStringRef Get_kVDADecoderConfiguration_avcCData() = 0;
144 class DllLibVDADecoder : public DllDynamic, DllLibVDADecoderInterface
146 DECLARE_DLL_WRAPPER(DllLibVDADecoder, DLL_PATH_LIBVDADECODER)
148 DEFINE_METHOD5(OSStatus, VDADecoderCreate, (CFDictionaryRef p1, CFDictionaryRef p2, VDADecoderOutputCallback* p3, void* p4, VDADecoder* p5))
149 DEFINE_METHOD4(OSStatus, VDADecoderDecode, (VDADecoder p1, uint32_t p2, CFTypeRef p3, CFDictionaryRef p4))
150 DEFINE_METHOD2(OSStatus, VDADecoderFlush, (VDADecoder p1, uint32_t p2))
151 DEFINE_METHOD1(OSStatus, VDADecoderDestroy, (VDADecoder p1))
152 DEFINE_GLOBAL(CFStringRef, kVDADecoderConfiguration_Height)
153 DEFINE_GLOBAL(CFStringRef, kVDADecoderConfiguration_Width)
154 DEFINE_GLOBAL(CFStringRef, kVDADecoderConfiguration_SourceFormat)
155 DEFINE_GLOBAL(CFStringRef, kVDADecoderConfiguration_avcCData)
156 BEGIN_METHOD_RESOLVE()
157 RESOLVE_METHOD(VDADecoderCreate)
158 RESOLVE_METHOD(VDADecoderDecode)
159 RESOLVE_METHOD(VDADecoderFlush)
160 RESOLVE_METHOD(VDADecoderDestroy)
161 RESOLVE_METHOD(kVDADecoderConfiguration_Height)
162 RESOLVE_METHOD(kVDADecoderConfiguration_Width)
163 RESOLVE_METHOD(kVDADecoderConfiguration_SourceFormat)
164 RESOLVE_METHOD(kVDADecoderConfiguration_avcCData)
168 ////////////////////////////////////////////////////////////////////////////////////////////
169 // helper function that wraps dts/pts into a dictionary
170 static CFDictionaryRef CreateDictionaryWithDisplayTime(double time, double dts, double pts)
172 CFStringRef key[3] = {
173 CFSTR("VideoDisplay_TIME"),
174 CFSTR("VideoDisplay_DTS"),
175 CFSTR("VideoDisplay_PTS")};
176 CFNumberRef value[3];
177 CFDictionaryRef display_time;
179 value[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &time);
180 value[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &dts);
181 value[2] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &pts);
183 display_time = CFDictionaryCreate(
184 kCFAllocatorDefault, (const void **)&key, (const void **)&value, 3,
185 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
194 // helper function to extract dts/pts from a dictionary
195 static void GetFrameDisplayTimeFromDictionary(
196 CFDictionaryRef inFrameInfoDictionary, frame_queue *frame)
198 // default to DVD_NOPTS_VALUE
199 frame->sort_time = -1.0;
200 frame->dts = DVD_NOPTS_VALUE;
201 frame->pts = DVD_NOPTS_VALUE;
202 if (inFrameInfoDictionary == NULL)
205 CFNumberRef value[3];
207 value[0] = (CFNumberRef)CFDictionaryGetValue(inFrameInfoDictionary, CFSTR("VideoDisplay_TIME"));
209 CFNumberGetValue(value[0], kCFNumberDoubleType, &frame->sort_time);
210 value[1] = (CFNumberRef)CFDictionaryGetValue(inFrameInfoDictionary, CFSTR("VideoDisplay_DTS"));
212 CFNumberGetValue(value[1], kCFNumberDoubleType, &frame->dts);
213 value[2] = (CFNumberRef)CFDictionaryGetValue(inFrameInfoDictionary, CFSTR("VideoDisplay_PTS"));
215 CFNumberGetValue(value[2], kCFNumberDoubleType, &frame->pts);
220 ////////////////////////////////////////////////////////////////////////////////////////////
221 ////////////////////////////////////////////////////////////////////////////////////////////
222 // GStreamer h264 parser
223 // Copyright (C) 2005 Michal Benes <michal.benes@itonis.tv>
224 // (C) 2008 Wim Taymans <wim.taymans@gmail.com>
226 // * License as published by the Free Software Foundation; either
227 // * version 2.1 of the License, or (at your option) any later version.
237 nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size)
240 bs->end = data + size;
242 // fill with something other than 0 to detect
243 // emulation prevention bytes
244 bs->cache = 0xffffffff;
248 nal_bs_read(nal_bitstream *bs, int n)
256 // fill up the cache if we need to
260 bool check_three_byte;
262 check_three_byte = TRUE;
264 if (bs->data >= bs->end)
266 // we're at the end, can't produce more than head number of bits
270 // get the byte, this can be an emulation_prevention_three_byte that we need
272 a_byte = *bs->data++;
273 if (check_three_byte && a_byte == 0x03 && ((bs->cache & 0xffff) == 0))
275 // next byte goes unconditionally to the cache, even if it's 0x03
276 check_three_byte = FALSE;
279 // shift bytes in cache, moving the head bits of the cache left
280 bs->cache = (bs->cache << 8) | a_byte;
284 // bring the required bits down and truncate
285 if ((shift = bs->head - n) > 0)
286 res = bs->cache >> shift;
290 // mask out required bits
300 nal_bs_eos(nal_bitstream *bs)
302 return (bs->data >= bs->end) && (bs->head == 0);
305 // read unsigned Exp-Golomb code
307 nal_bs_read_ue(nal_bitstream *bs)
311 while (nal_bs_read(bs, 1) == 0 && !nal_bs_eos(bs) && i < 32)
314 return ((1 << i) - 1 + nal_bs_read(bs, i));
323 int chroma_format_idc;
324 int separate_colour_plane_flag;
325 int bit_depth_luma_minus8;
326 int bit_depth_chroma_minus8;
327 int qpprime_y_zero_transform_bypass_flag;
328 int seq_scaling_matrix_present_flag;
330 int log2_max_frame_num_minus4;
331 int pic_order_cnt_type;
332 int log2_max_pic_order_cnt_lsb_minus4;
334 int max_num_ref_frames;
335 int gaps_in_frame_num_value_allowed_flag;
336 int pic_width_in_mbs_minus1;
337 int pic_height_in_map_units_minus1;
339 int frame_mbs_only_flag;
340 int mb_adaptive_frame_field_flag;
342 int direct_8x8_inference_flag;
344 int frame_cropping_flag;
345 int frame_crop_left_offset;
346 int frame_crop_right_offset;
347 int frame_crop_top_offset;
348 int frame_crop_bottom_offset;
352 parseh264_sps(uint8_t *sps, uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames)
355 sps_info_struct sps_info;
357 nal_bs_init(&bs, sps, sps_size);
359 sps_info.profile_idc = nal_bs_read(&bs, 8);
360 nal_bs_read(&bs, 1); // constraint_set0_flag
361 nal_bs_read(&bs, 1); // constraint_set1_flag
362 nal_bs_read(&bs, 1); // constraint_set2_flag
363 nal_bs_read(&bs, 1); // constraint_set3_flag
364 nal_bs_read(&bs, 4); // reserved
365 sps_info.level_idc = nal_bs_read(&bs, 8);
366 sps_info.sps_id = nal_bs_read_ue(&bs);
368 if (sps_info.profile_idc == 100 ||
369 sps_info.profile_idc == 110 ||
370 sps_info.profile_idc == 122 ||
371 sps_info.profile_idc == 244 ||
372 sps_info.profile_idc == 44 ||
373 sps_info.profile_idc == 83 ||
374 sps_info.profile_idc == 86)
376 sps_info.chroma_format_idc = nal_bs_read_ue(&bs);
377 if (sps_info.chroma_format_idc == 3)
378 sps_info.separate_colour_plane_flag = nal_bs_read(&bs, 1);
379 sps_info.bit_depth_luma_minus8 = nal_bs_read_ue(&bs);
380 sps_info.bit_depth_chroma_minus8 = nal_bs_read_ue(&bs);
381 sps_info.qpprime_y_zero_transform_bypass_flag = nal_bs_read(&bs, 1);
383 sps_info.seq_scaling_matrix_present_flag = nal_bs_read (&bs, 1);
384 if (sps_info.seq_scaling_matrix_present_flag)
386 /* TODO: unfinished */
389 sps_info.log2_max_frame_num_minus4 = nal_bs_read_ue(&bs);
390 if (sps_info.log2_max_frame_num_minus4 > 12)
391 { // must be between 0 and 12
395 sps_info.pic_order_cnt_type = nal_bs_read_ue(&bs);
396 if (sps_info.pic_order_cnt_type == 0)
398 sps_info.log2_max_pic_order_cnt_lsb_minus4 = nal_bs_read_ue(&bs);
400 else if (sps_info.pic_order_cnt_type == 1)
401 { // TODO: unfinished
403 delta_pic_order_always_zero_flag = gst_nal_bs_read (bs, 1);
404 offset_for_non_ref_pic = gst_nal_bs_read_se (bs);
405 offset_for_top_to_bottom_field = gst_nal_bs_read_se (bs);
407 num_ref_frames_in_pic_order_cnt_cycle = gst_nal_bs_read_ue (bs);
408 for( i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++ )
409 offset_for_ref_frame[i] = gst_nal_bs_read_se (bs);
413 sps_info.max_num_ref_frames = nal_bs_read_ue(&bs);
414 sps_info.gaps_in_frame_num_value_allowed_flag = nal_bs_read(&bs, 1);
415 sps_info.pic_width_in_mbs_minus1 = nal_bs_read_ue(&bs);
416 sps_info.pic_height_in_map_units_minus1 = nal_bs_read_ue(&bs);
418 sps_info.frame_mbs_only_flag = nal_bs_read(&bs, 1);
419 if (!sps_info.frame_mbs_only_flag)
420 sps_info.mb_adaptive_frame_field_flag = nal_bs_read(&bs, 1);
422 sps_info.direct_8x8_inference_flag = nal_bs_read(&bs, 1);
424 sps_info.frame_cropping_flag = nal_bs_read(&bs, 1);
425 if (sps_info.frame_cropping_flag)
427 sps_info.frame_crop_left_offset = nal_bs_read_ue(&bs);
428 sps_info.frame_crop_right_offset = nal_bs_read_ue(&bs);
429 sps_info.frame_crop_top_offset = nal_bs_read_ue(&bs);
430 sps_info.frame_crop_bottom_offset = nal_bs_read_ue(&bs);
433 *interlaced = !sps_info.frame_mbs_only_flag;
434 *max_ref_frames = sps_info.max_num_ref_frames;
437 ////////////////////////////////////////////////////////////////////////////////////////////
438 // TODO: refactor this so as not to need these ffmpeg routines.
439 // These are not exposed in ffmpeg's API so we dupe them here.
440 // AVC helper functions for muxers,
441 // * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
442 // This is part of FFmpeg
443 // * License as published by the Free Software Foundation; either
444 // * version 2.1 of the License, or (at your option) any later version.
445 #define VDA_RB16(x) \
446 ((((const uint8_t*)(x))[0] << 8) | \
447 ((const uint8_t*)(x)) [1])
449 #define VDA_RB24(x) \
450 ((((const uint8_t*)(x))[0] << 16) | \
451 (((const uint8_t*)(x))[1] << 8) | \
452 ((const uint8_t*)(x))[2])
454 #define VDA_RB32(x) \
455 ((((const uint8_t*)(x))[0] << 24) | \
456 (((const uint8_t*)(x))[1] << 16) | \
457 (((const uint8_t*)(x))[2] << 8) | \
458 ((const uint8_t*)(x))[3])
460 #define VDA_WB32(p, d) { \
461 ((uint8_t*)(p))[3] = (d); \
462 ((uint8_t*)(p))[2] = (d) >> 8; \
463 ((uint8_t*)(p))[1] = (d) >> 16; \
464 ((uint8_t*)(p))[0] = (d) >> 24; }
466 static const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
468 const uint8_t *a = p + 4 - ((intptr_t)p & 3);
470 for (end -= 3; p < a && p < end; p++)
472 if (p[0] == 0 && p[1] == 0 && p[2] == 1)
476 for (end -= 3; p < end; p += 4)
478 uint32_t x = *(const uint32_t*)p;
479 if ((x - 0x01010101) & (~x) & 0x80808080) // generic
483 if (p[0] == 0 && p[2] == 1)
485 if (p[2] == 0 && p[3] == 1)
490 if (p[2] == 0 && p[4] == 1)
492 if (p[4] == 0 && p[5] == 1)
498 for (end += 3; p < end; p++)
500 if (p[0] == 0 && p[1] == 0 && p[2] == 1)
507 const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end)
509 const uint8_t *out= avc_find_startcode_internal(p, end);
510 if (p<out && out<end && !out[-1])
515 const int avc_parse_nal_units(DllAvFormat *av_format_ctx,
516 ByteIOContext *pb, const uint8_t *buf_in, int size)
518 const uint8_t *p = buf_in;
519 const uint8_t *end = p + size;
520 const uint8_t *nal_start, *nal_end;
523 nal_start = avc_find_startcode(p, end);
524 while (nal_start < end)
526 while (!*(nal_start++));
527 nal_end = avc_find_startcode(nal_start, end);
528 av_format_ctx->put_be32(pb, nal_end - nal_start);
529 av_format_ctx->put_buffer(pb, nal_start, nal_end - nal_start);
530 size += 4 + nal_end - nal_start;
536 const int avc_parse_nal_units_buf(DllAvUtil *av_util_ctx, DllAvFormat *av_format_ctx,
537 const uint8_t *buf_in, uint8_t **buf, int *size)
540 int ret = av_format_ctx->url_open_dyn_buf(&pb);
544 avc_parse_nal_units(av_format_ctx, pb, buf_in, *size);
546 av_util_ctx->av_freep(buf);
547 *size = av_format_ctx->url_close_dyn_buf(pb, buf);
551 const int isom_write_avcc(DllAvUtil *av_util_ctx, DllAvFormat *av_format_ctx,
552 ByteIOContext *pb, const uint8_t *data, int len)
554 // extradata from bytestream h264, convert to avcC atom data for bitstream
557 /* check for h264 start code */
558 if (VDA_RB32(data) == 0x00000001 || VDA_RB24(data) == 0x000001)
560 uint8_t *buf=NULL, *end, *start;
561 uint32_t sps_size=0, pps_size=0;
562 uint8_t *sps=0, *pps=0;
564 int ret = avc_parse_nal_units_buf(av_util_ctx, av_format_ctx, data, &buf, &len);
570 /* look for sps and pps */
575 size = VDA_RB32(buf);
576 nal_type = buf[4] & 0x1f;
577 if (nal_type == 7) /* SPS */
582 //parse_sps(sps+1, sps_size-1);
584 else if (nal_type == 8) /* PPS */
593 av_format_ctx->put_byte(pb, 1); /* version */
594 av_format_ctx->put_byte(pb, sps[1]); /* profile */
595 av_format_ctx->put_byte(pb, sps[2]); /* profile compat */
596 av_format_ctx->put_byte(pb, sps[3]); /* level */
597 av_format_ctx->put_byte(pb, 0xff); /* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
598 av_format_ctx->put_byte(pb, 0xe1); /* 3 bits reserved (111) + 5 bits number of sps (00001) */
600 av_format_ctx->put_be16(pb, sps_size);
601 av_format_ctx->put_buffer(pb, sps, sps_size);
604 av_format_ctx->put_byte(pb, 1); /* number of pps */
605 av_format_ctx->put_be16(pb, pps_size);
606 av_format_ctx->put_buffer(pb, pps, pps_size);
608 av_util_ctx->av_free(start);
612 av_format_ctx->put_buffer(pb, data, len);
619 static DllLibVDADecoder *g_DllLibVDADecoder = (DllLibVDADecoder*)-1;
620 ////////////////////////////////////////////////////////////////////////////////////////////
621 ////////////////////////////////////////////////////////////////////////////////////////////
622 CDVDVideoCodecVDA::CDVDVideoCodecVDA() : CDVDVideoCodec()
624 if (g_DllLibVDADecoder == (DllLibVDADecoder*)-1)
626 m_dll = new DllLibVDADecoder;
630 m_dll = g_DllLibVDADecoder;
632 m_vda_decoder = NULL;
633 m_pFormatName = "vda-";
636 m_display_queue = NULL;
637 pthread_mutex_init(&m_queue_mutex, NULL);
639 m_convert_bytestream = false;
640 m_convert_3byteTo4byteNALSize = false;
642 m_dllAvFormat = NULL;
644 memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
647 CDVDVideoCodecVDA::~CDVDVideoCodecVDA()
650 pthread_mutex_destroy(&m_queue_mutex);
654 bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
656 if (g_guiSettings.GetBool("videoplayer.usevda") && !hints.software)
659 int32_t width, height, profile, level;
661 uint8_t *extradata; // extra data for codec to use
662 unsigned int extrasize; // size of extra data
666 height = hints.height;
668 profile = hints.profile;
669 extrasize = hints.extrasize;
670 extradata = (uint8_t*)hints.extradata;
672 if (hints.profile == 77 && hints.level == 32)
674 // Main@L3.2, VDA cannot handle it
675 CLog::Log(LOGNOTICE, "%s - Main@L3.2 detected, VDA cannot decode.", __FUNCTION__);
679 if (Cocoa_GPUForDisplayIsNvidiaPureVideo3() && !CDVDCodecUtils::IsVP3CompatibleWidth(width))
681 CLog::Log(LOGNOTICE, "%s - Nvidia 9400 GPU hardware limitation, cannot decode a width of %d", __FUNCTION__, width);
688 // source must be H.264 with valid avcC atom data in extradata
689 if (extrasize < 7 || extradata == NULL)
691 CLog::Log(LOGNOTICE, "%s - avcC atom too data small or missing", __FUNCTION__);
694 // valid avcC atom data always starts with the value 1 (version)
695 if ( *extradata != 1 )
697 if (extradata[0] == 0 && extradata[1] == 0 && extradata[2] == 0 && extradata[3] == 1)
699 // video content is from x264 or from bytestream h264 (AnnexB format)
700 // NAL reformating to bitstream format needed
701 m_dllAvUtil = new DllAvUtil;
702 m_dllAvFormat = new DllAvFormat;
703 if (!m_dllAvUtil->Load() || !m_dllAvFormat->Load())
709 if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
714 m_convert_bytestream = true;
715 // create a valid avcC atom data from ffmpeg's extradata
716 isom_write_avcc(m_dllAvUtil, m_dllAvFormat, pb, extradata, extrasize);
717 // unhook from ffmpeg's extradata
719 // extract the avcC atom data into extradata then write it into avcCData for VDADecoder
720 extrasize = m_dllAvFormat->url_close_dyn_buf(pb, &extradata);
721 // CFDataCreate makes a copy of extradata contents
722 avcCData = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)extradata, extrasize);
723 // done with the converted extradata, we MUST free using av_free
724 m_dllAvUtil->av_free(extradata);
728 CLog::Log(LOGNOTICE, "%s - invalid avcC atom data", __FUNCTION__);
734 if (extradata[4] == 0xFE)
736 // video content is from so silly encoder that think 3 byte NAL sizes
737 // are valid, setup to convert 3 byte NAL sizes to 4 byte.
738 m_dllAvUtil = new DllAvUtil;
739 m_dllAvFormat = new DllAvFormat;
740 if (!m_dllAvUtil->Load() || !m_dllAvFormat->Load())
744 m_convert_3byteTo4byteNALSize = true;
746 // CFDataCreate makes a copy of extradata contents
747 avcCData = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)extradata, extrasize);
751 m_pFormatName = "vda-h264";
758 // check the avcC atom's sps for number of reference frames and
759 // bail if interlaced, VDA does not handle interlaced h264.
760 uint32_t avcc_len = CFDataGetLength(avcCData);
763 // avcc atoms with length less than 8 are borked.
769 bool interlaced = true;
770 uint8_t *spc = (uint8_t*)CFDataGetBytePtr(avcCData) + 6;
771 uint32_t sps_size = VDA_RB16(spc);
773 parseh264_sps(spc+3, sps_size-1, &interlaced, &m_max_ref_frames);
779 if (m_max_ref_frames == 0)
780 m_max_ref_frames = 2;
783 // input stream is qualified, now we can load dlls.
784 m_dllSwScale = new DllSwScale;
785 if (!m_dllSwScale->Load())
791 // setup the decoder configuration dict
792 CFMutableDictionaryRef decoderConfiguration = CFDictionaryCreateMutable(
793 kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
795 CFNumberRef avcWidth = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
796 CFNumberRef avcHeight = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
797 CFNumberRef avcFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &m_format);
799 CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_Height(), avcHeight);
800 CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_Width(), avcWidth);
801 CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_SourceFormat(), avcFormat);
802 CFDictionarySetValue(decoderConfiguration, m_dll->Get_kVDADecoderConfiguration_avcCData(), avcCData);
804 // release the retained object refs, decoderConfiguration owns them now
806 CFRelease(avcHeight);
807 CFRelease(avcFormat);
810 // setup the destination image buffer dict, vda will output this pict format
811 CFMutableDictionaryRef destinationImageBufferAttributes = CFDictionaryCreateMutable(
812 kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
814 OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8;
815 CFNumberRef pixelFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &cvPixelFormatType);
816 CFDictionarySetValue(destinationImageBufferAttributes, kCVPixelBufferPixelFormatTypeKey, pixelFormat);
818 // create the VDADecoder object
822 status = m_dll->VDADecoderCreate(decoderConfiguration, destinationImageBufferAttributes,
823 (VDADecoderOutputCallback *)VDADecoderCallback, this, (VDADecoder*)&m_vda_decoder);
827 CLog::Log(LOGERROR, "%s - exception",__FUNCTION__);
828 status = kVDADecoderDecoderFailedErr;
830 CFRelease(decoderConfiguration);
831 CFRelease(destinationImageBufferAttributes);
832 if (status != kVDADecoderNoErr)
834 if (status == kVDADecoderDecoderFailedErr)
835 CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, currently in use by another process",
838 CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, status(%d), profile(%d), level(%d)",
839 __FUNCTION__, (int)status, profile, level);
843 // allocate a YV12 DVDVideoPicture buffer.
844 // first make sure all properties are reset.
845 memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
846 unsigned int iPixels = width * height;
847 unsigned int iChromaPixels = iPixels/4;
849 m_videobuffer.pts = DVD_NOPTS_VALUE;
850 m_videobuffer.iFlags = DVP_FLAG_ALLOCATED;
851 m_videobuffer.format = DVDVideoPicture::FMT_YUV420P;
852 m_videobuffer.color_range = 0;
853 m_videobuffer.color_matrix = 4;
854 m_videobuffer.iWidth = width;
855 m_videobuffer.iHeight = height;
856 m_videobuffer.iDisplayWidth = width;
857 m_videobuffer.iDisplayHeight = height;
859 m_videobuffer.iLineSize[0] = width; //Y
860 m_videobuffer.iLineSize[1] = width/2; //U
861 m_videobuffer.iLineSize[2] = width/2; //V
862 m_videobuffer.iLineSize[3] = 0;
864 m_videobuffer.data[0] = (BYTE*)malloc(iPixels); //Y
865 m_videobuffer.data[1] = (BYTE*)malloc(iChromaPixels); //U
866 m_videobuffer.data[2] = (BYTE*)malloc(iChromaPixels); //V
867 m_videobuffer.data[3] = NULL;
869 // set all data to 0 for less artifacts.. hmm.. what is black in YUV??
870 memset(m_videobuffer.data[0], 0, iPixels);
871 memset(m_videobuffer.data[1], 0, iChromaPixels);
872 memset(m_videobuffer.data[2], 0, iChromaPixels);
874 m_DropPictures = false;
875 m_max_ref_frames = std::min(m_max_ref_frames, 5);
876 m_sort_time_offset = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency();
884 void CDVDVideoCodecVDA::Dispose()
889 m_dll->VDADecoderDestroy((VDADecoder)m_vda_decoder);
890 m_vda_decoder = NULL;
892 if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED)
894 free(m_videobuffer.data[0]);
895 free(m_videobuffer.data[1]);
896 free(m_videobuffer.data[2]);
897 m_videobuffer.iFlags = 0;
906 delete m_dllAvFormat;
907 m_dllAvFormat = NULL;
916 void CDVDVideoCodecVDA::SetDropState(bool bDrop)
918 m_DropPictures = bDrop;
921 int CDVDVideoCodecVDA::Decode(BYTE* pData, int iSize, double dts, double pts)
929 uint32_t avc_flags = 0;
931 CFDictionaryRef avc_time;
933 if (m_convert_bytestream)
935 // convert demuxer packet from bytestream (AnnexB) to bitstream
938 uint8_t *demuxer_content;
940 if(m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
944 demuxer_bytes = avc_parse_nal_units(m_dllAvFormat, pb, pData, iSize);
945 demuxer_bytes = m_dllAvFormat->url_close_dyn_buf(pb, &demuxer_content);
946 avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes);
947 m_dllAvUtil->av_free(demuxer_content);
949 else if (m_convert_3byteTo4byteNALSize)
951 // convert demuxer packet from 3 byte NAL sizes to 4 byte
953 if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
957 uint8_t *end = pData + iSize;
958 uint8_t *nal_start = pData;
959 while (nal_start < end)
961 nal_size = VDA_RB24(nal_start);
962 m_dllAvFormat->put_be32(pb, nal_size);
964 m_dllAvFormat->put_buffer(pb, nal_start, nal_size);
965 nal_start += nal_size;
968 uint8_t *demuxer_content;
969 int demuxer_bytes = m_dllAvFormat->url_close_dyn_buf(pb, &demuxer_content);
970 avc_demux = CFDataCreate(kCFAllocatorDefault, demuxer_content, demuxer_bytes);
971 m_dllAvUtil->av_free(demuxer_content);
975 avc_demux = CFDataCreate(kCFAllocatorDefault, pData, iSize);
977 sort_time = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency();
978 avc_time = CreateDictionaryWithDisplayTime(sort_time - m_sort_time_offset, dts, pts);
981 avc_flags = kVDADecoderDecodeFlags_DontEmitFrame;
983 status = m_dll->VDADecoderDecode((VDADecoder)m_vda_decoder, avc_flags, avc_demux, avc_time);
985 CFRelease(avc_demux);
986 if (status != kVDADecoderNoErr)
988 CLog::Log(LOGNOTICE, "%s - VDADecoderDecode failed, status(%d)", __FUNCTION__, (int)status);
993 if (!m_queue_depth || m_queue_depth < m_max_ref_frames)
998 return VC_PICTURE | VC_BUFFER;
1001 void CDVDVideoCodecVDA::Reset(void)
1003 CCocoaAutoPool pool;
1004 m_dll->VDADecoderFlush((VDADecoder)m_vda_decoder, 0);
1006 while (m_queue_depth)
1009 m_sort_time_offset = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency();
1012 bool CDVDVideoCodecVDA::GetPicture(DVDVideoPicture* pDvdVideoPicture)
1014 CCocoaAutoPool pool;
1015 FourCharCode pixel_buffer_format;
1016 CVPixelBufferRef picture_buffer_ref;
1018 // clone the video picture buffer settings.
1019 *pDvdVideoPicture = m_videobuffer;
1021 // get the top yuv frame, we risk getting the wrong frame if the frame queue
1022 // depth is less than the number of encoded reference frames. If queue depth
1023 // is greater than the number of encoded reference frames, then the top frame
1024 // will never change and we can just grab a ref to the top frame. This way
1025 // we don't lockout the vdadecoder while doing color format convert.
1026 pthread_mutex_lock(&m_queue_mutex);
1027 picture_buffer_ref = m_display_queue->pixel_buffer_ref;
1028 pixel_buffer_format = m_display_queue->pixel_buffer_format;
1029 pDvdVideoPicture->dts = m_display_queue->dts;
1030 pDvdVideoPicture->pts = m_display_queue->pts;
1031 pthread_mutex_unlock(&m_queue_mutex);
1033 // lock the CVPixelBuffer down
1034 CVPixelBufferLockBaseAddress(picture_buffer_ref, 0);
1035 int row_stride = CVPixelBufferGetBytesPerRowOfPlane(picture_buffer_ref, 0);
1036 uint8_t *base_ptr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(picture_buffer_ref, 0);
1039 if (pixel_buffer_format == kCVPixelFormatType_422YpCbCr8)
1040 UYVY422_to_YUV420P(base_ptr, row_stride, pDvdVideoPicture);
1041 else if (pixel_buffer_format == kCVPixelFormatType_32BGRA)
1042 BGRA_to_YUV420P(base_ptr, row_stride, pDvdVideoPicture);
1044 // unlock the CVPixelBuffer
1045 CVPixelBufferUnlockBaseAddress(picture_buffer_ref, 0);
1047 // now we can pop the top frame.
1050 //CLog::Log(LOGNOTICE, "%s - VDADecoderDecode dts(%f), pts(%f)", __FUNCTION__,
1051 // pDvdVideoPicture->dts, pDvdVideoPicture->pts);
1053 return VC_PICTURE | VC_BUFFER;
1056 void CDVDVideoCodecVDA::UYVY422_to_YUV420P(uint8_t *yuv422_ptr, int yuv422_stride, DVDVideoPicture *picture)
1058 // convert PIX_FMT_UYVY422 to PIX_FMT_YUV420P.
1059 struct SwsContext *swcontext = m_dllSwScale->sws_getContext(
1060 m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_UYVY422,
1061 m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_YUV420P,
1062 SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
1065 uint8_t *src[] = { yuv422_ptr, 0, 0, 0 };
1066 int srcStride[] = { yuv422_stride, 0, 0, 0 };
1068 uint8_t *dst[] = { picture->data[0], picture->data[1], picture->data[2], 0 };
1069 int dstStride[] = { picture->iLineSize[0], picture->iLineSize[1], picture->iLineSize[2], 0 };
1071 m_dllSwScale->sws_scale(swcontext, src, srcStride, 0, picture->iHeight, dst, dstStride);
1072 m_dllSwScale->sws_freeContext(swcontext);
1076 void CDVDVideoCodecVDA::BGRA_to_YUV420P(uint8_t *bgra_ptr, int bgra_stride, DVDVideoPicture *picture)
1078 // convert PIX_FMT_BGRA to PIX_FMT_YUV420P.
1079 struct SwsContext *swcontext = m_dllSwScale->sws_getContext(
1080 m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_BGRA,
1081 m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_YUV420P,
1082 SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
1085 uint8_t *src[] = { bgra_ptr, 0, 0, 0 };
1086 int srcStride[] = { bgra_stride, 0, 0, 0 };
1088 uint8_t *dst[] = { picture->data[0], picture->data[1], picture->data[2], 0 };
1089 int dstStride[] = { picture->iLineSize[0], picture->iLineSize[1], picture->iLineSize[2], 0 };
1091 m_dllSwScale->sws_scale(swcontext, src, srcStride, 0, picture->iHeight, dst, dstStride);
1092 m_dllSwScale->sws_freeContext(swcontext);
1096 void CDVDVideoCodecVDA::DisplayQueuePop(void)
1098 CCocoaAutoPool pool;
1099 if (!m_display_queue || m_queue_depth == 0)
1102 // pop the top frame off the queue
1103 pthread_mutex_lock(&m_queue_mutex);
1104 frame_queue *top_frame = m_display_queue;
1105 m_display_queue = m_display_queue->nextframe;
1107 pthread_mutex_unlock(&m_queue_mutex);
1110 CVPixelBufferRelease(top_frame->pixel_buffer_ref);
1114 void CDVDVideoCodecVDA::VDADecoderCallback(
1115 void *decompressionOutputRefCon,
1116 CFDictionaryRef frameInfo,
1119 CVImageBufferRef imageBuffer)
1121 CCocoaAutoPool pool;
1122 // Warning, this is an async callback. There can be multiple frames in flight.
1123 CDVDVideoCodecVDA *ctx = (CDVDVideoCodecVDA*)decompressionOutputRefCon;
1125 if (imageBuffer == NULL)
1127 //CLog::Log(LOGDEBUG, "%s - imageBuffer is NULL", __FUNCTION__);
1130 OSType format_type = CVPixelBufferGetPixelFormatType(imageBuffer);
1131 if ((format_type != kCVPixelFormatType_422YpCbCr8) && (format_type != kCVPixelFormatType_32BGRA) )
1133 CLog::Log(LOGERROR, "%s - imageBuffer format is not '2vuy' or 'BGRA',is reporting 0x%x",
1134 __FUNCTION__, (unsigned int)format_type);
1137 if (kVDADecodeInfo_FrameDropped & infoFlags)
1139 CLog::Log(LOGDEBUG, "%s - frame dropped", __FUNCTION__);
1143 // allocate a new frame and populate it with some information.
1144 // this pointer to a frame_queue type keeps track of the newest decompressed frame
1145 // and is then inserted into a linked list of frame pointers depending on the display time
1146 // parsed out of the bitstream and stored in the frameInfo dictionary by the client
1147 frame_queue *newFrame = (frame_queue*)calloc(sizeof(frame_queue), 1);
1148 newFrame->nextframe = NULL;
1149 newFrame->pixel_buffer_format = format_type;
1150 newFrame->pixel_buffer_ref = CVPixelBufferRetain(imageBuffer);
1151 GetFrameDisplayTimeFromDictionary(frameInfo, newFrame);
1153 // if both dts or pts are good we use those, else use decoder insert time for frame sort
1154 if ((newFrame->pts != DVD_NOPTS_VALUE) || (newFrame->dts != DVD_NOPTS_VALUE))
1156 // if pts is borked (stupid avi's), use dts for frame sort
1157 if (newFrame->pts == DVD_NOPTS_VALUE)
1158 newFrame->sort_time = newFrame->dts;
1160 newFrame->sort_time = newFrame->pts;
1163 // since the frames we get may be in decode order rather than presentation order
1164 // our hypothetical callback places them in a queue of frames which will
1165 // hold them in display order for display on another thread
1166 pthread_mutex_lock(&ctx->m_queue_mutex);
1168 frame_queue *queueWalker = ctx->m_display_queue;
1169 if (!queueWalker || (newFrame->sort_time < queueWalker->sort_time))
1171 // we have an empty queue, or this frame earlier than the current queue head.
1172 newFrame->nextframe = queueWalker;
1173 ctx->m_display_queue = newFrame;
1175 // walk the queue and insert this frame where it belongs in display order.
1176 bool frameInserted = false;
1177 frame_queue *nextFrame = NULL;
1179 while (!frameInserted)
1181 nextFrame = queueWalker->nextframe;
1182 if (!nextFrame || (newFrame->sort_time < nextFrame->sort_time))
1184 // if the next frame is the tail of the queue, or our new frame is earlier.
1185 newFrame->nextframe = nextFrame;
1186 queueWalker->nextframe = newFrame;
1187 frameInserted = true;
1189 queueWalker = nextFrame;
1192 ctx->m_queue_depth++;
1194 pthread_mutex_unlock(&ctx->m_queue_mutex);