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

📄 speex.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
    void *p_state;    SpeexHeader *p_header;    const SpeexMode *p_mode;    SpeexCallback callback;    p_sys->p_header = p_header =        speex_packet_to_header( (char *)p_oggpacket->packet,                                p_oggpacket->bytes );    if( !p_header )    {        msg_Err( p_dec, "cannot read Speex header" );        return VLC_EGENERIC;    }    if( p_header->mode >= SPEEX_NB_MODES || p_header->mode < 0 )    {        msg_Err( p_dec, "mode number %d does not (yet/any longer) exist in "                 "this version of libspeex.", p_header->mode );        return VLC_EGENERIC;    }    p_mode = speex_mode_list[p_header->mode];    if( p_mode == NULL )        return VLC_EGENERIC;    if( p_header->speex_version_id > 1 )    {        msg_Err( p_dec, "this file was encoded with Speex bit-stream "                 "version %d which is not supported by this decoder.",                 p_header->speex_version_id );        return VLC_EGENERIC;    }    if( p_mode->bitstream_version < p_header->mode_bitstream_version )    {        msg_Err( p_dec, "file encoded with a newer version of Speex." );        return VLC_EGENERIC;    }    if( p_mode->bitstream_version > p_header->mode_bitstream_version )    {        msg_Err( p_dec, "file encoded with an older version of Speex." );        return VLC_EGENERIC;    }    msg_Dbg( p_dec, "Speex %d Hz audio using %s mode %s%s",             p_header->rate, p_mode->modeName,             ( p_header->nb_channels == 1 ) ? " (mono" : " (stereo",             p_header->vbr ? ", VBR)" : ")" );    /* Take care of speex decoder init */    speex_bits_init( &p_sys->bits );    p_sys->p_state = p_state = speex_decoder_init( p_mode );    if( !p_state )    {        msg_Err( p_dec, "decoder initialization failed" );        return VLC_EGENERIC;    }    if( p_header->nb_channels == 2 )    {        SpeexStereoState stereo = SPEEX_STEREO_STATE_INIT;        p_sys->stereo = stereo;        callback.callback_id = SPEEX_INBAND_STEREO;        callback.func = speex_std_stereo_request_handler;        callback.data = &p_sys->stereo;        speex_decoder_ctl( p_state, SPEEX_SET_HANDLER, &callback );    }    if( p_header->nb_channels <= 0 ||        p_header->nb_channels > 5 )    {        msg_Err( p_dec, "invalid number of channels (not between 1 and 5): %i",                 p_header->nb_channels );        return VLC_EGENERIC;    }    /* Setup the format */    p_dec->fmt_out.audio.i_physical_channels =        p_dec->fmt_out.audio.i_original_channels =            pi_channels_maps[p_header->nb_channels];    p_dec->fmt_out.audio.i_channels = p_header->nb_channels;    p_dec->fmt_out.audio.i_rate = p_header->rate;    aout_DateInit( &p_sys->end_date, p_header->rate );    return VLC_SUCCESS;}/***************************************************************************** * ProcessPacket: processes a Speex 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 )    {	if ( p_sys->p_header->frames_per_packet > 1 )	{	    short *p_frame_holder = NULL;	    int i_bits_before = 0, i_bits_after = 0, i_bytes_in_speex_frame = 0,	        i_pcm_output_size = 0, i_bits_in_speex_frame = 0;	    block_t *p_new_block = NULL;	    i_pcm_output_size = p_sys->p_header->frame_size;	    p_frame_holder = (short*)malloc( sizeof(short)*i_pcm_output_size );            speex_bits_read_from( &p_sys->bits, (char*)p_oggpacket->packet,	        p_oggpacket->bytes);            i_bits_before = speex_bits_remaining( &p_sys->bits );	    speex_decode_int(p_sys->p_state, &p_sys->bits, p_frame_holder);	    i_bits_after = speex_bits_remaining( &p_sys->bits );            i_bits_in_speex_frame = i_bits_before - i_bits_after;	    i_bytes_in_speex_frame = ( i_bits_in_speex_frame + 	        (8 - (i_bits_in_speex_frame % 8)) )                / 8;            p_new_block = block_New( p_dec, i_bytes_in_speex_frame );	    memset( p_new_block->p_buffer, 0xff, i_bytes_in_speex_frame );	    /*	     * Copy the first frame in this packet to a new packet.	     */	    speex_bits_rewind( &p_sys->bits );	    speex_bits_write( &p_sys->bits, 	        (char*)p_new_block->p_buffer, 		    (int)i_bytes_in_speex_frame );	    /*	     * Move the remaining part of the original packet (subsequent	     * frames, if there are any) into the beginning 	     * of the original packet so	     * they are preserved following the realloc. 	     * Note: Any bits that	     * remain in the initial packet	     * are "filler" if they do not constitute	     * an entire byte. 	     */	    if ( i_bits_after > 7 )	    {	        /* round-down since we rounded-up earlier (to include		 * the speex terminator code. 		 */	        i_bytes_in_speex_frame--;	        speex_bits_write( &p_sys->bits, 		        (char*)p_block->p_buffer, 		        p_block->i_buffer - i_bytes_in_speex_frame );            p_block = block_Realloc( p_block, 	            0, 		        p_block->i_buffer-i_bytes_in_speex_frame );	        *pp_block = p_block;	    }	    else	    {	        speex_bits_reset( &p_sys->bits );	    }	    free( p_frame_holder );	    return SendPacket( p_dec, p_new_block);	}	else	{            return SendPacket( p_dec, p_block );	}    }    else    {        aout_buffer_t *p_aout_buffer;        if( p_sys->i_headers >= p_sys->p_header->extra_headers + 2 )            p_aout_buffer = DecodePacket( p_dec, p_oggpacket );        else            p_aout_buffer = NULL; /* Skip headers */        if( p_block ) block_Release( p_block );        return p_aout_buffer;    }}static aout_buffer_t *DecodeRtpSpeexPacket( decoder_t *p_dec, block_t **pp_block ){    block_t *p_speex_bit_block = *pp_block;    decoder_sys_t *p_sys = p_dec->p_sys;    aout_buffer_t *p_aout_buffer;    int i_decode_ret;    unsigned int i_speex_frame_size;    if ( !p_speex_bit_block || p_speex_bit_block->i_pts == 0 ) return NULL;    /*       If the SpeexBits buffer size is 0 (a default value),      we know that a proper initialization has not yet been done.    */    if ( p_sys->bits.buf_size==0 )    {	p_sys->p_header = (SpeexHeader *)malloc(sizeof(SpeexHeader));	if ( !p_sys->p_header )	{	    msg_Err( p_dec, "Could not allocate a Speex header.");	    return NULL;	}	speex_init_header( p_sys->p_header,p_sys->rtp_rate,1,&speex_nb_mode );        speex_bits_init( &p_sys->bits );	p_sys->p_state = speex_decoder_init( &speex_nb_mode );	if ( !p_sys->p_state )	{	    msg_Err( p_dec, "Could not allocate a Speex decoder." );	    free( p_sys->p_header );	    return NULL;	}        /*	  Assume that variable bit rate is enabled. Also assume	  that there is only one frame per packet. 	*/	p_sys->p_header->vbr = 1;	p_sys->p_header->frames_per_packet = 1;        p_dec->fmt_out.audio.i_channels = p_sys->p_header->nb_channels;	p_dec->fmt_out.audio.i_physical_channels = 	p_dec->fmt_out.audio.i_original_channels = 	    pi_channels_maps[p_sys->p_header->nb_channels];        p_dec->fmt_out.audio.i_rate = p_sys->p_header->rate;        if ( speex_mode_query( &speex_nb_mode, 	    SPEEX_MODE_FRAME_SIZE, 	    &i_speex_frame_size ) )	{	    msg_Err( p_dec, "Could not determine the frame size." );	    speex_decoder_destroy( p_sys->p_state );	    free( p_sys->p_header );	    return NULL;	}	p_dec->fmt_out.audio.i_bytes_per_frame = i_speex_frame_size;	aout_DateInit(&p_sys->end_date, p_sys->p_header->rate);    }    /*       If the SpeexBits are initialized but there is       still no header, an error must be thrown.    */    if ( !p_sys->p_header )    {        msg_Err( p_dec, "There is no valid Speex header found." );	return NULL;    }    *pp_block = NULL;    if ( !aout_DateGet( &p_sys->end_date ) )        aout_DateSet( &p_sys->end_date, p_speex_bit_block->i_dts );    /*      Ask for a new audio output buffer and make sure      we get one.     */    p_aout_buffer = p_dec->pf_aout_buffer_new( p_dec,         p_sys->p_header->frame_size );    if ( !p_aout_buffer || p_aout_buffer->i_nb_bytes == 0 )    {        msg_Err(p_dec, "Oops: No new buffer was returned!");	return NULL;    }    /*      Read the Speex payload into the SpeexBits buffer.    */    speex_bits_read_from( &p_sys->bits,         (char*)p_speex_bit_block->p_buffer,         p_speex_bit_block->i_buffer );        /*       Decode the input and ensure that no errors       were encountered.    */    i_decode_ret = speex_decode_int( p_sys->p_state, &p_sys->bits,             (int16_t*)p_aout_buffer->p_buffer );    if ( i_decode_ret < 0 )    {        msg_Err( p_dec, "Decoding failed. Perhaps we have a bad stream?" );	return NULL;    }    /*       Handle date management on the audio output buffer.     */    p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );    p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,         p_sys->p_header->frame_size );            p_sys->i_frame_in_packet++;    block_Release( p_speex_bit_block );    return p_aout_buffer;}/***************************************************************************** * DecodePacket: decodes a Speex packet. *****************************************************************************/static aout_buffer_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket ){    decoder_sys_t *p_sys = p_dec->p_sys;    if( p_oggpacket->bytes )    {        /* Copy Ogg packet to Speex bitstream */        speex_bits_read_from( &p_sys->bits, (char *)p_oggpacket->packet,                              p_oggpacket->bytes );        p_sys->i_frame_in_packet = 0;    }    /* Decode one frame at a time */    if( p_sys->i_frame_in_packet < p_sys->p_header->frames_per_packet )    {        aout_buffer_t *p_aout_buffer;        if( p_sys->p_header->frame_size == 0 )            return NULL;        p_aout_buffer =            p_dec->pf_aout_buffer_new( p_dec, p_sys->p_header->frame_size );        if( !p_aout_buffer )        {            return NULL;        }        switch( speex_decode_int( p_sys->p_state, &p_sys->bits,

⌨️ 快捷键说明

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