module-rtp: support more formats

This commit is contained in:
Wim Taymans 2022-10-06 16:04:15 +02:00
parent da44be28cf
commit dfb6206207
2 changed files with 57 additions and 47 deletions

View file

@ -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;

View file

@ -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;