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().
This commit is contained in:
Max Kellermann 2009-01-17 13:09:29 +01:00
parent d83eff80a5
commit fd948571f8
2 changed files with 65 additions and 33 deletions

View File

@ -207,25 +207,49 @@ tail_chunk(size_t frame_size)
return chunk; return chunk;
} }
static size_t void *
music_chunk_append(struct music_chunk *chunk, const void *data, size_t length, music_pipe_write(const struct audio_format *audio_format,
size_t frame_size) 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;
assert(rest >= frame_size); chunk = tail_chunk(frame_size);
if (chunk == NULL)
return NULL;
if (length > rest) if (chunk->length == 0) {
length = rest; /* if the chunk is empty, nobody has set bitRate and
times yet */
/* don't split frames */ chunk->bit_rate = bit_rate;
length /= frame_size; chunk->times = data_time;
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; 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, 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) float data_time, uint16_t bit_rate)
{ {
const unsigned char *data = data0; const unsigned char *data = data0;
const size_t frame_size = audio_format_frame_size(audio_format);
size_t ret = 0, nbytes; size_t ret = 0, nbytes;
struct music_chunk *chunk = NULL; void *dest;
/* no partial frames allowed */
assert((datalen % frame_size) == 0);
while (datalen) { while (datalen) {
chunk = tail_chunk(frame_size); dest = music_pipe_write(audio_format, data_time, bit_rate,
if (chunk == NULL) &nbytes);
return ret; if (dest == NULL)
break;
if (chunk->length == 0) {
/* if the chunk is empty, nobody has set bitRate and
times yet */
chunk->bit_rate = bit_rate;
chunk->times = data_time;
}
nbytes = music_chunk_append(chunk, data, datalen,
frame_size);
assert(nbytes > 0); assert(nbytes > 0);
if (nbytes > datalen)
nbytes = datalen;
memcpy(dest, data, nbytes);
music_pipe_expand(audio_format, nbytes);
datalen -= nbytes; datalen -= nbytes;
data += nbytes; data += nbytes;
ret += nbytes; ret += nbytes;
} }
if (chunk != NULL && chunk->length == sizeof(chunk->data))
music_pipe_flush();
return ret; return ret;
} }

View File

@ -147,6 +147,24 @@ music_pipe_peek(void)
return music_pipe_get_chunk(music_pipe.begin); return music_pipe_get_chunk(music_pipe.begin);
} }
/**
* 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. * Append a data block to the buffer.
* *