mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
adapter: pass follower direction to converter
Partially revert 86af9de739
The PortParam does not give enough information to derive the direction
of the converter. If the converter is configured in convert/convert
there is just no way to know when to output a quantum or not.
Fix this by doing a quick probe of the follower and then pass the
direction to the converter.
See !2227
This commit is contained in:
parent
4b24619160
commit
d2c2276088
2 changed files with 44 additions and 10 deletions
|
|
@ -1413,6 +1413,20 @@ static const struct spa_node_events follower_node_events = {
|
||||||
.event = follower_event,
|
.event = follower_event,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void follower_probe_info(void *data, const struct spa_node_info *info)
|
||||||
|
{
|
||||||
|
struct impl *this = data;
|
||||||
|
if (info->max_input_ports > 0)
|
||||||
|
this->direction = SPA_DIRECTION_INPUT;
|
||||||
|
else
|
||||||
|
this->direction = SPA_DIRECTION_OUTPUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct spa_node_events follower_probe_events = {
|
||||||
|
SPA_VERSION_NODE_EVENTS,
|
||||||
|
.info = follower_probe_info,
|
||||||
|
};
|
||||||
|
|
||||||
static int follower_ready(void *data, int status)
|
static int follower_ready(void *data, int status)
|
||||||
{
|
{
|
||||||
struct impl *this = data;
|
struct impl *this = data;
|
||||||
|
|
@ -1775,23 +1789,36 @@ static int load_converter(struct impl *this, const struct spa_dict *info,
|
||||||
struct spa_handle *hnd_convert = NULL;
|
struct spa_handle *hnd_convert = NULL;
|
||||||
void *iface_conv = NULL;
|
void *iface_conv = NULL;
|
||||||
bool unload_handle = false;
|
bool unload_handle = false;
|
||||||
|
struct spa_dict_item *items;
|
||||||
|
struct spa_dict cinfo;
|
||||||
|
char direction[16];
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
if (info)
|
items = alloca((info->n_items + 1) * sizeof(struct spa_dict_item));
|
||||||
factory_name = spa_dict_lookup(info, "audio.adapt.converter");
|
cinfo = SPA_DICT(items, 0);
|
||||||
|
for (i = 0; i < info->n_items; i++)
|
||||||
|
items[cinfo.n_items++] = info->items[i];
|
||||||
|
|
||||||
|
snprintf(direction, sizeof(direction), "%s",
|
||||||
|
SPA_DIRECTION_REVERSE(this->direction) == SPA_DIRECTION_INPUT ?
|
||||||
|
"input" : "output");
|
||||||
|
items[cinfo.n_items++] = SPA_DICT_ITEM("convert.direction", direction);
|
||||||
|
|
||||||
|
factory_name = spa_dict_lookup(&cinfo, "audio.adapt.converter");
|
||||||
if (factory_name == NULL)
|
if (factory_name == NULL)
|
||||||
factory_name = SPA_NAME_AUDIO_CONVERT;
|
factory_name = SPA_NAME_AUDIO_CONVERT;
|
||||||
|
|
||||||
if (spa_streq(factory_name, SPA_NAME_AUDIO_CONVERT)) {
|
if (spa_streq(factory_name, SPA_NAME_AUDIO_CONVERT)) {
|
||||||
size_t size = spa_handle_factory_get_size(&spa_audioconvert_factory, info);
|
size_t size = spa_handle_factory_get_size(&spa_audioconvert_factory, &cinfo);
|
||||||
|
|
||||||
hnd_convert = calloc(1, size);
|
hnd_convert = calloc(1, size);
|
||||||
if (hnd_convert == NULL)
|
if (hnd_convert == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
spa_handle_factory_init(&spa_audioconvert_factory,
|
spa_handle_factory_init(&spa_audioconvert_factory,
|
||||||
hnd_convert, info, support, n_support);
|
hnd_convert, &cinfo, support, n_support);
|
||||||
} else if (this->ploader) {
|
} else if (this->ploader) {
|
||||||
hnd_convert = spa_plugin_loader_load(this->ploader, factory_name, info);
|
hnd_convert = spa_plugin_loader_load(this->ploader, factory_name, &cinfo);
|
||||||
if (!hnd_convert)
|
if (!hnd_convert)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
unload_handle = true;
|
unload_handle = true;
|
||||||
|
|
@ -1973,6 +2000,7 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
struct impl *this;
|
struct impl *this;
|
||||||
const char *str;
|
const char *str;
|
||||||
int ret;
|
int ret;
|
||||||
|
struct spa_hook probe_listener;
|
||||||
|
|
||||||
spa_return_val_if_fail(factory != NULL, -EINVAL);
|
spa_return_val_if_fail(factory != NULL, -EINVAL);
|
||||||
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
||||||
|
|
@ -2007,6 +2035,11 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
SPA_VERSION_NODE,
|
SPA_VERSION_NODE,
|
||||||
&impl_node, this);
|
&impl_node, this);
|
||||||
|
|
||||||
|
/* just probe the ports to get the direction */
|
||||||
|
spa_zero(probe_listener);
|
||||||
|
spa_node_add_listener(this->follower, &probe_listener, &follower_probe_events, this);
|
||||||
|
spa_hook_remove(&probe_listener);
|
||||||
|
|
||||||
ret = load_converter(this, info, support, n_support);
|
ret = load_converter(this, info, support, n_support);
|
||||||
spa_log_info(this->log, "%p: loaded converter %s, hnd %p, convert %p", this,
|
spa_log_info(this->log, "%p: loaded converter %s, hnd %p, convert %p", this,
|
||||||
this->convertname, this->hnd_convert, this->convert);
|
this->convertname, this->hnd_convert, this->convert);
|
||||||
|
|
|
||||||
|
|
@ -1646,11 +1646,6 @@ static int reconfigure_mode(struct impl *this, enum spa_param_port_config_mode m
|
||||||
i = dir->n_ports++;
|
i = dir->n_ports++;
|
||||||
init_port(this, direction, i, 0, false, false, true);
|
init_port(this, direction, i, 0, false, false, true);
|
||||||
}
|
}
|
||||||
/* when output is convert mode, we are in OUTPUT (merge) mode, we always output all
|
|
||||||
* the incoming data to output. When output is DSP, we need to output quantum size
|
|
||||||
* chunks. */
|
|
||||||
this->direction = this->dir[SPA_DIRECTION_OUTPUT].mode == SPA_PARAM_PORT_CONFIG_MODE_convert ?
|
|
||||||
SPA_DIRECTION_OUTPUT : SPA_DIRECTION_INPUT;
|
|
||||||
|
|
||||||
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS | SPA_NODE_CHANGE_MASK_PARAMS;
|
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS | SPA_NODE_CHANGE_MASK_PARAMS;
|
||||||
this->info.flags &= ~SPA_NODE_FLAG_NEED_CONFIGURE;
|
this->info.flags &= ~SPA_NODE_FLAG_NEED_CONFIGURE;
|
||||||
|
|
@ -4060,6 +4055,12 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
else if (spa_streq(k, "resample.prefill"))
|
else if (spa_streq(k, "resample.prefill"))
|
||||||
SPA_FLAG_UPDATE(this->resample.options,
|
SPA_FLAG_UPDATE(this->resample.options,
|
||||||
RESAMPLE_OPTION_PREFILL, spa_atob(s));
|
RESAMPLE_OPTION_PREFILL, spa_atob(s));
|
||||||
|
else if (spa_streq(k, "convert.direction")) {
|
||||||
|
if (spa_streq(s, "output"))
|
||||||
|
this->direction = SPA_DIRECTION_OUTPUT;
|
||||||
|
else
|
||||||
|
this->direction = SPA_DIRECTION_INPUT;
|
||||||
|
}
|
||||||
else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
|
else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) {
|
||||||
if (s != NULL)
|
if (s != NULL)
|
||||||
spa_audio_parse_position(s, strlen(s), this->props.channel_map,
|
spa_audio_parse_position(s, strlen(s), this->props.channel_map,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue