diff options
author | Lennart Poettering <lennart@poettering.net> | 2007-09-16 22:00:38 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2007-09-16 22:00:38 +0000 |
commit | 1d1eda60595622a79e598e7c986cc3c23e6a5c34 (patch) | |
tree | ca18fd77ddc8033f5d51e52b27658cd968cae361 | |
parent | 5df7a85473f1c06a8baf6a4d81433bde18f86714 (diff) |
add a "length" argument to the seek functions, as an optimization to request a certain block size if any data needs to be generated. this is merely a hint.
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1833 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r-- | src/modules/module-combine.c | 8 | ||||
-rw-r--r-- | src/modules/module-sine.c | 2 | ||||
-rw-r--r-- | src/pulsecore/play-memblockq.c | 2 | ||||
-rw-r--r-- | src/pulsecore/play-memchunk.c | 2 | ||||
-rw-r--r-- | src/pulsecore/protocol-esound.c | 4 | ||||
-rw-r--r-- | src/pulsecore/protocol-native.c | 4 | ||||
-rw-r--r-- | src/pulsecore/protocol-simple.c | 2 | ||||
-rw-r--r-- | src/pulsecore/sink-input.c | 56 | ||||
-rw-r--r-- | src/pulsecore/sink-input.h | 10 | ||||
-rw-r--r-- | src/pulsecore/sink.c | 44 | ||||
-rw-r--r-- | src/pulsecore/sound-file-stream.c | 10 |
11 files changed, 94 insertions, 50 deletions
diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index f2633ab4..235e04e6 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -275,7 +275,7 @@ finish: pa_log_debug("Thread shutting down"); } -static void request_memblock(struct output *o) { +static void request_memblock(struct output *o, size_t length) { pa_memchunk chunk; pa_assert(o); @@ -306,7 +306,7 @@ static void request_memblock(struct output *o) { struct output *j; /* Do it! */ - pa_sink_render(o->userdata->sink, o->userdata->block_size, &chunk); + pa_sink_render(o->userdata->sink, length, &chunk); /* OK, let's send this data to the other threads */ for (j = o->userdata->thread_info.outputs; j; j = j->next) @@ -323,7 +323,7 @@ static void request_memblock(struct output *o) { } /* Called from I/O thread context */ -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { struct output *o; pa_sink_input_assert_ref(i); @@ -331,7 +331,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { pa_assert(o); /* If necessary, get some new data */ - request_memblock(o); + request_memblock(o, length); return pa_memblockq_peek(o->memblockq, chunk); } diff --git a/src/modules/module-sine.c b/src/modules/module-sine.c index f48cb09e..5684f94c 100644 --- a/src/modules/module-sine.c +++ b/src/modules/module-sine.c @@ -58,7 +58,7 @@ static const char* const valid_modargs[] = { NULL, }; -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { struct userdata *u; pa_assert(i); diff --git a/src/pulsecore/play-memblockq.c b/src/pulsecore/play-memblockq.c index 68ce21b1..5652ac2b 100644 --- a/src/pulsecore/play-memblockq.c +++ b/src/pulsecore/play-memblockq.c @@ -97,7 +97,7 @@ static void sink_input_kill_cb(pa_sink_input *i) { memblockq_stream_unlink(MEMBLOCKQ_STREAM(i->userdata)); } -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { memblockq_stream *u; pa_assert(i); diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c index f60f706e..fd931a24 100644 --- a/src/pulsecore/play-memchunk.c +++ b/src/pulsecore/play-memchunk.c @@ -97,7 +97,7 @@ static void sink_input_kill_cb(pa_sink_input *i) { memchunk_stream_unlink(MEMCHUNK_STREAM(i->userdata)); } -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { memchunk_stream *u; pa_assert(i); diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c index fc881c81..b6943634 100644 --- a/src/pulsecore/protocol-esound.c +++ b/src/pulsecore/protocol-esound.c @@ -150,7 +150,7 @@ typedef struct proto_handler { } esd_proto_handler_info_t; static void sink_input_drop_cb(pa_sink_input *i, size_t length); -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk); static void sink_input_kill_cb(pa_sink_input *i); static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); static pa_usec_t source_output_get_latency_cb(pa_source_output *o); @@ -1237,7 +1237,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int } /* Called from thread context */ -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { connection*c; int r; diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index 52cec097..24f5997e 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -199,7 +199,7 @@ enum { CONNECTION_MESSAGE_REVOKE }; -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk); +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk); static void sink_input_drop_cb(pa_sink_input *i, size_t length); static void sink_input_kill_cb(pa_sink_input *i); @@ -973,7 +973,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int } /* Called from thread context */ -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { playback_stream *s; pa_sink_input_assert_ref(i); diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c index db7c9a69..da5f24e7 100644 --- a/src/pulsecore/protocol-simple.c +++ b/src/pulsecore/protocol-simple.c @@ -343,7 +343,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int } /* Called from thread context */ -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { connection *c; int r; diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 009000e3..f2855fc9 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -41,9 +41,9 @@ #include "sink-input.h" -#define CONVERT_BUFFER_LENGTH 4096 -#define MOVE_BUFFER_LENGTH (1024*1024) -#define SILENCE_BUFFER_LENGTH (64*1024) +#define CONVERT_BUFFER_LENGTH (PA_PAGE_SIZE) +#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12) +#define MOVE_BUFFER_LENGTH (PA_PAGE_SIZE*256) static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject); @@ -368,13 +368,15 @@ pa_usec_t pa_sink_input_get_latency(pa_sink_input *i) { } /* Called from thread context */ -int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) { +int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume) { int ret = -1; int do_volume_adj_here; int volume_is_norm; + size_t block_size_max; pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state)); + pa_assert(pa_frame_aligned(length, &i->sink->sample_spec)); pa_assert(chunk); pa_assert(volume); @@ -383,6 +385,15 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) pa_assert(i->thread_info.state == PA_SINK_INPUT_RUNNING || i->thread_info.state == PA_SINK_INPUT_DRAINED); + /* Default buffer size */ + if (length <= 0) + length = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sink->sample_spec); + + /* Make sure the buffer fits in the mempool tile */ + block_size_max = pa_mempool_block_size_max(i->sink->core->mempool); + if (length > block_size_max) + length = pa_frame_align(block_size_max, &i->sink->sample_spec); + if (i->thread_info.move_silence > 0) { size_t l; @@ -390,7 +401,10 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) * while until the old sink has drained its playback buffer */ if (!i->thread_info.silence_memblock) - i->thread_info.silence_memblock = pa_silence_memblock_new(i->sink->core->mempool, &i->sink->sample_spec, SILENCE_BUFFER_LENGTH); + i->thread_info.silence_memblock = pa_silence_memblock_new( + i->sink->core->mempool, + &i->sink->sample_spec, + pa_frame_align(SILENCE_BUFFER_LENGTH, &i->sink->sample_spec)); chunk->memblock = pa_memblock_ref(i->thread_info.silence_memblock); chunk->index = 0; @@ -404,7 +418,7 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) if (!i->thread_info.resampler) { do_volume_adj_here = 0; /* FIXME??? */ - ret = i->peek(i, chunk); + ret = i->peek(i, length, chunk); goto finish; } @@ -413,15 +427,22 @@ int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume) while (!i->thread_info.resampled_chunk.memblock) { pa_memchunk tchunk; - size_t l; + size_t l, rmbs; - if ((ret = i->peek(i, &tchunk)) < 0) + l = pa_resampler_request(i->thread_info.resampler, length); + + if (l <= 0) + l = pa_frame_align(CONVERT_BUFFER_LENGTH, &i->sample_spec); + + rmbs = pa_resampler_max_block_size(i->thread_info.resampler); + if (l > rmbs) + l = rmbs; + + if ((ret = i->peek(i, l, &tchunk)) < 0) goto finish; pa_assert(tchunk.length > 0); - l = pa_resampler_request(i->thread_info.resampler, CONVERT_BUFFER_LENGTH); - if (tchunk.length > l) tchunk.length = l; @@ -477,6 +498,7 @@ finish: void pa_sink_input_drop(pa_sink_input *i, size_t length) { pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_LINKED(i->thread_info.state)); + pa_assert(pa_frame_aligned(length, &i->sink->sample_spec)); pa_assert(length > 0); if (i->thread_info.move_silence > 0) { @@ -527,9 +549,9 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) { pa_memchunk chunk; pa_cvolume volume; - if (pa_sink_input_peek(i, &chunk, &volume) >= 0) { + if (pa_sink_input_peek(i, length, &chunk, &volume) >= 0) { size_t l; - + pa_memblock_unref(chunk.memblock); l = chunk.length; @@ -541,11 +563,13 @@ void pa_sink_input_drop(pa_sink_input *i, size_t length) { } else { size_t l; - + + l = pa_resampler_request(i->thread_info.resampler, length); + /* Hmmm, peeking failed, so let's at least drop * the right amount of data */ - if ((l = pa_resampler_request(i->thread_info.resampler, length)) > 0) + if (l > 0) if (i->drop) i->drop(i, l); @@ -798,9 +822,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest, int immediately) { i->thread_info.move_silence = 0; else i->thread_info.move_silence = pa_usec_to_bytes( - pa_bytes_to_usec(i->thread_info.move_silence, &i->sample_spec) + + pa_bytes_to_usec(i->thread_info.move_silence, &origin->sample_spec) + silence_usec, - &i->sample_spec); + &dest->sample_spec); pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_ADD_INPUT, i, 0, NULL); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index a101828f..7d405640 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -83,8 +83,12 @@ struct pa_sink_input { int muted; /* Returns the chunk of audio data (but doesn't drop it - * yet!). Returns -1 on failure. Called from IO thread context. */ - int (*peek) (pa_sink_input *i, pa_memchunk *chunk); + * yet!). Returns -1 on failure. Called from IO thread context. If + * data needs to be generated from scratch then please in the + * specified length. This is an optimization only. If less data is + * available, it's fine to return a smaller block. If more data is + * already ready, it is better to return the full block.*/ + int (*peek) (pa_sink_input *i, size_t length, pa_memchunk *chunk); /* Drops the specified number of bytes, usually called right after * peek(), but not necessarily. Called from IO thread context. */ @@ -217,7 +221,7 @@ pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i); /* To be used exclusively by the sink driver thread */ -int pa_sink_input_peek(pa_sink_input *i, pa_memchunk *chunk, pa_cvolume *volume); +int pa_sink_input_peek(pa_sink_input *i, size_t length, pa_memchunk *chunk, pa_cvolume *volume); void pa_sink_input_drop(pa_sink_input *i, size_t length); int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 318b191a..45cc96bf 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -46,7 +46,8 @@ #include "sink.h" #define MAX_MIX_CHANNELS 32 -#define SILENCE_BUFFER_LENGTH (64*1024) +#define MIX_BUFFER_LENGTH (PA_PAGE_SIZE) +#define SILENCE_BUFFER_LENGTH (PA_PAGE_SIZE*12) static PA_DEFINE_CHECK_TYPE(pa_sink, pa_msgobject); @@ -311,7 +312,7 @@ void pa_sink_ping(pa_sink *s) { pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_PING, NULL, 0, NULL, NULL); } -static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { +static unsigned fill_mix_info(pa_sink *s, size_t length, pa_mix_info *info, unsigned maxinfo) { pa_sink_input *i; unsigned n = 0; void *state = NULL; @@ -322,7 +323,7 @@ static unsigned fill_mix_info(pa_sink *s, pa_mix_info *info, unsigned maxinfo) { while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL)) && maxinfo > 0) { pa_sink_input_assert_ref(i); - if (pa_sink_input_peek(i, &info->chunk, &info->volume) < 0) + if (pa_sink_input_peek(i, length, &info->chunk, &info->volume) < 0) continue; info->userdata = pa_sink_input_ref(i); @@ -399,20 +400,32 @@ static void inputs_drop(pa_sink *s, pa_mix_info *info, unsigned n, size_t length void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_mix_info info[MAX_MIX_CHANNELS]; unsigned n; - + size_t block_size_max; + pa_sink_assert_ref(s); pa_assert(PA_SINK_OPENED(s->thread_info.state)); - pa_assert(length); + pa_assert(pa_frame_aligned(length, &s->sample_spec)); pa_assert(result); pa_sink_ref(s); - n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, info, MAX_MIX_CHANNELS) : 0; + if (length <= 0) + length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec); + + block_size_max = pa_mempool_block_size_max(s->core->mempool); + if (length > block_size_max) + length = pa_frame_align(block_size_max, &s->sample_spec); + + pa_assert(length > 0); + + n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, length, info, MAX_MIX_CHANNELS) : 0; if (n == 0) { if (length > SILENCE_BUFFER_LENGTH) - length = SILENCE_BUFFER_LENGTH; + length = pa_frame_align(SILENCE_BUFFER_LENGTH, &s->sample_spec); + + pa_assert(length > 0); if (!s->silence || pa_memblock_get_length(s->silence) < length) { if (s->silence) @@ -470,11 +483,12 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_assert(PA_SINK_OPENED(s->thread_info.state)); pa_assert(target); pa_assert(target->memblock); - pa_assert(target->length); + pa_assert(target->length > 0); + pa_assert(pa_frame_aligned(target->length, &s->sample_spec)); pa_sink_ref(s); - n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, info, MAX_MIX_CHANNELS) : 0; + n = s->thread_info.state == PA_SINK_RUNNING ? fill_mix_info(s, target->length, info, MAX_MIX_CHANNELS) : 0; if (n == 0) { pa_silence_memchunk(target, &s->sample_spec); @@ -536,7 +550,8 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { pa_assert(PA_SINK_OPENED(s->thread_info.state)); pa_assert(target); pa_assert(target->memblock); - pa_assert(target->length); + pa_assert(target->length > 0); + pa_assert(pa_frame_aligned(target->length, &s->sample_spec)); pa_sink_ref(s); @@ -559,13 +574,15 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { pa_sink_assert_ref(s); pa_assert(PA_SINK_OPENED(s->thread_info.state)); - pa_assert(length); + pa_assert(length > 0); + pa_assert(pa_frame_aligned(length, &s->sample_spec)); pa_assert(result); /*** This needs optimization ***/ - result->memblock = pa_memblock_new(s->core->mempool, result->length = length); result->index = 0; + result->length = length; + result->memblock = pa_memblock_new(s->core->mempool, length); pa_sink_render_into_full(s, result); } @@ -577,6 +594,7 @@ void pa_sink_skip(pa_sink *s, size_t length) { pa_sink_assert_ref(s); pa_assert(PA_SINK_OPENED(s->thread_info.state)); pa_assert(length > 0); + pa_assert(pa_frame_aligned(length, &s->sample_spec)); if (pa_source_used_by(s->monitor_source)) { pa_memchunk chunk; @@ -853,7 +871,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse pa_cvolume volume; size_t n; - if (pa_sink_input_peek(info->sink_input, &memchunk, &volume) < 0) + if (pa_sink_input_peek(info->sink_input, info->buffer_bytes, &memchunk, &volume) < 0) break; n = memchunk.length > info->buffer_bytes ? info->buffer_bytes : memchunk.length; diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c index 8a04b821..6c70c4f1 100644 --- a/src/pulsecore/sound-file-stream.c +++ b/src/pulsecore/sound-file-stream.c @@ -44,8 +44,6 @@ #include "sound-file-stream.h" -#define BUF_SIZE (1024*16) - typedef struct file_stream { pa_msgobject parent; pa_core *core; @@ -113,7 +111,7 @@ static void sink_input_kill_cb(pa_sink_input *i) { file_stream_unlink(FILE_STREAM(i->userdata)); } -static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { +static int sink_input_peek_cb(pa_sink_input *i, size_t length, pa_memchunk *chunk) { file_stream *u; pa_assert(i); @@ -128,7 +126,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { if (!u->memchunk.memblock) { - u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, BUF_SIZE); + u->memchunk.memblock = pa_memblock_new(i->sink->core->mempool, length); u->memchunk.index = 0; if (u->readf_function) { @@ -137,7 +135,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { size_t fs = pa_frame_size(&i->sample_spec); p = pa_memblock_acquire(u->memchunk.memblock); - n = u->readf_function(u->sndfile, p, BUF_SIZE/fs); + n = u->readf_function(u->sndfile, p, length/fs); pa_memblock_release(u->memchunk.memblock); if (n <= 0) @@ -149,7 +147,7 @@ static int sink_input_peek_cb(pa_sink_input *i, pa_memchunk *chunk) { void *p; p = pa_memblock_acquire(u->memchunk.memblock); - n = sf_read_raw(u->sndfile, p, BUF_SIZE); + n = sf_read_raw(u->sndfile, p, length); pa_memblock_release(u->memchunk.memblock); if (n <= 0) |