From 8bcbe90b250e651fa499524a8c677e19198427a7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 23 Sep 2008 23:59:54 +0200 Subject: flac: moved code from flacWrite() to _flac_common.c There is still a lot of duplicated code in flac_plugin.c and oggflac_plugin.c. Move code from flac_plugin.c to _flac_common.c, and use the new function flac_common_write() also in oggflac_plugin.c, porting lots of optimizations over to it. --- src/inputPlugins/_flac_common.c | 91 +++++++++++++++++++++++++++++++++++++++ src/inputPlugins/_flac_common.h | 15 ++----- src/inputPlugins/flac_plugin.c | 74 +------------------------------ src/inputPlugins/oggflac_plugin.c | 46 +------------------- 4 files changed, 97 insertions(+), 129 deletions(-) (limited to 'src') diff --git a/src/inputPlugins/_flac_common.c b/src/inputPlugins/_flac_common.c index e0c251489..5a98e63bc 100644 --- a/src/inputPlugins/_flac_common.c +++ b/src/inputPlugins/_flac_common.c @@ -196,4 +196,95 @@ void flac_error_common_cb(const char *plugin, } } +/* keep this inlined, this is just macro but prettier :) */ +static inline int flacSendChunk(FlacData * data) +{ + if (decoder_data(data->decoder, data->inStream, + 1, data->chunk, + data->chunk_length, data->time, + data->bitRate, + data->replayGainInfo) == DECODE_COMMAND_STOP) + return -1; + + return 0; +} + +static void flac_convert_stereo16(unsigned char *dest, + const FLAC__int32 * const buf[], + unsigned int position, unsigned int end) +{ + for (; position < end; ++position) { + *(uint16_t*)dest = buf[0][position]; + dest += 2; + *(uint16_t*)dest = buf[1][position]; + dest += 2; + } +} + +static void flac_convert(unsigned char *dest, + unsigned int num_channels, + unsigned int bytes_per_sample, + const FLAC__int32 * const buf[], + unsigned int position, unsigned int end) +{ + unsigned int c_chan, i; + FLAC__uint16 u16; + unsigned char *uc; + + for (; position < end; ++position) { + for (c_chan = 0; c_chan < num_channels; c_chan++) { + u16 = buf[c_chan][position]; + uc = (unsigned char *)&u16; + for (i = 0; i < bytes_per_sample; i++) { + *dest++ = *uc++; + } + } + } +} + +FLAC__StreamDecoderWriteStatus +flac_common_write(FlacData *data, const FLAC__Frame * frame, + const FLAC__int32 *const buf[]) +{ + unsigned int c_samp; + const unsigned int num_channels = frame->header.channels; + const unsigned int bytes_per_sample = + audio_format_sample_size(&data->audio_format); + const unsigned int bytes_per_channel = + bytes_per_sample * frame->header.channels; + const unsigned int max_samples = FLAC_CHUNK_SIZE / bytes_per_channel; + unsigned int num_samples; + + assert(data->audio_format.bits > 0); + + for (c_samp = 0; c_samp < frame->header.blocksize; + c_samp += num_samples) { + num_samples = frame->header.blocksize - c_samp; + if (num_samples > max_samples) + num_samples = max_samples; + + if (num_channels == 2 && bytes_per_sample == 2) + flac_convert_stereo16(data->chunk, + buf, c_samp, + c_samp + num_samples); + else + flac_convert(data->chunk, + num_channels, bytes_per_sample, buf, + c_samp, c_samp + num_samples); + data->chunk_length = num_samples * bytes_per_channel; + + if (flacSendChunk(data) < 0) { + return + FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + } + data->chunk_length = 0; + if (decoder_get_command(data->decoder) == DECODE_COMMAND_SEEK) { + return + FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + } + } + + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + #endif /* HAVE_FLAC || HAVE_OGGFLAC */ diff --git a/src/inputPlugins/_flac_common.h b/src/inputPlugins/_flac_common.h index a758a7369..4ca97cae0 100644 --- a/src/inputPlugins/_flac_common.h +++ b/src/inputPlugins/_flac_common.h @@ -164,18 +164,9 @@ void flac_error_common_cb(const char *plugin, struct tag *copyVorbisCommentBlockToMpdTag(const FLAC__StreamMetadata * block, struct tag *tag); -/* keep this inlined, this is just macro but prettier :) */ -static inline int flacSendChunk(FlacData * data) -{ - if (decoder_data(data->decoder, data->inStream, - 1, data->chunk, - data->chunk_length, data->time, - data->bitRate, - data->replayGainInfo) == DECODE_COMMAND_STOP) - return -1; - - return 0; -} +FLAC__StreamDecoderWriteStatus +flac_common_write(FlacData *data, const FLAC__Frame * frame, + const FLAC__int32 *const buf[]); #endif /* HAVE_FLAC || HAVE_OGGFLAC */ diff --git a/src/inputPlugins/flac_plugin.c b/src/inputPlugins/flac_plugin.c index efa3e8355..fb518871a 100644 --- a/src/inputPlugins/flac_plugin.c +++ b/src/inputPlugins/flac_plugin.c @@ -195,59 +195,16 @@ static void flacMetadata(mpd_unused const flac_decoder * dec, flac_metadata_common_cb(block, (FlacData *) vdata); } -static void flac_convert_stereo16(unsigned char *dest, - const FLAC__int32 * const buf[], - unsigned int position, unsigned int end) -{ - for (; position < end; ++position) { - *(uint16_t*)dest = buf[0][position]; - dest += 2; - *(uint16_t*)dest = buf[1][position]; - dest += 2; - } -} - -static void flac_convert(unsigned char *dest, - unsigned int num_channels, - unsigned int bytes_per_sample, - const FLAC__int32 * const buf[], - unsigned int position, unsigned int end) -{ - unsigned int c_chan, i; - FLAC__uint16 u16; - unsigned char *uc; - - for (; position < end; ++position) { - for (c_chan = 0; c_chan < num_channels; c_chan++) { - u16 = buf[c_chan][position]; - uc = (unsigned char *)&u16; - for (i = 0; i < bytes_per_sample; i++) { - *dest++ = *uc++; - } - } - } -} - static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, const FLAC__Frame * frame, const FLAC__int32 * const buf[], void *vdata) { - FlacData *data = (FlacData *) vdata; FLAC__uint32 samples = frame->header.blocksize; - unsigned int c_samp; - const unsigned int num_channels = frame->header.channels; - const unsigned int bytes_per_sample = - audio_format_sample_size(&data->audio_format); - const unsigned int bytes_per_channel = - bytes_per_sample * frame->header.channels; - const unsigned int max_samples = FLAC_CHUNK_SIZE / bytes_per_channel; - unsigned int num_samples; + FlacData *data = (FlacData *) vdata; float timeChange; FLAC__uint64 newPosition = 0; - assert(data->audio_format.bits > 0); - timeChange = ((float)samples) / frame->header.sample_rate; data->time += timeChange; @@ -261,34 +218,7 @@ static FLAC__StreamDecoderWriteStatus flacWrite(const flac_decoder *dec, } data->position = newPosition; - for (c_samp = 0; c_samp < frame->header.blocksize; - c_samp += num_samples) { - num_samples = frame->header.blocksize - c_samp; - if (num_samples > max_samples) - num_samples = max_samples; - - if (num_channels == 2 && bytes_per_sample == 2) - flac_convert_stereo16(data->chunk, - buf, c_samp, - c_samp + num_samples); - else - flac_convert(data->chunk, - num_channels, bytes_per_sample, buf, - c_samp, c_samp + num_samples); - data->chunk_length = num_samples * bytes_per_channel; - - if (flacSendChunk(data) < 0) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } - data->chunk_length = 0; - if (decoder_get_command(data->decoder) == DECODE_COMMAND_SEEK) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; - } - } - - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + return flac_common_write(data, frame, buf); } static struct tag *flacMetadataDup(char *file, int *vorbisCommentFound) diff --git a/src/inputPlugins/oggflac_plugin.c b/src/inputPlugins/oggflac_plugin.c index 31ddaab7f..342ebc149 100644 --- a/src/inputPlugins/oggflac_plugin.c +++ b/src/inputPlugins/oggflac_plugin.c @@ -157,50 +157,12 @@ static FLAC__StreamDecoderWriteStatus oggflacWrite(mpd_unused const { FlacData *data = (FlacData *) vdata; FLAC__uint32 samples = frame->header.blocksize; - FLAC__uint16 u16; - unsigned char *uc; - unsigned int c_samp, c_chan; - unsigned int i; float timeChange; timeChange = ((float)samples) / frame->header.sample_rate; data->time += timeChange; - /* ogg123 uses a complicated method of calculating bitrate - * with averaging which I'm not too fond of. - * (waste of memory/CPU cycles, especially given this is _lossless_) - * a get_decode_position() is not available in OggFLAC, either - * - * this does not give an accurate bitrate: - * (bytes_last_read was set in the read callback) - data->bitRate = ((8.0 * data->bytes_last_read * - frame->header.sample_rate) - /((float)samples * 1000)) + 0.5; - */ - - for (c_samp = 0; c_samp < frame->header.blocksize; c_samp++) { - for (c_chan = 0; c_chan < frame->header.channels; - c_chan++) { - u16 = buf[c_chan][c_samp]; - uc = (unsigned char *)&u16; - for (i = 0; i < audio_format_sample_size(&data->audio_format); i++) { - if (data->chunk_length >= FLAC_CHUNK_SIZE) { - if (flacSendChunk(data) < 0) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; - } - data->chunk_length = 0; - if (decoder_get_command(data->decoder) == DECODE_COMMAND_SEEK) { - return - FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; - } - } - data->chunk[data->chunk_length++] = *(uc++); - } - } - } - - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; + return flac_common_write(data, frame, buf); } /* used by TagDup */ @@ -372,12 +334,6 @@ static int oggflac_decode(struct decoder * mpd_decoder, InputStream * inStream) (OggFLAC__seekable_stream_decoder_get_state(decoder)); OggFLAC__seekable_stream_decoder_finish(decoder); } - /* send last little bit */ - if (data.chunk_length > 0 && - decoder_get_command(mpd_decoder) == DECODE_COMMAND_NONE) { - flacSendChunk(&data); - decoder_flush(mpd_decoder); - } fail: oggflac_cleanup(&data, decoder); -- cgit v1.2.3