Exemple #1
0
/*****************************************************************************
 * ffmpeg_InitCodec: setup codec extra initialization data for ffmpeg
 *****************************************************************************/
static void ffmpeg_InitCodec( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_size = p_dec->fmt_in.i_extra;

    if( !i_size ) return;

    if( p_sys->i_codec_id == CODEC_ID_SVQ3 )
    {
        uint8_t *p;

        p_sys->p_context->extradata_size = i_size + 12;
        p = p_sys->p_context->extradata  =
            malloc( p_sys->p_context->extradata_size );
        if( !p )
            return;

        memcpy( &p[0],  "SVQ3", 4 );
        memset( &p[4], 0, 8 );
        memcpy( &p[12], p_dec->fmt_in.p_extra, i_size );

        /* Now remove all atoms before the SMI one */
        if( p_sys->p_context->extradata_size > 0x5a &&
            strncmp( (char*)&p[0x56], "SMI ", 4 ) )
        {
            uint8_t *psz = &p[0x52];

            while( psz < &p[p_sys->p_context->extradata_size - 8] )
            {
                int i_size = GetDWBE( psz );
                if( i_size <= 1 )
                {
                    /* FIXME handle 1 as long size */
                    break;
                }
                if( !strncmp( (char*)&psz[4], "SMI ", 4 ) )
                {
                    memmove( &p[0x52], psz,
                             &p[p_sys->p_context->extradata_size] - psz );
                    break;
                }

                psz += i_size;
            }
        }
    }
    else
    {
        p_sys->p_context->extradata_size = i_size;
        p_sys->p_context->extradata =
            malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
        if( p_sys->p_context->extradata )
        {
            memcpy( p_sys->p_context->extradata,
                    p_dec->fmt_in.p_extra, i_size );
            memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
                    0, FF_INPUT_BUFFER_PADDING_SIZE );
        }
    }
}
Exemple #2
0
static void U32BDecode( void *outp, const uint8_t *in, unsigned samples )
{
    uint32_t *out = outp;

    for( size_t i = 0; i < samples; i++ )
    {
        *(out++) = GetDWBE( in ) - 0x80000000;
        in += 4;
    }
}
Exemple #3
0
static bool IsLbm(stream_t *s)
{
    const uint8_t *header;
    if (stream_Peek(s, &header, 12) < 12)
        return false;
    if (memcmp(&header[0], "FORM", 4) ||
        GetDWBE(&header[4]) <= 4 ||
        (memcmp(&header[8], "ILBM", 4) && memcmp(&header[8], "PBM ", 4)))
        return false;
    return true;
}
Exemple #4
0
/* Attempt to find dirac picture number in an encapsulation unit */
static int ReadDiracPictureNumber( uint32_t *p_picnum, block_t *p_block )
{
    uint32_t u_pos = 4;
    /* protect against falling off the edge */
    while( u_pos + 13 < p_block->i_buffer )
    {
        /* find the picture startcode */
        if( p_block->p_buffer[u_pos] & 0x08 )
        {
            *p_picnum = GetDWBE( p_block->p_buffer + u_pos + 9 );
            return 1;
        }
        /* skip to the next dirac data unit */
        uint32_t u_npo = GetDWBE( p_block->p_buffer + u_pos + 1 );
        assert( u_npo <= UINT32_MAX - u_pos );
        if( u_npo == 0 )
            u_npo = 13;
        u_pos += u_npo;
    }
    return 0;
}
Exemple #5
0
static void S32IDecode( void *outp, const uint8_t *in, unsigned samples )
{
    int32_t *out = outp;

    for( size_t i = 0; i < samples; i++ )
    {
#ifdef WORDS_BIGENDIAN
        *(out++) = GetDWLE( in );
#else
        *(out++) = GetDWBE( in );
#endif
        in += 4;
    }
}
static void F32IDecode( void *outp, const uint8_t *in, unsigned samples )
{
    float *out = outp;

    for( size_t i = 0; i < samples; i++ )
    {
        union { float f; uint32_t u; } s;

#ifdef WORDS_BIGENDIAN
        s.u = GetDWLE( in );
#else
        s.u = GetDWBE( in );
#endif
        *(out++) = s.f;
        in += 4;
    }
}
Exemple #7
0
/***
 * Packet (Data Unit) inspection, learns parameters from sequence
 * headers, sets up flags, drops unwanted data units, sets
 * encapsulation unit termination policy
 */
static int dirac_InspectDataUnit( decoder_t *p_dec, block_t **pp_block, block_t *p_eu )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block = *pp_block;
    uint8_t u_parse_code = p_block->p_buffer[4];

    if( dirac_isEOS( u_parse_code ) )
    {
        if( p_sys->b_seen_eos )
        {
            /* remove duplicate EOS packets */
            block_Release( p_block );
            *pp_block = NULL;
            return DIRAC_DU_IN_EU;
        }
        /* p_block is an EOS packet */
        p_eu->i_flags |= BLOCK_FLAG_END_OF_SEQUENCE;
        /* for the moment, let this end an encapsulation unit */
        /* seeing an eos packet requires a flush of the packetizer
         * this is detected by the caller of this function */
        p_sys->b_seen_seq_hdr = false;
        p_sys->b_seen_eos = true;
        return DIRAC_DU_ENDS_EU;
#if 0
        /* let anything down streem know too */
        /*
        Actually, this is a bad idea:
         - It sets the discontinuity for every dirac EOS packet
           which doesnt imply a time discontinuity.
         - When the synchronizer detects a real discontinuity, it
           should copy the flags through.
        p_eu->i_flags |= BLOCK_FLAG_DISCONTINUITY;
        */
#endif
    }
    p_sys->b_seen_eos = false;

    if( dirac_isPicture( u_parse_code ) )
    {
        /* timestamps apply to pictures only */
        p_eu->i_dts = p_sys->i_eu_dts;
        p_eu->i_pts = p_sys->i_eu_pts;
        p_sys->i_eu_dts = p_sys->i_eu_pts = VLC_TS_INVALID;

        if( !p_sys->b_seen_seq_hdr )
        {
            /* can't timestamp in this case, discard later
             * so that the timestamps aren't lost */
            p_eu->i_flags |= DIRAC_DISCARD;
        }
        /* p_block is a picture -- it ends the 'encapsulation unit' */
        if( dirac_numRefs( u_parse_code ) )
        {
            /* if this picture is not an I frame, ensure that the
             * random access point flags are not set */
            p_eu->i_flags &= ~BLOCK_FLAG_TYPE_I;
        }
        dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
        if( p_dbe && p_block->i_buffer > 13+4 )
        {
            /* record the picture number to save the time gen functions
             * from having to inspect the data for it */
            p_dbe->u_picture_number = GetDWBE( p_block->p_buffer + 13 );
        }
        return DIRAC_DU_ENDS_EU;
    }

    if( dirac_isSeqHdr( u_parse_code ) )
    {
        if( !dirac_UnpackSeqHdr( &p_sys->seq_hdr, p_block ) )
        {
            /* couldn't parse the sequence header, just ignore it */
            return DIRAC_DU_IN_EU;
        }
        p_sys->b_seen_seq_hdr = true;

       /* a sequence header followed by an I frame is a random
        * access point; assume that this is the case */
        p_eu->i_flags |= BLOCK_FLAG_TYPE_I;

        es_format_t *p_es = &p_dec->fmt_out;

        p_es->video.i_width  = p_sys->seq_hdr.u_width;
        p_es->video.i_height = p_sys->seq_hdr.u_height;

        vlc_ureduce( &p_es->video.i_frame_rate, &p_es->video.i_frame_rate_base
                   , p_sys->seq_hdr.u_fps_num, p_sys->seq_hdr.u_fps_den, 0 );

        /* when field coding, dts needs to be incremented in terms of field periods */
        unsigned u_pics_per_sec = p_sys->seq_hdr.u_fps_num;
        if( p_sys->seq_hdr.u_picture_coding_mode == DIRAC_FIELD_CODING )
        {
            u_pics_per_sec *= 2;
        }
        date_Change( &p_sys->dts, u_pics_per_sec, p_sys->seq_hdr.u_fps_den );

        /* TODO: set p_sys->reorder_buf.u_size_max */
        p_sys->i_pts_offset = p_sys->reorder_buf.u_size_max
                            * 1000000
                            * p_es->video.i_frame_rate_base / p_es->video.i_frame_rate + 1;

        /* stash a copy of the seqhdr
         *  - required for ogg muxing
         *  - useful for error checking
         *  - it isn't allowed to change until an eos */
        free( p_es->p_extra );
        p_es->p_extra = calloc( 1, p_block->i_buffer + 13 );
        if( !p_es->p_extra )
        {
            p_es->i_extra = 0;
            return DIRAC_DU_IN_EU;
        }
        p_es->i_extra = p_block->i_buffer;
        memcpy( p_es->p_extra, p_block->p_buffer, p_block->i_buffer );
        /* append EOS as per Ogg guidelines */
        p_block = dirac_EmitEOS( p_dec, p_block->i_buffer );
        if( p_block )
        {
            memcpy( (uint8_t*)p_es->p_extra + p_es->i_extra, p_block->p_buffer, 13 );
            p_es->i_extra += 13;
        }

        return DIRAC_DU_IN_EU;
    }

    /* doesn't end an encapsulation unit */
    return DIRAC_DU_IN_EU;
}
Exemple #8
0
/*****************************************************************************
 * OpenVideo:
 *****************************************************************************/
static int OpenVideo( decoder_t *p_dec )
{
#ifndef WIN32
    decoder_sys_t *p_sys = malloc( sizeof( decoder_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;

    long                                i_result;
    ComponentDescription                desc;
    Component                           prev;
    ComponentResult                     cres;
    ImageSubCodecDecompressCapabilities icap;   /* for ImageCodecInitialize() */
    CodecInfo                           cinfo;  /* for ImageCodecGetCodecInfo() */
    ImageDescription                    *id;

    char                fcc[4];
    int     i_vide = p_dec->fmt_in.i_extra;
    uint8_t *p_vide = p_dec->fmt_in.p_extra;

    p_dec->p_sys = p_sys;
    p_dec->pf_decode_video = DecodeVideo;
    p_sys->i_late = 0;

    if( i_vide <= 0 )
    {
        msg_Err( p_dec, "missing extra info" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    if( p_dec->fmt_in.i_original_fourcc )
        memcpy( fcc, &p_dec->fmt_in.i_original_fourcc, 4 );
    else
        memcpy( fcc, &p_dec->fmt_in.i_codec, 4 );

    msg_Dbg( p_dec, "quicktime_video %4.4s %dx%d",
             fcc, p_dec->fmt_in.video.i_width, p_dec->fmt_in.video.i_height );

    /* get lock, avoid segfault */
    vlc_mutex_lock( &qt_mutex );

#ifdef __APPLE__
    EnterMovies();
#endif

    if( QTVideoInit( p_dec ) )
    {
        msg_Err( p_dec, "cannot initialize QT");
        goto exit_error;
    }

#ifndef __APPLE__
    if( ( i_result = p_sys->InitializeQTML( 6 + 16 ) ) )
    {
        msg_Dbg( p_dec, "error on InitializeQTML = %d", (int)i_result );
        goto exit_error;
    }
#endif

    /* init ComponentDescription */
    memset( &desc, 0, sizeof( ComponentDescription ) );
    desc.componentType      = FCC( 'i', 'm', 'd', 'c' );
    desc.componentSubType   = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
    desc.componentManufacturer = 0;
    desc.componentFlags        = 0;
    desc.componentFlagsMask    = 0;

    if( !( prev = p_sys->FindNextComponent( NULL, &desc ) ) )
    {
        msg_Err( p_dec, "cannot find requested component" );
        goto exit_error;
    }
    msg_Dbg( p_dec, "component id=0x%p", prev );

    p_sys->ci =  p_sys->OpenComponent( prev );
    msg_Dbg( p_dec, "component instance p=0x%p", p_sys->ci );

    memset( &icap, 0, sizeof( ImageSubCodecDecompressCapabilities ) );
    cres =  p_sys->ImageCodecInitialize( p_sys->ci, &icap );
    msg_Dbg( p_dec, "ImageCodecInitialize->0x%X size=%d (%d)",
             (int)cres, (int)icap.recordSize, (int)icap.decompressRecordSize);

    memset( &cinfo, 0, sizeof( CodecInfo ) );
    cres =  p_sys->ImageCodecGetCodecInfo( p_sys->ci, &cinfo );
    msg_Dbg( p_dec,
             "Flags: compr: 0x%x decomp: 0x%x format: 0x%x",
             (unsigned int)cinfo.compressFlags,
             (unsigned int)cinfo.decompressFlags,
             (unsigned int)cinfo.formatFlags );
    msg_Dbg( p_dec, "quicktime_video: Codec name: %.*s",
             ((unsigned char*)&cinfo.typeName)[0],
             ((unsigned char*)&cinfo.typeName)+1 );

    /* make a yuy2 gworld */
    p_sys->OutBufferRect.top    = 0;
    p_sys->OutBufferRect.left   = 0;
    p_sys->OutBufferRect.right  = p_dec->fmt_in.video.i_width;
    p_sys->OutBufferRect.bottom = p_dec->fmt_in.video.i_height;


    /* codec data FIXME use codec not SVQ3 */
    msg_Dbg( p_dec, "vide = %d", i_vide  );
    id = malloc( sizeof( ImageDescription ) + ( i_vide - 70 ) );
    if( !id )
        goto exit_error;
    id->idSize          = sizeof( ImageDescription ) + ( i_vide - 70 );
    id->cType           = FCC( fcc[0], fcc[1], fcc[2], fcc[3] );
    id->version         = GetWBE ( p_vide +  0 );
    id->revisionLevel   = GetWBE ( p_vide +  2 );
    id->vendor          = GetDWBE( p_vide +  4 );
    id->temporalQuality = GetDWBE( p_vide +  8 );
    id->spatialQuality  = GetDWBE( p_vide + 12 );
    id->width           = GetWBE ( p_vide + 16 );
    id->height          = GetWBE ( p_vide + 18 );
    id->hRes            = GetDWBE( p_vide + 20 );
    id->vRes            = GetDWBE( p_vide + 24 );
    id->dataSize        = GetDWBE( p_vide + 28 );
    id->frameCount      = GetWBE ( p_vide + 32 );
    memcpy( &id->name, p_vide + 34, 32 );
    id->depth           = GetWBE ( p_vide + 66 );
    id->clutID          = GetWBE ( p_vide + 68 );
    if( i_vide > 70 )
    {
        memcpy( ((char*)&id->clutID) + 2, p_vide + 70, i_vide - 70 );
    }

    msg_Dbg( p_dec, "idSize=%d ver=%d rev=%d vendor=%d tempQ=%d "
             "spaQ=%d w=%d h=%d dpi=%d%d dataSize=%d depth=%d frameCount=%d clutID=%d",
             (int)id->idSize, id->version, id->revisionLevel, (int)id->vendor,
             (int)id->temporalQuality, (int)id->spatialQuality,
             (int)id->width, (int)id->height,
             (int)id->hRes, (int)id->vRes,
             (int)id->dataSize,
             id->depth,
             id->frameCount,
             id->clutID );

    p_sys->framedescHandle = (ImageDescriptionHandle) NewHandleClear( id->idSize );
    memcpy( *p_sys->framedescHandle, id, id->idSize );

    if( p_dec->fmt_in.video.i_width != 0 && p_dec->fmt_in.video.i_height != 0) 
        p_sys->plane = malloc( p_dec->fmt_in.video.i_width * p_dec->fmt_in.video.i_height * 3 );
    if( !p_sys->plane )
        goto exit_error;

    i_result = p_sys->QTNewGWorldFromPtr( &p_sys->OutBufferGWorld,
                                          /*pixel format of new GWorld==YUY2 */
                                          kYUVSPixelFormat,
                                          /* we should benchmark if yvu9 is
                                           * faster for svq3, too */
                                          &p_sys->OutBufferRect,
                                          0, 0, 0,
                                          p_sys->plane,
                                          p_dec->fmt_in.video.i_width * 2 );

    msg_Dbg( p_dec, "NewGWorldFromPtr returned:%ld",
             65536 - ( i_result&0xffff ) );

    memset( &p_sys->decpar, 0, sizeof( CodecDecompressParams ) );
    p_sys->decpar.imageDescription = p_sys->framedescHandle;
    p_sys->decpar.startLine        = 0;
    p_sys->decpar.stopLine         = ( **p_sys->framedescHandle ).height;
    p_sys->decpar.frameNumber      = 1;
    p_sys->decpar.matrixFlags      = 0;
    p_sys->decpar.matrixType       = 0;
    p_sys->decpar.matrix           = 0;
    p_sys->decpar.capabilities     = &p_sys->codeccap;
    p_sys->decpar.accuracy         = codecNormalQuality;
    p_sys->decpar.srcRect          = p_sys->OutBufferRect;
    p_sys->decpar.transferMode     = srcCopy;
    p_sys->decpar.dstPixMap        = **p_sys->GetGWorldPixMap( p_sys->OutBufferGWorld );/*destPixmap;  */

    cres =  p_sys->ImageCodecPreDecompress( p_sys->ci, &p_sys->decpar );
    msg_Dbg( p_dec, "quicktime_video: ImageCodecPreDecompress cres=0x%X",
             (int)cres );

    es_format_Init( &p_dec->fmt_out, VIDEO_ES, 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->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * p_dec->fmt_in.video.i_width / p_dec->fmt_in.video.i_height;

    vlc_mutex_unlock( &qt_mutex );
    return VLC_SUCCESS;

exit_error:
#ifdef LOADER
    Restore_LDT_Keeper( p_sys->ldt_fs );
#endif
    vlc_mutex_unlock( &qt_mutex );

#else
    VLC_UNUSED( p_dec );
#endif /* !WIN32 */

    return VLC_EGENERIC;
}
Exemple #9
0
static int BdHeader( decoder_sys_t *p_sys,
                     unsigned *pi_rate,
                     unsigned *pi_channels,
                     unsigned *pi_channels_padding,
                     unsigned *pi_original_channels,
                     unsigned *pi_bits,
                     const uint8_t *p_header )
{
    const uint32_t h = GetDWBE( p_header );
    const uint32_t *pi_channels_in = NULL;
    switch( ( h & 0xf000) >> 12 )
    {
    case 1:
        *pi_channels = 1;
        *pi_original_channels = AOUT_CHAN_CENTER;
        break;
    case 3:
        *pi_channels = 2;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        break;
    case 4:
        *pi_channels = 3;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER;
        pi_channels_in = pi_3channels_in;
        break;
    case 5:
        *pi_channels = 3;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER;
        break;
    case 6:
        *pi_channels = 4;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARCENTER;
        break;
    case 7:
        *pi_channels = 4;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        pi_channels_in = pi_4channels_in;
        break;
    case 8:
        *pi_channels = 5;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        pi_channels_in = pi_5channels_in;
        break;
    case 9:
        *pi_channels = 6;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_LFE;
        pi_channels_in = pi_6channels_in;
        break;
    case 10:
        *pi_channels = 7;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
        pi_channels_in = pi_7channels_in;
        break;
    case 11:
        *pi_channels = 8;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
                                AOUT_CHAN_LFE;
        pi_channels_in = pi_8channels_in;
        break;

    default:
        return -1;
    }
    *pi_channels_padding = *pi_channels & 1;

    switch( (h >> 6) & 0x03 )
    {
    case 1:
        *pi_bits = 16;
        break;
    case 2: /* 20 bits but samples are stored on 24 bits */
    case 3: /* 24 bits */
        *pi_bits = 24;
        break;
    default:
        return -1;
    }
    switch( (h >> 8) & 0x0f ) 
    {
    case 1:
        *pi_rate = 48000;
        break;
    case 4:
        *pi_rate = 96000;
        break;
    case 5:
        *pi_rate = 192000;
        break;
    default:
        return -1;
    }

    if( pi_channels_in )
    {
        p_sys->i_chans_to_reorder =
            aout_CheckChannelReorder( pi_channels_in, NULL,
                                      *pi_original_channels,
                                      p_sys->pi_chan_table );
    }

    return 0;
}
Exemple #10
0
static void NITCallBack( scan_session_t *p_session, dvbpsi_nit_t *p_nit )
{
    vlc_object_t *p_obj = p_session->p_obj;

    msg_Dbg( p_obj, "NITCallBack" );
    msg_Dbg( p_obj, "new NIT network_id=%d version=%d current_next=%d",
             p_nit->i_network_id, p_nit->i_version, p_nit->b_current_next );

    /* */
    if( p_session->p_nit && p_session->p_nit->b_current_next )
    {
        dvbpsi_DeleteNIT( p_session->p_nit );
        p_session->p_nit = NULL;
    }
    if( p_session->p_nit )
    {
        dvbpsi_DeleteNIT( p_nit );
        return;
    }

    /* */
    p_session->p_nit = p_nit;

    dvbpsi_descriptor_t *p_dsc;
    for( p_dsc = p_nit->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
    {
        if( p_dsc->i_tag == 0x40 )
        {
            msg_Dbg( p_obj, "   * network name descriptor" );
            char str1[257];

            memcpy( str1, p_dsc->p_data, p_dsc->i_length );
            str1[p_dsc->i_length] = '\0';
            msg_Dbg( p_obj, "       * name %s", str1 );
        }
        else if( p_dsc->i_tag == 0x4a )
        {
            msg_Dbg( p_obj, "   * linkage descriptor" );
            uint16_t i_ts_id = GetWBE( &p_dsc->p_data[0] );
            uint16_t i_on_id = GetWBE( &p_dsc->p_data[2] );
            uint16_t i_service_id = GetWBE( &p_dsc->p_data[4] );
            int i_linkage_type = p_dsc->p_data[6];

            msg_Dbg( p_obj, "       * ts_id %d", i_ts_id );
            msg_Dbg( p_obj, "       * on_id %d", i_on_id );
            msg_Dbg( p_obj, "       * service_id %d", i_service_id );
            msg_Dbg( p_obj, "       * linkage_type %d", i_linkage_type );
        }
        else 
        {
            msg_Dbg( p_obj, "   * dsc 0x%x", p_dsc->i_tag );
        }
    }

    dvbpsi_nit_ts_t *p_ts;
    for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
    {
        msg_Dbg( p_obj, "   * ts ts_id=0x%x original_id=0x%x", p_ts->i_ts_id, p_ts->i_orig_network_id );

        uint32_t i_private_data_id = 0;
        dvbpsi_descriptor_t *p_dsc;
        for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
        {
            if( p_dsc->i_tag == 0x41 )
            {
                msg_Dbg( p_obj, "       * service list descriptor" );
                for( int i = 0; i < p_dsc->i_length/3; i++ )
                {
                    uint16_t i_service_id = GetWBE( &p_dsc->p_data[3*i+0] );
                    uint8_t  i_service_type = p_dsc->p_data[3*i+2];
                    msg_Dbg( p_obj, "           * service_id=%d type=%d", i_service_id, i_service_type );
                }
            }
            else if( p_dsc->i_tag == 0x5a )
            {
                dvbpsi_terr_deliv_sys_dr_t *p_t = dvbpsi_DecodeTerrDelivSysDr( p_dsc );
                msg_Dbg( p_obj, "       * terrestrial delivery system" );
                msg_Dbg( p_obj, "           * centre_frequency 0x%x", p_t->i_centre_frequency  );
                msg_Dbg( p_obj, "           * bandwidth %d", 8 - p_t->i_bandwidth );
                msg_Dbg( p_obj, "           * constellation %d", p_t->i_constellation );
                msg_Dbg( p_obj, "           * hierarchy %d", p_t->i_hierarchy_information );
                msg_Dbg( p_obj, "           * code_rate hp %d lp %d", p_t->i_code_rate_hp_stream, p_t->i_code_rate_lp_stream );
                msg_Dbg( p_obj, "           * guard_interval %d", p_t->i_guard_interval );
                msg_Dbg( p_obj, "           * transmission_mode %d", p_t->i_transmission_mode );
                msg_Dbg( p_obj, "           * other_frequency_flag %d", p_t->i_other_frequency_flag );
            }
            else if( p_dsc->i_tag == 0x5f )
            {
                msg_Dbg( p_obj, "       * private data specifier descriptor" );
                i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
                msg_Dbg( p_obj, "           * value 0x%8.8x", i_private_data_id );
            }
            else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
            {
                msg_Dbg( p_obj, "       * logical channel descriptor (EICTA)" );
                for( int i = 0; i < p_dsc->i_length/4; i++ )
                {
                    uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
                    int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;
                    msg_Dbg( p_obj, "           * service_id=%d channel_number=%d", i_service_id, i_channel_number );
                }

            }
            else
            {
                msg_Warn( p_obj, "       * dsc 0x%x", p_dsc->i_tag );
            }
        }
    }
}
Exemple #11
0
/*****************************************************************************
 * Decode:
 *****************************************************************************/
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
{
    block_t       *p_block;
    subpicture_t  *p_spu = NULL;

    if( ( pp_block == NULL ) || ( *pp_block == NULL ) ) return NULL;
    p_block = *pp_block;
    *pp_block = NULL;

    if( ( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) ||
          p_block->i_buffer < sizeof(uint16_t) )
    {
        block_Release( p_block );
        return NULL;
    }

    uint8_t *p_buf = p_block->p_buffer;

    /* Read our raw string and create the styled segment for HTML */
    uint16_t i_psz_length = GetWBE( p_buf );
    char *psz_subtitle = malloc( i_psz_length + 1 );
    if ( !psz_subtitle ) return NULL;
    memcpy( psz_subtitle, p_block->p_buffer + sizeof(uint16_t), i_psz_length );
    psz_subtitle[ i_psz_length ] = '\0';
    p_buf += i_psz_length + sizeof(uint16_t);

    for( uint16_t i=0; i < i_psz_length; i++ )
     if ( psz_subtitle[i] == '\r' ) psz_subtitle[i] = '\n';

    segment_t *p_segment = calloc( 1, sizeof(segment_t) );
    if ( !p_segment )
    {
        free( psz_subtitle );
        return NULL;
    }
    p_segment->psz_string = strdup( psz_subtitle );
    p_segment->i_size = strlen( psz_subtitle );
    if ( p_dec->fmt_in.subs.p_style )
    {
        p_segment->styles.i_color = p_dec->fmt_in.subs.p_style->i_font_color;
        p_segment->styles.i_color |= p_dec->fmt_in.subs.p_style->i_font_alpha << 24;
        if ( p_dec->fmt_in.subs.p_style->i_style_flags )
            p_segment->styles.i_flags = p_dec->fmt_in.subs.p_style->i_style_flags;
        p_segment->styles.i_fontsize = p_dec->fmt_in.subs.p_style->i_font_size;
    }

    if ( !p_segment->psz_string )
    {
        SegmentFree( p_segment );
        free( psz_subtitle );
        return NULL;
    }

    /* Create the subpicture unit */
    p_spu = decoder_NewSubpictureText( p_dec );
    if( !p_spu )
    {
        free( psz_subtitle );
        SegmentFree( p_segment );
        return NULL;
    }
    subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;

    /* Parse our styles */
    while( (size_t)(p_buf - p_block->p_buffer) + 8 < p_block->i_buffer )
    {
        uint32_t i_atomsize = GetDWBE( p_buf );
        vlc_fourcc_t i_atomtype = VLC_FOURCC(p_buf[4],p_buf[5],p_buf[6],p_buf[7]);
        p_buf += 8;
        switch( i_atomtype )
        {

        case VLC_FOURCC('s','t','y','l'):
        {
            if ( (size_t)(p_buf - p_block->p_buffer) < 14 ) break;
            uint16_t i_nbrecords = GetWBE(p_buf);
            uint16_t i_cur_record = 0;
            p_buf += 2;
            while( i_cur_record++ < i_nbrecords )
            {
                if ( (size_t)(p_buf - p_block->p_buffer) < 12 ) break;
                uint16_t i_start = __MIN( GetWBE(p_buf), i_psz_length - 1 );
                uint16_t i_end =  __MIN( GetWBE(p_buf + 2), i_psz_length - 1 );

                segment_style_t style;
                style.i_flags = ConvertFlags( p_buf[6] );
                style.i_fontsize = p_buf[7];
                style.i_color = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB
                style.i_color |= (GetDWBE(p_buf+8) & 0xFF) << 24;
                ApplySegmentStyle( &p_segment, i_start, i_end, &style );

                if ( i_nbrecords == 1 )
                {
                    if ( p_buf[6] )
                    {
                        p_spu_sys->style_flags.i_value = ConvertFlags( p_buf[6] );
                        p_spu_sys->style_flags.b_set = true;
                    }
                    p_spu_sys->i_font_height_abs_to_src = p_buf[7];
                    p_spu_sys->font_color.i_value = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB
                    p_spu_sys->font_color.i_value |= (GetDWBE(p_buf+8) & 0xFF) << 24;
                    p_spu_sys->font_color.b_set = true;
                }

                p_buf += 12;
            }
        }   break;

        case VLC_FOURCC('d','r','p','o'):
            if ( (size_t)(p_buf - p_block->p_buffer) < 4 ) break;
            p_spu_sys->i_drop_shadow = __MAX( GetWBE(p_buf), GetWBE(p_buf+2) );
            break;

        case VLC_FOURCC('d','r','p','t'):
            if ( (size_t)(p_buf - p_block->p_buffer) < 2 ) break;
            p_spu_sys->i_drop_shadow_alpha = GetWBE(p_buf);
            break;

        default:
            break;

        }
        p_buf += i_atomsize;
    }

    p_spu->i_start    = p_block->i_pts;
    p_spu->i_stop     = p_block->i_pts + p_block->i_length;
    p_spu->b_ephemer  = (p_block->i_length == 0);
    p_spu->b_absolute = false;

    p_spu_sys->align = SUBPICTURE_ALIGN_BOTTOM;
    p_spu_sys->text  = psz_subtitle;
    p_spu_sys->p_htmlsegments = p_segment;

    block_Release( p_block );

    return p_spu;
}
Exemple #12
0
/*****************************************************************************
 * Open
 *****************************************************************************/
static int OpenCommon( vlc_object_t *p_this, bool b_force )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    const uint8_t *p_peek;
    ssize_t i_peek = 0;
    ssize_t i_offset = 0;
    ssize_t i_skip = 0;
    unsigned i_max_packets = PS_PACKET_PROBE;
    int format = MPEG_PS;
    int i_mux_rate = 0;
    vlc_tick_t i_length = VLC_TICK_INVALID;

    i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 16 );
    if( i_peek < 16 )
    {
        msg_Dbg( p_demux, "cannot peek" );
        return VLC_EGENERIC;
    }

    if( !memcmp( p_peek, "PSMF", 4 ) &&
        (GetDWBE( &p_peek[4] ) & 0x30303030) == 0x30303030 )
    {
        i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 100 );
        if( i_peek < 100 )
            return VLC_EGENERIC;
        i_skip = i_offset = GetWBE( &p_peek[10] );
        format = PSMF_PS;
        msg_Info( p_demux, "Detected PSMF-PS header");
        i_mux_rate = GetDWBE( &p_peek[96] );
        if( GetDWBE( &p_peek[86] ) > 0 )
            i_length = vlc_tick_from_samples( GetDWBE( &p_peek[92] ), GetDWBE( &p_peek[86] ));
    }
    else if( !memcmp( p_peek, "RIFF", 4 ) && !memcmp( &p_peek[8], "CDXA", 4 ) )
    {
        format = CDXA_PS;
        i_max_packets = 0; /* We can't probe here */
        i_skip = CDXA_HEADER_SIZE;
        msg_Info( p_demux, "Detected CDXA-PS" );
        /* FIXME: have a proper way to decap CD sectors or make an access stream filter */
    }
    else if( b_force )
    {
        msg_Warn( p_demux, "this does not look like an MPEG PS stream, "
                  "continuing anyway" );
        i_max_packets = 0;
    }

    for( unsigned i=0; i<i_max_packets; i++ )
    {
        if( i_peek < i_offset + 16 )
        {
            i_peek = vlc_stream_Peek( p_demux->s, &p_peek, i_offset + 16 );
            if( i_peek < i_offset + 16 )
                return VLC_EGENERIC;
        }

        const uint8_t startcode[3] = { 0x00, 0x00, 0x01 };
        const uint8_t *p_header = &p_peek[i_offset];
        if( memcmp( p_header, startcode, 3 ) ||
           ( (p_header[3] & 0xB0) != 0xB0 &&
            !(p_header[3] >= 0xC0 && p_header[3] <= 0xEF) &&
              p_header[3] != PS_STREAM_ID_EXTENDED &&
              p_header[3] != PS_STREAM_ID_DIRECTORY ) )
            return VLC_EGENERIC;

        ssize_t i_pessize = ps_pkt_size( p_header, 16 );
        if( i_pessize < 5 )
            return VLC_EGENERIC;
        i_offset += i_pessize;
    }

    if( i_skip > 0 && !p_demux->b_preparsing &&
        vlc_stream_Read( p_demux->s, NULL, i_skip ) != i_skip )
        return VLC_EGENERIC;

    /* Fill p_demux field */
    p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
    if( !p_sys ) return VLC_ENOMEM;

    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;

    /* Init p_sys */
    p_sys->i_mux_rate = i_mux_rate;
    p_sys->i_pack_scr  = VLC_TICK_INVALID;
    p_sys->i_first_scr = VLC_TICK_INVALID;
    p_sys->i_scr = VLC_TICK_INVALID;
    p_sys->i_scr_track_id = 0;
    p_sys->i_length   = i_length;
    p_sys->i_current_pts = VLC_TICK_INVALID;
    p_sys->i_time_track_index = -1;
    p_sys->i_aob_mlp_count = 0;
    p_sys->i_start_byte = i_skip;
    p_sys->i_lastpack_byte = i_skip;

    p_sys->b_lost_sync = false;
    p_sys->b_have_pack = false;
    p_sys->b_bad_scr   = false;
    p_sys->b_seekable  = false;
    p_sys->format      = format;
    p_sys->current_title = 0;
    p_sys->current_seekpoint = 0;
    p_sys->updates = 0;

    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &p_sys->b_seekable );

    ps_psm_init( &p_sys->psm );
    ps_track_init( p_sys->tk );

    /* TODO prescanning of ES */

    return VLC_SUCCESS;
}
Exemple #13
0
void scan_session_Clean( scan_t *p_scan, scan_session_t *p_session )
{
    const int i_service_start = p_scan->i_service;

    dvbpsi_pat_t *p_pat = p_session->p_pat;
    dvbpsi_sdt_t *p_sdt = p_session->p_sdt;

#ifdef DVBPSI_USE_NIT
    dvbpsi_nit_t *p_nit = p_session->p_nit;
#endif

    if( p_pat )
    {
        /* Parse PAT */
        dvbpsi_pat_program_t *p_program;
        for( p_program = p_pat->p_first_program; p_program != NULL; p_program = p_program->p_next )
        {
            if( p_program->i_number == 0 )  /* NIT */
                continue;

            scan_service_t *s = scan_service_New( p_program->i_number, &p_session->cfg );
            TAB_APPEND( p_scan->i_service, p_scan->pp_service, s );
        }
    }
    /* Parse SDT */
    if( p_pat && p_sdt )
    {
        dvbpsi_sdt_service_t *p_srv;
        for( p_srv = p_sdt->p_first_service; p_srv; p_srv = p_srv->p_next )
        {
            scan_service_t *s = ScanFindService( p_scan, i_service_start, p_srv->i_service_id );
            dvbpsi_descriptor_t *p_dr;

            if( s )
                s->b_crypted = p_srv->b_free_ca;

            for( p_dr = p_srv->p_first_descriptor; p_dr; p_dr = p_dr->p_next )
            {
                if( p_dr->i_tag == 0x48 )
                {
                    dvbpsi_service_dr_t *pD = dvbpsi_DecodeServiceDr( p_dr );

                    if( s )
                    {
                        if( !s->psz_name )
                            s->psz_name = dvbsi_to_utf8( pD->i_service_name, pD->i_service_name_length );

                        if( s->type == SERVICE_UNKNOWN )
                        {
                            switch( pD->i_service_type )
                            {
                            case 0x01: s->type = SERVICE_DIGITAL_TELEVISION; break;
                            case 0x02: s->type = SERVICE_DIGITAL_RADIO; break;
                            case 0x16: s->type = SERVICE_DIGITAL_TELEVISION_AC_SD; break;
                            case 0x19: s->type = SERVICE_DIGITAL_TELEVISION_AC_HD; break;
                            }
                        }
                    }
                }
            }
        }
    }

#ifdef DVBPSI_USE_NIT
    /* Parse NIT */
    if( p_pat && p_nit )
    {
        dvbpsi_nit_ts_t *p_ts;
        for( p_ts = p_nit->p_first_ts; p_ts != NULL; p_ts = p_ts->p_next )
        {
            uint32_t i_private_data_id = 0;
            dvbpsi_descriptor_t *p_dsc;

            if( p_ts->i_orig_network_id != p_nit->i_network_id || p_ts->i_ts_id != p_pat->i_ts_id )
                continue;

            for( p_dsc = p_ts->p_first_descriptor; p_dsc != NULL; p_dsc = p_dsc->p_next )
            {
                if( p_dsc->i_tag == 0x5f )
                {
                    i_private_data_id = GetDWBE( &p_dsc->p_data[0] );
                }
                else if( i_private_data_id == 0x28 && p_dsc->i_tag == 0x83 )
                {
                    for( int i = 0; i < p_dsc->i_length/4; i++ )
                    {
                        uint16_t i_service_id = GetWBE( &p_dsc->p_data[4*i+0] );
                        int i_channel_number = GetWBE( &p_dsc->p_data[4*i+2] ) & 0x3ff;

                        scan_service_t *s = ScanFindService( p_scan, i_service_start, i_service_id );
                        if( s && s->i_channel < 0 )
                            s->i_channel = i_channel_number;
                    }
                }
            }
        }
    }
#endif

    /* */
    for( int i = i_service_start; i < p_scan->i_service; i++ )
    {
        scan_service_t *p_srv = p_scan->pp_service[i];

        p_srv->i_snr = p_session->i_snr;
        if( p_sdt )
            p_srv->i_sdt_version = p_sdt->i_version;
#ifdef DVBPSI_USE_NIT
        if( p_nit )
        {
            p_srv->i_network_id = p_nit->i_network_id;
            p_srv->i_nit_version = p_nit->i_version;
        }
#endif
    }


    /* */
    if( p_session->pat )
        dvbpsi_DetachPAT( p_session->pat );
    if( p_session->p_pat )
        dvbpsi_DeletePAT( p_session->p_pat );

    if( p_session->sdt )
        dvbpsi_DetachDemux( p_session->sdt );
    if( p_session->p_sdt )
        dvbpsi_DeleteSDT( p_session->p_sdt );
#ifdef DVBPSI_USE_NIT
    if( p_session->nit )
        dvbpsi_DetachDemux( p_session->nit );
    if( p_session->p_nit )
        dvbpsi_DeleteNIT( p_session->p_nit );
#endif
}
Exemple #14
0
int OpenDemux( vlc_object_t* p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    const uint8_t *p_peek;
    ssize_t i_peek = vlc_stream_Peek( p_demux->s, &p_peek, 2048 );
    if( unlikely( i_peek <= 32 ) )
        return VLC_EGENERIC;

    const char *psz_xml = (const char *) p_peek;
    size_t i_xml  = i_peek;

    /* Try to probe without xml module/loading the full document */
    char *psz_alloc = NULL;
    switch( GetQWBE(p_peek) )
    {
        /* See RFC 3023 Part 4 */
        case UINT64_C(0xFFFE3C003F007800): /* UTF16 BOM<? */
        case UINT64_C(0xFFFE3C003F007400): /* UTF16 BOM<t */
        case UINT64_C(0xFEFF003C003F0078): /* UTF16 BOM<? */
        case UINT64_C(0xFEFF003C003F0074): /* UTF16 BOM<t */
            psz_alloc = FromCharset( "UTF-16", p_peek, i_peek );
            break;
        case UINT64_C(0x3C003F0078006D00): /* UTF16-LE <?xm */
        case UINT64_C(0x3C003F0074007400): /* UTF16-LE <tt */
            psz_alloc = FromCharset( "UTF-16LE", p_peek, i_peek );
            break;
        case UINT64_C(0x003C003F0078006D): /* UTF16-BE <?xm */
        case UINT64_C(0x003C003F00740074): /* UTF16-BE <tt */
            psz_alloc = FromCharset( "UTF-16BE", p_peek, i_peek );
            break;
        case UINT64_C(0xEFBBBF3C3F786D6C): /* UTF8 BOM<?xml */
        case UINT64_C(0x3C3F786D6C207665): /* UTF8 <?xml ve */
        case UINT64_C(0xEFBBBF3C74742078): /* UTF8 BOM<tt x*/
            break;
        default:
            if(GetDWBE(p_peek) != UINT32_C(0x3C747420)) /* tt node without xml document marker */
                return VLC_EGENERIC;
    }

    if( psz_alloc )
    {
        psz_xml = psz_alloc;
        i_xml = strlen( psz_alloc );
    }

    /* Simplified probing. Valid TTML must have a namespace declaration */
    const char *psz_tt = strnstr( psz_xml, "tt ", i_xml );
    if( !psz_tt || psz_tt == psz_xml ||
        (psz_tt[-1] != ':' && psz_tt[-1] != '<') )
    {
        free( psz_alloc );
        return VLC_EGENERIC;
    }
    else
    {
        const char * const rgsz[] =
        {
            "=\"http://www.w3.org/ns/ttml\"",
            "=\"http://www.w3.org/2004/11/ttaf1\"",
            "=\"http://www.w3.org/2006/04/ttaf1\"",
            "=\"http://www.w3.org/2006/10/ttaf1\"",
        };
        const char *psz_ns = NULL;
        for( size_t i=0; i<ARRAY_SIZE(rgsz) && !psz_ns; i++ )
        {
            psz_ns = strnstr( psz_xml, rgsz[i],
                              i_xml - (psz_tt - psz_xml) );
        }
        free( psz_alloc );
        if( !psz_ns )
            return VLC_EGENERIC;
    }

    p_demux->p_sys = p_sys = calloc( 1, sizeof( *p_sys ) );
    if( unlikely( p_sys == NULL ) )
        return VLC_ENOMEM;

    p_sys->b_first_time = true;
    p_sys->temporal_extent.i_type = TT_TIMINGS_PARALLEL;
    tt_time_Init( &p_sys->temporal_extent.begin );
    tt_time_Init( &p_sys->temporal_extent.end );
    tt_time_Init( &p_sys->temporal_extent.dur );
    p_sys->temporal_extent.begin.base = 0;

    p_sys->p_xml = xml_Create( p_demux );
    if( !p_sys->p_xml )
        goto error;

    p_sys->p_reader = xml_ReaderCreate( p_sys->p_xml, p_demux->s );
    if( !p_sys->p_reader )
        goto error;

#ifndef TTML_DEMUX_DEBUG
    p_sys->p_reader->obj.flags |= OBJECT_FLAGS_QUIET;
#endif

    if( ReadTTML( p_demux ) != VLC_SUCCESS )
        goto error;

    tt_timings_Resolve( (tt_basenode_t *) p_sys->p_rootnode, &p_sys->temporal_extent,
                        &p_sys->times.p_array, &p_sys->times.i_count );

#ifdef TTML_DEMUX_DEBUG
    {
        struct vlc_memstream stream;

        if( vlc_memstream_open( &stream ) )
            goto error;

        tt_time_t t;
        tt_time_Init( &t );
        tt_node_ToText( &stream, (tt_basenode_t*)p_sys->p_rootnode, &t /* invalid */ );

        vlc_memstream_putc( &stream, '\0' );

        if( vlc_memstream_close( &stream ) == VLC_SUCCESS )
        {
            msg_Dbg( p_demux, "%s", stream.ptr );
            free( stream.ptr );
        }
    }
#endif

    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;

    es_format_t fmt;
    es_format_Init( &fmt, SPU_ES, VLC_CODEC_TTML );
    p_sys->p_es = es_out_Add( p_demux->out, &fmt );
    if( !p_sys->p_es )
        goto error;

    es_format_Clean( &fmt );

    return VLC_SUCCESS;

error:
    CloseDemux( p_demux );

    return VLC_EGENERIC;
}
Exemple #15
0
input_attachment_t* ParseFlacPicture( const uint8_t *p_data, int i_data,
    int i_attachments, int *i_cover_score, int *i_cover_idx )
{
    /* TODO: Merge with ID3v2 copy in modules/meta_engine/taglib.cpp. */
    static const char pi_cover_score[] = {
        0,  /* Other */
        5,  /* 32x32 PNG image that should be used as the file icon */
        4,  /* File icon of a different size or format. */
        20, /* Front cover image of the album. */
        19, /* Back cover image of the album. */
        13, /* Inside leaflet page of the album. */
        18, /* Image from the album itself. */
        17, /* Picture of the lead artist or soloist. */
        16, /* Picture of the artist or performer. */
        14, /* Picture of the conductor. */
        15, /* Picture of the band or orchestra. */
        9,  /* Picture of the composer. */
        8,  /* Picture of the lyricist or text writer. */
        7,  /* Picture of the recording location or studio. */
        10, /* Picture of the artists during recording. */
        11, /* Picture of the artists during performance. */
        6,  /* Picture from a movie or video related to the track. */
        1,  /* Picture of a large, coloured fish. */
        12, /* Illustration related to the track. */
        3,  /* Logo of the band or performer. */
        2   /* Logo of the publisher (record company). */
    };

    int i_len;
    int i_type;
    char *psz_mime = NULL;
    char psz_name[128];
    char *psz_description = NULL;
    input_attachment_t *p_attachment = NULL;

    if( i_data < 4 + 3*4 )
        return NULL;
#define RM(x) do { i_data -= (x); p_data += (x); } while(0)

    i_type = GetDWBE( p_data ); RM(4);
    i_len = GetDWBE( p_data ); RM(4);

    if( i_len < 0 || i_data < i_len + 4 )
        goto error;
    psz_mime = strndup( (const char*)p_data, i_len ); RM(i_len);
    i_len = GetDWBE( p_data ); RM(4);
    if( i_len < 0 || i_data < i_len + 4*4 + 4)
        goto error;
    psz_description = strndup( (const char*)p_data, i_len ); RM(i_len);
    EnsureUTF8( psz_description );
    RM(4*4);
    i_len = GetDWBE( p_data ); RM(4);
    if( i_len < 0 || i_len > i_data )
        goto error;

    /* printf( "Picture type=%d mime=%s description='%s' file length=%d\n",
             i_type, psz_mime, psz_description, i_len ); */

    snprintf( psz_name, sizeof(psz_name), "picture%d", i_attachments );
    if( !strcasecmp( psz_mime, "image/jpeg" ) )
        strcat( psz_name, ".jpg" );
    else if( !strcasecmp( psz_mime, "image/png" ) )
        strcat( psz_name, ".png" );

    p_attachment = vlc_input_attachment_New( psz_name, psz_mime,
            psz_description, p_data, i_data );

    if( i_type >= 0 && (unsigned int)i_type < sizeof(pi_cover_score)/sizeof(pi_cover_score[0]) &&
        *i_cover_score < pi_cover_score[i_type] )
    {
        *i_cover_idx = i_attachments;
        *i_cover_score = pi_cover_score[i_type];
    }

error:
    free( psz_mime );
    free( psz_description );
    return p_attachment;
}
Exemple #16
0
/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out encapsulation units.
 ****************************************************************************/
static block_t *Encode( encoder_t *p_enc, picture_t *p_pic )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_block, *p_output_chain = NULL;
    int i_plane, i_line, i_width, i_src_stride;
    uint8_t *p_dst;

    if( !p_pic ) return NULL;
    /* we only know if the sequence is interlaced when the first
     * picture arrives, so final setup is done here */
    /* XXX todo, detect change of interlace */
    p_sys->ctx.src_params.topfieldfirst = p_pic->b_top_field_first;
    p_sys->ctx.src_params.source_sampling = !p_pic->b_progressive;

    if( p_sys->b_auto_field_coding )
        p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive;

    if( !p_sys->p_dirac )
    {
        date_t date;
        /* Initialise the encoder with the encoder context */
        p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 );
        if( !p_sys->p_dirac )
        {
            msg_Err( p_enc, "Failed to initialize dirac encoder" );
            return NULL;
        }
        date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base );
#if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2)
        int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac );
        i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1;
        date_Increment( &date, i_delayinpics );
#else
        date_Increment( &date, 1 );
#endif
        p_sys->i_pts_offset = date_Get( &date );

        /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced
         * for each frame input. Calculate time between fields for offsetting
         * the second field later. */
        if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
        {
            date_Set( &date, 0 );
            date_Increment( &date, 1 );
            p_sys->i_field_time = date_Get( &date ) / 2;
        }
    }

    /* Copy input picture into encoder input buffer (stride by stride) */
    /* Would be lovely to just pass the picture in, but there is noway for the
     * library to free it */
    p_dst = p_sys->p_buffer_in;
    for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
    {
        uint8_t *p_src = p_pic->p[i_plane].p_pixels;
        i_width = p_pic->p[i_plane].i_visible_pitch;
        i_src_stride = p_pic->p[i_plane].i_pitch;

        for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
        {
            vlc_memcpy( p_dst, p_src, i_width );
            p_dst += i_width;
            p_src += i_src_stride;
        }
    }

    /* Load one frame of data into encoder */
    if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in,
                            p_sys->i_buffer_in ) < 0 )
    {
        msg_Dbg( p_enc, "dirac_encoder_load() error" );
        return NULL;
    }

    /* store pts in a lookaside buffer, so that the same pts may
     * be used for the picture in coded order */
    StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date );
    p_sys->i_input_picnum++;

    /* store dts in a queue, so that they appear in order in
     * coded order */
    p_block = block_New( p_enc, 1 );
    if( !p_block )
        return NULL;
    p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
    block_FifoPut( p_sys->p_dts_fifo, p_block );
    p_block = NULL;

    /* for field coding mode, insert an extra value into both the
     * pts lookaside buffer and dts queue, offset to correspond
     * to a one field delay. */
    if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
    {
        StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time );
        p_sys->i_input_picnum++;

        p_block = block_New( p_enc, 1 );
        if( !p_block )
            return NULL;
        p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time;
        block_FifoPut( p_sys->p_dts_fifo, p_block );
        p_block = NULL;
    }

    dirac_encoder_state_t state;
    /* Retrieve encoded frames from encoder */
    do
    {
        p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out;
        p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out;
        state = dirac_encoder_output( p_sys->p_dirac );
        switch( state )
        {
        case ENC_STATE_AVAIL: {
            uint32_t pic_num;

            /* extract data from encoder temporary buffer. */
            p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size );
            if( !p_block )
                return NULL;
            memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer,
                    p_sys->p_dirac->enc_buf.size );

            /* if some flags were set for a previous block, prevent
             * them from getting lost */
            if( p_sys->p_chain )
                p_block->i_flags |= p_sys->p_chain->i_flags;

            /* store all extracted blocks in a chain and gather up when an
             * entire encapsulation unit is avaliable (ends with a picture) */
            block_ChainAppend( &p_sys->p_chain, p_block );

            /* Presence of a Sequence header indicates a seek point */
            if( 0 == p_block->p_buffer[4] )
            {
                p_block->i_flags |= BLOCK_FLAG_TYPE_I;

                if( !p_enc->fmt_out.p_extra ) {
                    const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
                    uint32_t len = GetDWBE( p_block->p_buffer + 5 );
                    /* if it hasn't been done so far, stash a copy of the
                     * sequence header for muxers such as ogg */
                    /* The OggDirac spec advises that a Dirac EOS DataUnit
                     * is appended to the sequence header to allow guard
                     * against poor streaming servers */
                    /* XXX, should this be done using the packetizer ? */
                    p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) );
                    if( !p_enc->fmt_out.p_extra )
                        return NULL;
                    memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len);
                    memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) );
                    SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len );
                    p_enc->fmt_out.i_extra = len + sizeof(eos);
                }
            }

            if( ReadDiracPictureNumber( &pic_num, p_block ) )
            {
                /* Finding a picture terminates an ecapsulation unit, gather
                 * all data and output; use the next dts value queued up
                 * and find correct pts in the tlb */
                p_block = block_FifoGet( p_sys->p_dts_fifo );
                p_sys->p_chain->i_dts = p_block->i_dts;
                p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num );
                block_Release( p_block );
                block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) );
                p_sys->p_chain = NULL;
            } else {
                p_block = NULL;
            }
            break;
            }

        case ENC_STATE_BUFFER:
            break;
        case ENC_STATE_INVALID:
        default:
            break;
        }
    } while( state == ENC_STATE_AVAIL );

    return p_output_chain;
}
Exemple #17
0
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open (vlc_object_t * p_this)
{
    demux_t       *p_demux = (demux_t *)p_this;
    stream_t      *stream = p_demux->s;
    demux_sys_t   *p_sys;
    const uint8_t *peek;
    unsigned       tracks, ppqn;
    bool     multitrack;

    /* (Try to) parse the SMF header */
    /* Header chunk always has 6 bytes payload */
    if (stream_Peek (stream, &peek, 14) < 14)
        return VLC_EGENERIC;

    /* Skip RIFF MIDI header if present */
    if (!memcmp (peek, "RIFF", 4) && !memcmp (peek + 8, "RMID", 4))
    {
        uint32_t riff_len = GetDWLE (peek + 4);

        msg_Dbg (p_this, "detected RIFF MIDI file (%u bytes)",
                 (unsigned)riff_len);
        if ((stream_Read (stream, NULL, 12) < 12))
            return VLC_EGENERIC;

        /* Look for the RIFF data chunk */
        for (;;)
        {
            char chnk_hdr[8];
            uint32_t chnk_len;

            if ((riff_len < 8)
             || (stream_Read (stream, chnk_hdr, 8) < 8))
                return VLC_EGENERIC;

            riff_len -= 8;
            chnk_len = GetDWLE (chnk_hdr + 4);
            if (riff_len < chnk_len)
                return VLC_EGENERIC;
            riff_len -= chnk_len;

            if (!memcmp (chnk_hdr, "data", 4))
                break; /* found! */

            if (stream_Read (stream, NULL, chnk_len) < (ssize_t)chnk_len)
                return VLC_EGENERIC;
        }

        /* Read real SMF header. Assume RIFF data chunk length is proper. */
        if (stream_Peek (stream, &peek, 14) < 14)
            return VLC_EGENERIC;
    }

    if (memcmp (peek, "MThd\x00\x00\x00\x06", 8))
        return VLC_EGENERIC;
    peek += 8;

    /* First word: SMF type */
    switch (GetWBE (peek))
    {
        case 0:
            multitrack = false;
            break;
        case 1:
            multitrack = true;
            break;
        default:
            /* We don't implement SMF2 (as do many) */
            msg_Err (p_this, "unsupported SMF file type %u", GetWBE (peek));
            return VLC_EGENERIC;
    }
    peek += 2;

    /* Second word: number of tracks */
    tracks = GetWBE (peek);
    peek += 2;
    if (!multitrack && (tracks != 1))
    {
        msg_Err (p_this, "invalid SMF type 0 file");
        return VLC_EGENERIC;
    }

    msg_Dbg (p_this, "detected Standard MIDI File (type %u) with %u track(s)",
             multitrack, tracks);

    /* Third/last word: timing */
    ppqn = GetWBE (peek);
    if (ppqn & 0x8000)
    {
        /* FIXME */
        msg_Err (p_this, "SMPTE timestamps not implemented");
        return VLC_EGENERIC;
    }
    else
    {
        msg_Dbg (p_this, " %u pulses per quarter note", ppqn);
    }

    p_sys = malloc (sizeof (*p_sys) + (sizeof (mtrk_t) * tracks));
    if (p_sys == NULL)
        return VLC_ENOMEM;

    /* We've had a valid SMF header - now skip it*/
    if (stream_Read (stream, NULL, 14) < 14)
        goto error;

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;

    /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */
    date_Init (&p_sys->pts, ppqn * 2, 1);
    date_Set (&p_sys->pts, 0);
    p_sys->pulse        = 0;
    p_sys->ppqn         = ppqn;

    p_sys->trackc       = tracks;
    /* Prefetch track offsets */
    for (unsigned i = 0; i < tracks; i++)
    {
        uint8_t head[8];

        if (i > 0)
        {
            /* Seeking screws streaming up, but there is no way around this,
             * as SMF1 tracks are performed simultaneously.
             * Not a big deal as SMF1 are usually only a few kbytes anyway. */
            if (stream_Seek (stream,  p_sys->trackv[i-1].end))
            {
                msg_Err (p_this, "cannot build SMF index (corrupted file?)");
                goto error;
            }
        }

        for (;;)
        {
            if (stream_Read (stream, head, 8) < 8)
            {
                /* FIXME: don't give up if we have at least one valid track */
                msg_Err (p_this, "incomplete SMF chunk, file is corrupted");
                goto error;
            }

            if (memcmp (head, "MTrk", 4) == 0)
                break;

            msg_Dbg (p_this, "skipping unknown SMF chunk");
            stream_Read (stream, NULL, GetDWBE (head + 4));
        }

        p_sys->trackv[i].offset = stream_Tell (stream);
        p_sys->trackv[i].end = p_sys->trackv[i].offset + GetDWBE (head + 4);
        p_sys->trackv[i].next = 0;
        ReadDeltaTime (stream, p_sys->trackv + i);
        p_sys->trackv[i].running_event = 0xF6;
        /* Why 0xF6 (Tuning Calibration)?
         * Because it has zero bytes of data, so the parser will detect the
         * error if the first event uses running status. */
    }

    es_format_t  fmt;
    es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MIDI);
    fmt.audio.i_channels = 2;
    fmt.audio.i_rate = 44100; /* dummy value */
    p_sys->es = es_out_Add (p_demux->out, &fmt);

    return VLC_SUCCESS;

error:
    free (p_sys);
    return VLC_EGENERIC;
}
Exemple #18
0
/*****************************************************************************
 * InitVideo: initialize the video decoder
 *****************************************************************************
 * the ffmpeg codec will be opened, some memory allocated. The vout is not yet
 * opened (done after the first decoded frame).
 *****************************************************************************/
int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
                      AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
{
    decoder_sys_t *p_sys;
    vlc_value_t lockval;
    vlc_value_t val;

    var_Get( p_dec->p_libvlc, "avcodec", &lockval );

    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_dec->p_sys = p_sys =
          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
    {
        msg_Err( p_dec, "out of memory" );
        return VLC_EGENERIC;
    }

    p_dec->p_sys->p_context = p_context;
    p_dec->p_sys->p_codec = p_codec;
    p_dec->p_sys->i_codec_id = i_codec_id;
    p_dec->p_sys->psz_namecodec = psz_namecodec;
    p_sys->p_ff_pic = avcodec_alloc_frame();

    /* ***** Fill p_context with init values ***** */
    /* FIXME: remove when ffmpeg deals properly with avc1 */
    if( p_dec->fmt_in.i_codec != VLC_FOURCC('a','v','c','1') )
    /* End FIXME */
    p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_codec );
    p_sys->p_context->width  = p_dec->fmt_in.video.i_width;
    p_sys->p_context->height = p_dec->fmt_in.video.i_height;
    p_sys->p_context->bits_per_sample = p_dec->fmt_in.video.i_bits_per_pixel;

    /*  ***** Get configuration of ffmpeg plugin ***** */
    p_sys->p_context->workaround_bugs =
        config_GetInt( p_dec, "ffmpeg-workaround-bugs" );
    p_sys->p_context->error_resilience =
        config_GetInt( p_dec, "ffmpeg-error-resilience" );

    var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    var_Get( p_dec, "grayscale", &val );
    if( val.b_bool ) p_sys->p_context->flags |= CODEC_FLAG_GRAY;

    var_Create( p_dec, "ffmpeg-vismv", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_dec, "ffmpeg-vismv", &val );
#if LIBAVCODEC_BUILD >= 4698
    if( val.i_int ) p_sys->p_context->debug_mv = val.i_int;
#endif

    var_Create( p_dec, "ffmpeg-lowres", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
    var_Get( p_dec, "ffmpeg-lowres", &val );
#if LIBAVCODEC_BUILD >= 4723
    if( val.i_int > 0 && val.i_int <= 2 ) p_sys->p_context->lowres = val.i_int;
#endif

    /* ***** ffmpeg frame skipping ***** */
    var_Create( p_dec, "ffmpeg-hurry-up", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    var_Get( p_dec, "ffmpeg-hurry-up", &val );
    p_sys->b_hurry_up = val.b_bool;

    /* ***** ffmpeg direct rendering ***** */
    p_sys->b_direct_rendering = 0;
    var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
    var_Get( p_dec, "ffmpeg-dr", &val );
    if( val.b_bool && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
        ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) &&
        /* Apparently direct rendering doesn't work with YUV422P */
        p_sys->p_context->pix_fmt != PIX_FMT_YUV422P &&
        /* H264 uses too many reference frames */
        p_sys->i_codec_id != CODEC_ID_H264 &&
        !(p_sys->p_context->width % 16) && !(p_sys->p_context->height % 16) &&
#if LIBAVCODEC_BUILD >= 4698
        !p_sys->p_context->debug_mv )
#else
        1 )
#endif
    {
        /* Some codecs set pix_fmt only after the 1st frame has been decoded,
         * so we need to do another check in ffmpeg_GetFrameBuf() */
        p_sys->b_direct_rendering = 1;
    }

#ifdef LIBAVCODEC_PP
    p_sys->p_pp = NULL;
    p_sys->b_pp = p_sys->b_pp_async = p_sys->b_pp_init = VLC_FALSE;
    p_sys->p_pp = E_(OpenPostproc)( p_dec, &p_sys->b_pp_async );
#endif

    /* ffmpeg doesn't properly release old pictures when frames are skipped */
    //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = 0;
    if( p_sys->b_direct_rendering )
    {
        msg_Dbg( p_dec, "using direct rendering" );
        p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;
    }

    /* Always use our get_buffer wrapper so we can calculate the
     * PTS correctly */
    p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;
    p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
    p_sys->p_context->opaque = p_dec;

    /* ***** init this codec with special data ***** */
    if( p_dec->fmt_in.i_extra )
    {
        int i_size = p_dec->fmt_in.i_extra;

        if( p_sys->i_codec_id == CODEC_ID_SVQ3 )
        {
            uint8_t *p;

            p_sys->p_context->extradata_size = i_size + 12;
            p = p_sys->p_context->extradata  =
                malloc( p_sys->p_context->extradata_size );

            memcpy( &p[0],  "SVQ3", 4 );
            memset( &p[4], 0, 8 );
            memcpy( &p[12], p_dec->fmt_in.p_extra, i_size );

            /* Now remove all atoms before the SMI one */
            if( p_sys->p_context->extradata_size > 0x5a &&
                strncmp( &p[0x56], "SMI ", 4 ) )
            {
                uint8_t *psz = &p[0x52];

                while( psz < &p[p_sys->p_context->extradata_size - 8] )
                {
                    int i_size = GetDWBE( psz );
                    if( i_size <= 1 )
                    {
                        /* FIXME handle 1 as long size */
                        break;
                    }
                    if( !strncmp( &psz[4], "SMI ", 4 ) )
                    {
                        memmove( &p[0x52], psz,
                                 &p[p_sys->p_context->extradata_size] - psz );
                        break;
                    }

                    psz += i_size;
                }
            }
        }
        else if( p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '0' ) ||
                 p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '1', '3' ) ||
                 p_dec->fmt_in.i_codec == VLC_FOURCC( 'R', 'V', '2', '0' ) )
        {
            if( p_dec->fmt_in.i_extra == 8 )
            {
                p_sys->p_context->extradata_size = 8;
                p_sys->p_context->extradata = malloc( 8 );

                memcpy( p_sys->p_context->extradata,
                        p_dec->fmt_in.p_extra,
                        p_dec->fmt_in.i_extra );
                p_sys->p_context->sub_id= ((uint32_t*)p_dec->fmt_in.p_extra)[1];

                msg_Warn( p_dec, "using extra data for RV codec sub_id=%08x",
                          p_sys->p_context->sub_id );
            }
        }
        /* FIXME: remove when ffmpeg deals properly with avc1 */
        else if( p_dec->fmt_in.i_codec == VLC_FOURCC('a','v','c','1') )
        {
            ;
        }
        /* End FIXME */
        else
        {
            p_sys->p_context->extradata_size = i_size;
            p_sys->p_context->extradata =
                malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
            memcpy( p_sys->p_context->extradata,
                    p_dec->fmt_in.p_extra, i_size );
            memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
                    0, FF_INPUT_BUFFER_PADDING_SIZE );
        }
    }

    /* ***** misc init ***** */
    p_sys->input_pts = p_sys->input_dts = 0;
    p_sys->i_pts = 0;
    p_sys->b_has_b_frames = VLC_FALSE;
    p_sys->b_first_frame = VLC_TRUE;
    p_sys->i_late_frames = 0;
    p_sys->i_buffer = 0;
    p_sys->i_buffer_orig = 1;
    p_sys->p_buffer_orig = p_sys->p_buffer = malloc( p_sys->i_buffer_orig );

    /* Set output properties */
    p_dec->fmt_out.i_cat = VIDEO_ES;
    p_dec->fmt_out.i_codec = ffmpeg_PixFmtToChroma( p_context->pix_fmt );

    /* Setup palette */
#if LIBAVCODEC_BUILD >= 4688
    if( p_dec->fmt_in.video.p_palette )
        p_sys->p_context->palctrl =
            (AVPaletteControl *)p_dec->fmt_in.video.p_palette;
    else
        p_sys->p_context->palctrl = &palette_control;
#endif

    /* ***** Open the codec ***** */
    vlc_mutex_lock( lockval.p_address );
    if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 )
    {
        vlc_mutex_unlock( lockval.p_address );
        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
        free( p_sys );
        return VLC_EGENERIC;
    }
    vlc_mutex_unlock( lockval.p_address );
    msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );


    return VLC_SUCCESS;
}
Exemple #19
0
static void SetupESDS( demux_t *p_demux, mp4_track_t *p_track, const MP4_descriptor_decoder_config_t *p_decconfig )
{
    /* First update information based on i_objectTypeIndication */
    switch( p_decconfig->i_objectProfileIndication )
    {
    case( 0x20 ): /* MPEG4 VIDEO */
        p_track->fmt.i_codec = VLC_CODEC_MP4V;
        break;
    case( 0x21 ): /* H.264 */
        p_track->fmt.i_codec = VLC_CODEC_H264;
        break;
    case( 0x40):
        p_track->fmt.i_codec = VLC_CODEC_MP4A;
        if( p_decconfig->i_decoder_specific_info_len >= 2 &&
                p_decconfig->p_decoder_specific_info[0]       == 0xF8 &&
                (p_decconfig->p_decoder_specific_info[1]&0xE0) == 0x80 )
        {
            p_track->fmt.i_codec = VLC_CODEC_ALS;
        }
        break;
    case( 0x60):
    case( 0x61):
    case( 0x62):
    case( 0x63):
    case( 0x64):
    case( 0x65): /* MPEG2 video */
        p_track->fmt.i_codec = VLC_CODEC_MPGV;
        break;
        /* Theses are MPEG2-AAC */
    case( 0x66): /* main profile */
    case( 0x67): /* Low complexity profile */
    case( 0x68): /* Scaleable Sampling rate profile */
        p_track->fmt.i_codec = VLC_CODEC_MP4A;
        break;
        /* True MPEG 2 audio */
    case( 0x69):
        p_track->fmt.i_codec = VLC_CODEC_MPGA;
        break;
    case( 0x6a): /* MPEG1 video */
        p_track->fmt.i_codec = VLC_CODEC_MPGV;
        break;
    case( 0x6b): /* MPEG1 audio */
        p_track->fmt.i_codec = VLC_CODEC_MPGA;
        break;
    case( 0x6c ): /* jpeg */
        p_track->fmt.i_codec = VLC_CODEC_JPEG;
        break;
    case( 0x6d ): /* png */
        p_track->fmt.i_codec = VLC_CODEC_PNG;
        break;
    case( 0x6e ): /* jpeg2000 */
        p_track->fmt.i_codec = VLC_FOURCC( 'M','J','2','C' );
        break;
    case( 0xa3 ): /* vc1 */
        p_track->fmt.i_codec = VLC_CODEC_VC1;
        break;
    case( 0xa4 ):
        p_track->fmt.i_codec = VLC_CODEC_DIRAC;
        break;
    case( 0xa5 ):
        p_track->fmt.i_codec = VLC_CODEC_A52;
        break;
    case( 0xa6 ):
        p_track->fmt.i_codec = VLC_CODEC_EAC3;
        break;
    case( 0xa9 ): /* dts */
    case( 0xaa ): /* DTS-HD HRA */
    case( 0xab ): /* DTS-HD Master Audio */
        p_track->fmt.i_codec = VLC_CODEC_DTS;
        break;
    case( 0xDD ):
        p_track->fmt.i_codec = VLC_CODEC_VORBIS;
        break;

        /* Private ID */
    case( 0xe0 ): /* NeroDigital: dvd subs */
        if( p_track->fmt.i_cat == SPU_ES )
        {
            p_track->fmt.i_codec = VLC_CODEC_SPU;
            if( p_track->i_width > 0 )
                p_track->fmt.subs.spu.i_original_frame_width = p_track->i_width;
            if( p_track->i_height > 0 )
                p_track->fmt.subs.spu.i_original_frame_height = p_track->i_height;
            break;
        }
    case( 0xe1 ): /* QCelp for 3gp */
        if( p_track->fmt.i_cat == AUDIO_ES )
        {
            p_track->fmt.i_codec = VLC_CODEC_QCELP;
        }
        break;

        /* Fallback */
    default:
        /* Unknown entry, but don't touch i_fourcc */
        msg_Warn( p_demux,
                  "unknown objectProfileIndication(0x%x) (Track[ID 0x%x])",
                  p_decconfig->i_objectProfileIndication,
                  p_track->i_track_ID );
        break;
    }

    p_track->fmt.i_extra = p_decconfig->i_decoder_specific_info_len;
    if( p_track->fmt.i_extra > 0 )
    {
        p_track->fmt.p_extra = malloc( p_track->fmt.i_extra );
        memcpy( p_track->fmt.p_extra, p_decconfig->p_decoder_specific_info,
                p_track->fmt.i_extra );
    }
    if( p_track->fmt.i_codec == VLC_CODEC_SPU &&
            p_track->fmt.i_extra >= 16 * 4 )
    {
        for( int i = 0; i < 16; i++ )
        {
            p_track->fmt.subs.spu.palette[1 + i] =
                    GetDWBE((char*)p_track->fmt.p_extra + i * 4);
        }
        p_track->fmt.subs.spu.palette[0] = 0xBeef;
    }
}
Exemple #20
0
/*****************************************************************************
 * Decode:
 *****************************************************************************/
static int Decode( decoder_t *p_dec, block_t *p_block )
{
    subpicture_t  *p_spu = NULL;

    if( p_block == NULL ) /* No Drain */
        return VLCDEC_SUCCESS;

    if( ( p_block->i_flags & (BLOCK_FLAG_CORRUPTED) ) ||
          p_block->i_buffer < sizeof(uint16_t) )
    {
        block_Release( p_block );
        return VLCDEC_SUCCESS;
    }

    uint8_t *p_buf = p_block->p_buffer;

    /* Read our raw string and create the styled segment for HTML */
    uint16_t i_psz_bytelength = GetWBE( p_buf );
    const uint8_t *p_pszstart = p_block->p_buffer + sizeof(uint16_t);
    char *psz_subtitle;
    if ( i_psz_bytelength > 2 &&
         ( !memcmp( p_pszstart, "\xFE\xFF", 2 ) || !memcmp( p_pszstart, "\xFF\xFE", 2 ) )
       )
    {
        psz_subtitle = FromCharset( "UTF-16", p_pszstart, i_psz_bytelength );
        if ( !psz_subtitle )
            return VLCDEC_SUCCESS;
    }
    else
    {
        psz_subtitle = malloc( i_psz_bytelength + 1 );
        if ( !psz_subtitle )
            return VLCDEC_SUCCESS;
        memcpy( psz_subtitle, p_pszstart, i_psz_bytelength );
        psz_subtitle[ i_psz_bytelength ] = '\0';
    }
    p_buf += i_psz_bytelength + sizeof(uint16_t);

    for( uint16_t i=0; i < i_psz_bytelength; i++ )
     if ( psz_subtitle[i] == '\r' ) psz_subtitle[i] = '\n';

    tx3g_segment_t *p_segment3g = tx3g_segment_New( psz_subtitle );
    p_segment3g->i_size = str8len( psz_subtitle );
    if ( p_dec->fmt_in.subs.p_style )
        p_segment3g->s->style = text_style_Duplicate( p_dec->fmt_in.subs.p_style );

    free( psz_subtitle );

    if ( !p_segment3g->s->psz_text )
    {
        text_segment_Delete( p_segment3g->s );
        free( p_segment3g );
        return VLCDEC_SUCCESS;
    }

    /* Create the subpicture unit */
    p_spu = decoder_NewSubpictureText( p_dec );
    if( !p_spu )
    {
        text_segment_Delete( p_segment3g->s );
        free( p_segment3g );
        return VLCDEC_SUCCESS;
    }
    subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;

    /* Parse our styles */
    while( (size_t)(p_buf - p_block->p_buffer) + 8 < p_block->i_buffer )
    {
        uint32_t i_atomsize = GetDWBE( p_buf );
        vlc_fourcc_t i_atomtype = VLC_FOURCC(p_buf[4],p_buf[5],p_buf[6],p_buf[7]);
        p_buf += 8;
        switch( i_atomtype )
        {

        case VLC_FOURCC('s','t','y','l'):
        {
            if ( (size_t)(p_buf - p_block->p_buffer) < 14 ) break;
            uint16_t i_nbrecords = GetWBE(p_buf);
            uint16_t i_cur_record = 0;
            p_buf += 2;
            while( i_cur_record++ < i_nbrecords )
            {
                if ( (size_t)(p_buf - p_block->p_buffer) < 12 ) break;
                uint16_t i_start = __MIN( GetWBE(p_buf), i_psz_bytelength - 1 );
                uint16_t i_end =  __MIN( GetWBE(p_buf + 2), i_psz_bytelength - 1 );

                text_style_t style;
                memset( &style, 0, sizeof(text_style_t) );
                style.i_style_flags = ConvertFlags( p_buf[6] );
                style.i_font_size = p_buf[7];
                style.i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> RGB
                style.i_font_alpha = GetDWBE(p_buf+8) & 0xFF;
                style.i_features = STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA;
                ApplySegmentStyle( &p_segment3g, i_start, i_end, &style );

                if ( i_nbrecords == 1 )
                {
                    if ( p_buf[6] )
                    {
                        if( (p_spu_sys->p_default_style->i_style_flags = ConvertFlags( p_buf[6] )) )
                            p_spu_sys->p_default_style->i_features |= STYLE_HAS_FLAGS;
                    }
                    p_spu_sys->p_default_style->i_font_size = p_buf[7];
                    p_spu_sys->p_default_style->i_font_color = GetDWBE(p_buf+8) >> 8;// RGBA -> ARGB
                    p_spu_sys->p_default_style->i_font_alpha = (GetDWBE(p_buf+8) & 0xFF) << 24;
                    p_spu_sys->p_default_style->i_features |= (STYLE_HAS_FONT_COLOR | STYLE_HAS_FONT_ALPHA);
                }

                p_buf += 12;
            }
        }   break;

        case VLC_FOURCC('d','r','p','o'):
            if ( (size_t)(p_buf - p_block->p_buffer) < 4 ) break;
            p_spu_sys->p_default_style->i_shadow_width = __MAX( GetWBE(p_buf), GetWBE(p_buf+2) );
            break;

        case VLC_FOURCC('d','r','p','t'):
            if ( (size_t)(p_buf - p_block->p_buffer) < 2 ) break;
            p_spu_sys->p_default_style->i_shadow_alpha = GetWBE(p_buf);
            p_spu_sys->p_default_style->i_features |= STYLE_HAS_SHADOW_ALPHA;
            break;

        default:
            break;

        }
        p_buf += i_atomsize;
    }

    p_spu->i_start    = p_block->i_pts;
    p_spu->i_stop     = p_block->i_pts + p_block->i_length;
    p_spu->b_ephemer  = (p_block->i_length == 0);
    p_spu->b_absolute = false;

    p_spu_sys->region.inner_align = SUBPICTURE_ALIGN_BOTTOM;

    FontSizeConvert( p_dec->fmt_in.subs.p_style,  p_spu_sys->p_default_style );

    /* Unwrap */
    text_segment_t *p_text_segments = p_segment3g->s;
    text_segment_t *p_cur = p_text_segments;
    while( p_segment3g )
    {
        FontSizeConvert( p_dec->fmt_in.subs.p_style, p_segment3g->s->style );

        tx3g_segment_t * p_old = p_segment3g;
        p_segment3g = p_segment3g->p_next3g;
        free( p_old );
        if( p_segment3g )
            p_cur->p_next = p_segment3g->s;
        p_cur = p_cur->p_next;
    }

    p_spu_sys->region.p_segments = p_text_segments;

    block_Release( p_block );

    decoder_QueueSub( p_dec, p_spu );
    return VLCDEC_SUCCESS;
}
Exemple #21
0
void xiph_decode (demux_t *demux, void *data, block_t *block)
{
    rtp_xiph_t *self = (rtp_xiph_t *)data;			// sunqueen modify

    if (!data || block->i_buffer < 4)
        goto drop;

    /* 32-bits RTP header (§2.2) */
    uint32_t ident = GetDWBE (block->p_buffer);
    block->i_buffer -= 4;
    block->p_buffer += 4;

    unsigned fragtype = (ident >> 6) & 3;
    unsigned datatype = (ident >> 4) & 3;
    unsigned pkts = (ident) & 15;
    ident >>= 8;

    /* RTP defragmentation */
    if (self->block && (block->i_flags & BLOCK_FLAG_DISCONTINUITY))
    {   /* Screwed! discontinuity within a fragmented packet */
        msg_Warn (demux, self->vorbis ?
                  "discontinuity in fragmented Vorbis packet" :
                  "discontinuity in fragmented Theora packet");
        block_Release (self->block);
        self->block = NULL;
    }

    if (fragtype <= 1)
    {
        if (self->block) /* Invalid first fragment */
        {
            block_Release (self->block);
            self->block = NULL;
        }
    }
    else
    {
        if (!self->block)
            goto drop; /* Invalid non-first fragment */
    }

    if (fragtype > 0)
    {   /* Fragment */
        if (pkts > 0 || block->i_buffer < 2)
            goto drop;

        size_t fraglen = GetWBE (block->p_buffer);
        if (block->i_buffer < (fraglen + 2))
            goto drop; /* Invalid payload length */
        block->i_buffer = fraglen;
        if (fragtype == 1)/* Keep first fragment */
        {
            block->i_buffer += 2;
            self->block = block;
        }
        else
        {   /* Append non-first fragment */
            size_t len = self->block->i_buffer;
            self->block = block_Realloc (self->block, 0, len + fraglen);
            if (!self->block)
            {
                block_Release (block);
                return;
            }
            memcpy (self->block->p_buffer + len, block->p_buffer + 2,
                    fraglen);
            block_Release (block);
        }
        if (fragtype < 3)
            return; /* Non-last fragment */

        /* Last fragment reached, process it */
        block = self->block;
        self->block = NULL;
        SetWBE (block->p_buffer, block->i_buffer - 2);
        pkts = 1;
    }

    /* RTP payload packets processing */
    while (pkts > 0)
    {
        if (block->i_buffer < 2)
            goto drop;

        size_t len = GetWBE (block->p_buffer);
        block->i_buffer -= 2;
        block->p_buffer += 2;
        if (block->i_buffer < len)
            goto drop;

        switch (datatype)
        {
            case 0: /* Raw payload */
            {
                if (self->ident != ident)
                {
                    msg_Warn (demux, self->vorbis ?
                        "ignoring raw Vorbis payload without configuration" :
                        "ignoring raw Theora payload without configuration");
                    break;
                }
                block_t *raw = block_Alloc (len);
                memcpy (raw->p_buffer, block->p_buffer, len);
                raw->i_pts = block->i_pts; /* FIXME: what about pkts > 1 */
                codec_decode (demux, self->id, raw);
                break;
            }

            case 1: /* Packed configuration frame (§3.1.1) */
            {
                if (self->ident == ident)
                    break; /* Ignore config retransmission */

                void *extv;
                ssize_t extc = xiph_header (&extv, block->p_buffer, len);
                if (extc < 0)
                    break;

                es_format_t fmt;
                es_format_Init (&fmt, self->vorbis ? AUDIO_ES : VIDEO_ES,
                                self->vorbis ? VLC_CODEC_VORBIS
                                             : VLC_CODEC_THEORA);
                fmt.p_extra = extv;
                fmt.i_extra = extc;
                codec_destroy (demux, self->id);
                msg_Dbg (demux, self->vorbis ?
                         "Vorbis packed configuration received (%06"PRIx32")" :
                         "Theora packed configuration received (%06"PRIx32")",
                         ident);
                self->ident = ident;
                self->id = (es_out_id_t *)codec_init (demux, &fmt);			// sunqueen modify
                break;
            }
        }

        block->i_buffer -= len;
        block->p_buffer += len;
        pkts--;
    }

drop:
    block_Release (block);
}
Exemple #22
0
/***
 * Encapsulation (packetization) suitable for all muxing standards
 * maps [DataUnit] -> EncapsulationUnit
 */
static block_t *dirac_BuildEncapsulationUnit( decoder_t *p_dec, block_t *p_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    assert(p_block->i_buffer >= 13 && 0x42424344 == GetDWBE( p_block->p_buffer ));

    if( p_sys->i_eu_pts <= VLC_TS_INVALID && p_sys->i_eu_dts <= VLC_TS_INVALID )
    {
        /* earliest block with pts/dts gets to set the pts/dts for the dated
         * encapsulation unit as a whole */
        /* NB, the 'earliest block' criteria is aribtary */
        if( p_block->i_pts > VLC_TS_INVALID || p_block->i_dts > VLC_TS_INVALID )
        {
            p_sys->i_eu_pts = p_block->i_pts;
            p_sys->i_eu_dts = p_block->i_dts;
        }
    }

    /* inpectdataunit also updates flags for the EU.
     *  - if this is the first block in the EU, then it hasn't been added
     *    to the chain yet (so, p_block will become the front of the chain
     *  - otherwise, use the flags of the chain (first block) */
    block_t *p_eu = p_sys->p_eu ? p_sys->p_eu : p_block;
    int i_block = dirac_InspectDataUnit( p_dec, &p_block, p_eu);

    if( !p_block )
    {
        /* block has been discarded during inspection */
        /* becareful, don't discard anything that is dated,
         * as this needs to go into the timegen loop.  set
         * the DIRAC_DISCARD block flag, and it'll be dropped
         * at output time */
        return NULL;
    }

    block_ChainLastAppend( &p_sys->pp_eu_last, p_block );

    dirac_block_encap_t *p_dbe = dirac_GetBlockEncap( p_block );
#ifdef SANITIZE_PREV_PARSE_OFFSET
    /* fixup prev_parse_offset to point to the last data unit
     * to arrive */
    if( p_dbe )
    {
        SetDWBE( p_block->p_buffer + 9, p_sys->u_eu_last_npo );
        p_sys->u_eu_last_npo = p_dbe->u_last_next_offset;
    }
#endif

    if( i_block != DIRAC_DU_ENDS_EU )
    {
        /* encapsulation unit not ended */
        return NULL;
    }

    /* gather up encapsulation unit, reassociating the final
     * private state with the gathered block */
    block_t *p_eu_last = (block_t*) p_sys->pp_eu_last - offsetof( block_t, p_next );
    p_dbe = dirac_RemoveBlockEncap( p_eu_last );

    uint8_t u_parse_code = p_block->p_buffer[4];

    /* gather up the encapsulation unit */
    p_block = block_ChainGather( p_sys->p_eu );
    assert( p_block ); /* block_ChainGather doesn't define when it frees chain */

    p_block->i_flags |= DIRAC_NON_DATED;
    if( p_dbe )
    {
        dirac_AddBlockEncap( &p_block, p_dbe );
        if( dirac_isPicture( u_parse_code ) ) p_block->i_flags &= ~DIRAC_NON_DATED;
    }
    p_sys->p_eu = NULL;
    p_sys->pp_eu_last = &p_sys->p_eu;
    return p_block;
}
Exemple #23
0
static int BdHeader( unsigned *pi_rate,
                     unsigned *pi_channels, unsigned *pi_original_channels,
                     unsigned *pi_bits,
                     const uint8_t *p_header )
{
    const uint32_t h = GetDWBE( p_header );
    switch( ( h & 0xf000) >> 12 )
    {
    case 1:
        *pi_channels = 1;
        *pi_original_channels = AOUT_CHAN_CENTER;
        break;
    case 3:
        *pi_channels = 2;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
        break;
    case 4:
        *pi_channels = 3;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER;
        break;
    case 5:
        *pi_channels = 3;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARCENTER;
        break;
    case 6:
        *pi_channels = 4;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARCENTER;
        break;
    case 7:
        *pi_channels = 4;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        break;
    case 8:
        *pi_channels = 5;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT;
        break;
    case 9:
        *pi_channels = 6;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_LFE;
        break;
    case 10:
        *pi_channels = 7;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT;
        break;
    case 11:
        *pi_channels = 8;
        *pi_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER |
                                AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT |
                                AOUT_CHAN_MIDDLELEFT | AOUT_CHAN_MIDDLERIGHT |
                                AOUT_CHAN_LFE;
        break;

    default:
        return -1;
    }
    switch( (h >> 6) & 0x03 )
    {
    case 1:
        *pi_bits = 16;
        break;
    case 2: /* 20 bits but samples are stored on 24 bits */
    case 3: /* 24 bits */
        *pi_bits = 24;
        break;
    default:
        return -1;
    }
    switch( (h >> 8) & 0x0f ) 
    {
    case 1:
        *pi_rate = 48000;
        break;
    case 4:
        *pi_rate = 96000;
        break;
    case 5:
        *pi_rate = 192000;
        break;
    default:
        return -1;
    }
    return 0;
}
Exemple #24
0
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;

    uint8_t      hdr[20];
    const uint8_t *p_peek;
    int          i_cat;
    int          i_samples, i_modulo;

    if( stream_Peek( p_demux->s , &p_peek, 4 ) < 4 )
        return VLC_EGENERIC;

    if( memcmp( p_peek, ".snd", 4 ) )
        return VLC_EGENERIC;

    /* skip signature */
    stream_Read( p_demux->s, NULL, 4 );   /* cannot fail */

    /* read header */
    if( stream_Read( p_demux->s, hdr, 20 ) < 20 )
    {
        msg_Err( p_demux, "cannot read" );
        return VLC_EGENERIC;
    }

    if( GetDWBE( &hdr[0]  ) < 24 )
    {
        msg_Err( p_demux, "invalid file" );
        return VLC_EGENERIC;
    }

    DEMUX_INIT_COMMON();
    p_sys = p_demux->p_sys;
    p_sys->i_time = 0;
    p_sys->i_header_size = GetDWBE( &hdr[0] );

    /* skip extra header data */
    if( p_sys->i_header_size > 24 )
    {
        stream_Read( p_demux->s, NULL, p_sys->i_header_size - 24 );
    }

    /* init fmt */
    es_format_Init( &p_sys->fmt, AUDIO_ES, 0 );
    p_sys->fmt.audio.i_rate     = GetDWBE( &hdr[12] );
    p_sys->fmt.audio.i_channels = GetDWBE( &hdr[16] );

#if 0
    p_sys->au.i_header_size   = GetDWBE( &p_sys->au.i_header_size );
    p_sys->au.i_data_size     = GetDWBE( &p_sys->au.i_data_size );
    p_sys->au.i_encoding      = GetDWBE( &p_sys->au.i_encoding );
    p_sys->au.i_sample_rate   = GetDWBE( &p_sys->au.i_sample_rate );
    p_sys->au.i_channels      = GetDWBE( &p_sys->au.i_channels );
#endif
    switch( GetDWBE( &hdr[8] ) )
    {
    case AU_ALAW_8:        /* 8-bit ISDN A-law */
        p_sys->fmt.i_codec               = VLC_CODEC_ALAW;
        p_sys->fmt.audio.i_bitspersample = 8;
        p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_MULAW_8:       /* 8-bit ISDN u-law */
        p_sys->fmt.i_codec               = VLC_CODEC_MULAW;
        p_sys->fmt.audio.i_bitspersample = 8;
        p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_8:      /* 8-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 8;
        p_sys->fmt.audio.i_blockalign    = 1 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_16:     /* 16-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 16;
        p_sys->fmt.audio.i_blockalign    = 2 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_24:     /* 24-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 24;
        p_sys->fmt.audio.i_blockalign    = 3 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_LINEAR_32:     /* 32-bit linear PCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 't','w','o','s' );
        p_sys->fmt.audio.i_bitspersample = 32;
        p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_FLOAT:         /* 32-bit IEEE floating point */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_FLOAT );
        p_sys->fmt.audio.i_bitspersample = 32;
        p_sys->fmt.audio.i_blockalign    = 4 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_DOUBLE:        /* 64-bit IEEE floating point */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_DOUBLE );
        p_sys->fmt.audio.i_bitspersample = 64;
        p_sys->fmt.audio.i_blockalign    = 8 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_PCM;
        break;

    case AU_ADPCM_G721:    /* 4-bit CCITT g.721 ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G721 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    case AU_ADPCM_G722:    /* CCITT g.722 ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G722 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    case AU_ADPCM_G723_3:  /* CCITT g.723 3-bit ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_3 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    case AU_ADPCM_G723_5:  /* CCITT g.723 5-bit ADPCM */
        p_sys->fmt.i_codec               = VLC_FOURCC( 'a', 'u', 0, AU_ADPCM_G723_5 );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0 * p_sys->fmt.audio.i_channels;
        i_cat                    = AU_CAT_ADPCM;
        break;

    default:
        msg_Warn( p_demux, "unknow encoding=0x%x", GetDWBE( &hdr[8] ) );
        p_sys->fmt.audio.i_bitspersample = 0;
        p_sys->fmt.audio.i_blockalign    = 0;
        i_cat                    = AU_CAT_UNKNOWN;
        break;
    }

    p_sys->fmt.i_bitrate = p_sys->fmt.audio.i_rate *
                           p_sys->fmt.audio.i_channels *
                           p_sys->fmt.audio.i_bitspersample;

    if( i_cat == AU_CAT_UNKNOWN || i_cat == AU_CAT_ADPCM )
    {
        p_sys->i_frame_size = 0;
        p_sys->i_frame_length = 0;

        msg_Err( p_demux, "unsupported codec/type (Please report it)" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    if( p_sys->fmt.audio.i_rate == 0 )
    {
        msg_Err( p_demux, "invalid samplerate: 0" );
        free( p_sys );
        return VLC_EGENERIC;
    }

    /* add the es */
    p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );

    /* calculate 50ms frame size/time */
    i_samples = __MAX( p_sys->fmt.audio.i_rate / 20, 1 );
    p_sys->i_frame_size = i_samples * p_sys->fmt.audio.i_channels *
                          ( (p_sys->fmt.audio.i_bitspersample + 7) / 8 );
    if( p_sys->fmt.audio.i_blockalign > 0 )
    {
        if( ( i_modulo = p_sys->i_frame_size % p_sys->fmt.audio.i_blockalign ) != 0 )
        {
            p_sys->i_frame_size += p_sys->fmt.audio.i_blockalign - i_modulo;
        }
    }
    p_sys->i_frame_length = (mtime_t)1000000 *
                            (mtime_t)i_samples /
                            (mtime_t)p_sys->fmt.audio.i_rate;

    return VLC_SUCCESS;
}