diff options
author | Max Kellermann <max@duempel.org> | 2010-01-06 09:54:09 +0100 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2010-01-06 10:17:16 +0100 |
commit | a942384fbf4bc939086671a1741ee72244a70f28 (patch) | |
tree | 04a4c51ef656f29ef299d4b64570bd48a5f04a12 /src/decoder | |
parent | de0cdee4aaf891f69b876134c14dd7df6af4f331 (diff) | |
download | mpd-a942384fbf4bc939086671a1741ee72244a70f28.tar.gz mpd-a942384fbf4bc939086671a1741ee72244a70f28.tar.xz mpd-a942384fbf4bc939086671a1741ee72244a70f28.zip |
decoder/flac: support streams without STREAMINFO block
Diffstat (limited to 'src/decoder')
-rw-r--r-- | src/decoder/_flac_common.c | 41 | ||||
-rw-r--r-- | src/decoder/flac_decoder_plugin.c | 12 |
2 files changed, 52 insertions, 1 deletions
diff --git a/src/decoder/_flac_common.c b/src/decoder/_flac_common.c index 9a3449096..6e28792ec 100644 --- a/src/decoder/_flac_common.c +++ b/src/decoder/_flac_common.c @@ -161,16 +161,55 @@ void flac_error_common_cb(const char *plugin, } } +/** + * This function attempts to call decoder_initialized() in case there + * was no STREAMINFO block. This is allowed for nonseekable streams, + * where the server sends us only a part of the file, without + * providing the STREAMINFO block from the beginning of the file + * (e.g. when seeking with SqueezeBox Server). + */ +static bool +flac_got_first_frame(struct flac_data *data, const FLAC__FrameHeader *header) +{ + if (data->unsupported) + return false; + + GError *error = NULL; + if (!audio_format_init_checked(&data->audio_format, + header->sample_rate, + flac_sample_format(header->bits_per_sample), + header->channels, &error)) { + g_warning("%s", error->message); + g_error_free(error); + data->unsupported = true; + return false; + } + + data->frame_size = audio_format_frame_size(&data->audio_format); + + decoder_initialized(data->decoder, &data->audio_format, + data->input_stream->seekable, + (float)data->total_frames / + (float)data->audio_format.sample_rate); + + data->initialized = true; + + return true; +} + FLAC__StreamDecoderWriteStatus flac_common_write(struct flac_data *data, const FLAC__Frame * frame, const FLAC__int32 *const buf[], FLAC__uint64 nbytes) { enum decoder_command cmd; - size_t buffer_size = frame->header.blocksize * data->frame_size; void *buffer; unsigned bit_rate; + if (!data->initialized && !flac_got_first_frame(data, &frame->header)) + return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT; + + size_t buffer_size = frame->header.blocksize * data->frame_size; buffer = pcm_buffer_get(&data->buffer, buffer_size); flac_convert(buffer, frame->header.channels, diff --git a/src/decoder/flac_decoder_plugin.c b/src/decoder/flac_decoder_plugin.c index d139354b8..022ee7045 100644 --- a/src/decoder/flac_decoder_plugin.c +++ b/src/decoder/flac_decoder_plugin.c @@ -247,6 +247,18 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd, return false; } + if (data->initialized) + /* done */ + return true; + + if (data->input_stream->seekable) + /* allow the workaround below only for nonseekable + streams*/ + return false; + + /* no stream_info packet found; try to initialize the decoder + from the first frame header */ + FLAC__stream_decoder_process_single(sd); return data->initialized; } |