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:
parent
d83eff80a5
commit
fd948571f8
80
src/pipe.c
80
src/pipe.c
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
src/pipe.h
18
src/pipe.h
@ -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.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user