From c8b8b24a9ccff93fad8f48379b70f44418d0b129 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 23 Jun 2022 12:39:51 +0200 Subject: [PATCH] modules: fix format parsing Use the same logic for parsing the format. --- src/modules/module-echo-cancel.c | 18 +++--- src/modules/module-example-sink.c | 95 +++++++++++++++------------- src/modules/module-example-source.c | 95 +++++++++++++++------------- src/modules/module-filter-chain.c | 5 +- src/modules/module-loopback.c | 1 + src/modules/module-pipe-tunnel.c | 48 ++++++++------- src/modules/module-pulse-tunnel.c | 30 ++++----- src/modules/module-raop-sink.c | 96 ++++++++++++++++------------- 8 files changed, 210 insertions(+), 178 deletions(-) diff --git a/src/modules/module-echo-cancel.c b/src/modules/module-echo-cancel.c index 8d1205a2a..17ef2b09b 100644 --- a/src/modules/module-echo-cancel.c +++ b/src/modules/module-echo-cancel.c @@ -125,6 +125,10 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic +#define DEFAULT_RATE 48000 +#define DEFAULT_CHANNELS 2 +#define DEFAULT_POSITION "[ FL FR ]" + /* Hopefully this is enough for any combination of AEC engine and resampler * input requirement for rate matching */ #define MAX_BUFSIZE_MS 100 @@ -859,9 +863,15 @@ static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_ *info = SPA_AUDIO_INFO_RAW_INIT( .format = SPA_AUDIO_FORMAT_F32P); info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate); + if (info->rate == 0) + info->rate = DEFAULT_RATE; + info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) parse_position(info, str, strlen(str)); + if (info->channels == 0) + parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION)); } static void copy_props(struct impl *impl, struct pw_properties *props, const char *key) @@ -927,14 +937,6 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) parse_audio_info(props, &impl->info); - if (impl->info.channels == 0) { - impl->info.channels = 2; - impl->info.position[0] = SPA_AUDIO_CHANNEL_FL; - impl->info.position[1] = SPA_AUDIO_CHANNEL_FR; - } - if (impl->info.rate == 0) - impl->info.rate = 48000; - if ((str = pw_properties_get(props, "source.props")) != NULL) pw_properties_update_string(impl->source_props, str, strlen(str)); if ((str = pw_properties_get(props, "sink.props")) != NULL) diff --git a/src/modules/module-example-sink.c b/src/modules/module-example-sink.c index 1d5face87..dcb574a96 100644 --- a/src/modules/module-example-sink.c +++ b/src/modules/module-example-sink.c @@ -107,7 +107,7 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); "[ node.description= ] " \ "[ audio.format= ] " \ "[ audio.rate= ] " \ - "[ audio.channels= ] " \ + "[ audio.channels= ] " \ "[ audio.position= ] " \ "[ stream.props= ] " @@ -340,56 +340,59 @@ static void parse_position(struct spa_audio_info_raw *info, const char *val, siz } } -static int parse_audio_info(struct impl *impl) +static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - struct pw_properties *props = impl->stream_props; - struct spa_audio_info_raw *info = &impl->info; const char *str; spa_zero(*info); - if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) == NULL) str = DEFAULT_FORMAT; info->format = format_from_name(str, strlen(str)); - switch (info->format) { - case SPA_AUDIO_FORMAT_S8: - case SPA_AUDIO_FORMAT_U8: - impl->frame_size = 1; - break; - case SPA_AUDIO_FORMAT_S16: - impl->frame_size = 2; - break; - case SPA_AUDIO_FORMAT_S24: - impl->frame_size = 3; - break; - case SPA_AUDIO_FORMAT_S24_32: - case SPA_AUDIO_FORMAT_S32: - case SPA_AUDIO_FORMAT_F32: - impl->frame_size = 4; - break; - case SPA_AUDIO_FORMAT_F64: - impl->frame_size = 8; - break; - default: - pw_log_error("unsupported format '%s'", str); - return -EINVAL; - } - info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, DEFAULT_RATE); - if (info->rate == 0) { - pw_log_error("invalid rate '%s'", str); - return -EINVAL; - } - info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, DEFAULT_CHANNELS); - if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) == NULL) - str = DEFAULT_POSITION; - parse_position(info, str, strlen(str)); - if (info->channels == 0) { - pw_log_error("invalid channels '%s'", str); - return -EINVAL; - } - impl->frame_size *= info->channels; - return 0; + info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate); + if (info->rate == 0) + info->rate = DEFAULT_RATE; + + info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); + if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) + parse_position(info, str, strlen(str)); + if (info->channels == 0) + parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION)); +} + +static int calc_frame_size(const struct spa_audio_info_raw *info) +{ + int res = info->channels; + switch (info->format) { + case SPA_AUDIO_FORMAT_U8: + case SPA_AUDIO_FORMAT_S8: + case SPA_AUDIO_FORMAT_ALAW: + case SPA_AUDIO_FORMAT_ULAW: + return res; + case SPA_AUDIO_FORMAT_S16: + case SPA_AUDIO_FORMAT_S16_OE: + case SPA_AUDIO_FORMAT_U16: + return res * 2; + case SPA_AUDIO_FORMAT_S24: + case SPA_AUDIO_FORMAT_S24_OE: + case SPA_AUDIO_FORMAT_U24: + return res * 3; + case SPA_AUDIO_FORMAT_S24_32: + case SPA_AUDIO_FORMAT_S24_32_OE: + case SPA_AUDIO_FORMAT_S32: + case SPA_AUDIO_FORMAT_S32_OE: + case SPA_AUDIO_FORMAT_U32: + case SPA_AUDIO_FORMAT_U32_OE: + case SPA_AUDIO_FORMAT_F32: + case SPA_AUDIO_FORMAT_F32_OE: + return res * 4; + case SPA_AUDIO_FORMAT_F64: + case SPA_AUDIO_FORMAT_F64_OE: + return res * 8; + default: + return 0; + } } static void copy_props(struct impl *impl, struct pw_properties *props, const char *key) @@ -467,7 +470,11 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_MEDIA_CLASS); - if ((res = parse_audio_info(impl)) < 0) { + parse_audio_info(impl->stream_props, &impl->info); + + impl->frame_size = calc_frame_size(&impl->info); + if (impl->frame_size == 0) { + res = -EINVAL; pw_log_error( "can't parse audio format"); goto error; } diff --git a/src/modules/module-example-source.c b/src/modules/module-example-source.c index 2b480538f..ea1e714a2 100644 --- a/src/modules/module-example-source.c +++ b/src/modules/module-example-source.c @@ -107,7 +107,7 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); "[ node.description= ] " \ "[ audio.format= ] " \ "[ audio.rate= ] " \ - "[ audio.channels= ] " \ + "[ audio.channels= ] " \ "[ audio.position= ] " \ "[ stream.props= ] " @@ -344,56 +344,59 @@ static void parse_position(struct spa_audio_info_raw *info, const char *val, siz } } -static int parse_audio_info(struct impl *impl) +static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - struct pw_properties *props = impl->stream_props; - struct spa_audio_info_raw *info = &impl->info; const char *str; spa_zero(*info); - if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) == NULL) str = DEFAULT_FORMAT; info->format = format_from_name(str, strlen(str)); - switch (info->format) { - case SPA_AUDIO_FORMAT_S8: - case SPA_AUDIO_FORMAT_U8: - impl->frame_size = 1; - break; - case SPA_AUDIO_FORMAT_S16: - impl->frame_size = 2; - break; - case SPA_AUDIO_FORMAT_S24: - impl->frame_size = 3; - break; - case SPA_AUDIO_FORMAT_S24_32: - case SPA_AUDIO_FORMAT_S32: - case SPA_AUDIO_FORMAT_F32: - impl->frame_size = 4; - break; - case SPA_AUDIO_FORMAT_F64: - impl->frame_size = 8; - break; - default: - pw_log_error("unsupported format '%s'", str); - return -EINVAL; - } - info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, DEFAULT_RATE); - if (info->rate == 0) { - pw_log_error("invalid rate '%s'", str); - return -EINVAL; - } - info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, DEFAULT_CHANNELS); - if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) == NULL) - str = DEFAULT_POSITION; - parse_position(info, str, strlen(str)); - if (info->channels == 0) { - pw_log_error("invalid channels '%s'", str); - return -EINVAL; - } - impl->frame_size *= info->channels; - return 0; + info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate); + if (info->rate == 0) + info->rate = DEFAULT_RATE; + + info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); + if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) + parse_position(info, str, strlen(str)); + if (info->channels == 0) + parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION)); +} + +static int calc_frame_size(const struct spa_audio_info_raw *info) +{ + int res = info->channels; + switch (info->format) { + case SPA_AUDIO_FORMAT_U8: + case SPA_AUDIO_FORMAT_S8: + case SPA_AUDIO_FORMAT_ALAW: + case SPA_AUDIO_FORMAT_ULAW: + return res; + case SPA_AUDIO_FORMAT_S16: + case SPA_AUDIO_FORMAT_S16_OE: + case SPA_AUDIO_FORMAT_U16: + return res * 2; + case SPA_AUDIO_FORMAT_S24: + case SPA_AUDIO_FORMAT_S24_OE: + case SPA_AUDIO_FORMAT_U24: + return res * 3; + case SPA_AUDIO_FORMAT_S24_32: + case SPA_AUDIO_FORMAT_S24_32_OE: + case SPA_AUDIO_FORMAT_S32: + case SPA_AUDIO_FORMAT_S32_OE: + case SPA_AUDIO_FORMAT_U32: + case SPA_AUDIO_FORMAT_U32_OE: + case SPA_AUDIO_FORMAT_F32: + case SPA_AUDIO_FORMAT_F32_OE: + return res * 4; + case SPA_AUDIO_FORMAT_F64: + case SPA_AUDIO_FORMAT_F64_OE: + return res * 8; + default: + return 0; + } } static void copy_props(struct impl *impl, struct pw_properties *props, const char *key) @@ -471,7 +474,11 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_MEDIA_CLASS); - if ((res = parse_audio_info(impl)) < 0) { + parse_audio_info(impl->stream_props, &impl->info); + + impl->frame_size = calc_frame_size(&impl->info); + if (impl->frame_size == 0) { + res = -EINVAL; pw_log_error( "can't parse audio format"); goto error; } diff --git a/src/modules/module-filter-chain.c b/src/modules/module-filter-chain.c index cbfb3830b..5031aee7c 100644 --- a/src/modules/module-filter-chain.c +++ b/src/modules/module-filter-chain.c @@ -2097,8 +2097,9 @@ static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_ *info = SPA_AUDIO_INFO_RAW_INIT( .format = SPA_AUDIO_FORMAT_F32P); - info->rate = pw_properties_get_int32(props, PW_KEY_AUDIO_RATE, 0); - info->channels = pw_properties_get_int32(props, PW_KEY_AUDIO_CHANNELS, 0); + info->rate = pw_properties_get_int32(props, PW_KEY_AUDIO_RATE, info->rate); + info->channels = pw_properties_get_int32(props, PW_KEY_AUDIO_CHANNELS, info->channels); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) parse_position(info, str, strlen(str)); } diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c index 543ee3d81..a005f76f4 100644 --- a/src/modules/module-loopback.c +++ b/src/modules/module-loopback.c @@ -453,6 +453,7 @@ static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_ .format = SPA_AUDIO_FORMAT_F32P); info->rate = pw_properties_get_int32(props, PW_KEY_AUDIO_RATE, 0); info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, 0); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) parse_position(info, str, strlen(str)); } diff --git a/src/modules/module-pipe-tunnel.c b/src/modules/module-pipe-tunnel.c index 8210d0885..d317ec741 100644 --- a/src/modules/module-pipe-tunnel.c +++ b/src/modules/module-pipe-tunnel.c @@ -107,6 +107,7 @@ * tunnel.mode = playback * # Set the pipe name to tunnel to * pipe.filename = "/tmp/fifo_output" + * #audio.format= * #audio.rate= * #audio.channels= * #audio.position= @@ -125,6 +126,11 @@ #define DEFAULT_CAPTURE_FILENAME "/tmp/fifo_input" #define DEFAULT_PLAYBACK_FILENAME "/tmp/fifo_output" +#define DEFAULT_FORMAT "S16" +#define DEFAULT_RATE 48000 +#define DEFAULT_CHANNELS 2 +#define DEFAULT_POSITION "[ FL FR ]" + PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic @@ -133,6 +139,7 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); "[ node.name= ] " \ "[ node.description= ] " \ "[ node.target= ] " \ + "[ audio.format= ] " \ "[ audio.rate= ] " \ "[ audio.channels= ] " \ "[ audio.position= ] " \ @@ -511,31 +518,28 @@ static inline uint32_t format_from_name(const char *name, size_t len) return SPA_AUDIO_FORMAT_UNKNOWN; } -static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { const char *str; - *info = SPA_AUDIO_INFO_RAW_INIT( - .rate = 48000, - .channels = 2, - .format = SPA_AUDIO_FORMAT_S16); - - if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) != NULL) { - uint32_t id; - - id = format_from_name(str, strlen(str)); - if (id != SPA_AUDIO_FORMAT_UNKNOWN) - info->format = id; - } + spa_zero(*info); + if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) == NULL) + str = DEFAULT_FORMAT; + info->format = format_from_name(str, strlen(str)); info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate); + if (info->rate == 0) + info->rate = DEFAULT_RATE; + info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) parse_position(info, str, strlen(str)); - + if (info->channels == 0) + parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION)); } -static int calc_frame_size(struct spa_audio_info_raw *info) +static int calc_frame_size(const struct spa_audio_info_raw *info) { int res = info->channels; switch (info->format) { @@ -662,13 +666,6 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) parse_audio_info(impl->stream_props, &impl->info); - if (impl->info.rate != 0 && - pw_properties_get(props, PW_KEY_NODE_RATE) == NULL) - pw_properties_setf(props, PW_KEY_NODE_RATE, - "1/%u", impl->info.rate), - - copy_props(impl, props, PW_KEY_NODE_RATE); - impl->frame_size = calc_frame_size(&impl->info); if (impl->frame_size == 0) { pw_log_error("unsupported audio format:%d channels:%d", @@ -676,6 +673,13 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) res = -EINVAL; goto error; } + if (impl->info.rate != 0 && + pw_properties_get(props, PW_KEY_NODE_RATE) == NULL) + pw_properties_setf(props, PW_KEY_NODE_RATE, + "1/%u", impl->info.rate), + + copy_props(impl, props, PW_KEY_NODE_RATE); + impl->leftover = calloc(1, impl->frame_size); if (impl->leftover == NULL) { res = -errno; diff --git a/src/modules/module-pulse-tunnel.c b/src/modules/module-pulse-tunnel.c index a8a641e9c..05ebf67e1 100644 --- a/src/modules/module-pulse-tunnel.c +++ b/src/modules/module-pulse-tunnel.c @@ -118,6 +118,11 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic +#define DEFAULT_FORMAT "S16" +#define DEFAULT_RATE 48000 +#define DEFAULT_CHANNELS 2 +#define DEFAULT_POSITION "[ FL FR ]" + #define MODULE_USAGE "[ remote.name= ] " \ "[ node.latency= ] " \ "[ node.name= ] " \ @@ -823,28 +828,25 @@ static inline uint32_t format_from_name(const char *name, size_t len) return SPA_AUDIO_FORMAT_UNKNOWN; } -static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { const char *str; - *info = SPA_AUDIO_INFO_RAW_INIT( - .rate = 48000, - .channels = 2, - .format = SPA_AUDIO_FORMAT_S16); - - if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) != NULL) { - uint32_t id; - - id = format_from_name(str, strlen(str)); - if (id != SPA_AUDIO_FORMAT_UNKNOWN) - info->format = id; - } + spa_zero(*info); + if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) == NULL) + str = DEFAULT_FORMAT; + info->format = format_from_name(str, strlen(str)); info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate); + if (info->rate == 0) + info->rate = DEFAULT_RATE; + info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) parse_position(info, str, strlen(str)); - + if (info->channels == 0) + parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION)); } static int calc_frame_size(struct spa_audio_info_raw *info) diff --git a/src/modules/module-raop-sink.c b/src/modules/module-raop-sink.c index 1914f72ac..9e6b38860 100644 --- a/src/modules/module-raop-sink.c +++ b/src/modules/module-raop-sink.c @@ -1484,56 +1484,59 @@ static void parse_position(struct spa_audio_info_raw *info, const char *val, siz } } -static int parse_audio_info(struct impl *impl) +static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - struct pw_properties *props = impl->stream_props; - struct spa_audio_info_raw *info = &impl->info; const char *str; spa_zero(*info); - if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) == NULL) str = DEFAULT_FORMAT; info->format = format_from_name(str, strlen(str)); - switch (info->format) { - case SPA_AUDIO_FORMAT_S8: - case SPA_AUDIO_FORMAT_U8: - impl->frame_size = 1; - break; - case SPA_AUDIO_FORMAT_S16: - impl->frame_size = 2; - break; - case SPA_AUDIO_FORMAT_S24: - impl->frame_size = 3; - break; - case SPA_AUDIO_FORMAT_S24_32: - case SPA_AUDIO_FORMAT_S32: - case SPA_AUDIO_FORMAT_F32: - impl->frame_size = 4; - break; - case SPA_AUDIO_FORMAT_F64: - impl->frame_size = 8; - break; - default: - pw_log_error("unsupported format '%s'", str); - return -EINVAL; - } - info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, DEFAULT_RATE); - if (info->rate == 0) { - pw_log_error("invalid rate '%s'", str); - return -EINVAL; - } - info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, DEFAULT_CHANNELS); - if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) == NULL) - str = DEFAULT_POSITION; - parse_position(info, str, strlen(str)); - if (info->channels == 0) { - pw_log_error("invalid channels '%s'", str); - return -EINVAL; - } - impl->frame_size *= info->channels; - return 0; + info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate); + if (info->rate == 0) + info->rate = DEFAULT_RATE; + + info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); + if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) + parse_position(info, str, strlen(str)); + if (info->channels == 0) + parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION)); +} + +static int calc_frame_size(struct spa_audio_info_raw *info) +{ + int res = info->channels; + switch (info->format) { + case SPA_AUDIO_FORMAT_U8: + case SPA_AUDIO_FORMAT_S8: + case SPA_AUDIO_FORMAT_ALAW: + case SPA_AUDIO_FORMAT_ULAW: + return res; + case SPA_AUDIO_FORMAT_S16: + case SPA_AUDIO_FORMAT_S16_OE: + case SPA_AUDIO_FORMAT_U16: + return res * 2; + case SPA_AUDIO_FORMAT_S24: + case SPA_AUDIO_FORMAT_S24_OE: + case SPA_AUDIO_FORMAT_U24: + return res * 3; + case SPA_AUDIO_FORMAT_S24_32: + case SPA_AUDIO_FORMAT_S24_32_OE: + case SPA_AUDIO_FORMAT_S32: + case SPA_AUDIO_FORMAT_S32_OE: + case SPA_AUDIO_FORMAT_U32: + case SPA_AUDIO_FORMAT_U32_OE: + case SPA_AUDIO_FORMAT_F32: + case SPA_AUDIO_FORMAT_F32_OE: + return res * 4; + case SPA_AUDIO_FORMAT_F64: + case SPA_AUDIO_FORMAT_F64_OE: + return res * 8; + default: + return 0; + } } static void copy_props(struct impl *impl, struct pw_properties *props, const char *key) @@ -1617,8 +1620,13 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_MEDIA_CLASS); - if ((res = parse_audio_info(impl)) < 0) { - pw_log_error( "can't parse audio format"); + parse_audio_info(impl->stream_props, &impl->info); + + impl->frame_size = calc_frame_size(&impl->info); + if (impl->frame_size == 0) { + pw_log_error("unsupported audio format:%d channels:%d", + impl->info.format, impl->info.channels); + res = -EINVAL; goto error; }