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;
}
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;
assert(rest >= frame_size);
chunk = tail_chunk(frame_size);
if (chunk == NULL)
return NULL;
if (length > rest)
length = rest;
if (chunk->length == 0) {
/* if the chunk is empty, nobody has set bitRate and
times yet */
/* don't split frames */
length /= frame_size;
length *= frame_size;
chunk->bit_rate = bit_rate;
chunk->times = data_time;
}
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 */
chunk->bit_rate = bit_rate;
chunk->times = data_time;
}
nbytes = music_chunk_append(chunk, data, datalen,
frame_size);
assert(nbytes > 0);
if (nbytes > datalen)
nbytes = datalen;
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;
}

View File

@ -147,6 +147,24 @@ music_pipe_peek(void)
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.
*