From 8616f82a67fa031ba224c6d23fa70c31724ef853 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Sun, 6 Nov 2011 18:20:01 +0530 Subject: [PATCH] sink-input,source-output: Add an update_rate() function This factors out the resampler updating code from finish_move() and makes a separate function for use from other points. --- src/pulsecore/sink-input.c | 121 +++++++++++++++++++--------------- src/pulsecore/sink-input.h | 1 + src/pulsecore/source-output.c | 118 +++++++++++++++++++-------------- src/pulsecore/source-output.h | 1 + 4 files changed, 136 insertions(+), 105 deletions(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index a64defa4..fbede019 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -1596,8 +1596,6 @@ static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) { /* Called from main context */ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { - pa_resampler *new_resampler; - pa_sink_input_assert_ref(i); pa_assert_ctl_context(); pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); @@ -1633,34 +1631,6 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { dest->sample_spec.rate); } - if (i->thread_info.resampler && - pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &dest->sample_spec) && - pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &dest->channel_map)) - - /* Try to reuse the old resampler if possible */ - new_resampler = i->thread_info.resampler; - - else if (!pa_sink_input_is_passthrough(i) && - ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) || - !pa_sample_spec_equal(&i->sample_spec, &dest->sample_spec) || - !pa_channel_map_equal(&i->channel_map, &dest->channel_map))) { - - /* Okay, we need a new resampler for the new sink */ - - if (!(new_resampler = pa_resampler_new( - i->core->mempool, - &i->sample_spec, &i->channel_map, - &dest->sample_spec, &dest->channel_map, - i->requested_resample_method, - ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | - ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | - (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { - pa_log_warn("Unsupported resampling operation."); - return -PA_ERR_NOTSUPPORTED; - } - } else - new_resampler = NULL; - if (i->moving) i->moving(i, dest); @@ -1673,30 +1643,7 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) { if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED) i->sink->n_corked++; - /* Replace resampler and render queue */ - if (new_resampler != i->thread_info.resampler) { - char *memblockq_name; - - if (i->thread_info.resampler) - pa_resampler_free(i->thread_info.resampler); - i->thread_info.resampler = new_resampler; - - pa_memblockq_free(i->thread_info.render_memblockq); - - memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index); - i->thread_info.render_memblockq = pa_memblockq_new( - memblockq_name, - 0, - MEMBLOCKQ_MAXLENGTH, - 0, - &i->sink->sample_spec, - 0, - 1, - 0, - &i->sink->silence); - pa_xfree(memblockq_name); - i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID; - } + pa_sink_input_update_rate(i); pa_sink_update_status(dest); @@ -2043,3 +1990,69 @@ finish: if (pl) pa_proplist_free(pl); } + +/* Called from main context */ +/* Updates the sink input's resampler with whatever the current sink requires + * -- useful when the underlying sink's rate might have changed */ +int pa_sink_input_update_rate(pa_sink_input *i) { + pa_resampler *new_resampler; + char *memblockq_name; + + pa_sink_input_assert_ref(i); + pa_assert_ctl_context(); + + if (i->thread_info.resampler && + pa_sample_spec_equal(pa_resampler_output_sample_spec(i->thread_info.resampler), &i->sink->sample_spec) && + pa_channel_map_equal(pa_resampler_output_channel_map(i->thread_info.resampler), &i->sink->channel_map)) + + new_resampler = i->thread_info.resampler; + + else if (!pa_sink_input_is_passthrough(i) && + ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) || + !pa_sample_spec_equal(&i->sample_spec, &i->sink->sample_spec) || + !pa_channel_map_equal(&i->channel_map, &i->sink->channel_map))) { + + new_resampler = pa_resampler_new(i->core->mempool, + &i->sample_spec, &i->channel_map, + &i->sink->sample_spec, &i->sink->channel_map, + i->requested_resample_method, + ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | + ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | + (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)); + + if (!new_resampler) { + pa_log_warn("Unsupported resampling operation."); + return -PA_ERR_NOTSUPPORTED; + } + } else + new_resampler = NULL; + + if (new_resampler == i->thread_info.resampler) + return 0; + + if (i->thread_info.resampler) + pa_resampler_free(i->thread_info.resampler); + + i->thread_info.resampler = new_resampler; + + pa_memblockq_free(i->thread_info.render_memblockq); + + memblockq_name = pa_sprintf_malloc("sink input render_memblockq [%u]", i->index); + i->thread_info.render_memblockq = pa_memblockq_new( + memblockq_name, + 0, + MEMBLOCKQ_MAXLENGTH, + 0, + &i->sink->sample_spec, + 0, + 1, + 0, + &i->sink->silence); + pa_xfree(memblockq_name); + + i->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID; + + pa_log_debug("Updated resmpler for sink input %d", i->index); + + return 0; +} diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 8d286da8..af2177a2 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -338,6 +338,7 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes, pa_bool_t rew void pa_sink_input_cork(pa_sink_input *i, pa_bool_t b); int pa_sink_input_set_rate(pa_sink_input *i, uint32_t rate); +int pa_sink_input_update_rate(pa_sink_input *i); /* This returns the sink's fields converted into out sample type */ size_t pa_sink_input_get_max_rewind(pa_sink_input *i); diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 21e8da97..47b93a93 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -1376,8 +1376,6 @@ static void update_volume_due_to_moving(pa_source_output *o, pa_source *dest) { /* Called from main context */ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t save) { - pa_resampler *new_resampler; - pa_source_output_assert_ref(o); pa_assert_ctl_context(); pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state)); @@ -1413,34 +1411,6 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t dest->sample_spec.rate); } - if (o->thread_info.resampler && - pa_sample_spec_equal(pa_resampler_input_sample_spec(o->thread_info.resampler), &dest->sample_spec) && - pa_channel_map_equal(pa_resampler_input_channel_map(o->thread_info.resampler), &dest->channel_map)) - - /* Try to reuse the old resampler if possible */ - new_resampler = o->thread_info.resampler; - - else if (!pa_source_output_is_passthrough(o) && - ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) || - !pa_sample_spec_equal(&o->sample_spec, &dest->sample_spec) || - !pa_channel_map_equal(&o->channel_map, &dest->channel_map))) { - - /* Okay, we need a new resampler for the new source */ - - if (!(new_resampler = pa_resampler_new( - o->core->mempool, - &dest->sample_spec, &dest->channel_map, - &o->sample_spec, &o->channel_map, - o->requested_resample_method, - ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | - ((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | - (o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)))) { - pa_log_warn("Unsupported resampling operation."); - return -PA_ERR_NOTSUPPORTED; - } - } else - new_resampler = NULL; - if (o->moving) o->moving(o, dest); @@ -1453,27 +1423,7 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED) o->source->n_corked++; - /* Replace resampler */ - if (new_resampler != o->thread_info.resampler) { - - if (o->thread_info.resampler) - pa_resampler_free(o->thread_info.resampler); - o->thread_info.resampler = new_resampler; - - pa_memblockq_free(o->thread_info.delay_memblockq); - - o->thread_info.delay_memblockq = pa_memblockq_new( - "source output delay_memblockq", - 0, - MEMBLOCKQ_MAXLENGTH, - 0, - &o->source->sample_spec, - 0, - 1, - 0, - &o->source->silence); - o->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID; - } + pa_source_output_update_rate(o); pa_source_update_status(dest); @@ -1646,3 +1596,69 @@ finish: if (pl) pa_proplist_free(pl); } + +/* Called from main context */ +/* Updates the source output's resampler with whatever the current source + * requires -- useful when the underlying source's rate might have changed */ +int pa_source_output_update_rate(pa_source_output *o) { + pa_resampler *new_resampler; + char *memblockq_name; + + pa_source_output_assert_ref(o); + pa_assert_ctl_context(); + + if (o->thread_info.resampler && + pa_sample_spec_equal(pa_resampler_input_sample_spec(o->thread_info.resampler), &o->source->sample_spec) && + pa_channel_map_equal(pa_resampler_input_channel_map(o->thread_info.resampler), &o->source->channel_map)) + + new_resampler = o->thread_info.resampler; + + else if (!pa_source_output_is_passthrough(o) && + ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) || + !pa_sample_spec_equal(&o->sample_spec, &o->source->sample_spec) || + !pa_channel_map_equal(&o->channel_map, &o->source->channel_map))) { + + new_resampler = pa_resampler_new(o->core->mempool, + &o->source->sample_spec, &o->source->channel_map, + &o->sample_spec, &o->channel_map, + o->requested_resample_method, + ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) | + ((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) | + (o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0)); + + if (!new_resampler) { + pa_log_warn("Unsupported resampling operation."); + return -PA_ERR_NOTSUPPORTED; + } + } else + new_resampler = NULL; + + if (new_resampler == o->thread_info.resampler) + return 0; + + if (o->thread_info.resampler) + pa_resampler_free(o->thread_info.resampler); + + o->thread_info.resampler = new_resampler; + + pa_memblockq_free(o->thread_info.delay_memblockq); + + memblockq_name = pa_sprintf_malloc("source output delay_memblockq [%u]", o->index); + o->thread_info.delay_memblockq = pa_memblockq_new( + memblockq_name, + 0, + MEMBLOCKQ_MAXLENGTH, + 0, + &o->source->sample_spec, + 0, + 1, + 0, + &o->source->silence); + pa_xfree(memblockq_name); + + o->actual_resample_method = new_resampler ? pa_resampler_get_method(new_resampler) : PA_RESAMPLER_INVALID; + + pa_log_debug("Updated resmpler for source output %d", o->index); + + return 0; +} diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 31263d4a..e60430f6 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -301,6 +301,7 @@ pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t void pa_source_output_cork(pa_source_output *o, pa_bool_t b); int pa_source_output_set_rate(pa_source_output *o, uint32_t rate); +int pa_source_output_update_rate(pa_source_output *o); size_t pa_source_output_get_max_rewind(pa_source_output *o); -- 2.39.2