filter-chain: instantiate graph when starting

Don't instantiate the graph when negotiated but when starting. This
allows us to get to the target graph rate in case the format rate is
supposed to follow the graph rate.

See #2969
This commit is contained in:
Wim Taymans 2023-06-28 12:04:07 +02:00
parent e03c3311eb
commit e3a41b2c49

View file

@ -518,6 +518,8 @@ static const struct spa_dict_item module_props[] = {
#define MAX_HNDL 64 #define MAX_HNDL 64
#define MAX_SAMPLES 8192 #define MAX_SAMPLES 8192
#define DEFAULT_RATE 48000
static float silence_data[MAX_SAMPLES]; static float silence_data[MAX_SAMPLES];
static float discard_data[MAX_SAMPLES]; static float discard_data[MAX_SAMPLES];
@ -656,6 +658,10 @@ struct impl {
struct spa_hook playback_listener; struct spa_hook playback_listener;
struct spa_audio_info_raw playback_info; struct spa_audio_info_raw playback_info;
struct spa_audio_info_raw info;
struct spa_io_position *position;
unsigned int do_disconnect:1; unsigned int do_disconnect:1;
long unsigned rate; long unsigned rate;
@ -858,7 +864,7 @@ static struct spa_pod *get_prop_info(struct graph *graph, struct spa_pod_builder
struct fc_port *p = &d->ports[port->p]; struct fc_port *p = &d->ports[port->p];
float def, min, max; float def, min, max;
char name[512]; char name[512];
uint32_t rate = impl->rate ? impl->rate : 48000; uint32_t rate = impl->rate ? impl->rate : DEFAULT_RATE;
if (p->hint & FC_HINT_SAMPLE_RATE) { if (p->hint & FC_HINT_SAMPLE_RATE) {
def = p->def * rate; def = p->def * rate;
@ -1107,6 +1113,7 @@ static void state_changed(void *data, enum pw_stream_state old,
{ {
struct impl *impl = data; struct impl *impl = data;
struct graph *graph = &impl->graph; struct graph *graph = &impl->graph;
int res;
switch (state) { switch (state) {
case PW_STREAM_STATE_PAUSED: case PW_STREAM_STATE_PAUSED:
@ -1121,6 +1128,40 @@ static void state_changed(void *data, enum pw_stream_state old,
case PW_STREAM_STATE_ERROR: case PW_STREAM_STATE_ERROR:
pw_log_info("module %p: error: %s", impl, error); pw_log_info("module %p: error: %s", impl, error);
break; break;
case PW_STREAM_STATE_STREAMING:
{
uint32_t target = impl->info.rate;
if (target == 0)
target = impl->position ?
impl->position->clock.target_rate.denom : DEFAULT_RATE;
if (target == 0) {
res = -EINVAL;
goto error;
}
if (impl->rate != target) {
impl->rate = target;
graph_cleanup(graph);
if ((res = graph_instantiate(graph)) < 0)
goto error;
}
break;
}
default:
break;
}
return;
error:
pw_stream_set_error(impl->capture, res, "can't start graph: %s",
spa_strerror(res));
}
static void io_changed(void *data, uint32_t id, void *area, uint32_t size)
{
struct impl *impl = data;
switch (id) {
case SPA_IO_Position:
impl->position = area;
break;
default: default:
break; break;
} }
@ -1134,22 +1175,19 @@ static void param_changed(void *data, uint32_t id, const struct spa_pod *param)
switch (id) { switch (id) {
case SPA_PARAM_Format: case SPA_PARAM_Format:
{
struct spa_audio_info_raw info;
spa_zero(info);
if (param == NULL) { if (param == NULL) {
graph_cleanup(graph); graph_cleanup(graph);
} else { } else {
struct spa_audio_info_raw info;
spa_zero(info);
if ((res = spa_format_audio_raw_parse(param, &info)) < 0) if ((res = spa_format_audio_raw_parse(param, &info)) < 0)
goto error; goto error;
if (info.rate == 0) {
res = -EINVAL;
goto error;
}
impl->rate = info.rate;
if ((res = graph_instantiate(graph)) < 0)
goto error;
} }
impl->info = info;
impl->rate = 0;
break; break;
}
case SPA_PARAM_Props: case SPA_PARAM_Props:
if (param != NULL) if (param != NULL)
param_props_changed(impl, param); param_props_changed(impl, param);
@ -1169,6 +1207,7 @@ static const struct pw_stream_events in_stream_events = {
PW_VERSION_STREAM_EVENTS, PW_VERSION_STREAM_EVENTS,
.destroy = capture_destroy, .destroy = capture_destroy,
.process = capture_process, .process = capture_process,
.io_changed = io_changed,
.state_changed = state_changed, .state_changed = state_changed,
.param_changed = param_changed .param_changed = param_changed
}; };
@ -1184,8 +1223,9 @@ static const struct pw_stream_events out_stream_events = {
PW_VERSION_STREAM_EVENTS, PW_VERSION_STREAM_EVENTS,
.destroy = playback_destroy, .destroy = playback_destroy,
.process = playback_process, .process = playback_process,
.io_changed = io_changed,
.state_changed = state_changed, .state_changed = state_changed,
.param_changed = param_changed .param_changed = param_changed,
}; };
static int setup_streams(struct impl *impl) static int setup_streams(struct impl *impl)