From dfb62062075b672fde2e1e46b044673f441bd22f Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 6 Oct 2022 16:04:15 +0200 Subject: [PATCH] module-rtp: support more formats --- src/modules/module-rtp-sink.c | 70 +++++++++++++-------------------- src/modules/module-rtp-source.c | 34 +++++++++++++--- 2 files changed, 57 insertions(+), 47 deletions(-) diff --git a/src/modules/module-rtp-sink.c b/src/modules/module-rtp-sink.c index f35f092d9..6547d263f 100644 --- a/src/modules/module-rtp-sink.c +++ b/src/modules/module-rtp-sink.c @@ -165,6 +165,26 @@ static const struct spa_dict_item module_info[] = { { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; +static const struct format_info { + uint32_t format; + uint32_t size; + const char *mime; +} format_info[] = { + { SPA_AUDIO_FORMAT_U8, 1, "L8" }, + { SPA_AUDIO_FORMAT_ALAW, 1, "PCMA" }, + { SPA_AUDIO_FORMAT_ULAW, 1, "PCMU" }, + { SPA_AUDIO_FORMAT_S16_BE, 2, "L16" }, + { SPA_AUDIO_FORMAT_S24_BE, 2, "L24" }, +}; + +static const struct format_info *find_format_info(uint32_t format) +{ + SPA_FOR_EACH_ELEMENT_VAR(format_info, f) + if (f->format == format) + return f; + return NULL; +} + struct impl { struct pw_impl_module *module; struct spa_hook module_listener; @@ -209,6 +229,7 @@ struct impl { uint32_t ntp; struct spa_audio_info_raw info; + const struct format_info *format_info; uint32_t frame_size; int payload; uint16_t seq; @@ -222,6 +243,7 @@ struct impl { int sap_fd; }; + static void stream_destroy(void *d) { struct impl *impl = d; @@ -473,7 +495,7 @@ static int get_ip(const struct sockaddr_storage *sa, char *ip, size_t len) static void send_sap(struct impl *impl, bool bye) { char buffer[2048], src_addr[64], dst_addr[64]; - const char *user_name, *af, *fmt; + const char *user_name, *af; struct sockaddr *sa = (struct sockaddr*)&impl->src_addr; struct sap_header header; struct iovec iov[4]; @@ -503,7 +525,6 @@ static void send_sap(struct impl *impl, bool bye) get_ip(&impl->src_addr, src_addr, sizeof(src_addr)); get_ip(&impl->dst_addr, dst_addr, sizeof(dst_addr)); - fmt = "L16"; if ((user_name = pw_get_user_name()) == NULL) user_name = "-"; @@ -522,7 +543,8 @@ static void send_sap(struct impl *impl, bool bye) af, dst_addr, impl->ntp, impl->port, impl->payload, - impl->payload, fmt, impl->info.rate, impl->info.channels); + impl->payload, impl->format_info->mime, + impl->info.rate, impl->info.channels); iov[3].iov_base = buffer; iov[3].iov_len = strlen(buffer); @@ -699,40 +721,6 @@ static void parse_audio_info(const struct pw_properties *props, struct spa_audio 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) { const char *str; @@ -790,9 +778,6 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) if (pw_properties_get(stream_props, PW_KEY_NODE_NETWORK) == NULL) pw_properties_set(stream_props, PW_KEY_NODE_NETWORK, "true"); -// if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL) -// pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); - if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) pw_properties_setf(props, PW_KEY_NODE_NAME, "rtp-sink-%u-%u", pid, id); if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL) @@ -815,13 +800,14 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) parse_audio_info(impl->stream_props, &impl->info); - impl->frame_size = calc_frame_size(&impl->info); - if (impl->frame_size == 0) { + impl->format_info = find_format_info(impl->info.format); + if (impl->format_info == NULL) { pw_log_error("unsupported audio format:%d channels:%d", impl->info.format, impl->info.channels); res = -EINVAL; goto out; } + impl->frame_size = impl->format_info->size * impl->info.channels; impl->msg_id_hash = rand(); impl->ntp = (uint32_t) time(NULL) + 2208988800U; diff --git a/src/modules/module-rtp-source.c b/src/modules/module-rtp-source.c index 95f51550f..f6b0cb7ef 100644 --- a/src/modules/module-rtp-source.c +++ b/src/modules/module-rtp-source.c @@ -150,6 +150,26 @@ struct impl { uint32_t n_sessions; }; +static const struct format_info { + uint32_t format; + uint32_t size; + const char *mime; +} format_info[] = { + { SPA_AUDIO_FORMAT_U8, 1, "L8" }, + { SPA_AUDIO_FORMAT_ALAW, 1, "PCMA" }, + { SPA_AUDIO_FORMAT_ULAW, 1, "PCMU" }, + { SPA_AUDIO_FORMAT_S16_BE, 2, "L16" }, + { SPA_AUDIO_FORMAT_S24_BE, 2, "L24" }, +}; + +static const struct format_info *find_format_info(const char *mime) +{ + SPA_FOR_EACH_ELEMENT_VAR(format_info, f) + if (spa_streq(f->mime, mime)) + return f; + return NULL; +} + struct sdp_info { uint16_t hash; @@ -162,6 +182,7 @@ struct sdp_info { uint16_t port; uint8_t payload; + const struct format_info *format_info; struct spa_audio_info_raw info; uint32_t stride; }; @@ -666,13 +687,16 @@ static int parse_sdp_a(struct impl *impl, char *c, struct sdp_info *info) return 0; c += len; - if (spa_strstartswith(c, "L16/")) { - info->info.format = SPA_AUDIO_FORMAT_S16_BE; - info->stride = 2; - c += 4; - } else + c[strcspn(c, "/")] = 0; + + info->format_info = find_format_info(c); + if (info->format_info == NULL) return -EINVAL; + info->info.format = info->format_info->format; + info->stride = info->format_info->size; + + c += strlen(c) + 1; if (sscanf(c, "%u/%u", &rate, &channels) == 2) { info->info.rate = rate; info->info.channels = channels;