Merge pull request #473 from Montellese/onplaybackspeedchanged
[vuplus_xbmc] / xbmc / cores / dvdplayer / DVDCodecs / Video / DVDVideoCodecVDA.cpp
1 /*
2  *      Copyright (C) 2005-2010 Team XBMC
3  *      http://www.xbmc.org
4  *
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)
8  *  any later version.
9  *
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.
14  *
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
19  *
20  */
21
22 #if (defined HAVE_CONFIG_H) && (!defined WIN32)
23   #include "config.h"
24 #endif
25
26 #if defined(HAVE_LIBVDADECODER)
27 #include "DynamicDll.h"
28 #include "settings/GUISettings.h"
29 #include "DVDClock.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>
39
40 /*
41  * if extradata size is greater than 7, then have a valid quicktime 
42  * avcC atom header.
43  *
44  *      -: avcC atom header :-
45  *  -----------------------------------
46  *  1 byte  - version
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
51  *  2 bits  - NAL length 
52  *            ( 0 - 1 byte; 1 - 2 bytes; 3 - 4 bytes)
53  *  3 bit   - reserved
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
58  *  }
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 
63  *  }
64  
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).
80 */
81
82 // missing in 10.4/10.5 SDKs.
83 #if (MAC_OS_X_VERSION_MAX_ALLOWED < 1060)
84 #include "dlfcn.h"
85 enum {
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')
89 };
90 #endif
91
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>
96 enum {
97   kVDADecoderNoErr = 0,
98   kVDADecoderHardwareNotSupportedErr = -12470,
99   kVDADecoderFormatNotSupportedErr = -12471,
100   kVDADecoderConfigurationError = -12472,
101   kVDADecoderDecoderFailedErr = -12473,
102 };
103 enum {
104   kVDADecodeInfo_Asynchronous = 1UL << 0,
105   kVDADecodeInfo_FrameDropped = 1UL << 1
106 };
107 enum {
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
111 };
112 enum {
113   // decode and return buffers for all frames currently in flight.
114   kVDADecoderFlush_EmitFrames = 1 << 0          
115 };
116
117 typedef struct OpaqueVDADecoder* VDADecoder;
118
119 typedef void (*VDADecoderOutputCallback)(
120   void *decompressionOutputRefCon,
121   CFDictionaryRef frameInfo,
122   OSStatus status,
123   uint32_t infoFlags,
124   CVImageBufferRef imageBuffer);
125
126 ////////////////////////////////////////////////////////////////////////////////////////////
127 class DllLibVDADecoderInterface
128 {
129 public:
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;
142 };
143
144 class DllLibVDADecoder : public DllDynamic, DllLibVDADecoderInterface
145 {
146   DECLARE_DLL_WRAPPER(DllLibVDADecoder, DLL_PATH_LIBVDADECODER)
147
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)
165   END_METHOD_RESOLVE()
166 };
167
168 ////////////////////////////////////////////////////////////////////////////////////////////
169 // helper function that wraps dts/pts into a dictionary
170 static CFDictionaryRef CreateDictionaryWithDisplayTime(double time, double dts, double pts)
171 {
172   CFStringRef key[3] = {
173     CFSTR("VideoDisplay_TIME"),
174     CFSTR("VideoDisplay_DTS"),
175     CFSTR("VideoDisplay_PTS")};
176   CFNumberRef value[3];
177   CFDictionaryRef display_time;
178
179   value[0] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &time);
180   value[1] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &dts);
181   value[2] = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &pts);
182
183   display_time = CFDictionaryCreate(
184     kCFAllocatorDefault, (const void **)&key, (const void **)&value, 3,
185     &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
186   
187   CFRelease(value[0]);
188   CFRelease(value[1]);
189   CFRelease(value[2]);
190
191   return display_time;
192 }
193
194 // helper function to extract dts/pts from a dictionary
195 static void GetFrameDisplayTimeFromDictionary(
196   CFDictionaryRef inFrameInfoDictionary, frame_queue *frame)
197 {
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)
203     return;
204
205   CFNumberRef value[3];
206   //
207   value[0] = (CFNumberRef)CFDictionaryGetValue(inFrameInfoDictionary, CFSTR("VideoDisplay_TIME"));
208   if (value[0])
209     CFNumberGetValue(value[0], kCFNumberDoubleType, &frame->sort_time);
210   value[1] = (CFNumberRef)CFDictionaryGetValue(inFrameInfoDictionary, CFSTR("VideoDisplay_DTS"));
211   if (value[1])
212     CFNumberGetValue(value[1], kCFNumberDoubleType, &frame->dts);
213   value[2] = (CFNumberRef)CFDictionaryGetValue(inFrameInfoDictionary, CFSTR("VideoDisplay_PTS"));
214   if (value[2])
215     CFNumberGetValue(value[2], kCFNumberDoubleType, &frame->pts);
216
217   return;
218 }
219
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>
225 // gsth264parse.c:
226 //  * License as published by the Free Software Foundation; either
227 //  * version 2.1 of the License, or (at your option) any later version.
228 typedef struct
229 {
230   const uint8_t *data;
231   const uint8_t *end;
232   int head;
233   uint64_t cache;
234 } nal_bitstream;
235
236 static void
237 nal_bs_init(nal_bitstream *bs, const uint8_t *data, size_t size)
238 {
239   bs->data = data;
240   bs->end  = data + size;
241   bs->head = 0;
242   // fill with something other than 0 to detect
243   //  emulation prevention bytes
244   bs->cache = 0xffffffff;
245 }
246
247 static uint32_t
248 nal_bs_read(nal_bitstream *bs, int n)
249 {
250   uint32_t res = 0;
251   int shift;
252
253   if (n == 0)
254     return res;
255
256   // fill up the cache if we need to
257   while (bs->head < n)
258   {
259     uint8_t a_byte;
260     bool check_three_byte;
261
262     check_three_byte = TRUE;
263 next_byte:
264     if (bs->data >= bs->end)
265     {
266       // we're at the end, can't produce more than head number of bits
267       n = bs->head;
268       break;
269     }
270     // get the byte, this can be an emulation_prevention_three_byte that we need
271     // to ignore.
272     a_byte = *bs->data++;
273     if (check_three_byte && a_byte == 0x03 && ((bs->cache & 0xffff) == 0))
274     {
275       // next byte goes unconditionally to the cache, even if it's 0x03
276       check_three_byte = FALSE;
277       goto next_byte;
278     }
279     // shift bytes in cache, moving the head bits of the cache left
280     bs->cache = (bs->cache << 8) | a_byte;
281     bs->head += 8;
282   }
283
284   // bring the required bits down and truncate
285   if ((shift = bs->head - n) > 0)
286     res = bs->cache >> shift;
287   else
288     res = bs->cache;
289
290   // mask out required bits
291   if (n < 32)
292     res &= (1 << n) - 1;
293
294   bs->head = shift;
295
296   return res;
297 }
298
299 static bool
300 nal_bs_eos(nal_bitstream *bs)
301 {
302   return (bs->data >= bs->end) && (bs->head == 0);
303 }
304
305 // read unsigned Exp-Golomb code
306 static int
307 nal_bs_read_ue(nal_bitstream *bs)
308 {
309   int i = 0;
310
311   while (nal_bs_read(bs, 1) == 0 && !nal_bs_eos(bs) && i < 32)
312     i++;
313
314   return ((1 << i) - 1 + nal_bs_read(bs, i));
315 }
316
317 typedef struct
318 {
319   int profile_idc;
320   int level_idc;
321   int sps_id;
322
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;
329
330   int log2_max_frame_num_minus4;
331   int pic_order_cnt_type;
332   int log2_max_pic_order_cnt_lsb_minus4;
333
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;
338
339   int frame_mbs_only_flag;
340   int mb_adaptive_frame_field_flag;
341
342   int direct_8x8_inference_flag;
343
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;
349 } sps_info_struct;
350
351 static void
352 parseh264_sps(uint8_t *sps, uint32_t sps_size, bool *interlaced, int32_t *max_ref_frames)
353 {
354   nal_bitstream bs;
355   sps_info_struct sps_info;
356
357   nal_bs_init(&bs, sps, sps_size);
358
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);
367
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)
375   {
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);
382
383     sps_info.seq_scaling_matrix_present_flag = nal_bs_read (&bs, 1);
384     if (sps_info.seq_scaling_matrix_present_flag)
385     {
386       /* TODO: unfinished */
387     }
388   }
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
392     return;
393   }
394
395   sps_info.pic_order_cnt_type = nal_bs_read_ue(&bs);
396   if (sps_info.pic_order_cnt_type == 0)
397   {
398     sps_info.log2_max_pic_order_cnt_lsb_minus4 = nal_bs_read_ue(&bs);
399   }
400   else if (sps_info.pic_order_cnt_type == 1)
401   { // TODO: unfinished
402     /*
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);
406
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);
410     */
411   }
412
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);
417
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);
421
422   sps_info.direct_8x8_inference_flag      = nal_bs_read(&bs, 1);
423
424   sps_info.frame_cropping_flag            = nal_bs_read(&bs, 1);
425   if (sps_info.frame_cropping_flag)
426   {
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);
431   }
432
433   *interlaced = !sps_info.frame_mbs_only_flag;
434   *max_ref_frames = sps_info.max_num_ref_frames;
435 }
436
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])
448
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])
453
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])
459
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; }
465
466 static const uint8_t *avc_find_startcode_internal(const uint8_t *p, const uint8_t *end)
467 {
468   const uint8_t *a = p + 4 - ((intptr_t)p & 3);
469
470   for (end -= 3; p < a && p < end; p++)
471   {
472     if (p[0] == 0 && p[1] == 0 && p[2] == 1)
473       return p;
474   }
475
476   for (end -= 3; p < end; p += 4)
477   {
478     uint32_t x = *(const uint32_t*)p;
479     if ((x - 0x01010101) & (~x) & 0x80808080) // generic
480     {
481       if (p[1] == 0)
482       {
483         if (p[0] == 0 && p[2] == 1)
484           return p;
485         if (p[2] == 0 && p[3] == 1)
486           return p+1;
487       }
488       if (p[3] == 0)
489       {
490         if (p[2] == 0 && p[4] == 1)
491           return p+2;
492         if (p[4] == 0 && p[5] == 1)
493           return p+3;
494       }
495     }
496   }
497
498   for (end += 3; p < end; p++)
499   {
500     if (p[0] == 0 && p[1] == 0 && p[2] == 1)
501       return p;
502   }
503
504   return end + 3;
505 }
506
507 const uint8_t *avc_find_startcode(const uint8_t *p, const uint8_t *end)
508 {
509   const uint8_t *out= avc_find_startcode_internal(p, end);
510   if (p<out && out<end && !out[-1])
511     out--;
512   return out;
513 }
514
515 const int avc_parse_nal_units(DllAvFormat *av_format_ctx,
516   ByteIOContext *pb, const uint8_t *buf_in, int size)
517 {
518   const uint8_t *p = buf_in;
519   const uint8_t *end = p + size;
520   const uint8_t *nal_start, *nal_end;
521
522   size = 0;
523   nal_start = avc_find_startcode(p, end);
524   while (nal_start < end)
525   {
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;
531     nal_start = nal_end;
532   }
533   return size;
534 }
535
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)
538 {
539   ByteIOContext *pb;
540   int ret = av_format_ctx->url_open_dyn_buf(&pb);
541   if (ret < 0)
542     return ret;
543
544   avc_parse_nal_units(av_format_ctx, pb, buf_in, *size);
545
546   av_util_ctx->av_freep(buf);
547   *size = av_format_ctx->url_close_dyn_buf(pb, buf);
548   return 0;
549 }
550
551 const int isom_write_avcc(DllAvUtil *av_util_ctx, DllAvFormat *av_format_ctx,
552   ByteIOContext *pb, const uint8_t *data, int len)
553 {
554   // extradata from bytestream h264, convert to avcC atom data for bitstream
555   if (len > 6)
556   {
557     /* check for h264 start code */
558     if (VDA_RB32(data) == 0x00000001 || VDA_RB24(data) == 0x000001)
559     {
560       uint8_t *buf=NULL, *end, *start;
561       uint32_t sps_size=0, pps_size=0;
562       uint8_t *sps=0, *pps=0;
563
564       int ret = avc_parse_nal_units_buf(av_util_ctx, av_format_ctx, data, &buf, &len);
565       if (ret < 0)
566         return ret;
567       start = buf;
568       end = buf + len;
569
570       /* look for sps and pps */
571       while (buf < end)
572       {
573         unsigned int size;
574         uint8_t nal_type;
575         size = VDA_RB32(buf);
576         nal_type = buf[4] & 0x1f;
577         if (nal_type == 7) /* SPS */
578         {
579           sps = buf + 4;
580           sps_size = size;
581           
582           //parse_sps(sps+1, sps_size-1);
583         }
584         else if (nal_type == 8) /* PPS */
585         {
586           pps = buf + 4;
587           pps_size = size;
588         }
589         buf += size + 4;
590       }
591       assert(sps);
592
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) */
599
600       av_format_ctx->put_be16(pb, sps_size);
601       av_format_ctx->put_buffer(pb, sps, sps_size);
602       if (pps)
603       {
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);
607       }
608       av_util_ctx->av_free(start);
609     }
610     else
611     {
612       av_format_ctx->put_buffer(pb, data, len);
613     }
614   }
615   return 0;
616 }
617
618
619 static DllLibVDADecoder *g_DllLibVDADecoder = (DllLibVDADecoder*)-1;
620 ////////////////////////////////////////////////////////////////////////////////////////////
621 ////////////////////////////////////////////////////////////////////////////////////////////
622 CDVDVideoCodecVDA::CDVDVideoCodecVDA() : CDVDVideoCodec()
623 {
624   if (g_DllLibVDADecoder == (DllLibVDADecoder*)-1)
625   {
626     m_dll = new DllLibVDADecoder;
627     m_dll->Load();
628   }
629   else
630     m_dll = g_DllLibVDADecoder;
631
632   m_vda_decoder = NULL;
633   m_pFormatName = "vda-";
634
635   m_queue_depth = 0;
636   m_display_queue = NULL;
637   pthread_mutex_init(&m_queue_mutex, NULL);
638
639   m_convert_bytestream = false;
640   m_convert_3byteTo4byteNALSize = false;
641   m_dllAvUtil = NULL;
642   m_dllAvFormat = NULL;
643   m_dllSwScale = NULL;
644   memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
645 }
646
647 CDVDVideoCodecVDA::~CDVDVideoCodecVDA()
648 {
649   Dispose();
650   pthread_mutex_destroy(&m_queue_mutex);
651   //delete m_dll;
652 }
653
654 bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
655 {
656   if (g_guiSettings.GetBool("videoplayer.usevda") && !hints.software)
657   {
658     CCocoaAutoPool pool;
659     int32_t width, height, profile, level;
660     CFDataRef avcCData;
661     uint8_t *extradata; // extra data for codec to use
662     unsigned int extrasize; // size of extra data
663
664     //
665     width  = hints.width;
666     height = hints.height;
667     level  = hints.level;
668     profile = hints.profile;
669     extrasize = hints.extrasize;
670     extradata = (uint8_t*)hints.extradata;
671     
672     if (hints.profile == 77 && hints.level == 32)
673     {
674       // Main@L3.2, VDA cannot handle it
675       CLog::Log(LOGNOTICE, "%s - Main@L3.2 detected, VDA cannot decode.", __FUNCTION__);
676       return false;
677     }
678  
679     if (Cocoa_GPUForDisplayIsNvidiaPureVideo3() && !CDVDCodecUtils::IsVP3CompatibleWidth(width))
680     {
681       CLog::Log(LOGNOTICE, "%s - Nvidia 9400 GPU hardware limitation, cannot decode a width of %d", __FUNCTION__, width);
682       return false;
683     }
684
685     switch (hints.codec)
686     {
687       case CODEC_ID_H264:
688         // source must be H.264 with valid avcC atom data in extradata
689         if (extrasize < 7 || extradata == NULL)
690         {
691           CLog::Log(LOGNOTICE, "%s - avcC atom too data small or missing", __FUNCTION__);
692           return false;
693         }
694         // valid avcC atom data always starts with the value 1 (version)
695         if ( *extradata != 1 )
696         {
697           if (extradata[0] == 0 && extradata[1] == 0 && extradata[2] == 0 && extradata[3] == 1)
698           {
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())
704             {
705               return false;
706             }
707
708             ByteIOContext *pb;
709             if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
710             {
711               return false;
712             }
713
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
718             extradata = NULL;
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);
725           }
726           else
727           {
728             CLog::Log(LOGNOTICE, "%s - invalid avcC atom data", __FUNCTION__);
729             return false;
730           }
731         }
732         else
733         {
734           if (extradata[4] == 0xFE)
735           {
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())
741               return false;
742
743             extradata[4] = 0xFF;
744             m_convert_3byteTo4byteNALSize = true;
745           }
746           // CFDataCreate makes a copy of extradata contents
747           avcCData = CFDataCreate(kCFAllocatorDefault, (const uint8_t*)extradata, extrasize);
748         }
749
750         m_format = 'avc1';
751         m_pFormatName = "vda-h264";
752       break;
753       default:
754         return false;
755       break;
756     }
757
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);
761     if (avcc_len < 8)
762     {
763       // avcc atoms with length less than 8 are borked.
764       CFRelease(avcCData);
765       return false;
766     }
767     else
768     {
769       bool interlaced = true;
770       uint8_t *spc = (uint8_t*)CFDataGetBytePtr(avcCData) + 6;
771       uint32_t sps_size = VDA_RB16(spc);
772       if (sps_size)
773         parseh264_sps(spc+3, sps_size-1, &interlaced, &m_max_ref_frames);
774       if (interlaced)
775       {
776         CFRelease(avcCData);
777         return false;
778       }
779       if (m_max_ref_frames == 0)
780         m_max_ref_frames = 2;
781     }
782
783     // input stream is qualified, now we can load dlls.
784     m_dllSwScale = new DllSwScale;
785     if (!m_dllSwScale->Load())
786     {
787       CFRelease(avcCData);
788       return false;
789     }
790
791     // setup the decoder configuration dict
792     CFMutableDictionaryRef decoderConfiguration = CFDictionaryCreateMutable(
793       kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
794
795     CFNumberRef avcWidth  = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width);
796     CFNumberRef avcHeight = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height);
797     CFNumberRef avcFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &m_format);
798
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);
803
804     // release the retained object refs, decoderConfiguration owns them now
805     CFRelease(avcWidth);
806     CFRelease(avcHeight);
807     CFRelease(avcFormat);
808     CFRelease(avcCData);
809
810     // setup the destination image buffer dict, vda will output this pict format
811     CFMutableDictionaryRef destinationImageBufferAttributes = CFDictionaryCreateMutable(
812       kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
813
814     OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8;
815     CFNumberRef pixelFormat  = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &cvPixelFormatType);
816     CFDictionarySetValue(destinationImageBufferAttributes, kCVPixelBufferPixelFormatTypeKey, pixelFormat);
817
818     // create the VDADecoder object
819     OSStatus status;
820     try
821     {
822       status = m_dll->VDADecoderCreate(decoderConfiguration, destinationImageBufferAttributes,
823         (VDADecoderOutputCallback *)VDADecoderCallback, this, (VDADecoder*)&m_vda_decoder);
824     }
825     catch (...)
826     {
827       CLog::Log(LOGERROR, "%s - exception",__FUNCTION__);
828       status = kVDADecoderDecoderFailedErr;
829     }
830     CFRelease(decoderConfiguration);
831     CFRelease(destinationImageBufferAttributes);
832     if (status != kVDADecoderNoErr)
833     {
834           if (status == kVDADecoderDecoderFailedErr)
835         CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, currently in use by another process",
836           __FUNCTION__);
837           else
838         CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, status(%d), profile(%d), level(%d)",
839           __FUNCTION__, (int)status, profile, level);
840       return false;
841     }
842
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;
848
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;
858
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;
863
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;
868
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);
873
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();
877
878     return true;
879   }
880
881   return false;
882 }
883
884 void CDVDVideoCodecVDA::Dispose()
885 {
886   CCocoaAutoPool pool;
887   if (m_vda_decoder)
888   {
889     m_dll->VDADecoderDestroy((VDADecoder)m_vda_decoder);
890     m_vda_decoder = NULL;
891   }
892   if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED)
893   {
894     free(m_videobuffer.data[0]);
895     free(m_videobuffer.data[1]);
896     free(m_videobuffer.data[2]);
897     m_videobuffer.iFlags = 0;
898   }
899   if (m_dllAvUtil)
900   {
901     delete m_dllAvUtil;
902     m_dllAvUtil = NULL;
903   }
904   if (m_dllAvFormat)
905   {
906     delete m_dllAvFormat;
907     m_dllAvFormat = NULL;
908   }
909   if (m_dllSwScale)
910   {
911     delete m_dllSwScale;
912     m_dllSwScale = NULL;
913   }
914 }
915
916 void CDVDVideoCodecVDA::SetDropState(bool bDrop)
917 {
918   m_DropPictures = bDrop;
919 }
920
921 int CDVDVideoCodecVDA::Decode(BYTE* pData, int iSize, double dts, double pts)
922 {
923   CCocoaAutoPool pool;
924   //
925   if (pData)
926   {
927     OSStatus status;
928     double sort_time;
929     uint32_t avc_flags = 0;
930     CFDataRef avc_demux;
931     CFDictionaryRef avc_time;
932
933     if (m_convert_bytestream)
934     {
935       // convert demuxer packet from bytestream (AnnexB) to bitstream
936       ByteIOContext *pb;
937       int demuxer_bytes;
938       uint8_t *demuxer_content;
939
940       if(m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
941       {
942         return VC_ERROR;
943       }
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);
948     }
949     else if (m_convert_3byteTo4byteNALSize)
950     {
951       // convert demuxer packet from 3 byte NAL sizes to 4 byte
952       ByteIOContext *pb;
953       if (m_dllAvFormat->url_open_dyn_buf(&pb) < 0)
954         return VC_ERROR;
955
956       uint32_t nal_size;
957       uint8_t *end = pData + iSize;
958       uint8_t *nal_start = pData;
959       while (nal_start < end)
960       {
961         nal_size = VDA_RB24(nal_start);
962         m_dllAvFormat->put_be32(pb, nal_size);
963         nal_start += 3;
964         m_dllAvFormat->put_buffer(pb, nal_start, nal_size);
965         nal_start += nal_size;
966       }
967
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);
972     }
973     else
974     {
975       avc_demux = CFDataCreate(kCFAllocatorDefault, pData, iSize);
976     }
977     sort_time = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency();
978     avc_time = CreateDictionaryWithDisplayTime(sort_time - m_sort_time_offset, dts, pts);
979
980     if (m_DropPictures)
981       avc_flags = kVDADecoderDecodeFlags_DontEmitFrame;
982
983     status = m_dll->VDADecoderDecode((VDADecoder)m_vda_decoder, avc_flags, avc_demux, avc_time);
984     CFRelease(avc_time);
985     CFRelease(avc_demux);
986     if (status != kVDADecoderNoErr)
987     {
988       CLog::Log(LOGNOTICE, "%s - VDADecoderDecode failed, status(%d)", __FUNCTION__, (int)status);
989       return VC_ERROR;
990     }
991   }
992
993   if (!m_queue_depth || m_queue_depth < m_max_ref_frames)
994   {
995     return VC_BUFFER;
996   }
997
998   return VC_PICTURE | VC_BUFFER;
999 }
1000
1001 void CDVDVideoCodecVDA::Reset(void)
1002 {
1003   CCocoaAutoPool pool;
1004   m_dll->VDADecoderFlush((VDADecoder)m_vda_decoder, 0);
1005
1006   while (m_queue_depth)
1007     DisplayQueuePop();
1008
1009   m_sort_time_offset = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency();
1010 }
1011
1012 bool CDVDVideoCodecVDA::GetPicture(DVDVideoPicture* pDvdVideoPicture)
1013 {
1014   CCocoaAutoPool pool;
1015   FourCharCode pixel_buffer_format;
1016   CVPixelBufferRef picture_buffer_ref;
1017
1018   // clone the video picture buffer settings.
1019   *pDvdVideoPicture = m_videobuffer;
1020
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);
1032
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);
1037   if (base_ptr)
1038   {
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);
1043   }
1044   // unlock the CVPixelBuffer
1045   CVPixelBufferUnlockBaseAddress(picture_buffer_ref, 0);
1046
1047   // now we can pop the top frame.
1048   DisplayQueuePop();
1049
1050   //CLog::Log(LOGNOTICE, "%s - VDADecoderDecode dts(%f), pts(%f)", __FUNCTION__,
1051   //  pDvdVideoPicture->dts, pDvdVideoPicture->pts);
1052
1053   return VC_PICTURE | VC_BUFFER;
1054 }
1055
1056 void CDVDVideoCodecVDA::UYVY422_to_YUV420P(uint8_t *yuv422_ptr, int yuv422_stride, DVDVideoPicture *picture)
1057 {
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);
1063   if (swcontext)
1064   {
1065     uint8_t  *src[] = { yuv422_ptr, 0, 0, 0 };
1066     int srcStride[] = { yuv422_stride, 0, 0, 0 };
1067
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 };
1070
1071     m_dllSwScale->sws_scale(swcontext, src, srcStride, 0, picture->iHeight, dst, dstStride);
1072     m_dllSwScale->sws_freeContext(swcontext);
1073   }
1074 }
1075
1076 void CDVDVideoCodecVDA::BGRA_to_YUV420P(uint8_t *bgra_ptr, int bgra_stride, DVDVideoPicture *picture)
1077 {
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);
1083   if (swcontext)
1084   {
1085     uint8_t  *src[] = { bgra_ptr, 0, 0, 0 };
1086     int srcStride[] = { bgra_stride, 0, 0, 0 };
1087
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 };
1090
1091     m_dllSwScale->sws_scale(swcontext, src, srcStride, 0, picture->iHeight, dst, dstStride);
1092     m_dllSwScale->sws_freeContext(swcontext);
1093   }
1094 }
1095
1096 void CDVDVideoCodecVDA::DisplayQueuePop(void)
1097 {
1098   CCocoaAutoPool pool;
1099   if (!m_display_queue || m_queue_depth == 0)
1100     return;
1101
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;
1106   m_queue_depth--;
1107   pthread_mutex_unlock(&m_queue_mutex);
1108
1109   // and release it
1110   CVPixelBufferRelease(top_frame->pixel_buffer_ref);
1111   free(top_frame);
1112 }
1113
1114 void CDVDVideoCodecVDA::VDADecoderCallback(
1115   void                *decompressionOutputRefCon,
1116    CFDictionaryRef    frameInfo,
1117    OSStatus           status,
1118    uint32_t           infoFlags,
1119    CVImageBufferRef   imageBuffer)
1120 {
1121   CCocoaAutoPool pool;
1122   // Warning, this is an async callback. There can be multiple frames in flight.
1123   CDVDVideoCodecVDA *ctx = (CDVDVideoCodecVDA*)decompressionOutputRefCon;
1124
1125   if (imageBuffer == NULL)
1126   {
1127     //CLog::Log(LOGDEBUG, "%s - imageBuffer is NULL", __FUNCTION__);
1128     return;
1129   }
1130   OSType format_type = CVPixelBufferGetPixelFormatType(imageBuffer);
1131   if ((format_type != kCVPixelFormatType_422YpCbCr8) && (format_type != kCVPixelFormatType_32BGRA) )
1132   {
1133     CLog::Log(LOGERROR, "%s - imageBuffer format is not '2vuy' or 'BGRA',is reporting 0x%x",
1134       __FUNCTION__, (unsigned int)format_type);
1135     return;
1136   }
1137   if (kVDADecodeInfo_FrameDropped & infoFlags)
1138   {
1139     CLog::Log(LOGDEBUG, "%s - frame dropped", __FUNCTION__);
1140     return;
1141   }
1142
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);
1152
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))
1155   {
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;
1159     else
1160       newFrame->sort_time = newFrame->pts;
1161   }
1162
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);
1167   //
1168   frame_queue *queueWalker = ctx->m_display_queue;
1169   if (!queueWalker || (newFrame->sort_time < queueWalker->sort_time))
1170   {
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;
1174   } else {
1175     // walk the queue and insert this frame where it belongs in display order.
1176     bool frameInserted = false;
1177     frame_queue *nextFrame = NULL;
1178     //
1179     while (!frameInserted)
1180     {
1181       nextFrame = queueWalker->nextframe;
1182       if (!nextFrame || (newFrame->sort_time < nextFrame->sort_time))
1183       {
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;
1188       }
1189       queueWalker = nextFrame;
1190     }
1191   }
1192   ctx->m_queue_depth++;
1193   //
1194   pthread_mutex_unlock(&ctx->m_queue_mutex);    
1195 }
1196
1197 #endif