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

📄 flac.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 3 页
字号:
            {                if( p_header[0] == 0xFF && p_header[1] == 0xF8 )                {                    /* Check if frame is valid and get frame info */                    int i_frame_length =                        SyncInfo( p_dec, p_header,                                  &p_sys->i_channels,                                  &p_sys->i_channels_conf,                                  &p_sys->i_rate,                                  &p_sys->i_bits_per_sample );                    if( i_frame_length )                    {                        p_sys->i_state = STATE_SEND_DATA;                        break;                    }                }                p_sys->i_frame_size++;            }            if( p_sys->i_state != STATE_SEND_DATA )            {                /* Need more data */                return NULL;            }        case STATE_SEND_DATA:            p_sout_block = block_New( p_dec, p_sys->i_frame_size );            /* Copy the whole frame into the buffer. When we reach this point             * we already know we have enough data available. */            block_GetBytes( &p_sys->bytestream, p_sout_block->p_buffer,                            p_sys->i_frame_size );            /* Make sure we don't reuse the same pts twice */            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = 0;            /* So p_block doesn't get re-added several times */            *pp_block = block_BytestreamPop( &p_sys->bytestream );            p_sys->i_state = STATE_NOSYNC;            /* Date management */            p_sout_block->i_pts =                p_sout_block->i_dts = aout_DateGet( &p_sys->end_date );            aout_DateIncrement( &p_sys->end_date, p_sys->i_frame_length );            p_sout_block->i_length =                aout_DateGet( &p_sys->end_date ) - p_sout_block->i_pts;            return p_sout_block;        }    }    return NULL;}#ifdef USE_LIBFLAC/**************************************************************************** * DecodeBlock: the whole thing ****************************************************************************/static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ){    decoder_sys_t *p_sys = p_dec->p_sys;    if( !pp_block || !*pp_block ) return NULL;    p_sys->p_aout_buffer = 0;    if( ( p_sys->p_block = PacketizeBlock( p_dec, pp_block ) ) )    {        if( !FLAC__stream_decoder_process_single( p_sys->p_flac ) )        {            decoder_state_error( p_dec,                FLAC__stream_decoder_get_state( p_sys->p_flac ) );            FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );        }        /* If the decoder is in the "aborted" state,         * FLAC__stream_decoder_process_single() won't return an error. */        if( FLAC__stream_decoder_get_state(p_dec->p_sys->p_flac)            == FLAC__STREAM_DECODER_ABORTED )        {            FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );        }        block_Release( p_sys->p_block );        p_sys->p_block = NULL;    }    return p_sys->p_aout_buffer;}/***************************************************************************** * DecoderReadCallback: called by libflac when it needs more data *****************************************************************************/static FLAC__StreamDecoderReadStatusDecoderReadCallback( const FLAC__StreamDecoder *decoder, FLAC__byte buffer[],                     unsigned *bytes, void *client_data ){    decoder_t *p_dec = (decoder_t *)client_data;    decoder_sys_t *p_sys = p_dec->p_sys;    if( p_sys->p_block && p_sys->p_block->i_buffer )    {        *bytes = __MIN(*bytes, (unsigned)p_sys->p_block->i_buffer);        memcpy( buffer, p_sys->p_block->p_buffer, *bytes );        p_sys->p_block->i_buffer -= *bytes;        p_sys->p_block->p_buffer += *bytes;    }    else    {        *bytes = 0;        return FLAC__STREAM_DECODER_READ_STATUS_ABORT;    }    return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;}/***************************************************************************** * DecoderWriteCallback: called by libflac to output decoded samples *****************************************************************************/static FLAC__StreamDecoderWriteStatusDecoderWriteCallback( const FLAC__StreamDecoder *decoder,                      const FLAC__Frame *frame,                      const FLAC__int32 *const buffer[], void *client_data ){    decoder_t *p_dec = (decoder_t *)client_data;    decoder_sys_t *p_sys = p_dec->p_sys;    p_sys->p_aout_buffer =        p_dec->pf_aout_buffer_new( p_dec, frame->header.blocksize );    if( p_sys->p_aout_buffer == NULL )        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;    switch( frame->header.bits_per_sample )    {    case 16:        Interleave16( (int16_t *)p_sys->p_aout_buffer->p_buffer, buffer,                      frame->header.channels, frame->header.blocksize );        break;    default:        Interleave32( (int32_t *)p_sys->p_aout_buffer->p_buffer, buffer,                      frame->header.channels, frame->header.blocksize );    }    /* Date management (already done by packetizer) */    p_sys->p_aout_buffer->start_date = p_sys->p_block->i_pts;    p_sys->p_aout_buffer->end_date =        p_sys->p_block->i_pts + p_sys->p_block->i_length;    return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;}/***************************************************************************** * DecoderMetadataCallback: called by libflac to when it encounters metadata *****************************************************************************/static void DecoderMetadataCallback( const FLAC__StreamDecoder *decoder,                                     const FLAC__StreamMetadata *metadata,                                     void *client_data ){    decoder_t *p_dec = (decoder_t *)client_data;    decoder_sys_t *p_sys = p_dec->p_sys;    switch( metadata->data.stream_info.bits_per_sample )    {    case 8:        p_dec->fmt_out.i_codec = VLC_FOURCC('s','8',' ',' ');        break;    case 16:        p_dec->fmt_out.i_codec = AOUT_FMT_S16_NE;        break;    default:        msg_Dbg( p_dec, "strange bit/sample value: %d",                 metadata->data.stream_info.bits_per_sample );        p_dec->fmt_out.i_codec = VLC_FOURCC('f','i','3','2');        break;    }    /* Setup the format */    p_dec->fmt_out.audio.i_rate     = metadata->data.stream_info.sample_rate;    p_dec->fmt_out.audio.i_channels = metadata->data.stream_info.channels;    p_dec->fmt_out.audio.i_physical_channels =        p_dec->fmt_out.audio.i_original_channels =            pi_channels_maps[metadata->data.stream_info.channels];    p_dec->fmt_out.audio.i_bitspersample =        metadata->data.stream_info.bits_per_sample;    aout_DateInit( &p_sys->end_date, p_dec->fmt_out.audio.i_rate );    msg_Dbg( p_dec, "channels:%d samplerate:%d bitspersamples:%d",             p_dec->fmt_out.audio.i_channels, p_dec->fmt_out.audio.i_rate,             p_dec->fmt_out.audio.i_bitspersample );    p_sys->b_stream_info = VLC_TRUE;    p_sys->stream_info = metadata->data.stream_info;    return;}/***************************************************************************** * DecoderErrorCallback: called when the libflac decoder encounters an error *****************************************************************************/static void DecoderErrorCallback( const FLAC__StreamDecoder *decoder,                                  FLAC__StreamDecoderErrorStatus status,                                  void *client_data ){    decoder_t *p_dec = (decoder_t *)client_data;    switch( status )    {    case FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC:        msg_Err( p_dec, "an error in the stream caused the decoder to "                 "lose synchronization." );        break;    case FLAC__STREAM_DECODER_ERROR_STATUS_BAD_HEADER:        msg_Err( p_dec, "the decoder encountered a corrupted frame header." );        break;    case FLAC__STREAM_DECODER_ERROR_STATUS_FRAME_CRC_MISMATCH:        msg_Err( p_dec, "frame's data did not match the CRC in the "                 "footer." );        break;    default:        msg_Err( p_dec, "got decoder error: %d", status );    }    FLAC__stream_decoder_flush( p_dec->p_sys->p_flac );    return;}/***************************************************************************** * Interleave: helper function to interleave channels *****************************************************************************/static void Interleave32( int32_t *p_out, const int32_t * const *pp_in,                          int i_nb_channels, int i_samples ){    int i, j;    for ( j = 0; j < i_samples; j++ )    {        for ( i = 0; i < i_nb_channels; i++ )        {            p_out[j * i_nb_channels + i] = pp_in[i][j];        }    }}static void Interleave16( int16_t *p_out, const int32_t * const *pp_in,                          int i_nb_channels, int i_samples ){    int i, j;    for ( j = 0; j < i_samples; j++ )    {        for ( i = 0; i < i_nb_channels; i++ )        {            p_out[j * i_nb_channels + i] = (int32_t)(pp_in[i][j]);        }    }}/***************************************************************************** * decoder_state_error: print meaningful error messages *****************************************************************************/static void decoder_state_error( decoder_t *p_dec,                                 FLAC__StreamDecoderState state ){    switch ( state )    {    case FLAC__STREAM_DECODER_SEARCH_FOR_METADATA:        msg_Err( p_dec, "the decoder is ready to search for metadata." );        break;    case FLAC__STREAM_DECODER_READ_METADATA:        msg_Err( p_dec, "the decoder is ready to or is in the process of "                 "reading metadata." );        break;    case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:        msg_Err( p_dec, "the decoder is ready to or is in the process of "                 "searching for the frame sync code." );        break;    case FLAC__STREAM_DECODER_READ_FRAME:        msg_Err( p_dec, "the decoder is ready to or is in the process of "                 "reading a frame." );        break;    case FLAC__STREAM_DECODER_END_OF_STREAM:        msg_Err( p_dec, "the decoder has reached the end of the stream." );        break;    case FLAC__STREAM_DECODER_ABORTED:        msg_Err( p_dec, "the decoder was aborted by the read callback." );        break;    case FLAC__STREAM_DECODER_UNPARSEABLE_STREAM:        msg_Err( p_dec, "the decoder encountered reserved fields in use "                 "in the stream." );        break;    case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:        msg_Err( p_dec, "error when allocating memory." );        break;    case FLAC__STREAM_DECODER_ALREADY_INITIALIZED:        msg_Err( p_dec, "FLAC__stream_decoder_init() was called when the "                 "decoder was already initialized, usually because "                 "FLAC__stream_decoder_finish() was not called." );        break;    case FLAC__STREAM_DECODER_INVALID_CALLBACK:        msg_Err( p_dec, "FLAC__stream_decoder_init() was called without "                 "all callbacks being set." );        break;    case FLAC__STREAM_DECODER_UNINITIALIZED:        msg_Err( p_dec, "decoder in uninitialized state." );        break;    default:        msg_Err(p_dec, "unknown error" );    }}#endif/***************************************************************************** * SyncInfo: parse FLAC sync info *****************************************************************************/static int SyncInfo( decoder_t *p_dec, uint8_t *p_buf,                     int * pi_channels, int * pi_channels_conf,                     int * pi_sample_rate, int * pi_bits_per_sample ){    decoder_sys_t *p_sys = p_dec->p_sys;    int i_header, i_temp, i_read;    int i_blocksize = 0, i_blocksize_hint = 0, i_sample_rate_hint = 0;    uint64_t i_sample_number = 0;    vlc_bool_t b_variable_blocksize = ( p_sys->b_stream_info &&        p_sys->stream_info.min_blocksize != p_sys->stream_info.max_blocksize );    vlc_bool_t b_fixed_blocksize = ( p_sys->b_stream_info &&        p_sys->stream_info.min_blocksize == p_sys->stream_info.max_blocksize );    /* Check syncword */    if( p_buf[0] != 0xFF || p_buf[1] != 0xF8 ) return 0;    /* Check there is no emulated sync code in the rest of the header */    if( p_buf[2] == 0xff || p_buf[3] == 0xFF ) return 0;    /* Find blocksize (framelength) */    switch( i_temp = p_buf[2] >> 4 )    {    case 0:        if( b_fixed_blocksize )            i_blocksize = p_sys->stream_info.min_blocksize;        else return 0; /* We can't do anything with this */        break;    case 1:        i_blocksize = 192;        break;    case 2:    case 3:    case 4:    case 5:        i_blocksize = 576 << (i_temp - 2);        break;    case 6:    case 7:        i_blocksize_hint = i_temp;        break;    case 8:    case 9:    case 10:    case 11:    case 12:    case 13:    case 14:    case 15:        i_blocksize = 256 << (i_temp - 8);        break;    }    /* Find samplerate */    switch( i_temp = p_buf[2] & 0x0f )    {    case 0:        if( p_sys->b_stream_info )            *pi_sample_rate = p_sys->stream_info.sample_rate;        else return 0; /* We can't do anything with this */        break;    case 1:    case 2:    case 3:        return 0;        break;    case 4:        *pi_sample_rate = 8000;        break;    case 5:        *pi_sample_rate = 16000;        break;    case 6:        *pi_sample_rate = 22050;        break;    case 7:        *pi_sample_rate = 24000;        break;    case 8:        *pi_sample_rate = 32000;        break;    case 9:        *pi_sample_rate = 44100;        break;    case 10:        *pi_sample_rate = 48000;        break;    case 11:        *pi_sample_rate = 96000;        break;    case 12:    case 13:    case 14:        i_sample_rate_hint = i_temp;        break;    case 15:        return 0;    }    /* Find channels */    i_temp = (unsigned)(p_buf[3] >> 4);    if( i_temp & 8 )    {#ifdef USE_LIBFLAC        int i_channel_assignment; /* ??? */        switch( i_temp & 7 )        {        case 0:

⌨️ 快捷键说明

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