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