add new dont_rewind_render flag to allow quick starts of newly created streams

This commit is contained in:
Lennart Poettering 2009-01-15 00:40:06 +01:00
parent 06de6393d1
commit 75119e91cd
12 changed files with 32 additions and 22 deletions

View file

@ -504,7 +504,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
* we are heard right-away. */ * we are heard right-away. */
if (PA_SINK_INPUT_IS_LINKED(state) && if (PA_SINK_INPUT_IS_LINKED(state) &&
i->thread_info.state == PA_SINK_INPUT_INIT) i->thread_info.state == PA_SINK_INPUT_INIT)
pa_sink_input_request_rewind(i, 0, FALSE, TRUE); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
} }
/* Called from thread context */ /* Called from thread context */

View file

@ -144,7 +144,7 @@ static void sink_request_rewind(pa_sink *s) {
pa_assert_se(u = s->userdata); pa_assert_se(u = s->userdata);
/* Just hand this one over to the master sink */ /* Just hand this one over to the master sink */
pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes + pa_memblockq_get_length(u->memblockq), TRUE, FALSE); pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes + pa_memblockq_get_length(u->memblockq), TRUE, FALSE, FALSE);
} }
/* Called from I/O thread context */ /* Called from I/O thread context */
@ -355,7 +355,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
if (PA_SINK_INPUT_IS_LINKED(state) && if (PA_SINK_INPUT_IS_LINKED(state) &&
i->thread_info.state == PA_SINK_INPUT_INIT) { i->thread_info.state == PA_SINK_INPUT_INIT) {
pa_log_debug("Requesting rewind due to state change."); pa_log_debug("Requesting rewind due to state change.");
pa_sink_input_request_rewind(i, 0, FALSE, TRUE); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
} }
} }

View file

@ -119,7 +119,7 @@ static void sink_request_rewind(pa_sink *s) {
pa_sink_assert_ref(s); pa_sink_assert_ref(s);
pa_assert_se(u = s->userdata); pa_assert_se(u = s->userdata);
pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, TRUE, FALSE); pa_sink_input_request_rewind(u->sink_input, s->thread_info.rewind_nbytes, TRUE, FALSE, FALSE);
} }
/* Called from I/O thread context */ /* Called from I/O thread context */
@ -270,7 +270,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
if (PA_SINK_INPUT_IS_LINKED(state) && if (PA_SINK_INPUT_IS_LINKED(state) &&
i->thread_info.state == PA_SINK_INPUT_INIT) { i->thread_info.state == PA_SINK_INPUT_INIT) {
pa_log_debug("Requesting rewind due to state change."); pa_log_debug("Requesting rewind due to state change.");
pa_sink_input_request_rewind(i, 0, FALSE, TRUE); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
} }
} }

View file

@ -115,7 +115,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
* we are heard right-away. */ * we are heard right-away. */
if (PA_SINK_INPUT_IS_LINKED(state) && if (PA_SINK_INPUT_IS_LINKED(state) &&
i->thread_info.state == PA_SINK_INPUT_INIT) i->thread_info.state == PA_SINK_INPUT_INIT)
pa_sink_input_request_rewind(i, 0, FALSE, TRUE); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
} }
int pa__init(pa_module*m) { int pa__init(pa_module*m) {

View file

@ -313,7 +313,7 @@ static int rtpoll_work_cb(pa_rtpoll_item *i) {
if (pa_memblockq_is_readable(s->memblockq) && if (pa_memblockq_is_readable(s->memblockq) &&
s->sink_input->thread_info.underrun_for > 0) { s->sink_input->thread_info.underrun_for > 0) {
pa_log_debug("Requesting rewind due to end of underrun"); pa_log_debug("Requesting rewind due to end of underrun");
pa_sink_input_request_rewind(s->sink_input, 0, FALSE, TRUE); pa_sink_input_request_rewind(s->sink_input, 0, FALSE, TRUE, FALSE);
} }
return 1; return 1;

View file

@ -109,7 +109,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
* we are heard right-away. */ * we are heard right-away. */
if (PA_SINK_INPUT_IS_LINKED(state) && if (PA_SINK_INPUT_IS_LINKED(state) &&
i->thread_info.state == PA_SINK_INPUT_INIT) i->thread_info.state == PA_SINK_INPUT_INIT)
pa_sink_input_request_rewind(i, 0, FALSE, TRUE); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
} }
static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) { static int sink_input_pop_cb(pa_sink_input *i, size_t nbytes, pa_memchunk *chunk) {

View file

@ -1238,7 +1238,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) { if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) {
pa_log_debug("Requesting rewind due to end of underrun."); pa_log_debug("Requesting rewind due to end of underrun.");
pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE); pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE, FALSE);
} }
/* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */ /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */

View file

@ -1240,7 +1240,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
pa_log_debug("Requesting rewind due to end of underrun."); pa_log_debug("Requesting rewind due to end of underrun.");
pa_sink_input_request_rewind(s->sink_input, pa_sink_input_request_rewind(s->sink_input,
(size_t) (s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for), (size_t) (s->sink_input->thread_info.underrun_for == (size_t) -1 ? 0 : s->sink_input->thread_info.underrun_for),
FALSE, TRUE); FALSE, TRUE, FALSE);
} }
} else { } else {
@ -1253,7 +1253,7 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
* let's have it usk us again */ * let's have it usk us again */
pa_log_debug("Requesting rewind due to rewrite."); pa_log_debug("Requesting rewind due to rewrite.");
pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE); pa_sink_input_request_rewind(s->sink_input, (size_t) (indexr - indexw), TRUE, FALSE, FALSE);
} }
} }

View file

@ -323,7 +323,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) { if (pa_memblockq_is_readable(c->input_memblockq) && c->playback.underrun) {
pa_log_debug("Requesting rewind due to end of underrun."); pa_log_debug("Requesting rewind due to end of underrun.");
pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE); pa_sink_input_request_rewind(c->sink_input, 0, FALSE, TRUE, FALSE);
} }
/* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */ /* pa_log("got data, %u", pa_memblockq_get_length(c->input_memblockq)); */

View file

@ -265,6 +265,7 @@ pa_sink_input* pa_sink_input_new(
i->thread_info.requested_sink_latency = (pa_usec_t) -1; i->thread_info.requested_sink_latency = (pa_usec_t) -1;
i->thread_info.rewrite_nbytes = 0; i->thread_info.rewrite_nbytes = 0;
i->thread_info.rewrite_flush = FALSE; i->thread_info.rewrite_flush = FALSE;
i->thread_info.dont_rewind_render = FALSE;
i->thread_info.underrun_for = (uint64_t) -1; i->thread_info.underrun_for = (uint64_t) -1;
i->thread_info.playing_for = 0; i->thread_info.playing_for = 0;
i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
@ -658,7 +659,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
lbq = pa_memblockq_get_length(i->thread_info.render_memblockq); lbq = pa_memblockq_get_length(i->thread_info.render_memblockq);
if (nbytes > 0) { if (nbytes > 0 && !i->thread_info.dont_rewind_render) {
pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes); pa_log_debug("Have to rewind %lu bytes on render memblockq.", (unsigned long) nbytes);
pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes); pa_memblockq_rewind(i->thread_info.render_memblockq, nbytes);
} }
@ -714,6 +715,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
i->thread_info.rewrite_nbytes = 0; i->thread_info.rewrite_nbytes = 0;
i->thread_info.rewrite_flush = FALSE; i->thread_info.rewrite_flush = FALSE;
i->thread_info.dont_rewind_render = FALSE;
} }
/* Called from thread context */ /* Called from thread context */
@ -1091,7 +1093,7 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state
/* This will tell the implementing sink input driver to rewind /* This will tell the implementing sink input driver to rewind
* so that the unplayed already mixed data is not lost */ * so that the unplayed already mixed data is not lost */
pa_sink_input_request_rewind(i, 0, TRUE, TRUE); pa_sink_input_request_rewind(i, 0, TRUE, TRUE, FALSE);
} else if (uncorking) { } else if (uncorking) {
@ -1102,7 +1104,7 @@ void pa_sink_input_set_state_within_thread(pa_sink_input *i, pa_sink_input_state
/* OK, we're being uncorked. Make sure we're not rewound when /* OK, we're being uncorked. Make sure we're not rewound when
* the hw buffer is remixed and request a remix. */ * the hw buffer is remixed and request a remix. */
pa_sink_input_request_rewind(i, 0, FALSE, TRUE); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
} }
} }
@ -1115,12 +1117,12 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t
case PA_SINK_INPUT_MESSAGE_SET_VOLUME: case PA_SINK_INPUT_MESSAGE_SET_VOLUME:
i->thread_info.volume = *((pa_cvolume*) userdata); i->thread_info.volume = *((pa_cvolume*) userdata);
pa_sink_input_request_rewind(i, 0, TRUE, FALSE); pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
return 0; return 0;
case PA_SINK_INPUT_MESSAGE_SET_MUTE: case PA_SINK_INPUT_MESSAGE_SET_MUTE:
i->thread_info.muted = PA_PTR_TO_UINT(userdata); i->thread_info.muted = PA_PTR_TO_UINT(userdata);
pa_sink_input_request_rewind(i, 0, TRUE, FALSE); pa_sink_input_request_rewind(i, 0, TRUE, FALSE, FALSE);
return 0; return 0;
case PA_SINK_INPUT_MESSAGE_GET_LATENCY: { case PA_SINK_INPUT_MESSAGE_GET_LATENCY: {
@ -1195,7 +1197,7 @@ pa_bool_t pa_sink_input_safe_to_remove(pa_sink_input *i) {
} }
/* Called from IO context */ /* Called from IO context */
void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush) { void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sample spec */, pa_bool_t rewrite, pa_bool_t flush, pa_bool_t dont_rewind_render) {
size_t lbq; size_t lbq;
/* If 'rewrite' is TRUE the sink is rewound as far as requested /* If 'rewrite' is TRUE the sink is rewound as far as requested
@ -1206,7 +1208,9 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
* If 'rewrite' is FALSE the sink is rewound as far as requested * If 'rewrite' is FALSE the sink is rewound as far as requested
* and possible and the already rendered data is dropped so that * and possible and the already rendered data is dropped so that
* in the next iteration we read new data from the * in the next iteration we read new data from the
* implementor. This implies 'flush' is TRUE. */ * implementor. This implies 'flush' is TRUE. If
* dont_rewind_render is TRUE then the render memblockq is not
* rewound. */
pa_sink_input_assert_ref(i); pa_sink_input_assert_ref(i);
@ -1219,6 +1223,7 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
return; return;
pa_assert(rewrite || flush); pa_assert(rewrite || flush);
pa_assert(!dont_rewind_render || !rewrite);
/* Calculate how much we can rewind locally without having to /* Calculate how much we can rewind locally without having to
* touch the sink */ * touch the sink */
@ -1253,6 +1258,10 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam
i->thread_info.rewrite_flush || i->thread_info.rewrite_flush ||
(flush && i->thread_info.rewrite_nbytes != 0); (flush && i->thread_info.rewrite_nbytes != 0);
i->thread_info.dont_rewind_render =
i->thread_info.dont_rewind_render ||
dont_rewind_render;
if (nbytes != (size_t) -1) { if (nbytes != (size_t) -1) {
/* Transform to sink domain */ /* Transform to sink domain */

View file

@ -179,8 +179,9 @@ struct pa_sink_input {
/* We maintain a history of resampled audio data here. */ /* We maintain a history of resampled audio data here. */
pa_memblockq *render_memblockq; pa_memblockq *render_memblockq;
/* 0: rewrite nothing, (size_t) -1: rewrite everything, otherwise how many bytes to rewrite */
size_t rewrite_nbytes; size_t rewrite_nbytes;
pa_bool_t rewrite_flush; pa_bool_t rewrite_flush, dont_rewind_render;
uint64_t underrun_for, playing_for; uint64_t underrun_for, playing_for;
pa_sink_input *sync_prev, *sync_next; pa_sink_input *sync_prev, *sync_next;
@ -277,7 +278,7 @@ fully -- or at all. If the request for a rewrite was successful, the
sink driver will call ->rewind() and pass the number of bytes that sink driver will call ->rewind() and pass the number of bytes that
could be rewound in the HW device. This functionality is required for could be rewound in the HW device. This functionality is required for
implementing the "zero latency" write-through functionality. */ implementing the "zero latency" write-through functionality. */
void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t rewrite, pa_bool_t flush); void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t rewrite, pa_bool_t flush, pa_bool_t dont_rewind_render);
void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b); void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b);

View file

@ -133,7 +133,7 @@ static void sink_input_state_change_cb(pa_sink_input *i, pa_sink_input_state_t s
* we are heard right-away. */ * we are heard right-away. */
if (PA_SINK_INPUT_IS_LINKED(state) && if (PA_SINK_INPUT_IS_LINKED(state) &&
i->thread_info.state == PA_SINK_INPUT_INIT) i->thread_info.state == PA_SINK_INPUT_INIT)
pa_sink_input_request_rewind(i, 0, FALSE, TRUE); pa_sink_input_request_rewind(i, 0, FALSE, TRUE, TRUE);
} }
/* Called from IO thread context */ /* Called from IO thread context */