From 7b13776f2dd2feeb4bd28e8cf023ec81474e4eaa Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 11 Nov 2009 19:25:15 +0100 Subject: decoder/flac: store the whole stream info object, not duration We don't want to work with floating point values if possible. Get the integer number of frames from the FLAC__StreamMetadata_StreamInfo object, and convert it into a float duration on demand. This patch adds a check if the STREAMINFO packet has been received yet. --- src/decoder/_flac_common.c | 5 ++++- src/decoder/_flac_common.h | 14 +++++++++++++- src/decoder/flac_plugin.c | 14 ++++++++++---- src/decoder/oggflac_plugin.c | 10 +++++++++- 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/decoder/_flac_common.c b/src/decoder/_flac_common.c index 812ca6dae..fbeab43a7 100644 --- a/src/decoder/_flac_common.c +++ b/src/decoder/_flac_common.c @@ -35,6 +35,7 @@ flac_data_init(struct flac_data *data, struct decoder * decoder, { pcm_buffer_init(&data->buffer); + data->have_stream_info = false; data->next_frame = 0; data->time = 0; @@ -65,9 +66,11 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block, switch (block->type) { case FLAC__METADATA_TYPE_STREAMINFO: + data->stream_info = block->data.stream_info; + data->have_stream_info = true; + audio_format_init(&data->audio_format, si->sample_rate, si->bits_per_sample, si->channels); - data->total_time = ((float)si->total_samples) / (si->sample_rate); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: if (data->replay_gain_info) diff --git a/src/decoder/_flac_common.h b/src/decoder/_flac_common.h index e1e76932b..895cdf1b9 100644 --- a/src/decoder/_flac_common.h +++ b/src/decoder/_flac_common.h @@ -38,6 +38,19 @@ struct flac_data { struct pcm_buffer buffer; + /** + * Is the #stream_info member valid? + */ + bool have_stream_info; + + /** + * A copy of the stream info object passed to the metadata + * callback. Once we drop support for libFLAC 1.1.2, we can + * remove this attribute, and use + * FLAC__stream_decoder_get_total_samples() etc. + */ + FLAC__StreamMetadata_StreamInfo stream_info; + /** * The number of the next frame which is going to be decoded. */ @@ -46,7 +59,6 @@ struct flac_data { float time; unsigned int bit_rate; struct audio_format audio_format; - float total_time; FLAC__uint64 position; struct decoder *decoder; struct input_stream *input_stream; diff --git a/src/decoder/flac_plugin.c b/src/decoder/flac_plugin.c index 98bcd64d3..7a4f11451 100644 --- a/src/decoder/flac_plugin.c +++ b/src/decoder/flac_plugin.c @@ -400,6 +400,11 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd, return false; } + if (!data->have_stream_info) { + g_warning("no STREAMINFO packet found"); + return false; + } + if (!audio_format_valid(&data->audio_format)) { g_warning("Invalid audio format: %u:%u:%u\n", data->audio_format.sample_rate, @@ -408,12 +413,13 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd, return false; } - if (duration != 0) - data->total_time = (float)duration / - (float)data->audio_format.sample_rate; + if (duration == 0) + duration = data->stream_info.total_samples; decoder_initialized(data->decoder, &data->audio_format, - seekable, data->total_time); + seekable, + (float)duration / + (float)data->audio_format.sample_rate); return true; } diff --git a/src/decoder/oggflac_plugin.c b/src/decoder/oggflac_plugin.c index 3f8d640f3..ffd622600 100644 --- a/src/decoder/oggflac_plugin.c +++ b/src/decoder/oggflac_plugin.c @@ -237,6 +237,12 @@ full_decoder_init_and_read_metadata(struct flac_data *data, goto fail; } + if (!data->have_stream_info) { + OggFLAC__seekable_stream_decoder_delete(decoder); + g_warning("no STREAMINFO packet found"); + return NULL; + } + return decoder; fail: @@ -316,7 +322,9 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *input_stream) } decoder_initialized(mpd_decoder, &data.audio_format, - input_stream->seekable, data.total_time); + input_stream->seekable, + (float)data.stream_info.total_samples / + (float)data.audio_format.sample_rate); while (true) { OggFLAC__seekable_stream_decoder_process_single(decoder); -- cgit v1.2.3