📄 flac.c
字号:
{ 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 + -