1 /*****************************************************************************
2 * Copyright © 2010-2011 VideoLAN
4 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
5 * Narendra Sankar <nsankar@broadcom.com>
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.
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.
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 *****************************************************************************/
22 /*****************************************************************************
24 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
35 /* Workaround for some versions of libcrystalHD */
36 #if !defined(_WIN32) && !defined(__APPLE__)
37 # define __LINUX_USER__
41 #include <libcrystalhd/bc_dts_defs.h>
42 #include <libcrystalhd/bc_dts_types.h>
44 #if defined(HAVE_LIBCRYSTALHD_BC_DRV_IF_H) /* Win32 */
45 # include <libcrystalhd/bc_drv_if.h>
47 # define USE_DL_OPENING 1
49 # include <libcrystalhd/libcrystalhd_if.h>
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 */
56 # warning DLL opening mode
57 # define BC_FUNC( a ) Our ## a
58 # define BC_FUNC_PSYS( a ) p_sys->Our ## a
60 # define BC_FUNC( a ) a
61 # define BC_FUNC_PSYS( a ) a
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)
70 //#define DEBUG_CRYSTALHD 1
72 /*****************************************************************************
74 *****************************************************************************/
75 static int OpenDecoder ( vlc_object_t * );
76 static void CloseDecoder ( vlc_object_t * );
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" )
87 /*****************************************************************************
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);
94 /*****************************************************************************
95 * decoder_sys_t : CrysalHD decoder structure
96 *****************************************************************************/
99 HANDLE bcm_handle; /* Device Handle */
101 uint8_t *p_sps_pps_buf; /* SPS/PPS buffer */
102 uint32_t i_sps_pps_size; /* SPS/PPS size */
104 uint32_t i_nal_size; /* NAL header size */
106 #ifdef USE_DL_OPENING
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 );
120 /*****************************************************************************
121 * OpenDecoder: probe the decoder and return score
122 *****************************************************************************/
123 static int OpenDecoder( vlc_object_t *p_this )
125 decoder_t *p_dec = (decoder_t*)p_this;
126 decoder_sys_t *p_sys;
128 /* Codec specifics */
129 uint32_t i_bcm_codec_subtype = 0;
130 switch ( p_dec->fmt_in.i_codec )
133 if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
134 i_bcm_codec_subtype = BC_MSUBTYPE_AVC1;
136 i_bcm_codec_subtype = BC_MSUBTYPE_H264;
139 i_bcm_codec_subtype = BC_MSUBTYPE_VC1;
142 i_bcm_codec_subtype = BC_MSUBTYPE_WMV3;
145 i_bcm_codec_subtype = BC_MSUBTYPE_WMVA;
148 i_bcm_codec_subtype = BC_MSUBTYPE_MPEG2VIDEO;
150 /* Not ready for production yet
152 i_bcm_codec_subtype = BC_MSUBTYPE_DIVX;
155 i_bcm_codec_subtype = BC_MSUBTYPE_DIVX311;
161 /* Allocate the memory needed to store the decoder's structure */
162 p_sys = malloc( sizeof(*p_sys) );
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;
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"
179 static const char *psz_paths[PATHS_NB] = {
181 "C:\\Program Files\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME,
182 "C:\\Program Files (x86)\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME,
184 for( int i = 0; i < PATHS_NB; i++ )
186 HINSTANCE p_bcm_dll = LoadLibrary( psz_paths[i] );
189 p_sys->p_bcm_dll = p_bcm_dll;
193 if( !p_sys->p_bcm_dll )
195 msg_Dbg( p_dec, "Couldn't load the CrystalHD dll");
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; }
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; }
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 );
231 #endif /* USE_DL_OPENING */
233 #ifdef DEBUG_CRYSTALHD
234 msg_Dbg( p_dec, "Trying to open CrystalHD HW");
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) ) )
243 msg_Err( p_dec, "Couldn't find and open the BCM CrystalHD device" );
248 #ifdef DEBUG_CRYSTALHD
249 BC_INFO_CRYSTAL info;
250 if( BC_FUNC(DtsCrystalHDVersion)( p_sys->bcm_handle, &info ) == BC_STS_SUCCESS )
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 );
261 /* Special case for AVC1 */
262 if( i_bcm_codec_subtype == BC_MSUBTYPE_AVC1 )
264 if( p_dec->fmt_in.i_extra > 0 )
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 )
273 msg_Err( p_dec, "Missing extra infos for avc1" );
278 /* Always use YUY2 color */
279 if( BC_FUNC(DtsSetColorSpace)( p_sys->bcm_handle, OUTPUT_MODE422_YUY2 ) != BC_STS_SUCCESS )
281 msg_Err( p_dec, "Couldn't set the color space. Please report this!" );
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;
297 if( BC_FUNC(DtsSetInputFormat)( p_sys->bcm_handle, &p_in ) != BC_STS_SUCCESS )
299 msg_Err( p_dec, "Couldn't set the color space. Please report this!" );
304 if( BC_FUNC(DtsOpenDecoder)( p_sys->bcm_handle, BC_STREAM_TYPE_ES ) != BC_STS_SUCCESS )
306 msg_Err( p_dec, "Couldn't open the CrystalHD decoder" );
311 if( BC_FUNC(DtsStartDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
313 msg_Err( p_dec, "Couldn't start the decoder" );
317 if( BC_FUNC(DtsStartCapture)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
319 msg_Err( p_dec, "Couldn't start the capture" );
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;
331 p_dec->pf_decode_video = DecodeBlock;
333 msg_Info( p_dec, "Opened CrystalHD hardware with success" );
337 BC_FUNC_PSYS(DtsCloseDecoder)( p_sys->bcm_handle );
339 BC_FUNC_PSYS(DtsDeviceClose)( p_sys->bcm_handle );
344 /*****************************************************************************
345 * CloseDecoder: decoder destruction
346 *****************************************************************************/
347 static void CloseDecoder( vlc_object_t *p_this )
349 decoder_t *p_dec = (decoder_t *)p_this;
350 decoder_sys_t *p_sys = p_dec->p_sys;
352 if( BC_FUNC_PSYS(DtsFlushInput)( p_sys->bcm_handle, 2 ) != BC_STS_SUCCESS )
354 if( BC_FUNC_PSYS(DtsStopDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
356 if( BC_FUNC_PSYS(DtsCloseDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
358 if( BC_FUNC_PSYS(DtsDeviceClose)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
362 free( p_sys->p_sps_pps_buf );
363 #ifdef DEBUG_CRYSTALHD
364 msg_Dbg( p_dec, "done cleaning up CrystalHD" );
369 /****************************************************************************
370 * DecodeBlock: the whole thing
371 ****************************************************************************/
372 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
374 decoder_sys_t *p_sys = p_dec->p_sys;
377 BC_DTS_PROC_OUT proc_out;
378 BC_DTS_STATUS driver_stat;
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 )
389 if( ( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) == 0 )
391 /* Valid input block, so we can send to HW to decode */
393 BC_STATUS status = BC_FUNC_PSYS(DtsProcInput)( p_sys->bcm_handle,
396 p_block->i_pts >= VLC_TS_INVALID ? TO_BC_PTS(p_block->i_pts) : 0, false );
398 block_Release( p_block );
401 if( status != BC_STS_SUCCESS )
405 #ifdef DEBUG_CRYSTALHD
408 if( driver_stat.ReadyListCount != 0 )
409 msg_Err( p_dec, " Input NULL but have pictures %u", driver_stat.ReadyListCount );
413 if( driver_stat.ReadyListCount == 0 )
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?
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 );
428 if( !proc_out.Ybuff )
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 );
441 if( !(proc_out.PoutFlags & BC_POUT_FLAGS_PIB_VALID) )
443 msg_Dbg( p_dec, "Invalid PIB" );
447 p_pic = decoder_NewPicture( p_dec );
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);
457 free( proc_out.Ybuff );
460 case BC_STS_DEC_NOT_OPEN:
461 case BC_STS_DEC_NOT_STARTED:
462 msg_Err( p_dec, "Decoder not opened or started" );
466 msg_Warn( p_dec, "Invalid arguments. Please report" );
469 case BC_STS_FMT_CHANGE: /* Format change */
470 /* if( !(proc_out.PoutFlags & BC_POUT_FLAGS_PIB_VALID) )
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 )
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 )
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 );
503 /* Nothing is documented here... */
505 if( BC_FUNC_PSYS(DtsIsEndOfStream)( p_sys->bcm_handle, &b_eos ) == BC_STS_SUCCESS )
507 msg_Dbg( p_dec, "End of Stream" );
509 case BC_STS_TIMEOUT: /* Timeout */
510 msg_Err( p_dec, "ProcOutput timeout" );
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" );
518 msg_Err( p_dec, "Unknown return status. Please report %i", sts );
521 free( proc_out.Ybuff );
526 * FIXME: this should not exist */
527 static void crystal_CopyPicture ( picture_t *p_pic, BC_DTS_PROC_OUT* p_out )
530 uint8_t *p_dst, *p_dst_end;
531 uint8_t *p_src = p_out->Ybuff;
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);
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
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)
544 decoder_sys_t *p_sys = p_dec->p_sys;
546 uint32_t i_data_size = i_buf_size, i_nal_size;
547 unsigned int i_loop_end;
549 p_sys->i_sps_pps_size = 0;
551 p_sys->p_sps_pps_buf = malloc( p_dec->fmt_in.i_extra * 2 );
552 if( !p_sys->p_sps_pps_buf )
556 if( i_data_size < 7 )
558 msg_Err( p_dec, "Input Metadata too small" );
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;
568 for ( unsigned int j = 0; j < 2; j++ )
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 );
575 i_loop_end = p_buf[0] & (j == 0 ? 0x1f : 0xff);
576 p_buf++; i_data_size--;
578 for ( unsigned int i = 0; i < i_loop_end; i++)
580 if (i_data_size < 2 ) {
581 msg_Err( p_dec, "SPS is too small %u", i_data_size );
585 i_nal_size = (p_buf[0] << 8) | p_buf[1];
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 );
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;
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;
603 i_data_size -= i_nal_size;
610 free( p_sys->p_sps_pps_buf );
611 p_sys->p_sps_pps_buf = NULL;