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.
This commit is contained in:
Max Kellermann 2009-11-11 19:25:15 +01:00
parent f937ec9a7c
commit 7b13776f2d
4 changed files with 36 additions and 7 deletions

View File

@ -35,6 +35,7 @@ flac_data_init(struct flac_data *data, struct decoder * decoder,
{ {
pcm_buffer_init(&data->buffer); pcm_buffer_init(&data->buffer);
data->have_stream_info = false;
data->next_frame = 0; data->next_frame = 0;
data->time = 0; data->time = 0;
@ -65,9 +66,11 @@ void flac_metadata_common_cb(const FLAC__StreamMetadata * block,
switch (block->type) { switch (block->type) {
case FLAC__METADATA_TYPE_STREAMINFO: 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, audio_format_init(&data->audio_format, si->sample_rate,
si->bits_per_sample, si->channels); si->bits_per_sample, si->channels);
data->total_time = ((float)si->total_samples) / (si->sample_rate);
break; break;
case FLAC__METADATA_TYPE_VORBIS_COMMENT: case FLAC__METADATA_TYPE_VORBIS_COMMENT:
if (data->replay_gain_info) if (data->replay_gain_info)

View File

@ -38,6 +38,19 @@
struct flac_data { struct flac_data {
struct pcm_buffer buffer; 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. * The number of the next frame which is going to be decoded.
*/ */
@ -46,7 +59,6 @@ struct flac_data {
float time; float time;
unsigned int bit_rate; unsigned int bit_rate;
struct audio_format audio_format; struct audio_format audio_format;
float total_time;
FLAC__uint64 position; FLAC__uint64 position;
struct decoder *decoder; struct decoder *decoder;
struct input_stream *input_stream; struct input_stream *input_stream;

View File

@ -400,6 +400,11 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
return false; return false;
} }
if (!data->have_stream_info) {
g_warning("no STREAMINFO packet found");
return false;
}
if (!audio_format_valid(&data->audio_format)) { if (!audio_format_valid(&data->audio_format)) {
g_warning("Invalid audio format: %u:%u:%u\n", g_warning("Invalid audio format: %u:%u:%u\n",
data->audio_format.sample_rate, data->audio_format.sample_rate,
@ -408,12 +413,13 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
return false; return false;
} }
if (duration != 0) if (duration == 0)
data->total_time = (float)duration / duration = data->stream_info.total_samples;
(float)data->audio_format.sample_rate;
decoder_initialized(data->decoder, &data->audio_format, decoder_initialized(data->decoder, &data->audio_format,
seekable, data->total_time); seekable,
(float)duration /
(float)data->audio_format.sample_rate);
return true; return true;
} }

View File

@ -237,6 +237,12 @@ full_decoder_init_and_read_metadata(struct flac_data *data,
goto fail; goto fail;
} }
if (!data->have_stream_info) {
OggFLAC__seekable_stream_decoder_delete(decoder);
g_warning("no STREAMINFO packet found");
return NULL;
}
return decoder; return decoder;
fail: fail:
@ -316,7 +322,9 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *input_stream)
} }
decoder_initialized(mpd_decoder, &data.audio_format, 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) { while (true) {
OggFLAC__seekable_stream_decoder_process_single(decoder); OggFLAC__seekable_stream_decoder_process_single(decoder);