diff options
Diffstat (limited to 'src/decoder')
-rw-r--r-- | src/decoder/_flac_common.c | 40 | ||||
-rw-r--r-- | src/decoder/_flac_common.h | 20 | ||||
-rw-r--r-- | src/decoder/flac_decoder_plugin.c | 6 | ||||
-rw-r--r-- | src/decoder/oggflac_decoder_plugin.c | 6 |
4 files changed, 47 insertions, 25 deletions
diff --git a/src/decoder/_flac_common.c b/src/decoder/_flac_common.c index 0585a2c5a..477a4ba10 100644 --- a/src/decoder/_flac_common.c +++ b/src/decoder/_flac_common.c @@ -37,6 +37,7 @@ flac_data_init(struct flac_data *data, struct decoder * decoder, { pcm_buffer_init(&data->buffer); + data->unsupported = false; data->have_stream_info = false; data->first_frame = 0; data->next_frame = 0; @@ -81,38 +82,53 @@ bool flac_data_get_audio_format(struct flac_data *data, struct audio_format *audio_format) { - GError *error = NULL; + if (data->unsupported) + return false; if (!data->have_stream_info) { g_warning("no STREAMINFO packet found"); return false; } - data->sample_format = flac_sample_format(&data->stream_info); + *audio_format = data->audio_format; + return true; +} + +static void +flac_got_stream_info(struct flac_data *data, + const FLAC__StreamMetadata_StreamInfo *stream_info) +{ + if (data->have_stream_info || data->unsupported) + return; - if (!audio_format_init_checked(audio_format, - data->stream_info.sample_rate, - data->sample_format, - data->stream_info.channels, &error)) { + GError *error = NULL; + if (!audio_format_init_checked(&data->audio_format, + stream_info->sample_rate, + flac_sample_format(stream_info), + stream_info->channels, &error)) { g_warning("%s", error->message); g_error_free(error); - return false; + data->unsupported = true; + return; } - data->frame_size = audio_format_frame_size(audio_format); + data->frame_size = audio_format_frame_size(&data->audio_format); - return true; + data->total_frames = stream_info->total_samples; + data->have_stream_info = true; } void flac_metadata_common_cb(const FLAC__StreamMetadata * block, struct flac_data *data) { + if (data->unsupported) + return; + struct replay_gain_info *rgi; switch (block->type) { case FLAC__METADATA_TYPE_STREAMINFO: - data->stream_info = block->data.stream_info; - data->have_stream_info = true; + flac_got_stream_info(data, &block->data.stream_info); break; case FLAC__METADATA_TYPE_VORBIS_COMMENT: @@ -166,7 +182,7 @@ flac_common_write(struct flac_data *data, const FLAC__Frame * frame, buffer = pcm_buffer_get(&data->buffer, buffer_size); flac_convert(buffer, frame->header.channels, - data->sample_format, buf, + data->audio_format.format, buf, 0, frame->header.blocksize); if (nbytes > 0) diff --git a/src/decoder/_flac_common.h b/src/decoder/_flac_common.h index a2d832ad1..d67a5a9e9 100644 --- a/src/decoder/_flac_common.h +++ b/src/decoder/_flac_common.h @@ -38,8 +38,6 @@ struct flac_data { struct pcm_buffer buffer; - enum sample_format sample_format; - /** * The size of one frame in the output buffer. */ @@ -51,12 +49,20 @@ struct flac_data { 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. + * Does the FLAC file contain an unsupported audio format? + */ + bool unsupported; + + /** + * The validated audio format of the FLAC file. This + * attribute is defined if "have_stream_info" is true. + */ + struct audio_format audio_format; + + /** + * The total number of frames in this song. */ - FLAC__StreamMetadata_StreamInfo stream_info; + FLAC__uint64 total_frames; /** * The number of the first frame in this song. This is only diff --git a/src/decoder/flac_decoder_plugin.c b/src/decoder/flac_decoder_plugin.c index 65cccfb60..1a81e3fd4 100644 --- a/src/decoder/flac_decoder_plugin.c +++ b/src/decoder/flac_decoder_plugin.c @@ -251,12 +251,12 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd, return false; if (duration == 0) - duration = data->stream_info.total_samples; + duration = data->total_frames; decoder_initialized(data->decoder, &audio_format, seekable, (float)duration / - (float)data->stream_info.sample_rate); + (float)data->audio_format.sample_rate); return true; } @@ -281,7 +281,7 @@ flac_decoder_loop(struct flac_data *data, FLAC__StreamDecoder *flac_dec, if (cmd == DECODE_COMMAND_SEEK) { FLAC__uint64 seek_sample = t_start + decoder_seek_where(decoder) * - data->stream_info.sample_rate; + data->audio_format.sample_rate; if (seek_sample >= t_start && (t_end == 0 || seek_sample <= t_end) && FLAC__stream_decoder_seek_absolute(flac_dec, seek_sample)) { diff --git a/src/decoder/oggflac_decoder_plugin.c b/src/decoder/oggflac_decoder_plugin.c index 502448a12..63438c2b9 100644 --- a/src/decoder/oggflac_decoder_plugin.c +++ b/src/decoder/oggflac_decoder_plugin.c @@ -302,8 +302,8 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *input_stream) decoder_initialized(mpd_decoder, &audio_format, input_stream->seekable, - (float)data.stream_info.total_samples / - (float)data.stream_info.sample_rate); + (float)data.total_frames / + (float)data.audio_format.sample_rate); while (true) { OggFLAC__seekable_stream_decoder_process_single(decoder); @@ -313,7 +313,7 @@ oggflac_decode(struct decoder * mpd_decoder, struct input_stream *input_stream) } if (decoder_get_command(mpd_decoder) == DECODE_COMMAND_SEEK) { FLAC__uint64 seek_sample = decoder_seek_where(mpd_decoder) * - data.stream_info.sample_rate; + data.audio_format.sample_rate; if (OggFLAC__seekable_stream_decoder_seek_absolute (decoder, seek_sample)) { data.next_frame = seek_sample; |