mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-14 06:59:57 -05:00
modules: make sure we deactivate the graph safely
Use the loop lock to ensure the loop is not using the graph anymore when the deactivate or reset it.
This commit is contained in:
parent
3fdcf0d34c
commit
82229b3d87
1 changed files with 64 additions and 12 deletions
|
|
@ -1041,6 +1041,7 @@ struct impl {
|
||||||
struct spa_hook graph_listener;
|
struct spa_hook graph_listener;
|
||||||
uint32_t n_inputs;
|
uint32_t n_inputs;
|
||||||
uint32_t n_outputs;
|
uint32_t n_outputs;
|
||||||
|
bool graph_active;
|
||||||
|
|
||||||
struct spa_latency_info latency[2];
|
struct spa_latency_info latency[2];
|
||||||
struct spa_process_latency_info process_latency;
|
struct spa_process_latency_info process_latency;
|
||||||
|
|
@ -1131,6 +1132,7 @@ static void playback_process(void *d)
|
||||||
pw_log_trace_fp("%p: stride:%d size:%d requested:%"PRIu64" (%"PRIu64")", impl,
|
pw_log_trace_fp("%p: stride:%d size:%d requested:%"PRIu64" (%"PRIu64")", impl,
|
||||||
stride, data_size, out->requested, out->requested * stride);
|
stride, data_size, out->requested, out->requested * stride);
|
||||||
|
|
||||||
|
if (impl->graph_active)
|
||||||
spa_filter_graph_process(impl->graph, cin, cout, data_size / sizeof(float));
|
spa_filter_graph_process(impl->graph, cin, cout, data_size / sizeof(float));
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
@ -1140,6 +1142,62 @@ done:
|
||||||
pw_stream_queue_buffer(impl->playback, out);
|
pw_stream_queue_buffer(impl->playback, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int activate_graph(struct impl *impl)
|
||||||
|
{
|
||||||
|
char rate[64];
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (impl->graph_active)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
snprintf(rate, sizeof(rate), "%lu", impl->rate);
|
||||||
|
res = spa_filter_graph_activate(impl->graph, &SPA_DICT_ITEMS(
|
||||||
|
SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, rate)));
|
||||||
|
|
||||||
|
if (res >= 0) {
|
||||||
|
struct pw_loop *data_loop = pw_stream_get_data_loop(impl->playback);
|
||||||
|
pw_loop_lock(data_loop);
|
||||||
|
impl->graph_active = true;
|
||||||
|
pw_loop_unlock(data_loop);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int deactivate_graph(struct impl *impl)
|
||||||
|
{
|
||||||
|
struct pw_loop *data_loop;
|
||||||
|
|
||||||
|
if (!impl->graph_active)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
data_loop = pw_stream_get_data_loop(impl->playback);
|
||||||
|
|
||||||
|
pw_loop_lock(data_loop);
|
||||||
|
impl->graph_active = false;
|
||||||
|
pw_loop_unlock(data_loop);
|
||||||
|
|
||||||
|
return spa_filter_graph_deactivate(impl->graph);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_graph(struct impl *impl)
|
||||||
|
{
|
||||||
|
struct pw_loop *data_loop = pw_stream_get_data_loop(impl->playback);
|
||||||
|
int res;
|
||||||
|
bool old_active = impl->graph_active;
|
||||||
|
|
||||||
|
pw_loop_lock(data_loop);
|
||||||
|
impl->graph_active = false;
|
||||||
|
pw_loop_unlock(data_loop);
|
||||||
|
|
||||||
|
res = spa_filter_graph_reset(impl->graph);
|
||||||
|
|
||||||
|
pw_loop_lock(data_loop);
|
||||||
|
impl->graph_active = old_active;
|
||||||
|
pw_loop_unlock(data_loop);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
static void update_latencies(struct impl *impl)
|
static void update_latencies(struct impl *impl)
|
||||||
{
|
{
|
||||||
struct spa_latency_info latency;
|
struct spa_latency_info latency;
|
||||||
|
|
@ -1249,7 +1307,6 @@ static void io_changed(void *data, uint32_t id, void *area, uint32_t size)
|
||||||
static void param_changed(struct impl *impl, uint32_t id, const struct spa_pod *param,
|
static void param_changed(struct impl *impl, uint32_t id, const struct spa_pod *param,
|
||||||
enum spa_direction direction, struct pw_stream *stream, struct pw_stream *other)
|
enum spa_direction direction, struct pw_stream *stream, struct pw_stream *other)
|
||||||
{
|
{
|
||||||
struct spa_filter_graph *graph = impl->graph;
|
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
|
@ -1260,7 +1317,7 @@ static void param_changed(struct impl *impl, uint32_t id, const struct spa_pod *
|
||||||
if (param == NULL) {
|
if (param == NULL) {
|
||||||
pw_log_info("module %p: filter deactivate", impl);
|
pw_log_info("module %p: filter deactivate", impl);
|
||||||
if (direction == SPA_DIRECTION_INPUT)
|
if (direction == SPA_DIRECTION_INPUT)
|
||||||
spa_filter_graph_deactivate(graph);
|
deactivate_graph(impl);
|
||||||
impl->rate = 0;
|
impl->rate = 0;
|
||||||
} else {
|
} else {
|
||||||
if ((res = spa_format_audio_raw_parse(param, &info)) < 0)
|
if ((res = spa_format_audio_raw_parse(param, &info)) < 0)
|
||||||
|
|
@ -1309,13 +1366,12 @@ static void playback_state_changed(void *data, enum pw_stream_state old,
|
||||||
enum pw_stream_state state, const char *error)
|
enum pw_stream_state state, const char *error)
|
||||||
{
|
{
|
||||||
struct impl *impl = data;
|
struct impl *impl = data;
|
||||||
struct spa_filter_graph *graph = impl->graph;
|
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case PW_STREAM_STATE_PAUSED:
|
case PW_STREAM_STATE_PAUSED:
|
||||||
pw_stream_flush(impl->playback, false);
|
pw_stream_flush(impl->playback, false);
|
||||||
spa_filter_graph_reset(graph);
|
reset_graph(impl);
|
||||||
break;
|
break;
|
||||||
case PW_STREAM_STATE_UNCONNECTED:
|
case PW_STREAM_STATE_UNCONNECTED:
|
||||||
pw_log_info("module %p: unconnected", impl);
|
pw_log_info("module %p: unconnected", impl);
|
||||||
|
|
@ -1335,15 +1391,11 @@ static void playback_state_changed(void *data, enum pw_stream_state old,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (impl->rate != target) {
|
if (impl->rate != target) {
|
||||||
char rate[64];
|
|
||||||
impl->rate = target;
|
impl->rate = target;
|
||||||
snprintf(rate, sizeof(rate), "%lu", impl->rate);
|
deactivate_graph(impl);
|
||||||
spa_filter_graph_deactivate(graph);
|
|
||||||
if ((res = spa_filter_graph_activate(graph,
|
|
||||||
&SPA_DICT_ITEMS(
|
|
||||||
SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, rate)))) < 0)
|
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
|
if ((res = activate_graph(impl)) < 0)
|
||||||
|
goto error;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue