From b6af44d31e5c00b512e4c64b7075b771286e7c74 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 21 Jul 2014 19:29:37 +0200 Subject: audio: move initial decode to generic code This commit mainly moves the initial decoding of data (done to probe the audio format) to generic code. This will make it easier to make audio decoding non-blocking in a later commit. This commit also changes how decoders return data: instead of having them write the data into a prepared buffer, they return a reference to an internal buffer (by setting dec_audio.decoded). This makes it significantly easier to handle audio format changes, since the decoders don't really need to care anymore. --- audio/decode/dec_audio.c | 53 ++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'audio/decode/dec_audio.c') diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 907b154bf8..c2857353fa 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -56,13 +56,6 @@ static const struct ad_functions * const ad_drivers[] = { NULL }; -// ad_mpg123 needs to be able to decode 1152 samples at once -// ad_spdif needs up to 8192 -#define DECODE_MAX_UNIT MPMAX(8192, 1152) - -// At least 8192 samples, plus hack for ad_mpg123 and ad_spdif -#define DECODE_BUFFER_SAMPLES (8192 + DECODE_MAX_UNIT) - // Drop audio buffer and reinit it (after format change) // Returns whether the format was valid at all. static bool reinit_audio_buffer(struct dec_audio *da) @@ -73,7 +66,6 @@ static bool reinit_audio_buffer(struct dec_audio *da) return false; } mp_audio_buffer_reinit(da->decode_buffer, &da->decoded); - mp_audio_buffer_preallocate_min(da->decode_buffer, DECODE_BUFFER_SAMPLES); return true; } @@ -97,6 +89,21 @@ static int init_audio_codec(struct dec_audio *d_audio, const char *decoder) return 0; } + // Decode enough until we know the audio format. + for (int tries = 1; ; tries++) { + if (mp_audio_config_valid(&d_audio->decoded)) { + MP_VERBOSE(d_audio, "Initial decode succeeded after %d packets.\n", + tries); + break; + } + if (tries >= 50) { + MP_ERR(d_audio, "initial decode failed\n"); + uninit_decoder(d_audio); + return 0; + } + d_audio->ad_driver->decode_packet(d_audio); + } + d_audio->decode_buffer = mp_audio_buffer_create(NULL); if (!reinit_audio_buffer(d_audio)) { uninit_decoder(d_audio); @@ -241,26 +248,28 @@ static int filter_n_bytes(struct dec_audio *da, struct mp_audio_buffer *outbuf, mp_audio_buffer_get_format(da->decode_buffer, &config); while (mp_audio_buffer_samples(da->decode_buffer) < len) { - int maxlen = mp_audio_buffer_get_write_available(da->decode_buffer); - if (maxlen < DECODE_MAX_UNIT) - break; - struct mp_audio buffer; - mp_audio_buffer_get_write_buffer(da->decode_buffer, maxlen, &buffer); - buffer.samples = 0; - error = da->ad_driver->decode_audio(da, &buffer, maxlen); - if (error < 0) - break; - // Commit the data just read as valid data - mp_audio_buffer_finish_write(da->decode_buffer, buffer.samples); // Format change if (!mp_audio_config_equals(&da->decoded, &config)) { // If there are still samples left in the buffer, let them drain // first, and don't signal a format change to the caller yet. - if (mp_audio_buffer_samples(da->decode_buffer) > 0) - break; - error = AD_NEW_FMT; + if (mp_audio_buffer_samples(da->decode_buffer) == 0) + error = AD_NEW_FMT; break; } + if (da->decoded.samples > 0) { + int copy = MPMIN(da->decoded.samples, len); + struct mp_audio append = da->decoded; + append.samples = copy; + mp_audio_buffer_append(da->decode_buffer, &append); + mp_audio_skip_samples(&da->decoded, copy); + continue; + } + error = da->ad_driver->decode_packet(da); + if (error < 0) + break; + // No progress means the decoder is buffering input data. + if (!da->decoded.samples) + break; } // Filter -- cgit v1.2.3