]> git.sesse.net Git - vlc/blob - modules/codec/crystalhd.c
block_t ** parameter is never NULL for audio decoding
[vlc] / modules / codec / crystalhd.c
1 /*****************************************************************************
2  * Copyright © 2010-2011 VideoLAN
3  *
4  * Authors: Jean-Baptiste Kempf <jb@videolan.org>
5  *          Narendra Sankar <nsankar@broadcom.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20  *****************************************************************************/
21
22 /*****************************************************************************
23  * Preamble
24  *****************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 /* TODO
31  * - pts = 0?
32  * - mpeg4-asp
33  * - win32 testing
34  */
35
36 /* VLC includes */
37 #include <vlc_common.h>
38 #include <vlc_plugin.h>
39 #include <vlc_codec.h>
40
41 /* Workaround for some versions of libcrystalHD */
42 #if !defined(_WIN32) && !defined(__APPLE__)
43 #  define __LINUX_USER__
44 #endif
45
46 /* CrystalHD */
47 #include <libcrystalhd/bc_dts_defs.h>
48 #include <libcrystalhd/bc_dts_types.h>
49
50 #if defined(HAVE_LIBCRYSTALHD_BC_DRV_IF_H) /* Win32 */
51 #  include <libcrystalhd/bc_drv_if.h>
52 #elif defined(_WIN32)
53 #  define USE_DL_OPENING 1
54 #else
55 #  include <libcrystalhd/libcrystalhd_if.h>
56 #endif
57
58 /* On a normal Win32 build, well aren't going to ship the BCM dll
59    And forcing users to install the right dll at the right place will not work
60    Therefore, we need to dl_open and resolve the symbols */
61 #ifdef USE_DL_OPENING
62 #  warning DLL opening mode
63 #  define BC_FUNC( a ) Our ## a
64 #  define BC_FUNC_PSYS( a ) p_sys->Our ## a
65 #else
66 #  define BC_FUNC( a ) a
67 #  define BC_FUNC_PSYS( a ) a
68 #endif
69
70 #include <assert.h>
71
72 /* BC pts are multiple of 100ns */
73 #define TO_BC_PTS( a ) ( a * 10 + 1 )
74 #define FROM_BC_PTS( a ) ((a - 1) /10)
75
76 //#define DEBUG_CRYSTALHD 1
77
78 /*****************************************************************************
79  * Module descriptor
80  *****************************************************************************/
81 static int        OpenDecoder  ( vlc_object_t * );
82 static void       CloseDecoder ( vlc_object_t * );
83
84 vlc_module_begin ()
85     set_category( CAT_INPUT )
86     set_subcategory( SUBCAT_INPUT_VCODEC )
87     set_description( N_("Crystal HD hardware video decoder") )
88     set_capability( "decoder", 0 )
89     set_callbacks( OpenDecoder, CloseDecoder )
90     add_shortcut( "crystalhd" )
91 vlc_module_end ()
92
93 /*****************************************************************************
94  * Local prototypes
95  *****************************************************************************/
96 static picture_t *DecodeBlock   ( decoder_t *p_dec, block_t **pp_block );
97 // static void crystal_CopyPicture ( picture_t *, BC_DTS_PROC_OUT* );
98 static int crystal_insert_sps_pps(decoder_t *, uint8_t *, uint32_t);
99
100 /*****************************************************************************
101  * decoder_sys_t : CrysalHD decoder structure
102  *****************************************************************************/
103 struct decoder_sys_t
104 {
105     HANDLE bcm_handle;       /* Device Handle */
106
107     uint8_t *p_sps_pps_buf;  /* SPS/PPS buffer */
108     uint32_t i_sps_pps_size; /* SPS/PPS size */
109
110     uint32_t i_nal_size;     /* NAL header size */
111
112     /* Callback */
113     picture_t       *p_pic;
114     BC_DTS_PROC_OUT *proc_out;
115
116 #ifdef USE_DL_OPENING
117     HINSTANCE p_bcm_dll;
118     BC_STATUS (WINAPI *OurDtsCloseDecoder)( HANDLE hDevice );
119     BC_STATUS (WINAPI *OurDtsDeviceClose)( HANDLE hDevice );
120     BC_STATUS (WINAPI *OurDtsFlushInput)( HANDLE hDevice, U32 Mode );
121     BC_STATUS (WINAPI *OurDtsStopDecoder)( HANDLE hDevice );
122     BC_STATUS (WINAPI *OurDtsGetDriverStatus)( HANDLE hDevice,
123                             BC_DTS_STATUS *pStatus );
124     BC_STATUS (WINAPI *OurDtsProcInput)( HANDLE hDevice, U8 *pUserData,
125                             U32 ulSizeInBytes, U64 timeStamp, BOOL encrypted );
126     BC_STATUS (WINAPI *OurDtsProcOutput)( HANDLE hDevice, U32 milliSecWait,
127                             BC_DTS_PROC_OUT *pOut );
128     BC_STATUS (WINAPI *OurDtsIsEndOfStream)( HANDLE hDevice, U8* bEOS );
129 #endif
130 };
131
132 /*****************************************************************************
133 * OpenDecoder: probe the decoder and return score
134 *****************************************************************************/
135 static int OpenDecoder( vlc_object_t *p_this )
136 {
137     decoder_t *p_dec = (decoder_t*)p_this;
138     decoder_sys_t *p_sys;
139
140     /* Codec specifics */
141     uint32_t i_bcm_codec_subtype = 0;
142     switch ( p_dec->fmt_in.i_codec )
143     {
144     case VLC_CODEC_H264:
145         if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
146             i_bcm_codec_subtype = BC_MSUBTYPE_AVC1;
147         else
148             i_bcm_codec_subtype = BC_MSUBTYPE_H264;
149         break;
150     case VLC_CODEC_VC1:
151         i_bcm_codec_subtype = BC_MSUBTYPE_VC1;
152         break;
153     case VLC_CODEC_WMV3:
154         i_bcm_codec_subtype = BC_MSUBTYPE_WMV3;
155         break;
156     case VLC_CODEC_WMVA:
157         i_bcm_codec_subtype = BC_MSUBTYPE_WMVA;
158         break;
159     case VLC_CODEC_MPGV:
160         i_bcm_codec_subtype = BC_MSUBTYPE_MPEG2VIDEO;
161         break;
162 /* Not ready for production yet
163     case VLC_CODEC_MP4V:
164         i_bcm_codec_subtype = BC_MSUBTYPE_DIVX;
165         break;
166     case VLC_CODEC_DIV3:
167         i_bcm_codec_subtype = BC_MSUBTYPE_DIVX311;
168         break; */
169     default:
170         return VLC_EGENERIC;
171     }
172
173     /* Allocate the memory needed to store the decoder's structure */
174     p_sys = malloc( sizeof(*p_sys) );
175     if( !p_sys )
176         return VLC_ENOMEM;
177
178     /* Fill decoder_sys_t */
179     p_dec->p_sys            = p_sys;
180     p_sys->i_nal_size       = 4; // assume 4 byte start codes
181     p_sys->i_sps_pps_size   = 0;
182     p_sys->p_sps_pps_buf    = NULL;
183     p_dec->p_sys->p_pic     = NULL;
184     p_dec->p_sys->proc_out  = NULL;
185
186     /* Win32 code *
187      * We cannot link and ship BCM dll, even with LGPL license (too big)
188      * and if we don't ship it, the plugin would not work depending on the
189      * installation order => DLopen */
190 #ifdef USE_DL_OPENING
191 #  define DLL_NAME "bcmDIL.dll"
192 #  define PATHS_NB 3
193     static const char *psz_paths[PATHS_NB] = {
194     DLL_NAME,
195     "C:\\Program Files\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME,
196     "C:\\Program Files (x86)\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME,
197     };
198     for( int i = 0; i < PATHS_NB; i++ )
199     {
200         HINSTANCE p_bcm_dll = LoadLibrary( psz_paths[i] );
201         if( p_bcm_dll )
202         {
203             p_sys->p_bcm_dll = p_bcm_dll;
204             break;
205         }
206     }
207     if( !p_sys->p_bcm_dll )
208     {
209         msg_Dbg( p_dec, "Couldn't load the CrystalHD dll");
210         return VLC_EGENERIC;
211     }
212
213 #define LOAD_SYM( a ) \
214     BC_FUNC( a )  = (void *)GetProcAddress( p_sys->p_bcm_dll, TEXT( #a ) ); \
215     if( !BC_FUNC( a ) ) { \
216         msg_Err( p_dec, "missing symbol " # a ); return VLC_EGENERIC; }
217
218 #define LOAD_SYM_PSYS( a ) \
219     p_sys->BC_FUNC( a )  = (void *)GetProcAddress( p_sys->p_bcm_dll, #a ); \
220     if( !p_sys->BC_FUNC( a ) ) { \
221         msg_Err( p_dec, "missing symbol " # a ); return VLC_EGENERIC; }
222
223     BC_STATUS (WINAPI *OurDtsDeviceOpen)( HANDLE *hDevice, U32 mode );
224     LOAD_SYM( DtsDeviceOpen );
225     BC_STATUS (WINAPI *OurDtsCrystalHDVersion)( HANDLE  hDevice, PBC_INFO_CRYSTAL bCrystalInfo );
226     LOAD_SYM( DtsCrystalHDVersion );
227     BC_STATUS (WINAPI *OurDtsSetColorSpace)( HANDLE hDevice, BC_OUTPUT_FORMAT Mode422 );
228     LOAD_SYM( DtsSetColorSpace );
229     BC_STATUS (WINAPI *OurDtsSetInputFormat)( HANDLE hDevice, BC_INPUT_FORMAT *pInputFormat );
230     LOAD_SYM( DtsSetInputFormat );
231     BC_STATUS (WINAPI *OurDtsOpenDecoder)( HANDLE hDevice, U32 StreamType );
232     LOAD_SYM( DtsOpenDecoder );
233     BC_STATUS (WINAPI *OurDtsStartDecoder)( HANDLE hDevice );
234     LOAD_SYM( DtsStartDecoder );
235     BC_STATUS (WINAPI *OurDtsStartCapture)( HANDLE hDevice );
236     LOAD_SYM( DtsStartCapture );
237     LOAD_SYM_PSYS( DtsCloseDecoder );
238     LOAD_SYM_PSYS( DtsDeviceClose );
239     LOAD_SYM_PSYS( DtsFlushInput );
240     LOAD_SYM_PSYS( DtsStopDecoder );
241     LOAD_SYM_PSYS( DtsGetDriverStatus );
242     LOAD_SYM_PSYS( DtsProcInput );
243     LOAD_SYM_PSYS( DtsProcOutput );
244     LOAD_SYM_PSYS( DtsIsEndOfStream );
245 #undef LOAD_SYM
246 #undef LOAD_SYM_PSYS
247 #endif /* USE_DL_OPENING */
248
249 #ifdef DEBUG_CRYSTALHD
250     msg_Dbg( p_dec, "Trying to open CrystalHD HW");
251 #endif
252
253     /* Get the handle for the device */
254     if( BC_FUNC(DtsDeviceOpen)( &p_sys->bcm_handle,
255              (DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW | DTS_SKIP_TX_CHK_CPB) )
256              // | DTS_DFLT_RESOLUTION(vdecRESOLUTION_720p29_97) ) )
257              != BC_STS_SUCCESS )
258     {
259         msg_Err( p_dec, "Couldn't find and open the BCM CrystalHD device" );
260         free( p_sys );
261         return VLC_EGENERIC;
262     }
263
264 #ifdef DEBUG_CRYSTALHD
265     BC_INFO_CRYSTAL info;
266     if( BC_FUNC(DtsCrystalHDVersion)( p_sys->bcm_handle, &info ) == BC_STS_SUCCESS )
267     {
268         msg_Dbg( p_dec, "Using CrystalHD Driver version: %i.%i.%i, "
269             "Library version: %i.%i.%i, Firmware version: %i.%i.%i",
270             info.drvVersion.drvRelease, info.drvVersion.drvMajor,
271             info.drvVersion.drvMinor,
272             info.dilVersion.dilRelease, info.dilVersion.dilMajor,
273             info.dilVersion.dilMinor,
274             info.fwVersion.fwRelease,   info.fwVersion.fwMajor,
275             info.fwVersion.fwMinor );
276     }
277 #endif
278
279     /* Special case for AVC1 */
280     if( i_bcm_codec_subtype == BC_MSUBTYPE_AVC1 )
281     {
282         if( p_dec->fmt_in.i_extra > 0 )
283         {
284             msg_Dbg( p_dec, "Parsing extra infos for avc1" );
285             if( crystal_insert_sps_pps( p_dec, (uint8_t*)p_dec->fmt_in.p_extra,
286                         p_dec->fmt_in.i_extra ) != VLC_SUCCESS )
287                 goto error;
288         }
289         else
290         {
291             msg_Err( p_dec, "Missing extra infos for avc1" );
292             goto error;
293         }
294     }
295
296     /* Always use YUY2 color */
297     if( BC_FUNC(DtsSetColorSpace)( p_sys->bcm_handle, OUTPUT_MODE422_YUY2 )
298             != BC_STS_SUCCESS )
299     {
300         msg_Err( p_dec, "Couldn't set the color space. Please report this!" );
301         goto error;
302     }
303
304     /* Prepare Input for the device */
305     BC_INPUT_FORMAT p_in;
306     memset( &p_in, 0, sizeof(BC_INPUT_FORMAT) );
307     p_in.OptFlags    = 0x51; /* 0b 0 1 01 0001 */
308     p_in.mSubtype    = i_bcm_codec_subtype;
309     p_in.startCodeSz = p_sys->i_nal_size;
310     p_in.pMetaData   = p_sys->p_sps_pps_buf;
311     p_in.metaDataSz  = p_sys->i_sps_pps_size;
312     p_in.width       = p_dec->fmt_in.video.i_width;
313     p_in.height      = p_dec->fmt_in.video.i_height;
314     p_in.Progressive = true;
315
316     if( BC_FUNC(DtsSetInputFormat)( p_sys->bcm_handle, &p_in ) != BC_STS_SUCCESS )
317     {
318         msg_Err( p_dec, "Couldn't set the color space. Please report this!" );
319         goto error;
320     }
321
322     /* Open a decoder */
323     if( BC_FUNC(DtsOpenDecoder)( p_sys->bcm_handle, BC_STREAM_TYPE_ES )
324             != BC_STS_SUCCESS )
325     {
326         msg_Err( p_dec, "Couldn't open the CrystalHD decoder" );
327         goto error;
328     }
329
330     /* Start it */
331     if( BC_FUNC(DtsStartDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
332     {
333         msg_Err( p_dec, "Couldn't start the decoder" );
334         goto error;
335     }
336
337     if( BC_FUNC(DtsStartCapture)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
338     {
339         msg_Err( p_dec, "Couldn't start the capture" );
340         goto error_complete;
341     }
342
343     /* Set output properties */
344     p_dec->fmt_out.i_cat          = VIDEO_ES;
345     p_dec->fmt_out.i_codec        = VLC_CODEC_YUYV;
346     p_dec->fmt_out.video.i_width  = p_dec->fmt_in.video.i_width;
347     p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
348     p_dec->b_need_packetized      = true;
349
350     /* Set callbacks */
351     p_dec->pf_decode_video = DecodeBlock;
352
353     msg_Info( p_dec, "Opened CrystalHD hardware with success" );
354     return VLC_SUCCESS;
355
356 error_complete:
357     BC_FUNC_PSYS(DtsCloseDecoder)( p_sys->bcm_handle );
358 error:
359     BC_FUNC_PSYS(DtsDeviceClose)( p_sys->bcm_handle );
360     free( p_sys );
361     return VLC_EGENERIC;
362 }
363
364 /*****************************************************************************
365  * CloseDecoder: decoder destruction
366  *****************************************************************************/
367 static void CloseDecoder( vlc_object_t *p_this )
368 {
369     decoder_t *p_dec = (decoder_t *)p_this;
370     decoder_sys_t *p_sys = p_dec->p_sys;
371
372     if( BC_FUNC_PSYS(DtsFlushInput)( p_sys->bcm_handle, 2 ) != BC_STS_SUCCESS )
373         goto error;
374     if( BC_FUNC_PSYS(DtsStopDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
375         goto error;
376     if( BC_FUNC_PSYS(DtsCloseDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
377         goto error;
378     if( BC_FUNC_PSYS(DtsDeviceClose)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
379         goto error;
380
381 error:
382     free( p_sys->p_sps_pps_buf );
383 #ifdef DEBUG_CRYSTALHD
384     msg_Dbg( p_dec, "done cleaning up CrystalHD" );
385 #endif
386     free( p_sys );
387 }
388
389 static BC_STATUS ourCallback(void *shnd, uint32_t width, uint32_t height, uint32_t stride, void *pOut)
390 {
391     VLC_UNUSED(width); VLC_UNUSED(height); VLC_UNUSED(stride);
392
393     decoder_t *p_dec          = (decoder_t *)shnd;
394     BC_DTS_PROC_OUT *proc_out = p_dec->p_sys->proc_out;
395     BC_DTS_PROC_OUT *proc_in  = (BC_DTS_PROC_OUT*)pOut;
396
397     /* Direct Rendering */
398     /* Do not allocate for the second-field in the pair, in interlaced */
399     if( !(proc_in->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) ||
400         !(proc_in->PicInfo.flags & VDEC_FLAG_FIELDPAIR) )
401         p_dec->p_sys->p_pic = decoder_NewPicture( p_dec );
402
403     /* */
404     picture_t *p_pic = p_dec->p_sys->p_pic;
405     if( !p_pic )
406         return BC_STS_ERROR;
407
408     /* Interlacing */
409     p_pic->b_progressive     = !(proc_in->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC);
410     p_pic->b_top_field_first = !(proc_in->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
411     p_pic->i_nb_fields       = p_pic->b_progressive? 1: 2;
412
413     /* Filling out the struct */
414     proc_out->Ybuff      = !(proc_in->PicInfo.flags & VDEC_FLAG_FIELDPAIR) ?
415                              &p_pic->p[0].p_pixels[0] :
416                              &p_pic->p[0].p_pixels[p_pic->p[0].i_pitch];
417     proc_out->YbuffSz    = 2 * p_pic->p[0].i_pitch;
418     proc_out->StrideSz   = (proc_in->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC)?
419                             2 * (p_pic->p[0].i_pitch/2) - p_dec->fmt_out.video.i_width:
420                             p_pic->p[0].i_pitch/2 - p_dec->fmt_out.video.i_width;
421     proc_out->PoutFlags |= BC_POUT_FLAGS_STRIDE;              /* Trust Stride info */
422
423     return BC_STS_SUCCESS;
424 }
425
426 /****************************************************************************
427  * DecodeBlock: the whole thing
428  ****************************************************************************/
429 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
430 {
431     decoder_sys_t *p_sys = p_dec->p_sys;
432     block_t *p_block;
433
434     BC_DTS_PROC_OUT proc_out;
435     BC_DTS_STATUS driver_stat;
436
437     /* First check the status of the decode to produce pictures */
438     if( BC_FUNC_PSYS(DtsGetDriverStatus)( p_sys->bcm_handle, &driver_stat ) != BC_STS_SUCCESS )
439         return NULL;
440
441     p_block = *pp_block;
442     if( p_block )
443     {
444         if( ( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) == 0 )
445         {
446             /* Valid input block, so we can send to HW to decode */
447
448             BC_STATUS status = BC_FUNC_PSYS(DtsProcInput)( p_sys->bcm_handle,
449                                             p_block->p_buffer,
450                                             p_block->i_buffer,
451                                             p_block->i_pts >= VLC_TS_INVALID ? TO_BC_PTS(p_block->i_pts) : 0, false );
452
453             block_Release( p_block );
454             *pp_block = NULL;
455
456             if( status != BC_STS_SUCCESS )
457                 return NULL;
458         }
459     }
460 #ifdef DEBUG_CRYSTALHD
461     else
462     {
463         if( driver_stat.ReadyListCount != 0 )
464             msg_Err( p_dec, " Input NULL but have pictures %u", driver_stat.ReadyListCount );
465     }
466 #endif
467
468     if( driver_stat.ReadyListCount == 0 )
469         return NULL;
470
471     /* Prepare the Output structure */
472     /* We always expect and use YUY2 */
473     memset( &proc_out, 0, sizeof(BC_DTS_PROC_OUT) );
474     proc_out.PicInfo.width  = p_dec->fmt_out.video.i_width;
475     proc_out.PicInfo.height = p_dec->fmt_out.video.i_height;
476     proc_out.PoutFlags      = BC_POUT_FLAGS_SIZE;
477     proc_out.AppCallBack    = ourCallback;
478     proc_out.hnd            = p_dec;
479     p_sys->proc_out         = &proc_out;
480
481     /* */
482     BC_STATUS sts = BC_FUNC_PSYS(DtsProcOutput)( p_sys->bcm_handle, 128, &proc_out );
483 #ifdef DEBUG_CRYSTALHD
484     if( sts != BC_STS_SUCCESS )
485         msg_Err( p_dec, "DtsProcOutput returned %i", sts );
486 #endif
487
488     uint8_t b_eos;
489     picture_t *p_pic = p_sys->p_pic;
490     switch( sts )
491     {
492         case BC_STS_SUCCESS:
493             if( !(proc_out.PoutFlags & BC_POUT_FLAGS_PIB_VALID) )
494             {
495                 msg_Dbg( p_dec, "Invalid PIB" );
496                 break;
497             }
498
499             if( !p_pic )
500                 break;
501
502             /* In interlaced mode, do not push the first field in the pipeline */
503             if( (proc_out.PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&
504                !(proc_out.PicInfo.flags & VDEC_FLAG_FIELDPAIR) )
505                 return NULL;
506
507             //  crystal_CopyPicture( p_pic, &proc_out );
508             p_pic->date = proc_out.PicInfo.timeStamp > 0 ?
509                           FROM_BC_PTS(proc_out.PicInfo.timeStamp) : VLC_TS_INVALID;
510             //p_pic->date += 100 * 1000;
511 #ifdef DEBUG_CRYSTALHD
512             msg_Dbg( p_dec, "TS Output is %"PRIu64, p_pic->date);
513 #endif
514             return p_pic;
515
516         case BC_STS_DEC_NOT_OPEN:
517         case BC_STS_DEC_NOT_STARTED:
518             msg_Err( p_dec, "Decoder not opened or started" );
519             break;
520
521         case BC_STS_INV_ARG:
522             msg_Warn( p_dec, "Invalid arguments. Please report" );
523             break;
524
525         case BC_STS_FMT_CHANGE:    /* Format change */
526             /* if( !(proc_out.PoutFlags & BC_POUT_FLAGS_PIB_VALID) )
527                 break; */
528             p_dec->fmt_out.video.i_width  = proc_out.PicInfo.width;
529             p_dec->fmt_out.video.i_height = proc_out.PicInfo.height;
530             if( proc_out.PicInfo.height == 1088 )
531                 p_dec->fmt_out.video.i_height = 1080;
532 #define setAR( a, b, c ) case a: p_dec->fmt_out.video.i_sar_num = b; \
533                                  p_dec->fmt_out.video.i_sar_den = c; break;
534             switch( proc_out.PicInfo.aspect_ratio )
535             {
536                 setAR( vdecAspectRatioSquare, 1, 1 )
537                 setAR( vdecAspectRatio12_11, 12, 11 )
538                 setAR( vdecAspectRatio10_11, 10, 11 )
539                 setAR( vdecAspectRatio16_11, 16, 11 )
540                 setAR( vdecAspectRatio40_33, 40, 33 )
541                 setAR( vdecAspectRatio24_11, 24, 11 )
542                 setAR( vdecAspectRatio20_11, 20, 11 )
543                 setAR( vdecAspectRatio32_11, 32, 11 )
544                 setAR( vdecAspectRatio80_33, 80, 33 )
545                 setAR( vdecAspectRatio18_11, 18, 11 )
546                 setAR( vdecAspectRatio15_11, 15, 11 )
547                 setAR( vdecAspectRatio64_33, 64, 33 )
548                 setAR( vdecAspectRatio160_99, 160, 99 )
549                 setAR( vdecAspectRatio4_3, 4, 3 )
550                 setAR( vdecAspectRatio16_9, 16, 9 )
551                 setAR( vdecAspectRatio221_1, 221, 1 )
552                 default: break;
553             }
554 #undef setAR
555             msg_Dbg( p_dec, "Format Change Detected [%i, %i], AR: %i/%i",
556                     proc_out.PicInfo.width, proc_out.PicInfo.height,
557                     p_dec->fmt_out.video.i_sar_num,
558                     p_dec->fmt_out.video.i_sar_den );
559             break;
560
561         /* Nothing is documented here... */
562         case BC_STS_NO_DATA:
563             if( BC_FUNC_PSYS(DtsIsEndOfStream)( p_sys->bcm_handle, &b_eos )
564                     == BC_STS_SUCCESS )
565                 if( b_eos )
566                     msg_Dbg( p_dec, "End of Stream" );
567             break;
568         case BC_STS_TIMEOUT:       /* Timeout */
569             msg_Err( p_dec, "ProcOutput timeout" );
570             break;
571         case BC_STS_IO_XFR_ERROR:
572         case BC_STS_IO_USER_ABORT:
573         case BC_STS_IO_ERROR:
574             msg_Err( p_dec, "ProcOutput return mode not implemented. Please report" );
575             break;
576         default:
577             msg_Err( p_dec, "Unknown return status. Please report %i", sts );
578             break;
579     }
580     if( p_pic )
581         decoder_DeletePicture( p_dec, p_pic );
582     return NULL;
583 }
584
585 #if 0
586 /* Copy the data
587  * FIXME: this should not exist */
588 static void crystal_CopyPicture ( picture_t *p_pic, BC_DTS_PROC_OUT* p_out )
589 {
590     int i_dst_stride;
591     uint8_t *p_dst, *p_dst_end;
592     uint8_t *p_src = p_out->Ybuff;
593
594     p_dst         = p_pic->p[0].p_pixels;
595     i_dst_stride  = p_pic->p[0].i_pitch;
596     p_dst_end     = p_dst  + (i_dst_stride * p_out->PicInfo.height);
597
598     for( ; p_dst < p_dst_end; p_dst += i_dst_stride, p_src += (p_out->PicInfo.width * 2))
599         vlc_memcpy( p_dst, p_src, p_out->PicInfo.width * 2); // Copy in bytes
600 }
601 #endif
602
603 /* Parse the SPS/PPS Metadata to feed the decoder for avc1 */
604 static int crystal_insert_sps_pps( decoder_t *p_dec,
605                                    uint8_t *p_buf,
606                                    uint32_t i_buf_size)
607 {
608     decoder_sys_t *p_sys = p_dec->p_sys;
609     int i_profile;
610     uint32_t i_data_size = i_buf_size, i_nal_size;
611     unsigned int i_loop_end;
612
613     p_sys->i_sps_pps_size = 0;
614
615     p_sys->p_sps_pps_buf = malloc( p_dec->fmt_in.i_extra * 2 );
616     if( !p_sys->p_sps_pps_buf )
617         return VLC_ENOMEM;
618
619     /* */
620     if( i_data_size < 7 )
621     {
622         msg_Err( p_dec, "Input Metadata too small" );
623         goto error;
624     }
625
626     /* Read infos in first 6 bytes */
627     i_profile         = (p_buf[1] << 16) | (p_buf[2] << 8) | p_buf[3];
628     p_sys->i_nal_size = (p_buf[4] & 0x03) + 1;
629     p_buf            += 5;
630     i_data_size      -= 5;
631
632     for ( unsigned int j = 0; j < 2; j++ )
633     {
634         /* First time is SPS, Second is PPS */
635         if( i_data_size < 1 )
636         {
637             msg_Err( p_dec, "PPS too small after processing SPS/PPS %u",
638                     i_data_size );
639             goto error;
640         }
641         i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
642         p_buf++; i_data_size--;
643
644         for ( unsigned int i = 0; i < i_loop_end; i++)
645         {
646             if( i_data_size < 2 )
647             {
648                 msg_Err( p_dec, "SPS is too small %u", i_data_size );
649                 goto error;
650             }
651
652             i_nal_size = (p_buf[0] << 8) | p_buf[1];
653             p_buf += 2;
654             i_data_size -= 2;
655
656             if( i_data_size < i_nal_size )
657             {
658                 msg_Err( p_dec, "SPS size does not match NAL specified size %u",
659                         i_data_size );
660                 goto error;
661             }
662
663             p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 0;
664             p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 0;
665             p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 0;
666             p_sys->p_sps_pps_buf[p_sys->i_sps_pps_size++] = 1;
667
668             memcpy( p_sys->p_sps_pps_buf + p_sys->i_sps_pps_size, p_buf, i_nal_size );
669             p_sys->i_sps_pps_size += i_nal_size;
670
671             p_buf += i_nal_size;
672             i_data_size -= i_nal_size;
673         }
674     }
675
676     return VLC_SUCCESS;
677
678 error:
679     free( p_sys->p_sps_pps_buf );
680     p_sys->p_sps_pps_buf = NULL;
681     return VLC_ENOMEM;
682 }
683