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