From ef9ef03b1ffd3241072b37796f8be6e7e2a15131 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 22:40:28 +0200 Subject: decoder/faad: use MAX_CHANNELS .. instead of declaring a new constant. --- src/decoder/FaadDecoderPlugin.cxx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 9fd20167d..4d089c45f 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -34,8 +34,6 @@ #include #include -#define AAC_MAX_CHANNELS 6 - static const unsigned adts_sample_rates[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0 @@ -310,7 +308,7 @@ faad_get_file_time_float(InputStream &is) float length; buffer = decoder_buffer_new(nullptr, is, - FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS); + FAAD_MIN_STREAMSIZE * MAX_CHANNELS); length = faad_song_duration(buffer, is); if (length < 0) { @@ -366,7 +364,7 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is) DecoderBuffer *buffer; buffer = decoder_buffer_new(&mpd_decoder, is, - FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS); + FAAD_MIN_STREAMSIZE * MAX_CHANNELS); total_time = faad_song_duration(buffer, is); /* create the libfaad decoder */ -- cgit v1.2.3 From 6f1b4292f0d22067e2d8aa4ee86d5f0522906225 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 22:52:31 +0200 Subject: decoder/faad: make variables more local --- src/decoder/FaadDecoderPlugin.cxx | 120 ++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 4d089c45f..bca4ecd95 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -64,16 +64,13 @@ adts_check_frame(const unsigned char *data) static size_t adts_find_frame(DecoderBuffer *buffer) { - size_t length, frame_length; - bool ret; - while (true) { + size_t length; const uint8_t *data = (const uint8_t *) decoder_buffer_read(buffer, &length); if (data == nullptr || length < 8) { /* not enough data yet */ - ret = decoder_buffer_fill(buffer); - if (!ret) + if (!decoder_buffer_fill(buffer)) /* failed */ return 0; @@ -95,7 +92,7 @@ adts_find_frame(DecoderBuffer *buffer) } /* is it a frame? */ - frame_length = adts_check_frame(data); + const size_t frame_length = adts_check_frame(data); if (frame_length == 0) { /* it's just some random 0xff byte; discard it and continue searching */ @@ -107,8 +104,7 @@ adts_find_frame(DecoderBuffer *buffer) /* available buffer size is smaller than the frame will be - attempt to read more data */ - ret = decoder_buffer_fill(buffer); - if (!ret) { + if (!decoder_buffer_fill(buffer)) { /* not enough data; discard this frame to prevent a possible buffer overflow */ @@ -129,13 +125,12 @@ adts_find_frame(DecoderBuffer *buffer) static float adts_song_duration(DecoderBuffer *buffer) { - unsigned int frames, frame_length; unsigned sample_rate = 0; - float frames_per_second; /* Read all frames to ensure correct time and bitrate */ + unsigned frames; for (frames = 0;; frames++) { - frame_length = adts_find_frame(buffer); + const unsigned frame_length = adts_find_frame(buffer); if (frame_length == 0) break; @@ -153,7 +148,7 @@ adts_song_duration(DecoderBuffer *buffer) decoder_buffer_consume(buffer, frame_length); } - frames_per_second = (float)sample_rate / 1024.0; + float frames_per_second = (float)sample_rate / 1024.0; if (frames_per_second <= 0) return -1; @@ -163,21 +158,17 @@ adts_song_duration(DecoderBuffer *buffer) static float faad_song_duration(DecoderBuffer *buffer, InputStream &is) { - size_t fileread; - size_t tagsize; - size_t length; - bool success; - const auto size = is.GetSize(); - fileread = size >= 0 ? size : 0; + const size_t fileread = size >= 0 ? size : 0; decoder_buffer_fill(buffer); + size_t length; const uint8_t *data = (const uint8_t *) decoder_buffer_read(buffer, &length); if (data == nullptr) return -1; - tagsize = 0; + size_t tagsize = 0; if (length >= 10 && !memcmp(data, "ID3", 3)) { /* skip the ID3 tag */ @@ -186,7 +177,7 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) tagsize += 10; - success = decoder_buffer_skip(buffer, tagsize) && + const bool success = decoder_buffer_skip(buffer, tagsize) && decoder_buffer_fill(buffer); if (!success) return -1; @@ -211,7 +202,6 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) return song_length; } else if (length >= 5 && memcmp(data, "ADIF", 4) == 0) { /* obtain the duration from the ADIF header */ - unsigned bit_rate; size_t skip_size = (data[4] & 0x80) ? 9 : 0; if (8 + skip_size > length) @@ -219,7 +209,7 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) header */ return -1; - bit_rate = ((data[4 + skip_size] & 0x0F) << 19) | + unsigned bit_rate = ((data[4 + skip_size] & 0x0F) << 19) | (data[5 + skip_size] << 11) | (data[6 + skip_size] << 3) | (data[7 + skip_size] & 0xE0); @@ -240,17 +230,6 @@ static bool faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, AudioFormat &audio_format, Error &error) { - int32_t nbytes; - uint32_t sample_rate; - uint8_t channels; -#ifdef HAVE_FAAD_LONG - /* neaacdec.h declares all arguments as "unsigned long", but - internally expects uint32_t pointers. To avoid gcc - warnings, use this workaround. */ - unsigned long *sample_rate_p = (unsigned long *)(void *)&sample_rate; -#else - uint32_t *sample_rate_p = &sample_rate; -#endif size_t length; const unsigned char *data = (const unsigned char *) @@ -260,11 +239,21 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer, return false; } - nbytes = NeAACDecInit(decoder, - /* deconst hack, libfaad requires this */ - const_cast(data), - length, - sample_rate_p, &channels); + uint8_t channels; + uint32_t sample_rate; +#ifdef HAVE_FAAD_LONG + /* neaacdec.h declares all arguments as "unsigned long", but + internally expects uint32_t pointers. To avoid gcc + warnings, use this workaround. */ + unsigned long *sample_rate_p = (unsigned long *)(void *)&sample_rate; +#else + uint32_t *sample_rate_p = &sample_rate; +#endif + long nbytes = NeAACDecInit(decoder, + /* deconst hack, libfaad requires this */ + const_cast(data), + length, + sample_rate_p, &channels); if (nbytes < 0) { error.Set(faad_decoder_domain, "Not an AAC stream"); return false; @@ -304,15 +293,13 @@ faad_decoder_decode(NeAACDecHandle decoder, DecoderBuffer *buffer, static float faad_get_file_time_float(InputStream &is) { - DecoderBuffer *buffer; - float length; + DecoderBuffer *const buffer = + decoder_buffer_new(nullptr, is, + FAAD_MIN_STREAMSIZE * MAX_CHANNELS); - buffer = decoder_buffer_new(nullptr, is, - FAAD_MIN_STREAMSIZE * MAX_CHANNELS); - length = faad_song_duration(buffer, is); + float length = faad_song_duration(buffer, is); if (length < 0) { - bool ret; AudioFormat audio_format; NeAACDecHandle decoder = NeAACDecOpen(); @@ -324,9 +311,8 @@ faad_get_file_time_float(InputStream &is) decoder_buffer_fill(buffer); - ret = faad_decoder_init(decoder, buffer, audio_format, - IgnoreError()); - if (ret) + if (faad_decoder_init(decoder, buffer, audio_format, + IgnoreError())) length = 0; NeAACDecClose(decoder); @@ -345,31 +331,25 @@ faad_get_file_time_float(InputStream &is) static int faad_get_file_time(InputStream &is) { - int file_time = -1; - float length; - - if ((length = faad_get_file_time_float(is)) >= 0) - file_time = length + 0.5; + float length = faad_get_file_time_float(is); + if (length < 0) + return -1; - return file_time; + return int(length + 0.5); } static void faad_stream_decode(Decoder &mpd_decoder, InputStream &is) { - float total_time = 0; - AudioFormat audio_format; - bool ret; - uint16_t bit_rate = 0; - DecoderBuffer *buffer; + DecoderBuffer *const buffer = + decoder_buffer_new(&mpd_decoder, is, + FAAD_MIN_STREAMSIZE * MAX_CHANNELS); - buffer = decoder_buffer_new(&mpd_decoder, is, - FAAD_MIN_STREAMSIZE * MAX_CHANNELS); - total_time = faad_song_duration(buffer, is); + const float total_time = faad_song_duration(buffer, is); /* create the libfaad decoder */ - NeAACDecHandle decoder = NeAACDecOpen(); + const NeAACDecHandle decoder = NeAACDecOpen(); NeAACDecConfigurationPtr config = NeAACDecGetCurrentConfiguration(decoder); @@ -387,8 +367,8 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is) /* initialize it */ Error error; - ret = faad_decoder_init(decoder, buffer, audio_format, error); - if (!ret) { + AudioFormat audio_format; + if (!faad_decoder_init(decoder, buffer, audio_format, error)) { LogError(error); NeAACDecClose(decoder); decoder_buffer_free(buffer); @@ -402,21 +382,20 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is) /* the decoder loop */ DecoderCommand cmd; + uint16_t bit_rate = 0; do { - size_t frame_size; - const void *decoded; - NeAACDecFrameInfo frame_info; - /* find the next frame */ - frame_size = adts_find_frame(buffer); + const size_t frame_size = adts_find_frame(buffer); if (frame_size == 0) /* end of file */ break; /* decode it */ - decoded = faad_decoder_decode(decoder, buffer, &frame_info); + NeAACDecFrameInfo frame_info; + const void *const decoded = + faad_decoder_decode(decoder, buffer, &frame_info); if (frame_info.error > 0) { FormatWarning(faad_decoder_domain, @@ -468,7 +447,6 @@ faad_scan_stream(InputStream &is, const struct tag_handler *handler, void *handler_ctx) { int file_time = faad_get_file_time(is); - if (file_time < 0) return false; -- cgit v1.2.3 From 6585e18571df900c4ffe862ec02cd7376af7bbbd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 23:12:08 +0200 Subject: decoder/faad: check sample_rate, not frames_per_second Checking the integer is faster, easier and more reliable. --- src/decoder/FaadDecoderPlugin.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index bca4ecd95..7279d7107 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -148,10 +148,12 @@ adts_song_duration(DecoderBuffer *buffer) decoder_buffer_consume(buffer, frame_length); } - float frames_per_second = (float)sample_rate / 1024.0; - if (frames_per_second <= 0) + if (sample_rate == 0) return -1; + float frames_per_second = (float)sample_rate / 1024.0; + assert(frames_per_second > 0); + return (float)frames / frames_per_second; } -- cgit v1.2.3 From 9d9697b36626b2a74d9b535b284b6e3dacd2b414 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 6 Jan 2014 21:46:10 +0100 Subject: DecoderBuffer: add method _clear() --- src/DecoderBuffer.cxx | 6 ++++++ src/DecoderBuffer.hxx | 3 +++ src/decoder/FaadDecoderPlugin.cxx | 11 +++-------- 3 files changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/DecoderBuffer.cxx b/src/DecoderBuffer.cxx index 6aad53cb2..0b326a6fd 100644 --- a/src/DecoderBuffer.cxx +++ b/src/DecoderBuffer.cxx @@ -82,6 +82,12 @@ decoder_buffer_is_full(const DecoderBuffer *buffer) return buffer->consumed == 0 && buffer->length == buffer->size; } +void +decoder_buffer_clear(DecoderBuffer *buffer) +{ + buffer->length = buffer->consumed = 0; +} + static void decoder_buffer_shift(DecoderBuffer *buffer) { diff --git a/src/DecoderBuffer.hxx b/src/DecoderBuffer.hxx index 92cc31aa4..70cf63faa 100644 --- a/src/DecoderBuffer.hxx +++ b/src/DecoderBuffer.hxx @@ -56,6 +56,9 @@ decoder_buffer_is_empty(const DecoderBuffer *buffer); bool decoder_buffer_is_full(const DecoderBuffer *buffer); +void +decoder_buffer_clear(DecoderBuffer *buffer); + /** * Read data from the input_stream and append it to the buffer. * diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 7279d7107..9c8bdb6ef 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -81,7 +81,7 @@ adts_find_frame(DecoderBuffer *buffer) const uint8_t *p = (const uint8_t *)memchr(data, 0xff, length); if (p == nullptr) { /* no marker - discard the buffer */ - decoder_buffer_consume(buffer, length); + decoder_buffer_clear(buffer); continue; } @@ -108,10 +108,7 @@ adts_find_frame(DecoderBuffer *buffer) /* not enough data; discard this frame to prevent a possible buffer overflow */ - data = (const uint8_t *) - decoder_buffer_read(buffer, &length); - if (data != nullptr) - decoder_buffer_consume(buffer, length); + decoder_buffer_clear(buffer); } continue; @@ -196,9 +193,7 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) is.LockSeek(tagsize, SEEK_SET, IgnoreError()); - data = (const uint8_t *)decoder_buffer_read(buffer, &length); - if (data != nullptr) - decoder_buffer_consume(buffer, length); + decoder_buffer_clear(buffer); decoder_buffer_fill(buffer); return song_length; -- cgit v1.2.3 From 5958b78459776f1aecf284d97dbb21992c1e2d29 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 6 Jan 2014 22:16:56 +0100 Subject: DecoderBuffer: add "pure" attributes --- src/DecoderBuffer.hxx | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/DecoderBuffer.hxx b/src/DecoderBuffer.hxx index 70cf63faa..d09416b06 100644 --- a/src/DecoderBuffer.hxx +++ b/src/DecoderBuffer.hxx @@ -20,6 +20,8 @@ #ifndef MPD_DECODER_BUFFER_HXX #define MPD_DECODER_BUFFER_HXX +#include "Compiler.h" + #include /** @@ -50,9 +52,11 @@ decoder_buffer_new(Decoder *decoder, InputStream &is, void decoder_buffer_free(DecoderBuffer *buffer); +gcc_pure bool decoder_buffer_is_empty(const DecoderBuffer *buffer); +gcc_pure bool decoder_buffer_is_full(const DecoderBuffer *buffer); -- cgit v1.2.3 From 47e8fcf37e775b0069f8facb9544520f6ca11414 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 23:23:13 +0200 Subject: decoder/faad: remove unnecessary read Eliminate some overhead when the caller doesn't need the buffer. --- src/decoder/FaadDecoderPlugin.cxx | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 9c8bdb6ef..5ced8a8fb 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -192,9 +192,7 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) float song_length = adts_song_duration(buffer); is.LockSeek(tagsize, SEEK_SET, IgnoreError()); - decoder_buffer_clear(buffer); - decoder_buffer_fill(buffer); return song_length; } else if (length >= 5 && memcmp(data, "ADIF", 4) == 0) { -- cgit v1.2.3 From 18787ebe8f4159d68dc9bb283a6a6ddcbb2f15e7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 23:30:14 +0200 Subject: decoder/faad: move code to faad_decoder_new() Merge some duplicate code. --- src/decoder/FaadDecoderPlugin.cxx | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 5ced8a8fb..60d95d626 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -217,6 +217,21 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) return -1; } +static NeAACDecHandle +faad_decoder_new() +{ + const NeAACDecHandle decoder = NeAACDecOpen(); + + NeAACDecConfigurationPtr config = + NeAACDecGetCurrentConfiguration(decoder); + config->outputFormat = FAAD_FMT_16BIT; + config->downMatrix = 1; + config->dontUpSampleImplicitSBR = 0; + NeAACDecSetConfiguration(decoder, config); + + return decoder; +} + /** * Wrapper for NeAACDecInit() which works around some API * inconsistencies in libfaad. @@ -297,12 +312,7 @@ faad_get_file_time_float(InputStream &is) if (length < 0) { AudioFormat audio_format; - NeAACDecHandle decoder = NeAACDecOpen(); - - NeAACDecConfigurationPtr config = - NeAACDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; - NeAACDecSetConfiguration(decoder, config); + NeAACDecHandle decoder = faad_decoder_new(); decoder_buffer_fill(buffer); @@ -344,14 +354,7 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is) /* create the libfaad decoder */ - const NeAACDecHandle decoder = NeAACDecOpen(); - - NeAACDecConfigurationPtr config = - NeAACDecGetCurrentConfiguration(decoder); - config->outputFormat = FAAD_FMT_16BIT; - config->downMatrix = 1; - config->dontUpSampleImplicitSBR = 0; - NeAACDecSetConfiguration(decoder, config); + const NeAACDecHandle decoder = faad_decoder_new(); while (!decoder_buffer_is_full(buffer) && !is.LockIsEOF() && decoder_get_command(mpd_decoder) == DecoderCommand::NONE) { -- cgit v1.2.3 From 54b6f8a4ae90ef1603b817902c12650eeb8328c6 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 23:58:51 +0200 Subject: decoder/faad: test "seekable" after ADTS frame check Don't bother to check for ADIF just because the stream is not seekable. --- src/decoder/FaadDecoderPlugin.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 60d95d626..aa5c6835f 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -186,9 +186,13 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) return -1; } - if (is.IsSeekable() && length >= 2 && + if (length >= 2 && data[0] == 0xFF && ((data[1] & 0xF6) == 0xF0)) { /* obtain the duration from the ADTS header */ + + if (!is.IsSeekable()) + return -1; + float song_length = adts_song_duration(buffer); is.LockSeek(tagsize, SEEK_SET, IgnoreError()); -- cgit v1.2.3 From 835b0c44cdcc98c6b4eda2d1795797f364b2dc56 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 23:58:36 +0200 Subject: decoder/faad: use adts_check_frame() in faad_song_duration() Eliminate more duplicate code. --- src/decoder/FaadDecoderPlugin.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index aa5c6835f..bc3533228 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -186,8 +186,7 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is) return -1; } - if (length >= 2 && - data[0] == 0xFF && ((data[1] & 0xF6) == 0xF0)) { + if (length >= 8 && adts_check_frame(data) > 0) { /* obtain the duration from the ADTS header */ if (!is.IsSeekable()) -- cgit v1.2.3 From 06aa68938357f4a567e1f89b51a593f11fea8fee Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 12 Jul 2014 00:21:52 +0200 Subject: decoder/faad: bail out early if sample rate is invalid --- src/decoder/FaadDecoderPlugin.cxx | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index bc3533228..07c10fa69 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -140,6 +140,8 @@ adts_song_duration(DecoderBuffer *buffer) assert(frame_length <= buffer_length); sample_rate = adts_sample_rates[(data[2] & 0x3c) >> 2]; + if (sample_rate == 0) + break; } decoder_buffer_consume(buffer, frame_length); -- cgit v1.2.3 From a7d9f248eab1af41fd5dbb31e394c07b8e059220 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 12 Jul 2014 00:23:22 +0200 Subject: DecoderBuffer: add method _get_stream() --- src/DecoderBuffer.cxx | 6 ++++++ src/DecoderBuffer.hxx | 4 ++++ 2 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/DecoderBuffer.cxx b/src/DecoderBuffer.cxx index 0b326a6fd..78a2ccdc6 100644 --- a/src/DecoderBuffer.cxx +++ b/src/DecoderBuffer.cxx @@ -70,6 +70,12 @@ decoder_buffer_free(DecoderBuffer *buffer) g_free(buffer); } +const InputStream & +decoder_buffer_get_stream(const DecoderBuffer *buffer) +{ + return *buffer->is; +} + bool decoder_buffer_is_empty(const DecoderBuffer *buffer) { diff --git a/src/DecoderBuffer.hxx b/src/DecoderBuffer.hxx index d09416b06..0eaf0c4f3 100644 --- a/src/DecoderBuffer.hxx +++ b/src/DecoderBuffer.hxx @@ -52,6 +52,10 @@ decoder_buffer_new(Decoder *decoder, InputStream &is, void decoder_buffer_free(DecoderBuffer *buffer); +gcc_pure +const InputStream & +decoder_buffer_get_stream(const DecoderBuffer *buffer); + gcc_pure bool decoder_buffer_is_empty(const DecoderBuffer *buffer); -- cgit v1.2.3 From 4fe272a7fbe45ab76f3af417d989c37fd4298ed1 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 12 Jul 2014 00:14:15 +0200 Subject: DecoderBuffer: add method _available() --- src/DecoderBuffer.cxx | 6 ++++++ src/DecoderBuffer.hxx | 7 +++++++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/DecoderBuffer.cxx b/src/DecoderBuffer.cxx index 78a2ccdc6..4a5125bc5 100644 --- a/src/DecoderBuffer.cxx +++ b/src/DecoderBuffer.cxx @@ -130,6 +130,12 @@ decoder_buffer_fill(DecoderBuffer *buffer) return true; } +size_t +decoder_buffer_available(const DecoderBuffer *buffer) +{ + return buffer->length - buffer->consumed;; +} + const void * decoder_buffer_read(const DecoderBuffer *buffer, size_t *length_r) { diff --git a/src/DecoderBuffer.hxx b/src/DecoderBuffer.hxx index 0eaf0c4f3..65c6e0d2e 100644 --- a/src/DecoderBuffer.hxx +++ b/src/DecoderBuffer.hxx @@ -77,6 +77,13 @@ decoder_buffer_clear(DecoderBuffer *buffer); bool decoder_buffer_fill(DecoderBuffer *buffer); +/** + * How many bytes are stored in the buffer? + */ +gcc_pure +size_t +decoder_buffer_available(const DecoderBuffer *buffer); + /** * Reads data from the buffer. This data is not yet consumed, you * have to call decoder_buffer_consume() to do that. The returned -- cgit v1.2.3 From a960e2ef48d21e73c7db7ead6f73c1b1d3ee8d42 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Fri, 11 Jul 2014 22:52:26 +0200 Subject: decoder/faad: estimate song duration for remote files Previously, MPD tried to slurp the whole song file, count the number of frames and calculate the song duration from that. That however is extremely expensive for remote files, and will delay playback for a long time. Workaround: check only the first 128 frames and try to extrapolate from here. Fixes Mantis ticket 0004035. --- src/decoder/FaadDecoderPlugin.cxx | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src') diff --git a/src/decoder/FaadDecoderPlugin.cxx b/src/decoder/FaadDecoderPlugin.cxx index 07c10fa69..b446ac5be 100644 --- a/src/decoder/FaadDecoderPlugin.cxx +++ b/src/decoder/FaadDecoderPlugin.cxx @@ -122,6 +122,12 @@ adts_find_frame(DecoderBuffer *buffer) static float adts_song_duration(DecoderBuffer *buffer) { + const InputStream &is = decoder_buffer_get_stream(buffer); + const bool estimate = !is.CheapSeeking(); + const auto file_size = is.GetSize(); + if (estimate && file_size <= 0) + return -1; + unsigned sample_rate = 0; /* Read all frames to ensure correct time and bitrate */ @@ -145,6 +151,22 @@ adts_song_duration(DecoderBuffer *buffer) } decoder_buffer_consume(buffer, frame_length); + + if (estimate && frames == 128) { + /* if this is a remote file, don't slurp the + whole file just for checking the song + duration; instead, stop after some time and + extrapolate the song duration from what we + have until now */ + + const auto offset = is.GetOffset() + - decoder_buffer_available(buffer); + if (offset <= 0) + return -1; + + frames = (frames * file_size) / offset; + break; + } } if (sample_rate == 0) -- cgit v1.2.3