mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-04 13:29:59 -05:00
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.
This commit is contained in:
parent
75573435a0
commit
8616f82a67
4 changed files with 136 additions and 105 deletions
|
|
@ -1596,8 +1596,6 @@ static void update_volume_due_to_moving(pa_sink_input *i, pa_sink *dest) {
|
||||||
|
|
||||||
/* Called from main context */
|
/* Called from main context */
|
||||||
int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
|
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_sink_input_assert_ref(i);
|
||||||
pa_assert_ctl_context();
|
pa_assert_ctl_context();
|
||||||
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
|
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);
|
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)
|
if (i->moving)
|
||||||
i->moving(i, dest);
|
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)
|
if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
|
||||||
i->sink->n_corked++;
|
i->sink->n_corked++;
|
||||||
|
|
||||||
/* Replace resampler and render queue */
|
pa_sink_input_update_rate(i);
|
||||||
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_update_status(dest);
|
pa_sink_update_status(dest);
|
||||||
|
|
||||||
|
|
@ -2043,3 +1990,69 @@ finish:
|
||||||
if (pl)
|
if (pl)
|
||||||
pa_proplist_free(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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
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_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 */
|
/* This returns the sink's fields converted into out sample type */
|
||||||
size_t pa_sink_input_get_max_rewind(pa_sink_input *i);
|
size_t pa_sink_input_get_max_rewind(pa_sink_input *i);
|
||||||
|
|
|
||||||
|
|
@ -1376,8 +1376,6 @@ static void update_volume_due_to_moving(pa_source_output *o, pa_source *dest) {
|
||||||
|
|
||||||
/* Called from main context */
|
/* Called from main context */
|
||||||
int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t save) {
|
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_source_output_assert_ref(o);
|
||||||
pa_assert_ctl_context();
|
pa_assert_ctl_context();
|
||||||
pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state));
|
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);
|
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)
|
if (o->moving)
|
||||||
o->moving(o, dest);
|
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)
|
if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED)
|
||||||
o->source->n_corked++;
|
o->source->n_corked++;
|
||||||
|
|
||||||
/* Replace resampler */
|
pa_source_output_update_rate(o);
|
||||||
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_update_status(dest);
|
pa_source_update_status(dest);
|
||||||
|
|
||||||
|
|
@ -1646,3 +1596,69 @@ finish:
|
||||||
if (pl)
|
if (pl)
|
||||||
pa_proplist_free(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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
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_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);
|
size_t pa_source_output_get_max_rewind(pa_source_output *o);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue