Hi,
here is a patch that allows for seeking in aac files.
bye
eichhofener


diff --git a/src/decoder/DecoderBuffer.cxx b/src/decoder/DecoderBuffer.cxx
index 4767151..2667a7b 100644
--- a/src/decoder/DecoderBuffer.cxx
+++ b/src/decoder/DecoderBuffer.cxx
@@ -20,148 +20,94 @@
 #include "config.h"
 #include "DecoderBuffer.hxx"
 #include "DecoderAPI.hxx"
-#include "util/ConstBuffer.hxx"
 #include "util/VarSize.hxx"
+#include "util/Error.hxx"
 
 #include <assert.h>
 #include <string.h>
 #include <stdlib.h>
 
-struct DecoderBuffer {
-	Decoder *decoder;
-	InputStream *is;
 
-	/** the allocated size of the buffer */
-	size_t size;
-
-	/** the current length of the buffer */
-	size_t length;
-
-	/** number of bytes already consumed at the beginning of the
-	    buffer */
-	size_t consumed;
-
-	/** the actual buffer (dynamic size) */
-	unsigned char data[sizeof(size_t)];
-
-	DecoderBuffer(Decoder *_decoder, InputStream &_is,
-		      size_t _size)
-		:decoder(_decoder), is(&_is),
-		 size(_size), length(0), consumed(0) {}
-};
-
-DecoderBuffer *
-decoder_buffer_new(Decoder *decoder, InputStream &is,
-		   size_t size)
-{
-	assert(size > 0);
-
-	return NewVarSize<DecoderBuffer>(sizeof(DecoderBuffer::data),
-					 size,
-					 decoder, is, size);
-}
-
-void
-decoder_buffer_free(DecoderBuffer *buffer)
+void DecoderBuffer::shift()
 {
-	assert(buffer != nullptr);
+	assert(consumed > 0);
 
-	DeleteVarSize(buffer);
+	length -= consumed;
+	memmove(bufdata, bufdata + consumed, length);
+	consumed = 0;
 }
 
-bool
-decoder_buffer_is_empty(const DecoderBuffer *buffer)
-{
-	return buffer->consumed == buffer->length;
-}
-
-bool
-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)
-{
-	assert(buffer->consumed > 0);
-
-	buffer->length -= buffer->consumed;
-	memmove(buffer->data, buffer->data + buffer->consumed, buffer->length);
-	buffer->consumed = 0;
-}
-
-bool
-decoder_buffer_fill(DecoderBuffer *buffer)
+bool DecoderBuffer::fill()
 {
 	size_t nbytes;
 
-	if (buffer->consumed > 0)
-		decoder_buffer_shift(buffer);
+	if (consumed > 0) shift();
 
-	if (buffer->length >= buffer->size)
+	if (length >= bufsize)
 		/* buffer is full */
 		return false;
 
-	nbytes = decoder_read(buffer->decoder, *buffer->is,
-			      buffer->data + buffer->length,
-			      buffer->size - buffer->length);
+	nbytes = decoder_read(decoder, is,
+				  bufdata + length,
+				  bufsize - length);
 	if (nbytes == 0)
 		/* end of file, I/O error or decoder command
 		   received */
 		return false;
 
-	buffer->length += nbytes;
-	assert(buffer->length <= buffer->size);
+	length += nbytes;
+	assert(length <= bufsize);
 
 	return true;
 }
 
-ConstBuffer<void>
-decoder_buffer_read(const DecoderBuffer *buffer)
+ConstBuffer<void> DecoderBuffer::read() const
 {
 	return {
-		buffer->data + buffer->consumed,
-		buffer->length - buffer->consumed
+		bufdata + consumed,
+		length - consumed
 	};
 }
 
-void
-decoder_buffer_consume(DecoderBuffer *buffer, size_t nbytes)
+void DecoderBuffer::consume(size_t nbytes)
 {
 	/* just move the "consumed" pointer - decoder_buffer_shift()
 	   will do the real work later (called by
 	   decoder_buffer_fill()) */
-	buffer->consumed += nbytes;
+	consumed += nbytes;
+	offset += nbytes;
+
+	assert(consumed <= length);
+}
 
-	assert(buffer->consumed <= buffer->length);
+bool DecoderBuffer::seek(InputStream::offset_type o)
+{
+	Error e;
+	if(!is.Seek(o, SEEK_SET, e)) return false;
+
+	offset=o;
+	clear();
+	return true;
 }
 
-bool
-decoder_buffer_skip(DecoderBuffer *buffer, size_t nbytes)
+bool DecoderBuffer::skip(size_t nbytes)
 {
 	bool success;
 
 	/* this could probably be optimized by seeking */
 
 	while (true) {
-		auto data = decoder_buffer_read(buffer);
+		auto data = read();
 		if (!data.IsEmpty()) {
 			if (data.size > nbytes)
 				data.size = nbytes;
-			decoder_buffer_consume(buffer, data.size);
+			consume(data.size);
 			nbytes -= data.size;
 			if (nbytes == 0)
 				return true;
 		}
 
-		success = decoder_buffer_fill(buffer);
+		success = fill();
 		if (!success)
 			return false;
 	}
diff --git a/src/decoder/DecoderBuffer.hxx b/src/decoder/DecoderBuffer.hxx
index 4cadd77..9b7eaf9 100644
--- a/src/decoder/DecoderBuffer.hxx
+++ b/src/decoder/DecoderBuffer.hxx
@@ -21,6 +21,8 @@
 #define MPD_DECODER_BUFFER_HXX
 
 #include "Compiler.h"
+#include "input/InputStream.hxx"
+#include "util/ConstBuffer.hxx"
 
 #include <stddef.h>
 
@@ -29,83 +31,116 @@
  * create a buffer object, and use its high-level methods to fill and
  * read it.  It will automatically handle shifting the buffer.
  */
-struct DecoderBuffer;
-
 struct Decoder;
 struct InputStream;
 
 template<typename T> struct ConstBuffer;
 
-/**
- * Creates a new buffer.
- *
- * @param decoder the decoder object, used for decoder_read(), may be nullptr
- * @param is the input stream object where we should read from
- * @param size the maximum size of the buffer
- * @return the new decoder_buffer object
- */
-DecoderBuffer *
-decoder_buffer_new(Decoder *decoder, InputStream &is,
-		   size_t size);
-
-/**
- * Frees resources used by the decoder_buffer object.
- */
-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);
+class DecoderBuffer
+{
+public:
+	/**
+	* Creates a new buffer.
+	*
+	* @param decoder the decoder object, used for decoder_read(), may be nullptr
+	* @param is the input stream object where we should read from
+	* @param size the maximum size of the buffer
+	*/
+	DecoderBuffer(Decoder* _decoder, InputStream& _is, size_t _size)
+		:decoder(_decoder), is(_is), offset(0), bufsize(_size), length(0), consumed(0)
+	{
+		bufdata=new unsigned char[bufsize];
+	}
+
+	/**
+	* Frees resources used by the decoder_buffer object.
+	*/
+	~DecoderBuffer() { delete[] bufdata; }
+
+	/**
+	 * Read data from the input_stream and append it to the buffer.
+	 *
+	 * @return true if data was appended; false if there is no data
+	 * available (yet), end of file, I/O error or a decoder command was
+	 * received
+	 */
+	bool fill();
+
+	/**
+	 * Skips the specified number of bytes, discarding its data.
+	 *
+	 * @param buffer the decoder_buffer object
+	 * @param nbytes the number of bytes to skip
+	 * @return true on success, false on error
+	 */
+	bool skip(size_t nbytes);
+
+	/**
+	 * Reads data from the buffer.  This data is not yet consumed, you
+	 * have to call decoder_buffer_consume() to do that.  The returned
+	 * buffer becomes invalid after a decoder_buffer_fill() or a
+	 * decoder_buffer_consume() call.
+	 *
+	 * @param buffer the decoder_buffer object
+	 */
+	ConstBuffer<void> read() const;
+
+	/**
+	 * Consume (delete, invalidate) a part of the buffer.  The "nbytes"
+	 * parameter must not be larger than the length returned by
+	 * decoder_buffer_read().
+	 *
+	 * @param buffer the decoder_buffer object
+	 * @param nbytes the number of bytes to consume
+	 */
+	void consume(size_t nbytes);
+
+	bool seek(InputStream::offset_type offset);
+
+	void clear()
+	{
+		length = consumed = 0;
+	}
+
+	bool full() const
+	{
+		return consumed == 0 && length == bufsize;
+	}
+
+	InputStream::offset_type getOffset() const { return offset; }
+
+private:
+	bool empty() const
+	{
+		return consumed == length;
+	}
+
+	void shift();
+
+private:
+	Decoder* decoder;
+
+protected:
+	InputStream& is;
+
+private:
+	InputStream::offset_type offset;
+
+	/** the allocated size of the buffer */
+	size_t bufsize;
+
+	/** the current length of the buffer */
+	size_t length;
+
+	/** number of bytes already consumed at the beginning of the
+		buffer */
+	size_t consumed;
+
+	/** the actual buffer (dynamic size) */
+	unsigned char* bufdata;
+};
 
-void
-decoder_buffer_clear(DecoderBuffer *buffer);
 
-/**
- * Read data from the input_stream and append it to the buffer.
- *
- * @return true if data was appended; false if there is no data
- * available (yet), end of file, I/O error or a decoder command was
- * received
- */
-bool
-decoder_buffer_fill(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
- * buffer becomes invalid after a decoder_buffer_fill() or a
- * decoder_buffer_consume() call.
- *
- * @param buffer the decoder_buffer object
- */
-gcc_pure
-ConstBuffer<void>
-decoder_buffer_read(const DecoderBuffer *buffer);
-
-/**
- * Consume (delete, invalidate) a part of the buffer.  The "nbytes"
- * parameter must not be larger than the length returned by
- * decoder_buffer_read().
- *
- * @param buffer the decoder_buffer object
- * @param nbytes the number of bytes to consume
- */
-void
-decoder_buffer_consume(DecoderBuffer *buffer, size_t nbytes);
-
-/**
- * Skips the specified number of bytes, discarding its data.
- *
- * @param buffer the decoder_buffer object
- * @param nbytes the number of bytes to skip
- * @return true on success, false on error
- */
-bool
-decoder_buffer_skip(DecoderBuffer *buffer, size_t nbytes);
 
 #endif
diff --git a/src/decoder/plugins/FaadDecoderPlugin.cxx b/src/decoder/plugins/FaadDecoderPlugin.cxx
index e80665d..03d493b 100644
--- a/src/decoder/plugins/FaadDecoderPlugin.cxx
+++ b/src/decoder/plugins/FaadDecoderPlugin.cxx
@@ -35,21 +35,64 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <vector>
+#include <iostream>
+
 #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
+static constexpr Domain faad_decoder_domain("faad_decoder");
+
+
+class DecoderBufferFaad : public DecoderBuffer
+{
+public:
+	DecoderBufferFaad(Decoder* _decoder, InputStream& _is, size_t _size)
+	: DecoderBuffer(_decoder, _is, _size)
+	{
+		duration=faad_song_duration();
+	}
+
+	double getDuration() const { return duration; }
+	size_t adts_find_frame();
+
+	float seekSample(float seekTime);
+
+	enum { samplesPerFrame=1024 };
+private:
+	/**
+	 * Check whether the buffer head is an AAC frame, and return the frame
+	 * length.  Returns 0 if it is not a frame.
+	 */
+	static size_t adts_check_frame(const unsigned char *bufdata);
+
+	/**
+	 * Find the next AAC frame in the buffer.  Returns 0 if no frame is
+	 * found or if not enough data is available.
+	 */
+	float adts_song_duration();
+
+	float faad_song_duration();
+
+private:
+	static const unsigned adts_sample_rates[];
+
+	unsigned sampleRate;
+	float duration;
+
+	short offset0;
+	std::vector<short> offsets;
 };
 
-static constexpr Domain faad_decoder_domain("faad_decoder");
+const unsigned DecoderBufferFaad::adts_sample_rates[] =
+	{ 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050,
+	16000, 12000, 11025, 8000, 7350, 0, 0, 0
+};
 
 /**
  * Check whether the buffer head is an AAC frame, and return the frame
  * length.  Returns 0 if it is not a frame.
  */
-static size_t
-adts_check_frame(const unsigned char *data)
+size_t DecoderBufferFaad::adts_check_frame(const unsigned char *data)
 {
 	/* check syncword */
 	if (!((data[0] == 0xFF) && ((data[1] & 0xF6) == 0xF0)))
@@ -64,14 +107,13 @@ adts_check_frame(const unsigned char *data)
  * Find the next AAC frame in the buffer.  Returns 0 if no frame is
  * found or if not enough data is available.
  */
-static size_t
-adts_find_frame(DecoderBuffer *buffer)
+size_t DecoderBufferFaad::adts_find_frame()
 {
 	while (true) {
-		auto data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_read(buffer));
+		auto data = ConstBuffer<uint8_t>::FromVoid(read());
 		if (data.size < 8) {
 			/* not enough data yet */
-			if (!decoder_buffer_fill(buffer))
+			if (!fill())
 				/* failed */
 				return 0;
 
@@ -83,13 +125,13 @@ adts_find_frame(DecoderBuffer *buffer)
 			memchr(data.data, 0xff, data.size);
 		if (p == nullptr) {
 			/* no marker - discard the buffer */
-			decoder_buffer_clear(buffer);
+			clear();
 			continue;
 		}
 
 		if (p > data.data) {
 			/* discard data before 0xff */
-			decoder_buffer_consume(buffer, p - data.data);
+			consume(p - data.data);
 			continue;
 		}
 
@@ -98,7 +140,7 @@ adts_find_frame(DecoderBuffer *buffer)
 		if (frame_length == 0) {
 			/* it's just some random 0xff byte; discard it
 			   and continue searching */
-			decoder_buffer_consume(buffer, 1);
+			consume(1);
 			continue;
 		}
 
@@ -106,11 +148,11 @@ adts_find_frame(DecoderBuffer *buffer)
 			/* available buffer size is smaller than the
 			   frame will be - attempt to read more
 			   data */
-			if (!decoder_buffer_fill(buffer)) {
+			if (!fill()) {
 				/* not enough data; discard this frame
 				   to prevent a possible buffer
 				   overflow */
-				decoder_buffer_clear(buffer);
+				clear();
 			}
 
 			continue;
@@ -121,44 +163,52 @@ adts_find_frame(DecoderBuffer *buffer)
 	}
 }
 
-static float
-adts_song_duration(DecoderBuffer *buffer)
+float DecoderBufferFaad::adts_song_duration()
 {
-	unsigned sample_rate = 0;
+	sampleRate = 0;
+	short lastOffset=0;
+	offset0=0;
+	offsets.clear();
 
 	/* Read all frames to ensure correct time and bitrate */
 	unsigned frames = 0;
 	for (;; frames++) {
-		unsigned frame_length = adts_find_frame(buffer);
+		unsigned frame_length = adts_find_frame();
 		if (frame_length == 0)
 			break;
 
 		if (frames == 0) {
-			auto data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_read(buffer));
+			auto data = ConstBuffer<uint8_t>::FromVoid(read());
 			assert(!data.IsEmpty());
 			assert(frame_length <= data.size);
 
-			sample_rate = adts_sample_rates[(data.data[2] & 0x3c) >> 2];
+			sampleRate = adts_sample_rates[(data.data[2] & 0x3c) >> 2];
+			offset0=getOffset();
+			lastOffset=offset0;
+		}
+		else
+		{
+			offsets.push_back(getOffset()-lastOffset);
+			lastOffset=getOffset();
 		}
 
-		decoder_buffer_consume(buffer, frame_length);
+		consume(frame_length);
 	}
 
-	float frames_per_second = (float)sample_rate / 1024.0;
+	float frames_per_second = ((float)sampleRate) / samplesPerFrame;
 	if (frames_per_second <= 0)
 		return -1;
 
 	return (float)frames / frames_per_second;
 }
 
-static float
-faad_song_duration(DecoderBuffer *buffer, InputStream &is)
+float DecoderBufferFaad::faad_song_duration()
 {
 	const auto size = is.GetSize();
 	const size_t fileread = size >= 0 ? size : 0;
 
-	decoder_buffer_fill(buffer);
-	auto data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_read(buffer));
+	fill();
+	auto data = ConstBuffer<uint8_t>::FromVoid(read());
 	if (data.IsEmpty())
 		return -1;
 
@@ -167,29 +217,28 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is)
 		/* skip the ID3 tag */
 
 		tagsize = (data.data[6] << 21) | (data.data[7] << 14) |
-		    (data.data[8] << 7) | (data.data[9] << 0);
+			(data.data[8] << 7) | (data.data[9] << 0);
 
 		tagsize += 10;
 
-		bool success = decoder_buffer_skip(buffer, tagsize) &&
-			decoder_buffer_fill(buffer);
+		bool success = skip(tagsize) && fill();
 		if (!success)
 			return -1;
 
-		data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_read(buffer));
+		data = ConstBuffer<uint8_t>::FromVoid(read());
 		if (data.IsEmpty())
 			return -1;
 	}
 
 	if (is.IsSeekable() && data.size >= 2 &&
-	    data.data[0] == 0xFF && ((data.data[1] & 0xF6) == 0xF0)) {
+		data.data[0] == 0xFF && ((data.data[1] & 0xF6) == 0xF0)) {
 		/* obtain the duration from the ADTS header */
-		float song_length = adts_song_duration(buffer);
+		float song_length = adts_song_duration();
 
 		is.LockSeek(tagsize, SEEK_SET, IgnoreError());
 
-		decoder_buffer_clear(buffer);
-		decoder_buffer_fill(buffer);
+		clear();
+		fill();
 
 		return song_length;
 	} else if (data.size >= 5 && memcmp(data.data, "ADIF", 4) == 0) {
@@ -215,12 +264,25 @@ faad_song_duration(DecoderBuffer *buffer, InputStream &is)
 		return -1;
 }
 
+float DecoderBufferFaad::seekSample(float seekTime)
+{
+	int frame=seekTime*sampleRate/samplesPerFrame;
+
+	InputStream::offset_type seekOffset=offset0;
+	for(int i=0; i<frame; ++i)
+		seekOffset+=offsets[i];
+
+	std::cout << "seek offset "<< seekOffset << std::endl;
+	seek(seekOffset);
+	return ((float)frame)*samplesPerFrame/sampleRate;
+}
+
 /**
  * Wrapper for NeAACDecInit() which works around some API
  * inconsistencies in libfaad.
  */
 static bool
-faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
+faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer& buffer,
 		  AudioFormat &audio_format, Error &error)
 {
 	uint32_t sample_rate;
@@ -233,7 +295,7 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
 	uint32_t *sample_rate_p = &sample_rate;
 #endif
 
-	auto data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_read(buffer));
+	auto data = ConstBuffer<uint8_t>::FromVoid(buffer.read());
 	if (data.IsEmpty()) {
 		error.Set(faad_decoder_domain, "Empty file");
 		return false;
@@ -241,16 +303,16 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
 
 	uint8_t channels;
 	int32_t nbytes = NeAACDecInit(decoder,
-				      /* deconst hack, libfaad requires this */
-				      const_cast<uint8_t *>(data.data),
-				      data.size,
-				      sample_rate_p, &channels);
+					  /* deconst hack, libfaad requires this */
+					  const_cast<uint8_t *>(data.data),
+					  data.size,
+					  sample_rate_p, &channels);
 	if (nbytes < 0) {
 		error.Set(faad_decoder_domain, "Not an AAC stream");
 		return false;
 	}
 
-	decoder_buffer_consume(buffer, nbytes);
+	buffer.consume(nbytes);
 
 	return audio_format_init_checked(audio_format, sample_rate,
 					 SampleFormat::S16, channels, error);
@@ -261,17 +323,17 @@ faad_decoder_init(NeAACDecHandle decoder, DecoderBuffer *buffer,
  * inconsistencies in libfaad.
  */
 static const void *
-faad_decoder_decode(NeAACDecHandle decoder, DecoderBuffer *buffer,
-		    NeAACDecFrameInfo *frame_info)
+faad_decoder_decode(NeAACDecHandle decoder, DecoderBuffer& buffer,
+			NeAACDecFrameInfo *frame_info)
 {
-	auto data = ConstBuffer<uint8_t>::FromVoid(decoder_buffer_read(buffer));
+	auto data = ConstBuffer<uint8_t>::FromVoid(buffer.read());
 	if (data.IsEmpty())
 		return nullptr;
 
 	return NeAACDecDecode(decoder, frame_info,
-			      /* deconst hack, libfaad requires this */
-			      const_cast<uint8_t *>(data.data),
-			      data.size);
+				  /* deconst hack, libfaad requires this */
+				  const_cast<uint8_t *>(data.data),
+				  data.size);
 }
 
 /**
@@ -282,10 +344,8 @@ faad_decoder_decode(NeAACDecHandle decoder, DecoderBuffer *buffer,
 static float
 faad_get_file_time_float(InputStream &is)
 {
-	DecoderBuffer *buffer =
-		decoder_buffer_new(nullptr, is,
-				   FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
-	float length = faad_song_duration(buffer, is);
+	DecoderBufferFaad buffer(nullptr, is, FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
+	float length = buffer.getDuration();
 
 	if (length < 0) {
 		NeAACDecHandle decoder = NeAACDecOpen();
@@ -295,18 +355,16 @@ faad_get_file_time_float(InputStream &is)
 		config->outputFormat = FAAD_FMT_16BIT;
 		NeAACDecSetConfiguration(decoder, config);
 
-		decoder_buffer_fill(buffer);
+		buffer.fill();
 
 		AudioFormat audio_format;
 		if (faad_decoder_init(decoder, buffer, audio_format,
-				      IgnoreError()))
+					  IgnoreError()))
 			length = 0;
 
 		NeAACDecClose(decoder);
 	}
 
-	decoder_buffer_free(buffer);
-
 	return length;
 }
 
@@ -319,9 +377,9 @@ static int
 faad_get_file_time(InputStream &is)
 {
 	int file_time = -1;
-	float length;
+	float length=faad_get_file_time_float(is);
 
-	if ((length = faad_get_file_time_float(is)) >= 0)
+	if (length >= 0)
 		file_time = length + 0.5;
 
 	return file_time;
@@ -330,10 +388,8 @@ faad_get_file_time(InputStream &is)
 static void
 faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
 {
-	DecoderBuffer *buffer =
-		decoder_buffer_new(&mpd_decoder, is,
-				   FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
-	const float total_time = faad_song_duration(buffer, is);
+	DecoderBufferFaad buffer(&mpd_decoder, is, FAAD_MIN_STREAMSIZE * AAC_MAX_CHANNELS);
+	const float total_time = buffer.getDuration();
 
 	/* create the libfaad decoder */
 
@@ -346,10 +402,10 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
 	config->dontUpSampleImplicitSBR = 0;
 	NeAACDecSetConfiguration(decoder, config);
 
-	while (!decoder_buffer_is_full(buffer) && !is.LockIsEOF() &&
-	       decoder_get_command(mpd_decoder) == DecoderCommand::NONE) {
-		adts_find_frame(buffer);
-		decoder_buffer_fill(buffer);
+	while (!buffer.full() && !is.LockIsEOF() &&
+		   decoder_get_command(mpd_decoder) == DecoderCommand::NONE) {
+		buffer.adts_find_frame();
+		buffer.fill();
 	}
 
 	/* initialize it */
@@ -359,13 +415,12 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
 	if (!faad_decoder_init(decoder, buffer, audio_format, error)) {
 		LogError(error);
 		NeAACDecClose(decoder);
-		decoder_buffer_free(buffer);
 		return;
 	}
 
 	/* initialize the MPD core */
 
-	decoder_initialized(mpd_decoder, audio_format, false, total_time);
+	decoder_initialized(mpd_decoder, audio_format, true, total_time);
 
 	/* the decoder loop */
 
@@ -378,7 +433,7 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
 
 		/* find the next frame */
 
-		frame_size = adts_find_frame(buffer);
+		frame_size = buffer.adts_find_frame();
 		if (frame_size == 0)
 			/* end of file */
 			break;
@@ -389,34 +444,34 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
 
 		if (frame_info.error > 0) {
 			FormatWarning(faad_decoder_domain,
-				      "error decoding AAC stream: %s",
-				      NeAACDecGetErrorMessage(frame_info.error));
+					  "error decoding AAC stream: %s",
+					  NeAACDecGetErrorMessage(frame_info.error));
 			break;
 		}
 
 		if (frame_info.channels != audio_format.channels) {
 			FormatDefault(faad_decoder_domain,
-				      "channel count changed from %u to %u",
-				      audio_format.channels, frame_info.channels);
+					  "channel count changed from %u to %u",
+					  audio_format.channels, frame_info.channels);
 			break;
 		}
 
 		if (frame_info.samplerate != audio_format.sample_rate) {
 			FormatDefault(faad_decoder_domain,
-				      "sample rate changed from %u to %lu",
-				      audio_format.sample_rate,
-				      (unsigned long)frame_info.samplerate);
+					  "sample rate changed from %u to %lu",
+					  audio_format.sample_rate,
+					  (unsigned long)frame_info.samplerate);
 			break;
 		}
 
-		decoder_buffer_consume(buffer, frame_info.bytesconsumed);
+		buffer.consume(frame_info.bytesconsumed);
 
 		/* update bit rate and position */
 
 		if (frame_info.samples > 0) {
 			bit_rate = frame_info.bytesconsumed * 8.0 *
-			    frame_info.channels * audio_format.sample_rate /
-			    frame_info.samples / 1000 + 0.5;
+				frame_info.channels * audio_format.sample_rate /
+				frame_info.samples / 1000 + 0.5;
 		}
 
 		/* send PCM samples to MPD */
@@ -424,12 +479,22 @@ faad_stream_decode(Decoder &mpd_decoder, InputStream &is)
 		cmd = decoder_data(mpd_decoder, is, decoded,
 				   (size_t)frame_info.samples * 2,
 				   bit_rate);
+
+		if (cmd == DecoderCommand::SEEK)
+		{
+			float seekTime = decoder_seek_where(mpd_decoder);
+			float foundTime=buffer.seekSample(seekTime);
+			decoder_command_finished(mpd_decoder);
+			decoder_timestamp(mpd_decoder, foundTime);
+
+			cmd = DecoderCommand::NONE;
+		}
+
 	} while (cmd != DecoderCommand::STOP);
 
 	/* cleanup */
 
 	NeAACDecClose(decoder);
-	decoder_buffer_free(buffer);
 }
 
 static bool
_______________________________________________
mpd-devel mailing list
mpd-devel@musicpd.org
http://mailman.blarg.de/listinfo/mpd-devel

Reply via email to