aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-01-17 13:09:29 +0100
committerMax Kellermann <max@duempel.org>2009-01-17 13:09:29 +0100
commitfd948571f884e6354883e2ecfc24bab799fc0805 (patch)
tree5433efa559ffcd87c30ebe97899cdeac262ff5a2
parentd83eff80a51d7111f3df28dcc65fab9ebdf61632 (diff)
downloadmpd-fd948571f884e6354883e2ecfc24bab799fc0805.tar.gz
mpd-fd948571f884e6354883e2ecfc24bab799fc0805.tar.xz
mpd-fd948571f884e6354883e2ecfc24bab799fc0805.zip
music_pipe: added functions music_pipe_write() and music_pipe_expand()
This new API gives the caller a writable buffer to the music pipe chunk. This may allow the caller to eliminate several buffer copies, because it may manipulate the returned buffer, until it calls music_pipe_expand().
-rw-r--r--src/pipe.c78
-rw-r--r--src/pipe.h18
2 files changed, 64 insertions, 32 deletions
diff --git a/src/pipe.c b/src/pipe.c
index a11cfb4c5..b2680e37c 100644
--- a/src/pipe.c
+++ b/src/pipe.c
@@ -207,25 +207,49 @@ tail_chunk(size_t frame_size)
return chunk;
}
-static size_t
-music_chunk_append(struct music_chunk *chunk, const void *data, size_t length,
- size_t frame_size)
+void *
+music_pipe_write(const struct audio_format *audio_format,
+ float data_time, uint16_t bit_rate,
+ size_t *max_length_r)
{
- size_t rest = sizeof(chunk->data) - chunk->length;
+ const size_t frame_size = audio_format_frame_size(audio_format);
+ struct music_chunk *chunk;
+ size_t num_frames;
+
+ chunk = tail_chunk(frame_size);
+ if (chunk == NULL)
+ return NULL;
- assert(rest >= frame_size);
+ if (chunk->length == 0) {
+ /* if the chunk is empty, nobody has set bitRate and
+ times yet */
- if (length > rest)
- length = rest;
+ chunk->bit_rate = bit_rate;
+ chunk->times = data_time;
+ }
- /* don't split frames */
- length /= frame_size;
- length *= frame_size;
+ num_frames = (sizeof(chunk->data) - chunk->length) / frame_size;
+ *max_length_r = num_frames * frame_size;
+ return chunk->data + chunk->length;
+}
+
+void
+music_pipe_expand(const struct audio_format *audio_format, size_t length)
+{
+ const size_t frame_size = audio_format_frame_size(audio_format);
+ struct music_chunk *chunk;
+
+ /* no partial frames allowed */
+ assert(length % frame_size == 0);
+
+ chunk = tail_chunk(frame_size);
+ assert(chunk != NULL);
+ assert(chunk->length + length <= sizeof(chunk->data));
- memcpy(chunk->data + chunk->length, data, length);
chunk->length += length;
- return length;
+ if (chunk->length + frame_size > sizeof(chunk->data))
+ music_pipe_flush();
}
size_t music_pipe_append(const void *data0, size_t datalen,
@@ -233,38 +257,28 @@ size_t music_pipe_append(const void *data0, size_t datalen,
float data_time, uint16_t bit_rate)
{
const unsigned char *data = data0;
- const size_t frame_size = audio_format_frame_size(audio_format);
size_t ret = 0, nbytes;
- struct music_chunk *chunk = NULL;
-
- /* no partial frames allowed */
- assert((datalen % frame_size) == 0);
+ void *dest;
while (datalen) {
- chunk = tail_chunk(frame_size);
- if (chunk == NULL)
- return ret;
+ dest = music_pipe_write(audio_format, data_time, bit_rate,
+ &nbytes);
+ if (dest == NULL)
+ break;
- if (chunk->length == 0) {
- /* if the chunk is empty, nobody has set bitRate and
- times yet */
+ assert(nbytes > 0);
- chunk->bit_rate = bit_rate;
- chunk->times = data_time;
- }
+ if (nbytes > datalen)
+ nbytes = datalen;
- nbytes = music_chunk_append(chunk, data, datalen,
- frame_size);
- assert(nbytes > 0);
+ memcpy(dest, data, nbytes);
+ music_pipe_expand(audio_format, nbytes);
datalen -= nbytes;
data += nbytes;
ret += nbytes;
}
- if (chunk != NULL && chunk->length == sizeof(chunk->data))
- music_pipe_flush();
-
return ret;
}
diff --git a/src/pipe.h b/src/pipe.h
index 7d82c1693..526bedb26 100644
--- a/src/pipe.h
+++ b/src/pipe.h
@@ -148,6 +148,24 @@ music_pipe_peek(void)
}
/**
+ * Prepares appending to the music pipe. Returns a buffer where you
+ * may write into. After you are finished, call music_pipe_expand().
+ *
+ * @return a writable buffer
+ */
+void *
+music_pipe_write(const struct audio_format *audio_format,
+ float data_time, uint16_t bit_rate,
+ size_t *max_length_r);
+
+/**
+ * Tells the music pipe to move the end pointer, after you have
+ * written to the buffer returned by music_pipe_write().
+ */
+void
+music_pipe_expand(const struct audio_format *audio_format, size_t length);
+
+/**
* Append a data block to the buffer.
*
* @return the number of bytes actually written