decoder/flac: support streams without STREAMINFO block

This commit is contained in:
Max Kellermann 2010-01-06 09:54:09 +01:00
parent de0cdee4aa
commit a942384fbf
3 changed files with 53 additions and 1 deletions

1
NEWS
View File

@ -23,6 +23,7 @@ ver 0.16 (20??/??/??)
- ffmpeg: convert metadata to generic format - ffmpeg: convert metadata to generic format
- sndfile: new decoder plugin based on libsndfile - sndfile: new decoder plugin based on libsndfile
- flac: moved CUE sheet support to a playlist plugin - flac: moved CUE sheet support to a playlist plugin
- flac: support streams without STREAMINFO block
- mikmod: sample rate is configurable - mikmod: sample rate is configurable
- mpg123: new decoder plugin based on libmpg123 - mpg123: new decoder plugin based on libmpg123
- sidplay: support sub-tunes - sidplay: support sub-tunes

View File

@ -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__StreamDecoderWriteStatus
flac_common_write(struct flac_data *data, const FLAC__Frame * frame, flac_common_write(struct flac_data *data, const FLAC__Frame * frame,
const FLAC__int32 *const buf[], const FLAC__int32 *const buf[],
FLAC__uint64 nbytes) FLAC__uint64 nbytes)
{ {
enum decoder_command cmd; enum decoder_command cmd;
size_t buffer_size = frame->header.blocksize * data->frame_size;
void *buffer; void *buffer;
unsigned bit_rate; 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); buffer = pcm_buffer_get(&data->buffer, buffer_size);
flac_convert(buffer, frame->header.channels, flac_convert(buffer, frame->header.channels,

View File

@ -247,6 +247,18 @@ flac_decoder_initialize(struct flac_data *data, FLAC__StreamDecoder *sd,
return false; 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; return data->initialized;
} }