From ef71c1319a2f1e97bcf741bc430f58d2bc4db048 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 25 Jan 2024 22:25:19 +1100 Subject: [PATCH] webrtcbin: Improve SDP intersection for Opus Remove optional sprop-stereo and sprop-maxcapture fields from Opus remote offer caps before intersecting with local codec preferences. According to https://datatracker.ietf.org/doc/html/rfc7587#section-7.1 those fields are sender-only informative, and don't affect interoperability. Fixes cases where the webrtc media will end up receive-only if the local side wants to send stereo but the remote is sending mono, or vice versa. There may be other fields in other codecs, so the implementation anticipates needing to add further fields and codecs in the future. Part-of: --- .../gst-plugins-bad/ext/webrtc/gstwebrtcbin.c | 2 ++ .../gst-plugins-bad/ext/webrtc/utils.c | 25 +++++++++++++++++++ .../gst-plugins-bad/ext/webrtc/utils.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c index 1f728e386c..a38ff85ef6 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/gstwebrtcbin.c @@ -4542,6 +4542,8 @@ _create_answer_task (GstWebRTCBin * webrtc, const GstStructure * options, gst_sdp_media_set_proto (media, "UDP/TLS/RTP/SAVPF"); offer_caps = _rtp_caps_from_media (offer_media); + _remove_optional_offer_fields (offer_caps); + if (last_answer && i < gst_sdp_message_medias_len (last_answer) && (rtp_trans = _find_transceiver_for_mid (webrtc, mid))) { const GstSDPMedia *last_media = diff --git a/subprojects/gst-plugins-bad/ext/webrtc/utils.c b/subprojects/gst-plugins-bad/ext/webrtc/utils.c index f0741d1e55..e3552b3814 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/utils.c +++ b/subprojects/gst-plugins-bad/ext/webrtc/utils.c @@ -170,6 +170,31 @@ _g_checksum_to_webrtc_string (GChecksumType type) } } +void +_remove_optional_offer_fields (GstCaps * offer_caps) +{ + int i; + + for (i = 0; i < gst_caps_get_size (offer_caps); i++) { + GstStructure *s = gst_caps_get_structure (offer_caps, i); + const gchar *mtype = gst_structure_get_string (s, "media"); + const gchar *encoding_name = gst_structure_get_string (s, "encoding-name"); + + if (mtype == NULL || encoding_name == NULL) { + continue; + } + + /* Special cases for different codecs - sender-only fields + * that we don't need to care about for SDP intersection */ + if (g_str_equal (mtype, "audio")) { + if (g_str_equal (encoding_name, "OPUS")) { + gst_structure_remove_fields (s, "sprop-stereo", "sprop-maxcapturerate", + NULL); + } + } + } +} + GstCaps * _rtp_caps_from_media (const GstSDPMedia * media) { diff --git a/subprojects/gst-plugins-bad/ext/webrtc/utils.h b/subprojects/gst-plugins-bad/ext/webrtc/utils.h index e5d3d124ab..bcbe906a73 100644 --- a/subprojects/gst-plugins-bad/ext/webrtc/utils.h +++ b/subprojects/gst-plugins-bad/ext/webrtc/utils.h @@ -63,6 +63,8 @@ const gchar * _enum_value_to_string (GType type, guint val G_GNUC_INTERNAL const gchar * _g_checksum_to_webrtc_string (GChecksumType type); G_GNUC_INTERNAL +void _remove_optional_offer_fields (GstCaps *offer_caps); +G_GNUC_INTERNAL GstCaps * _rtp_caps_from_media (const GstSDPMedia * media); G_GNUC_INTERNAL GstWebRTCKind webrtc_kind_from_caps (const GstCaps * caps);