⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vorbis.c

📁 uclinux 下的vlc播放器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        p_dec->fmt_in.i_extra += oggpacket.bytes + 2;        block_Release( *pp_block );        p_sys->i_headers++;        return NULL;    }    if( p_sys->i_headers == 3 )    {        if( ProcessHeaders( p_dec ) != VLC_SUCCESS )        {            p_sys->i_headers = 0;            p_dec->fmt_in.i_extra = 0;            block_Release( *pp_block );            return NULL;        }        else p_sys->i_headers++;    }    return ProcessPacket( p_dec, &oggpacket, pp_block );}/***************************************************************************** * ProcessHeaders: process Vorbis headers. *****************************************************************************/static int ProcessHeaders( decoder_t *p_dec ){    decoder_sys_t *p_sys = p_dec->p_sys;    ogg_packet oggpacket;    uint8_t *p_extra;    int i_extra;    if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;    oggpacket.granulepos = -1;    oggpacket.b_o_s = 1; /* yes this actually is a b_o_s packet :) */    oggpacket.e_o_s = 0;    oggpacket.packetno = 0;    p_extra = p_dec->fmt_in.p_extra;    i_extra = p_dec->fmt_in.i_extra;    /* Take care of the initial Vorbis header */    oggpacket.bytes = *(p_extra++) << 8;    oggpacket.bytes |= (*(p_extra++) & 0xFF);    oggpacket.packet = p_extra;    p_extra += oggpacket.bytes;    i_extra -= (oggpacket.bytes + 2);    if( i_extra < 0 )    {        msg_Err( p_dec, "header data corrupted");        return VLC_EGENERIC;    }    if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )    {        msg_Err( p_dec, "this bitstream does not contain Vorbis audio data");        return VLC_EGENERIC;    }    /* Setup the format */    p_dec->fmt_out.audio.i_rate     = p_sys->vi.rate;    p_dec->fmt_out.audio.i_channels = p_sys->vi.channels;    if( p_dec->fmt_out.audio.i_channels < 0 ||        p_dec->fmt_out.audio.i_channels > 6 )    {        msg_Err( p_dec, "invalid number of channels (not between 1 and 6): %i",                 p_dec->fmt_out.audio.i_channels );        return VLC_EGENERIC;    }    p_dec->fmt_out.audio.i_physical_channels =        p_dec->fmt_out.audio.i_original_channels =            pi_channels_maps[p_sys->vi.channels];    p_dec->fmt_out.i_bitrate = p_sys->vi.bitrate_nominal;    aout_DateInit( &p_sys->end_date, p_sys->vi.rate );    aout_DateSet( &p_sys->end_date, 0 );    msg_Dbg( p_dec, "channels:%d samplerate:%ld bitrate:%ld",             p_sys->vi.channels, p_sys->vi.rate, p_sys->vi.bitrate_nominal );    /* The next packet in order is the comments header */    oggpacket.b_o_s = 0;    oggpacket.bytes = *(p_extra++) << 8;    oggpacket.bytes |= (*(p_extra++) & 0xFF);    oggpacket.packet = p_extra;    p_extra += oggpacket.bytes;    i_extra -= (oggpacket.bytes + 2);    if( i_extra < 0 )    {        msg_Err( p_dec, "header data corrupted");        return VLC_EGENERIC;    }    if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )    {        msg_Err( p_dec, "2nd Vorbis header is corrupted" );        return VLC_EGENERIC;    }    ParseVorbisComments( p_dec );    /* The next packet in order is the codebooks header     * We need to watch out that this packet is not missing as a     * missing or corrupted header is fatal. */    oggpacket.bytes = *(p_extra++) << 8;    oggpacket.bytes |= (*(p_extra++) & 0xFF);    oggpacket.packet = p_extra;    i_extra -= (oggpacket.bytes + 2);    if( i_extra < 0 )    {        msg_Err( p_dec, "header data corrupted");        return VLC_EGENERIC;    }    if( vorbis_synthesis_headerin( &p_sys->vi, &p_sys->vc, &oggpacket ) < 0 )    {        msg_Err( p_dec, "3rd Vorbis header is corrupted" );        return VLC_EGENERIC;    }    if( !p_sys->b_packetizer )    {        /* Initialize the Vorbis packet->PCM decoder */        vorbis_synthesis_init( &p_sys->vd, &p_sys->vi );        vorbis_block_init( &p_sys->vd, &p_sys->vb );    }    else    {        p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;        p_dec->fmt_out.p_extra =            realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );        memcpy( p_dec->fmt_out.p_extra,                p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );    }    ConfigureChannelOrder(p_sys->pi_chan_table, p_sys->vi.channels,            p_dec->fmt_out.audio.i_physical_channels, VLC_TRUE);    return VLC_SUCCESS;}/***************************************************************************** * ProcessPacket: processes a Vorbis packet. *****************************************************************************/static void *ProcessPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,                            block_t **pp_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    block_t *p_block = *pp_block;    /* Date management */    if( p_block && p_block->i_pts > 0 &&        p_block->i_pts != aout_DateGet( &p_sys->end_date ) )    {        aout_DateSet( &p_sys->end_date, p_block->i_pts );    }    if( !aout_DateGet( &p_sys->end_date ) )    {        /* We've just started the stream, wait for the first PTS. */        if( p_block ) block_Release( p_block );        return NULL;    }    *pp_block = NULL; /* To avoid being fed the same packet again */    if( p_sys->b_packetizer )    {        return SendPacket( p_dec, p_oggpacket, p_block );    }    else    {        aout_buffer_t *p_aout_buffer;        if( p_sys->i_headers >= 3 )            p_aout_buffer = DecodePacket( p_dec, p_oggpacket );        else            p_aout_buffer = NULL;        if( p_block ) block_Release( p_block );        return p_aout_buffer;    }}/***************************************************************************** * DecodePacket: decodes a Vorbis packet. *****************************************************************************/static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ){    decoder_sys_t *p_sys = p_dec->p_sys;    int           i_samples;#ifdef MODULE_NAME_IS_tremor    int32_t       **pp_pcm;#else    float         **pp_pcm;#endif    if( p_oggpacket->bytes &&#ifdef MODULE_NAME_IS_tremor        vorbis_synthesis( &p_sys->vb, p_oggpacket, 1 ) == 0 )#else        vorbis_synthesis( &p_sys->vb, p_oggpacket ) == 0 )#endif        vorbis_synthesis_blockin( &p_sys->vd, &p_sys->vb );    /* **pp_pcm is a multichannel float vector. In stereo, for     * example, pp_pcm[0] is left, and pp_pcm[1] is right. i_samples is     * the size of each channel. Convert the float values     * (-1.<=range<=1.) to whatever PCM format and write it out */    if( ( i_samples = vorbis_synthesis_pcmout( &p_sys->vd, &pp_pcm ) ) > 0 )    {        aout_buffer_t *p_aout_buffer;        p_aout_buffer =            p_dec->pf_aout_buffer_new( p_dec, i_samples );        if( p_aout_buffer == NULL ) return NULL;        /* Interleave the samples */#ifdef MODULE_NAME_IS_tremor        Interleave( (int32_t *)p_aout_buffer->p_buffer,                    (const int32_t **)pp_pcm, p_sys->vi.channels, i_samples, p_sys->pi_chan_table);#else        Interleave( (float *)p_aout_buffer->p_buffer,                    (const float **)pp_pcm, p_sys->vi.channels, i_samples, p_sys->pi_chan_table);#endif        /* Tell libvorbis how many samples we actually consumed */        vorbis_synthesis_read( &p_sys->vd, i_samples );        /* Date management */        p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );        p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,                                                      i_samples );        return p_aout_buffer;    }    else    {        return NULL;    }}/***************************************************************************** * SendPacket: send an ogg dated packet to the stream output. *****************************************************************************/static block_t *SendPacket( decoder_t *p_dec, ogg_packet *p_oggpacket,                            block_t *p_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    int i_block_size, i_samples;    i_block_size = vorbis_packet_blocksize( &p_sys->vi, p_oggpacket );    if( i_block_size < 0 ) i_block_size = 0; /* non audio packet */    i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;    p_sys->i_last_block_size = i_block_size;    /* Date management */    p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->end_date );    if( p_sys->i_headers >= 3 )        p_block->i_length = aout_DateIncrement( &p_sys->end_date, i_samples ) -            p_block->i_pts;    else        p_block->i_length = 0;    return p_block;}/***************************************************************************** * ParseVorbisComments: FIXME should be done in demuxer *****************************************************************************/static void ParseVorbisComments( decoder_t *p_dec ){    input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;    char *psz_name, *psz_value, *psz_comment;    int i = 0;    if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;    while( i < p_dec->p_sys->vc.comments )    {        psz_comment = strdup( p_dec->p_sys->vc.user_comments[i] );        if( !psz_comment )        {            msg_Warn( p_dec, "out of memory" );            break;        }        psz_name = psz_comment;        psz_value = strchr( psz_comment, '=' );        if( psz_value )        {            *psz_value = '\0';            psz_value++;            input_Control( p_input, INPUT_ADD_INFO, _("Vorbis comment"),                           psz_name, psz_value );            if( strcasestr( psz_name, "artist" ) )            {                vlc_input_item_AddInfo( p_input->input.p_item,                                        _(VLC_META_INFO_CAT), _(VLC_META_ARTIST),                                        "%s", psz_value );            }            else if( strcasestr( psz_name, "title" ) )            {                p_input->input.p_item->psz_name = strdup( psz_value );            }        }        /* FIXME */        var_SetInteger( p_input, "item-change", p_input->input.p_item->i_id );        free( psz_comment );        i++;    }}/***************************************************************************** * Interleave: helper function to interleave channels *****************************************************************************/static void ConfigureChannelOrder(int *pi_chan_table, int i_channels, uint32_t i_channel_mask, vlc_bool_t b_decode){    const uint32_t *pi_channels_in;    switch( i_channels )    {        case 6:        case 5:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -