aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2011-11-28 08:00:10 +0100
committerMax Kellermann <max@duempel.org>2011-11-28 09:21:32 +0100
commitcee5036aca85f37a28f2d52a2fc5ad19878ad511 (patch)
tree72e1498b0d2f41b8bbba8b5980ce818d224e2038
parent790823abb4671e6d94c8cb491f29e6448f2b1f85 (diff)
downloadmpd-cee5036aca85f37a28f2d52a2fc5ad19878ad511.tar.gz
mpd-cee5036aca85f37a28f2d52a2fc5ad19878ad511.tar.xz
mpd-cee5036aca85f37a28f2d52a2fc5ad19878ad511.zip
encoder/flac: use fifo_buffer instead of pcm_buffer
This fixes a buffer corruption bug; pcm_buffer is not designed to be a persistent buffers, and will discard anything between two consecutive calls.
-rw-r--r--Makefile.am3
-rw-r--r--NEWS2
-rw-r--r--src/encoder/flac_encoder.c36
3 files changed, 24 insertions, 17 deletions
diff --git a/Makefile.am b/Makefile.am
index 7478ffcc2..6401e3a48 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -994,6 +994,7 @@ test_run_encoder_SOURCES = test/run_encoder.c \
src/audio_format.c \
src/audio_parser.c \
src/pcm_buffer.c \
+ src/fifo_buffer.c src/growing_fifo.c \
$(ENCODER_SRC)
test_run_encoder_CPPFLAGS = $(AM_CPPFLAGS) \
$(ENCODER_CFLAGS)
@@ -1057,7 +1058,7 @@ test_run_output_SOURCES = test/run_output.c \
src/audio_parser.c \
src/timer.c \
src/tag.c src/tag_pool.c \
- src/fifo_buffer.c \
+ src/fifo_buffer.c src/growing_fifo.c \
src/page.c \
src/socket_util.c \
src/output_init.c src/output_list.c \
diff --git a/NEWS b/NEWS
index fc62549fb..b7f0e9f2c 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,8 @@
ver 0.16.6 (2010/??/??)
* decoder:
- fix assertion failure when resuming streams
+* encoder:
+ - flac: fix buffer corruption bug
* event_pipe: fix WIN32 regression
* define WINVER in ./configure
* WIN32: autodetect filesystem encoding
diff --git a/src/encoder/flac_encoder.c b/src/encoder/flac_encoder.c
index c34faad00..6389513ef 100644
--- a/src/encoder/flac_encoder.c
+++ b/src/encoder/flac_encoder.c
@@ -22,6 +22,8 @@
#include "encoder_plugin.h"
#include "audio_format.h"
#include "pcm_buffer.h"
+#include "fifo_buffer.h"
+#include "growing_fifo.h"
#include <assert.h>
#include <string.h>
@@ -38,8 +40,11 @@ struct flac_encoder {
struct pcm_buffer expand_buffer;
- struct pcm_buffer buffer;
- size_t buffer_length;
+ /**
+ * This buffer will hold encoded data from libFLAC until it is
+ * picked up with flac_encoder_read().
+ */
+ struct fifo_buffer *output_buffer;
};
extern const struct encoder_plugin flac_encoder_plugin;
@@ -140,11 +145,8 @@ flac_write_callback(G_GNUC_UNUSED const FLAC__StreamEncoder *fse,
{
struct flac_encoder *encoder = (struct flac_encoder *) client_data;
- char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length + bytes);
-
//transfer data to buffer
- memcpy( buffer + encoder->buffer_length, data, bytes);
- encoder->buffer_length += bytes;
+ growing_fifo_append(&encoder->output_buffer, data, bytes);
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
@@ -156,8 +158,8 @@ flac_encoder_close(struct encoder *_encoder)
FLAC__stream_encoder_delete(encoder->fse);
- pcm_buffer_deinit(&encoder->buffer);
pcm_buffer_deinit(&encoder->expand_buffer);
+ fifo_buffer_free(encoder->output_buffer);
}
static bool
@@ -201,10 +203,10 @@ flac_encoder_open(struct encoder *_encoder, struct audio_format *audio_format,
return false;
}
- encoder->buffer_length = 0;
- pcm_buffer_init(&encoder->buffer);
pcm_buffer_init(&encoder->expand_buffer);
+ encoder->output_buffer = growing_fifo_new();
+
/* this immediatelly outputs data throught callback */
#if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
@@ -325,16 +327,18 @@ static size_t
flac_encoder_read(struct encoder *_encoder, void *dest, size_t length)
{
struct flac_encoder *encoder = (struct flac_encoder *)_encoder;
- char *buffer = pcm_buffer_get(&encoder->buffer, encoder->buffer_length);
-
- if (length > encoder->buffer_length)
- length = encoder->buffer_length;
- memcpy(dest, buffer, length);
+ size_t max_length;
+ const char *src = fifo_buffer_read(encoder->output_buffer,
+ &max_length);
+ if (src == NULL)
+ return 0;
- encoder->buffer_length -= length;
- memmove(buffer, buffer + length, encoder->buffer_length);
+ if (length > max_length)
+ length = max_length;
+ memcpy(dest, src, length);
+ fifo_buffer_consume(encoder->output_buffer, length);
return length;
}