crystalhd.c 22 KB
Newer Older
1
/*****************************************************************************
2 3
 * crystalhd.c: CrystalHD decoder
 *****************************************************************************
4
 * Copyright © 2010-2011 VideoLAN
5 6 7 8
 *
 * Authors: Jean-Baptiste Kempf <jb@videolan.org>
 *          Narendra Sankar <nsankar@broadcom.com>
 *
9 10
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
11 12 13 14 15
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
Jean-Baptiste Kempf committed
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 21
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 23 24 25 26 27 28 29 30 31
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32 33 34 35 36 37
/* TODO
 * - pts = 0?
 * - mpeg4-asp
 * - win32 testing
 */

38 39 40 41
/* VLC includes */
#include <vlc_common.h>
#include <vlc_plugin.h>
#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 48 49 50 51
#endif

/* CrystalHD */
#include <libcrystalhd/bc_dts_defs.h>
#include <libcrystalhd/bc_dts_types.h>
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

#if defined(HAVE_LIBCRYSTALHD_BC_DRV_IF_H) /* Win32 */
#  include <libcrystalhd/bc_drv_if.h>
#elif defined(_WIN32)
#  define USE_DL_OPENING 1
#else
#  include <libcrystalhd/libcrystalhd_if.h>
#endif

/* On a normal Win32 build, well aren't going to ship the BCM dll
   And forcing users to install the right dll at the right place will not work
   Therefore, we need to dl_open and resolve the symbols */
#ifdef USE_DL_OPENING
#  warning DLL opening mode
#  define BC_FUNC( a ) Our ## a
#  define BC_FUNC_PSYS( a ) p_sys->Our ## a
68
#else
69 70
#  define BC_FUNC( a ) a
#  define BC_FUNC_PSYS( a ) a
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
#endif

#include <assert.h>

/* BC pts are multiple of 100ns */
#define TO_BC_PTS( a ) ( a * 10 + 1 )
#define FROM_BC_PTS( a ) ((a - 1) /10)

//#define DEBUG_CRYSTALHD 1

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int        OpenDecoder  ( vlc_object_t * );
static void       CloseDecoder ( vlc_object_t * );

vlc_module_begin ()
    set_category( CAT_INPUT )
    set_subcategory( SUBCAT_INPUT_VCODEC )
    set_description( N_("Crystal HD hardware video decoder") )
    set_capability( "decoder", 0 )
    set_callbacks( OpenDecoder, CloseDecoder )
    add_shortcut( "crystalhd" )
vlc_module_end ()

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
static picture_t *DecodeBlock   ( decoder_t *p_dec, block_t **pp_block );
100
// static void crystal_CopyPicture ( picture_t *, BC_DTS_PROC_OUT* );
101 102 103 104 105 106 107 108 109 110 111 112 113
static int crystal_insert_sps_pps(decoder_t *, uint8_t *, uint32_t);

/*****************************************************************************
 * decoder_sys_t : CrysalHD decoder structure
 *****************************************************************************/
struct decoder_sys_t
{
    HANDLE bcm_handle;       /* Device Handle */

    uint8_t *p_sps_pps_buf;  /* SPS/PPS buffer */
    uint32_t i_sps_pps_size; /* SPS/PPS size */

    uint32_t i_nal_size;     /* NAL header size */
114

115 116 117 118
    /* Callback */
    picture_t       *p_pic;
    BC_DTS_PROC_OUT *proc_out;

119 120 121 122 123 124
#ifdef USE_DL_OPENING
    HINSTANCE p_bcm_dll;
    BC_STATUS (WINAPI *OurDtsCloseDecoder)( HANDLE hDevice );
    BC_STATUS (WINAPI *OurDtsDeviceClose)( HANDLE hDevice );
    BC_STATUS (WINAPI *OurDtsFlushInput)( HANDLE hDevice, U32 Mode );
    BC_STATUS (WINAPI *OurDtsStopDecoder)( HANDLE hDevice );
125 126
    BC_STATUS (WINAPI *OurDtsGetDriverStatus)( HANDLE hDevice,
                            BC_DTS_STATUS *pStatus );
127 128
    BC_STATUS (WINAPI *OurDtsProcInput)( HANDLE hDevice, U8 *pUserData,
                            U32 ulSizeInBytes, U64 timeStamp, BOOL encrypted );
129 130
    BC_STATUS (WINAPI *OurDtsProcOutput)( HANDLE hDevice, U32 milliSecWait,
                            BC_DTS_PROC_OUT *pOut );
131 132
    BC_STATUS (WINAPI *OurDtsIsEndOfStream)( HANDLE hDevice, U8* bEOS );
#endif
133 134 135
};

/*****************************************************************************
136 137
* OpenDecoder: probe the decoder and return score
*****************************************************************************/
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
static int OpenDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t*)p_this;
    decoder_sys_t *p_sys;

    /* Codec specifics */
    uint32_t i_bcm_codec_subtype = 0;
    switch ( p_dec->fmt_in.i_codec )
    {
    case VLC_CODEC_H264:
        if( p_dec->fmt_in.i_original_fourcc == VLC_FOURCC( 'a', 'v', 'c', '1' ) )
            i_bcm_codec_subtype = BC_MSUBTYPE_AVC1;
        else
            i_bcm_codec_subtype = BC_MSUBTYPE_H264;
        break;
    case VLC_CODEC_VC1:
        i_bcm_codec_subtype = BC_MSUBTYPE_VC1;
        break;
    case VLC_CODEC_WMV3:
        i_bcm_codec_subtype = BC_MSUBTYPE_WMV3;
        break;
    case VLC_CODEC_WMVA:
        i_bcm_codec_subtype = BC_MSUBTYPE_WMVA;
        break;
    case VLC_CODEC_MPGV:
        i_bcm_codec_subtype = BC_MSUBTYPE_MPEG2VIDEO;
        break;
/* Not ready for production yet
    case VLC_CODEC_MP4V:
        i_bcm_codec_subtype = BC_MSUBTYPE_DIVX;
168 169 170
        break;
    case VLC_CODEC_DIV3:
        i_bcm_codec_subtype = BC_MSUBTYPE_DIVX311;
171 172 173 174 175 176 177 178 179 180 181
        break; */
    default:
        return VLC_EGENERIC;
    }

    /* Allocate the memory needed to store the decoder's structure */
    p_sys = malloc( sizeof(*p_sys) );
    if( !p_sys )
        return VLC_ENOMEM;

    /* Fill decoder_sys_t */
182 183 184 185 186 187
    p_dec->p_sys            = p_sys;
    p_sys->i_nal_size       = 4; // assume 4 byte start codes
    p_sys->i_sps_pps_size   = 0;
    p_sys->p_sps_pps_buf    = NULL;
    p_dec->p_sys->p_pic     = NULL;
    p_dec->p_sys->proc_out  = NULL;
188

189 190 191 192
    /* Win32 code *
     * We cannot link and ship BCM dll, even with LGPL license (too big)
     * and if we don't ship it, the plugin would not work depending on the
     * installation order => DLopen */
193
#ifdef USE_DL_OPENING
194 195 196 197 198 199 200 201 202
#  define DLL_NAME "bcmDIL.dll"
#  define PATHS_NB 3
    static const char *psz_paths[PATHS_NB] = {
    DLL_NAME,
    "C:\\Program Files\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME,
    "C:\\Program Files (x86)\\Broadcom\\Broadcom CrystalHD Decoder\\" DLL_NAME,
    };
    for( int i = 0; i < PATHS_NB; i++ )
    {
203
        HINSTANCE p_bcm_dll = LoadLibraryA( psz_paths[i] );
204 205 206 207 208 209
        if( p_bcm_dll )
        {
            p_sys->p_bcm_dll = p_bcm_dll;
            break;
        }
    }
210 211 212 213 214 215 216
    if( !p_sys->p_bcm_dll )
    {
        msg_Dbg( p_dec, "Couldn't load the CrystalHD dll");
        return VLC_EGENERIC;
    }

#define LOAD_SYM( a ) \
217
    BC_FUNC( a )  = (void *)GetProcAddress( p_sys->p_bcm_dll, ( #a ) ); \
218 219
    if( !BC_FUNC( a ) ) { \
        msg_Err( p_dec, "missing symbol " # a ); return VLC_EGENERIC; }
220 221

#define LOAD_SYM_PSYS( a ) \
222 223 224
    p_sys->BC_FUNC( a )  = (void *)GetProcAddress( p_sys->p_bcm_dll, #a ); \
    if( !p_sys->BC_FUNC( a ) ) { \
        msg_Err( p_dec, "missing symbol " # a ); return VLC_EGENERIC; }
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

    BC_STATUS (WINAPI *OurDtsDeviceOpen)( HANDLE *hDevice, U32 mode );
    LOAD_SYM( DtsDeviceOpen );
    BC_STATUS (WINAPI *OurDtsCrystalHDVersion)( HANDLE  hDevice, PBC_INFO_CRYSTAL bCrystalInfo );
    LOAD_SYM( DtsCrystalHDVersion );
    BC_STATUS (WINAPI *OurDtsSetColorSpace)( HANDLE hDevice, BC_OUTPUT_FORMAT Mode422 );
    LOAD_SYM( DtsSetColorSpace );
    BC_STATUS (WINAPI *OurDtsSetInputFormat)( HANDLE hDevice, BC_INPUT_FORMAT *pInputFormat );
    LOAD_SYM( DtsSetInputFormat );
    BC_STATUS (WINAPI *OurDtsOpenDecoder)( HANDLE hDevice, U32 StreamType );
    LOAD_SYM( DtsOpenDecoder );
    BC_STATUS (WINAPI *OurDtsStartDecoder)( HANDLE hDevice );
    LOAD_SYM( DtsStartDecoder );
    BC_STATUS (WINAPI *OurDtsStartCapture)( HANDLE hDevice );
    LOAD_SYM( DtsStartCapture );
    LOAD_SYM_PSYS( DtsCloseDecoder );
    LOAD_SYM_PSYS( DtsDeviceClose );
    LOAD_SYM_PSYS( DtsFlushInput );
    LOAD_SYM_PSYS( DtsStopDecoder );
    LOAD_SYM_PSYS( DtsGetDriverStatus );
    LOAD_SYM_PSYS( DtsProcInput );
    LOAD_SYM_PSYS( DtsProcOutput );
    LOAD_SYM_PSYS( DtsIsEndOfStream );
#undef LOAD_SYM
#undef LOAD_SYM_PSYS
#endif /* USE_DL_OPENING */
251 252 253 254 255 256

#ifdef DEBUG_CRYSTALHD
    msg_Dbg( p_dec, "Trying to open CrystalHD HW");
#endif

    /* Get the handle for the device */
257
    if( BC_FUNC(DtsDeviceOpen)( &p_sys->bcm_handle,
258 259 260
             (DTS_PLAYBACK_MODE | DTS_LOAD_FILE_PLAY_FW | DTS_SKIP_TX_CHK_CPB) )
             // | DTS_DFLT_RESOLUTION(vdecRESOLUTION_720p29_97) ) )
             != BC_STS_SUCCESS )
261 262 263 264 265 266 267 268
    {
        msg_Err( p_dec, "Couldn't find and open the BCM CrystalHD device" );
        free( p_sys );
        return VLC_EGENERIC;
    }

#ifdef DEBUG_CRYSTALHD
    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 273 274 275 276 277 278
            "Library version: %i.%i.%i, Firmware version: %i.%i.%i",
            info.drvVersion.drvRelease, info.drvVersion.drvMajor,
            info.drvVersion.drvMinor,
            info.dilVersion.dilRelease, info.dilVersion.dilMajor,
            info.dilVersion.dilMinor,
            info.fwVersion.fwRelease,   info.fwVersion.fwMajor,
            info.fwVersion.fwMinor );
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
    }
#endif

    /* Special case for AVC1 */
    if( i_bcm_codec_subtype == BC_MSUBTYPE_AVC1 )
    {
        if( p_dec->fmt_in.i_extra > 0 )
        {
            msg_Dbg( p_dec, "Parsing extra infos for avc1" );
            if( crystal_insert_sps_pps( p_dec, (uint8_t*)p_dec->fmt_in.p_extra,
                        p_dec->fmt_in.i_extra ) != VLC_SUCCESS )
                goto error;
        }
        else
        {
            msg_Err( p_dec, "Missing extra infos for avc1" );
            goto error;
        }
    }

299
    /* Always use YUY2 color */
300 301
    if( BC_FUNC(DtsSetColorSpace)( p_sys->bcm_handle, OUTPUT_MODE422_YUY2 )
            != BC_STS_SUCCESS )
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
    {
        msg_Err( p_dec, "Couldn't set the color space. Please report this!" );
        goto error;
    }

    /* Prepare Input for the device */
    BC_INPUT_FORMAT p_in;
    memset( &p_in, 0, sizeof(BC_INPUT_FORMAT) );
    p_in.OptFlags    = 0x51; /* 0b 0 1 01 0001 */
    p_in.mSubtype    = i_bcm_codec_subtype;
    p_in.startCodeSz = p_sys->i_nal_size;
    p_in.pMetaData   = p_sys->p_sps_pps_buf;
    p_in.metaDataSz  = p_sys->i_sps_pps_size;
    p_in.width       = p_dec->fmt_in.video.i_width;
    p_in.height      = p_dec->fmt_in.video.i_height;
    p_in.Progressive = true;

319
    if( BC_FUNC(DtsSetInputFormat)( p_sys->bcm_handle, &p_in ) != BC_STS_SUCCESS )
320 321 322 323 324 325
    {
        msg_Err( p_dec, "Couldn't set the color space. Please report this!" );
        goto error;
    }

    /* Open a decoder */
326 327
    if( BC_FUNC(DtsOpenDecoder)( p_sys->bcm_handle, BC_STREAM_TYPE_ES )
            != BC_STS_SUCCESS )
328 329 330 331 332 333
    {
        msg_Err( p_dec, "Couldn't open the CrystalHD decoder" );
        goto error;
    }

    /* Start it */
334
    if( BC_FUNC(DtsStartDecoder)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
335 336 337 338 339
    {
        msg_Err( p_dec, "Couldn't start the decoder" );
        goto error;
    }

340
    if( BC_FUNC(DtsStartCapture)( p_sys->bcm_handle ) != BC_STS_SUCCESS )
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
    {
        msg_Err( p_dec, "Couldn't start the capture" );
        goto error_complete;
    }

    /* Set output properties */
    p_dec->fmt_out.i_cat          = VIDEO_ES;
    p_dec->fmt_out.i_codec        = VLC_CODEC_YUYV;
    p_dec->fmt_out.video.i_width  = p_dec->fmt_in.video.i_width;
    p_dec->fmt_out.video.i_height = p_dec->fmt_in.video.i_height;
    p_dec->b_need_packetized      = true;

    /* Set callbacks */
    p_dec->pf_decode_video = DecodeBlock;

    msg_Info( p_dec, "Opened CrystalHD hardware with success" );
    return VLC_SUCCESS;

error_complete:
360
    BC_FUNC_PSYS(DtsCloseDecoder)( p_sys->bcm_handle );
361
error:
362
    BC_FUNC_PSYS(DtsDeviceClose)( p_sys->bcm_handle );
363 364 365 366 367 368 369 370 371 372 373 374
    free( p_sys );
    return VLC_EGENERIC;
}

/*****************************************************************************
 * CloseDecoder: decoder destruction
 *****************************************************************************/
static void CloseDecoder( vlc_object_t *p_this )
{
    decoder_t *p_dec = (decoder_t *)p_this;
    decoder_sys_t *p_sys = p_dec->p_sys;

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 383 384 385 386 387 388 389 390 391
        goto error;

error:
    free( p_sys->p_sps_pps_buf );
#ifdef DEBUG_CRYSTALHD
    msg_Dbg( p_dec, "done cleaning up CrystalHD" );
#endif
    free( p_sys );
}

392 393
static BC_STATUS ourCallback(void *shnd, uint32_t width, uint32_t height, uint32_t stride, void *pOut)
{
394 395
    VLC_UNUSED(width); VLC_UNUSED(height); VLC_UNUSED(stride);

396 397
    decoder_t *p_dec          = (decoder_t *)shnd;
    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 402 403 404 405 406 407
    /* Do not allocate for the second-field in the pair, in interlaced */
    if( !(proc_in->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) ||
        !(proc_in->PicInfo.flags & VDEC_FLAG_FIELDPAIR) )
        p_dec->p_sys->p_pic = decoder_NewPicture( p_dec );

    /* */
    picture_t *p_pic = p_dec->p_sys->p_pic;
408 409 410
    if( !p_pic )
        return BC_STS_ERROR;

411 412 413 414 415 416 417 418 419 420 421 422 423 424
    /* Interlacing */
    p_pic->b_progressive     = !(proc_in->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC);
    p_pic->b_top_field_first = !(proc_in->PicInfo.flags & VDEC_FLAG_BOTTOM_FIRST);
    p_pic->i_nb_fields       = p_pic->b_progressive? 1: 2;

    /* Filling out the struct */
    proc_out->Ybuff      = !(proc_in->PicInfo.flags & VDEC_FLAG_FIELDPAIR) ?
                             &p_pic->p[0].p_pixels[0] :
                             &p_pic->p[0].p_pixels[p_pic->p[0].i_pitch];
    proc_out->YbuffSz    = 2 * p_pic->p[0].i_pitch;
    proc_out->StrideSz   = (proc_in->PicInfo.flags & VDEC_FLAG_INTERLACED_SRC)?
                            2 * (p_pic->p[0].i_pitch/2) - p_dec->fmt_out.video.i_width:
                            p_pic->p[0].i_pitch/2 - p_dec->fmt_out.video.i_width;
    proc_out->PoutFlags |= BC_POUT_FLAGS_STRIDE;              /* Trust Stride info */
425 426 427 428

    return BC_STS_SUCCESS;
}

429 430 431 432 433 434 435 436 437 438 439 440
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************/
static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;

    BC_DTS_PROC_OUT proc_out;
    BC_DTS_STATUS driver_stat;

    /* 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 443 444 445 446 447 448 449 450
        return NULL;

    p_block = *pp_block;
    if( p_block )
    {
        if( ( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) == 0 )
        {
            /* Valid input block, so we can send to HW to decode */

451 452 453 454
            BC_STATUS status = BC_FUNC_PSYS(DtsProcInput)( p_sys->bcm_handle,
                                            p_block->p_buffer,
                                            p_block->i_buffer,
                                            p_block->i_pts >= VLC_TS_INVALID ? TO_BC_PTS(p_block->i_pts) : 0, false );
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478

            block_Release( p_block );
            *pp_block = NULL;

            if( status != BC_STS_SUCCESS )
                return NULL;
        }
    }
#ifdef DEBUG_CRYSTALHD
    else
    {
        if( driver_stat.ReadyListCount != 0 )
            msg_Err( p_dec, " Input NULL but have pictures %u", driver_stat.ReadyListCount );
    }
#endif

    if( driver_stat.ReadyListCount == 0 )
        return NULL;

    /* Prepare the Output structure */
    /* We always expect and use YUY2 */
    memset( &proc_out, 0, sizeof(BC_DTS_PROC_OUT) );
    proc_out.PicInfo.width  = p_dec->fmt_out.video.i_width;
    proc_out.PicInfo.height = p_dec->fmt_out.video.i_height;
479
    proc_out.PoutFlags      = BC_POUT_FLAGS_SIZE;
480 481 482
    proc_out.AppCallBack    = ourCallback;
    proc_out.hnd            = p_dec;
    p_sys->proc_out         = &proc_out;
483

484
    /* */
485
    BC_STATUS sts = BC_FUNC_PSYS(DtsProcOutput)( p_sys->bcm_handle, 128, &proc_out );
486 487 488 489 490 491
#ifdef DEBUG_CRYSTALHD
    if( sts != BC_STS_SUCCESS )
        msg_Err( p_dec, "DtsProcOutput returned %i", sts );
#endif

    uint8_t b_eos;
492
    picture_t *p_pic = p_sys->p_pic;
493 494 495 496 497 498 499 500 501 502 503 504
    switch( sts )
    {
        case BC_STS_SUCCESS:
            if( !(proc_out.PoutFlags & BC_POUT_FLAGS_PIB_VALID) )
            {
                msg_Dbg( p_dec, "Invalid PIB" );
                break;
            }

            if( !p_pic )
                break;

505 506 507 508 509
            /* In interlaced mode, do not push the first field in the pipeline */
            if( (proc_out.PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) &&
               !(proc_out.PicInfo.flags & VDEC_FLAG_FIELDPAIR) )
                return NULL;

510
            //  crystal_CopyPicture( p_pic, &proc_out );
511 512
            p_pic->date = proc_out.PicInfo.timeStamp > 0 ?
                          FROM_BC_PTS(proc_out.PicInfo.timeStamp) : VLC_TS_INVALID;
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532
            //p_pic->date += 100 * 1000;
#ifdef DEBUG_CRYSTALHD
            msg_Dbg( p_dec, "TS Output is %"PRIu64, p_pic->date);
#endif
            return p_pic;

        case BC_STS_DEC_NOT_OPEN:
        case BC_STS_DEC_NOT_STARTED:
            msg_Err( p_dec, "Decoder not opened or started" );
            break;

        case BC_STS_INV_ARG:
            msg_Warn( p_dec, "Invalid arguments. Please report" );
            break;

        case BC_STS_FMT_CHANGE:    /* Format change */
            /* if( !(proc_out.PoutFlags & BC_POUT_FLAGS_PIB_VALID) )
                break; */
            p_dec->fmt_out.video.i_width  = proc_out.PicInfo.width;
            p_dec->fmt_out.video.i_height = proc_out.PicInfo.height;
533 534
            if( proc_out.PicInfo.height == 1088 )
                p_dec->fmt_out.video.i_height = 1080;
535 536
#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;
537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
            switch( proc_out.PicInfo.aspect_ratio )
            {
                setAR( vdecAspectRatioSquare, 1, 1 )
                setAR( vdecAspectRatio12_11, 12, 11 )
                setAR( vdecAspectRatio10_11, 10, 11 )
                setAR( vdecAspectRatio16_11, 16, 11 )
                setAR( vdecAspectRatio40_33, 40, 33 )
                setAR( vdecAspectRatio24_11, 24, 11 )
                setAR( vdecAspectRatio20_11, 20, 11 )
                setAR( vdecAspectRatio32_11, 32, 11 )
                setAR( vdecAspectRatio80_33, 80, 33 )
                setAR( vdecAspectRatio18_11, 18, 11 )
                setAR( vdecAspectRatio15_11, 15, 11 )
                setAR( vdecAspectRatio64_33, 64, 33 )
                setAR( vdecAspectRatio160_99, 160, 99 )
                setAR( vdecAspectRatio4_3, 4, 3 )
                setAR( vdecAspectRatio16_9, 16, 9 )
                setAR( vdecAspectRatio221_1, 221, 1 )
                default: break;
            }
#undef setAR
            msg_Dbg( p_dec, "Format Change Detected [%i, %i], AR: %i/%i",
                    proc_out.PicInfo.width, proc_out.PicInfo.height,
560 561
                    p_dec->fmt_out.video.i_sar_num,
                    p_dec->fmt_out.video.i_sar_den );
562 563 564 565
            break;

        /* Nothing is documented here... */
        case BC_STS_NO_DATA:
566 567
            if( BC_FUNC_PSYS(DtsIsEndOfStream)( p_sys->bcm_handle, &b_eos )
                    == BC_STS_SUCCESS )
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
                if( b_eos )
                    msg_Dbg( p_dec, "End of Stream" );
            break;
        case BC_STS_TIMEOUT:       /* Timeout */
            msg_Err( p_dec, "ProcOutput timeout" );
            break;
        case BC_STS_IO_XFR_ERROR:
        case BC_STS_IO_USER_ABORT:
        case BC_STS_IO_ERROR:
            msg_Err( p_dec, "ProcOutput return mode not implemented. Please report" );
            break;
        default:
            msg_Err( p_dec, "Unknown return status. Please report %i", sts );
            break;
    }
583 584
    if( p_pic )
        decoder_DeletePicture( p_dec, p_pic );
585 586 587
    return NULL;
}

588
#if 0
589 590 591 592 593 594 595 596 597 598 599 600 601
/* Copy the data
 * FIXME: this should not exist */
static void crystal_CopyPicture ( picture_t *p_pic, BC_DTS_PROC_OUT* p_out )
{
    int i_dst_stride;
    uint8_t *p_dst, *p_dst_end;
    uint8_t *p_src = p_out->Ybuff;

    p_dst         = p_pic->p[0].p_pixels;
    i_dst_stride  = p_pic->p[0].i_pitch;
    p_dst_end     = p_dst  + (i_dst_stride * p_out->PicInfo.height);

    for( ; p_dst < p_dst_end; p_dst += i_dst_stride, p_src += (p_out->PicInfo.width * 2))
Rafaël Carré's avatar
Rafaël Carré committed
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 608 609
static int crystal_insert_sps_pps( decoder_t *p_dec,
                                   uint8_t *p_buf,
                                   uint32_t i_buf_size)
610 611
{
    decoder_sys_t *p_sys = p_dec->p_sys;
612
    int ret;
613 614 615 616 617 618 619

    p_sys->i_sps_pps_size = 0;

    p_sys->p_sps_pps_buf = malloc( p_dec->fmt_in.i_extra * 2 );
    if( !p_sys->p_sps_pps_buf )
        return VLC_ENOMEM;

620 621 622 623 624
    ret = convert_sps_pps( p_dec, p_buf, i_buf_size, p_sys->p_sps_pps_buf,
                           p_dec->fmt_in.i_extra * 2, &p_sys->i_sps_pps_size,
                           &p_sys->i_nal_size );
    if( !ret )
        return ret;
625 626 627

    free( p_sys->p_sps_pps_buf );
    p_sys->p_sps_pps_buf = NULL;
628
    return ret;
629 630
}