From 356a8d159606652c447220e047160c38acaa85ad Mon Sep 17 00:00:00 2001 From: ziyue <1213642868@qq.com> Date: Wed, 31 Mar 2021 18:32:43 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E9=83=A8=E5=88=86answer?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- webrtc/CMakeLists.txt | 2 +- webrtc/Sdp.cpp | 105 ++++++++++++++++++++++-- webrtc/Sdp.h | 18 ++--- webrtc/offer-simulcast.sdp | 156 +++++++++++++++++++++++++++++++++++ webrtc/offer.sdp | 161 +++++++++++++++++++++++++++++++++++++ 5 files changed, 423 insertions(+), 19 deletions(-) create mode 100644 webrtc/offer-simulcast.sdp create mode 100644 webrtc/offer.sdp diff --git a/webrtc/CMakeLists.txt b/webrtc/CMakeLists.txt index 03039aea..db7dd3a8 100644 --- a/webrtc/CMakeLists.txt +++ b/webrtc/CMakeLists.txt @@ -10,7 +10,7 @@ else () endif () include_directories(./) -file(GLOB SRC_LIST ./*.*) +file(GLOB SRC_LIST ./*.cpp ./*.h ./*.hpp) add_library(webrtc ${SRC_LIST}) set(LINK_LIB_LIST ${LINK_LIB_LIST} PARENT_SCOPE) diff --git a/webrtc/Sdp.cpp b/webrtc/Sdp.cpp index 5f40da33..ccedc67f 100644 --- a/webrtc/Sdp.cpp +++ b/webrtc/Sdp.cpp @@ -3,12 +3,9 @@ // #include "Sdp.h" -#include "assert.h" #include "Common/Parser.h" #include -#define CHECK(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__); - using onCreateSdpItem = function; static map sdpItemCreator; @@ -1148,7 +1145,6 @@ void RtcConfigure::RtcTrackConfigure::setDefaultSetting(TrackType type){ void RtcConfigure::setDefaultSetting(string ice_ufrag, string ice_pwd, - DtlsRole role, RtpDirection direction, const SdpAttrFingerprint &fingerprint) { video.setDefaultSetting(TrackVideo); @@ -1157,9 +1153,9 @@ void RtcConfigure::setDefaultSetting(string ice_ufrag, video.ice_ufrag = audio.ice_ufrag = application.ice_ufrag = ice_ufrag; video.ice_pwd = audio.ice_pwd = application.ice_pwd = ice_ufrag; - video.role = audio.role = application.role = role; video.direction = audio.direction = application.direction = direction; video.fingerprint = audio.fingerprint = application.fingerprint = fingerprint; + application.enable = false; } void RtcConfigure::addCandidate(const SdpAttrCandidate &candidate, TrackType type) { @@ -1203,5 +1199,100 @@ shared_ptr RtcConfigure::createOffer(){ } shared_ptr RtcConfigure::createAnswer(const RtcSession &offer){ - return nullptr; -} \ No newline at end of file + shared_ptr ret = std::make_shared(); + ret->version = offer.version; + ret->origin.parse("- 0 0 IN IP4 0.0.0.0"); + ret->session_name = "zlmediakit_webrtc_session"; + ret->session_info = "zlmediakit_webrtc_session"; + ret->connection.parse("IN IP4 0.0.0.0"); + ret->msid_semantic.parse("WMS *"); + matchMedia(ret, TrackVideo, offer.media, video); + matchMedia(ret, TrackAudio, offer.media, audio); + matchMedia(ret, TrackApplication, offer.media, application); + return ret; +} + +void RtcConfigure::matchMedia(shared_ptr &ret, TrackType type, const vector &medias, const RtcTrackConfigure &configure){ + if (!configure.enable) { + return; + } + for (auto &codec : configure.preferred_codec) { + for (auto &media : medias) { + if (media.type != type) { + continue; + } + if (media.ice_lite && configure.ice_lite) { + WarnL << "offer sdp开启了ice_lite模式,但是answer sdp配置为不支持"; + continue; + } + + const RtcCodecPlan *plan_ptr = nullptr; + for (auto &plan : media.plan) { + if (getCodecId(plan.codec) != codec) { + continue; + } + //命中偏好的编码格式 + if (!onMatchCodecPlan(plan, codec)) { + continue; + } + plan_ptr = &plan; + } + if (!plan_ptr) { + continue; + } + RtcMedia answer_media; + answer_media.type = media.type; + answer_media.mid = media.type; + answer_media.proto = media.proto; + answer_media.rtcp_mux = media.rtcp_mux && configure.rtcp_mux; + answer_media.rtcp_rsize = media.rtcp_rsize && configure.rtcp_rsize; + answer_media.ice_trickle = media.ice_trickle && configure.ice_trickle; + answer_media.ice_renomination = media.ice_renomination && configure.ice_renomination; + switch (media.role) { + case DtlsRole::actpass : { + answer_media.role = DtlsRole::passive; + break; + } + case DtlsRole::active : { + answer_media.role = DtlsRole::passive; + break; + } + case DtlsRole::passive : { + answer_media.role = DtlsRole::active; + break; + } + default: continue; + } + + switch (media.direction) { + case RtpDirection::sendonly : { + if (configure.direction != RtpDirection::recvonly && + configure.direction != RtpDirection::sendrecv) { + //我们不支持接收 + continue; + } + answer_media.direction = RtpDirection::recvonly; + break; + } + case RtpDirection::recvonly : { + if (configure.direction != RtpDirection::sendonly && + configure.direction != RtpDirection::sendrecv) { + //我们不支持发送 + continue; + } + answer_media.direction = RtpDirection::sendonly; + break; + } + case RtpDirection::sendrecv : { + //对方支持发送接收,那么最终能力根据配置来决定 + answer_media.direction = configure.direction; + break; + } + default: continue; + } + answer_media.plan.emplace_back(*plan_ptr); + ret->media.emplace_back(answer_media); + } + } + +} diff --git a/webrtc/Sdp.h b/webrtc/Sdp.h index a3ef62bc..602ce691 100644 --- a/webrtc/Sdp.h +++ b/webrtc/Sdp.h @@ -7,10 +7,13 @@ #include #include +#include "assert.h" #include "Extension/Frame.h" using namespace std; using namespace mediakit; +#define CHECK(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__); + //https://datatracker.ietf.org/doc/rfc4566/?include_text=1 //https://blog.csdn.net/aggresss/article/details/109850434 //https://aggresss.blog.csdn.net/article/details/106436703 @@ -545,15 +548,6 @@ public: ////////////////////////////////////////////////////////////////// -//ssrc类型 -enum class RtcSSRCType { - rtp = 0, - rtx, - sim_low, - sim_mid, - ssrc_high -}; - //ssrc相关信息 class RtcSSRC{ public: @@ -672,7 +666,6 @@ public: string ice_ufrag; string ice_pwd; - DtlsRole role{DtlsRole::invalid}; RtpDirection direction{RtpDirection::invalid}; SdpAttrFingerprint fingerprint; @@ -690,13 +683,16 @@ public: void setDefaultSetting(string ice_ufrag, string ice_pwd, - DtlsRole role, RtpDirection direction, const SdpAttrFingerprint &fingerprint); void addCandidate(const SdpAttrCandidate &candidate, TrackType type = TrackInvalid); shared_ptr createOffer(); shared_ptr createAnswer(const RtcSession &offer); + +private: + void matchMedia(shared_ptr &ret, TrackType type, const vector &medias, const RtcTrackConfigure &configure); + bool onMatchCodecPlan(const RtcCodecPlan &plan, CodecId codec) { return true; } }; diff --git a/webrtc/offer-simulcast.sdp b/webrtc/offer-simulcast.sdp new file mode 100644 index 00000000..91701061 --- /dev/null +++ b/webrtc/offer-simulcast.sdp @@ -0,0 +1,156 @@ +v=0 +o=- 99044479296054817 2 IN IP4 127.0.0.1 +s=- +t=0 0 +a=group:BUNDLE 0 1 +a=extmap-allow-mixed +a=msid-semantic: WMS +m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126 +c=IN IP4 0.0.0.0 +a=rtcp:9 IN IP4 0.0.0.0 +a=ice-ufrag:s95k +a=ice-pwd:JFAzK9rInMLPOosVj4Z7lC+Q +a=ice-options:trickle +a=fingerprint:sha-256 50:76:BB:FA:A8:D3:B7:19:81:C7:8D:19:60:C7:A9:7E:0E:5F:AA:3F:FE:68:60:98:B1:93:95:BC:A9:29:E4:D1 +a=setup:actpass +a=mid:0 +a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id +a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id +a=sendrecv +a=msid:- 83e7b60d-ce8f-4d7d-a7b9-d2209747bf55 +a=rtcp-mux +a=rtpmap:111 opus/48000/2 +a=rtcp-fb:111 transport-cc +a=fmtp:111 minptime=10;useinbandfec=1 +a=rtpmap:103 ISAC/16000 +a=rtpmap:104 ISAC/32000 +a=rtpmap:9 G722/8000 +a=rtpmap:0 PCMU/8000 +a=rtpmap:8 PCMA/8000 +a=rtpmap:106 CN/32000 +a=rtpmap:105 CN/16000 +a=rtpmap:13 CN/8000 +a=rtpmap:110 telephone-event/48000 +a=rtpmap:112 telephone-event/32000 +a=rtpmap:113 telephone-event/16000 +a=rtpmap:126 telephone-event/8000 +a=ssrc:1320289824 cname:YOYQAT5W3y5SSliB +a=ssrc:1320289824 msid:- 83e7b60d-ce8f-4d7d-a7b9-d2209747bf55 +a=ssrc:1320289824 mslabel:- +a=ssrc:1320289824 label:83e7b60d-ce8f-4d7d-a7b9-d2209747bf55 +m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 121 127 120 125 107 108 109 124 119 123 118 114 115 116 +c=IN IP4 0.0.0.0 +a=rtcp:9 IN IP4 0.0.0.0 +a=ice-ufrag:s95k +a=ice-pwd:JFAzK9rInMLPOosVj4Z7lC+Q +a=ice-options:trickle +a=fingerprint:sha-256 50:76:BB:FA:A8:D3:B7:19:81:C7:8D:19:60:C7:A9:7E:0E:5F:AA:3F:FE:68:60:98:B1:93:95:BC:A9:29:E4:D1 +a=setup:actpass +a=mid:1 +a=extmap:14 urn:ietf:params:rtp-hdrext:toffset +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time +a=extmap:13 urn:3gpp:video-orientation +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 +a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay +a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type +a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing +a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id +a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id +a=sendrecv +a=msid:- cd8e4810-dadf-4f11-8799-eed2560fe196 +a=rtcp-mux +a=rtcp-rsize +a=rtpmap:96 VP8/90000 +a=rtcp-fb:96 goog-remb +a=rtcp-fb:96 transport-cc +a=rtcp-fb:96 ccm fir +a=rtcp-fb:96 nack +a=rtcp-fb:96 nack pli +a=rtpmap:97 rtx/90000 +a=fmtp:97 apt=96 +a=rtpmap:98 VP9/90000 +a=rtcp-fb:98 goog-remb +a=rtcp-fb:98 transport-cc +a=rtcp-fb:98 ccm fir +a=rtcp-fb:98 nack +a=rtcp-fb:98 nack pli +a=fmtp:98 profile-id=0 +a=rtpmap:99 rtx/90000 +a=fmtp:99 apt=98 +a=rtpmap:100 VP9/90000 +a=rtcp-fb:100 goog-remb +a=rtcp-fb:100 transport-cc +a=rtcp-fb:100 ccm fir +a=rtcp-fb:100 nack +a=rtcp-fb:100 nack pli +a=fmtp:100 profile-id=2 +a=rtpmap:101 rtx/90000 +a=fmtp:101 apt=100 +a=rtpmap:102 H264/90000 +a=rtcp-fb:102 goog-remb +a=rtcp-fb:102 transport-cc +a=rtcp-fb:102 ccm fir +a=rtcp-fb:102 nack +a=rtcp-fb:102 nack pli +a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f +a=rtpmap:121 rtx/90000 +a=fmtp:121 apt=102 +a=rtpmap:127 H264/90000 +a=rtcp-fb:127 goog-remb +a=rtcp-fb:127 transport-cc +a=rtcp-fb:127 ccm fir +a=rtcp-fb:127 nack +a=rtcp-fb:127 nack pli +a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f +a=rtpmap:120 rtx/90000 +a=fmtp:120 apt=127 +a=rtpmap:125 H264/90000 +a=rtcp-fb:125 goog-remb +a=rtcp-fb:125 transport-cc +a=rtcp-fb:125 ccm fir +a=rtcp-fb:125 nack +a=rtcp-fb:125 nack pli +a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f +a=rtpmap:107 rtx/90000 +a=fmtp:107 apt=125 +a=rtpmap:108 H264/90000 +a=rtcp-fb:108 goog-remb +a=rtcp-fb:108 transport-cc +a=rtcp-fb:108 ccm fir +a=rtcp-fb:108 nack +a=rtcp-fb:108 nack pli +a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f +a=rtpmap:109 rtx/90000 +a=fmtp:109 apt=108 +a=rtpmap:124 H264/90000 +a=rtcp-fb:124 goog-remb +a=rtcp-fb:124 transport-cc +a=rtcp-fb:124 ccm fir +a=rtcp-fb:124 nack +a=rtcp-fb:124 nack pli +a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f +a=rtpmap:119 rtx/90000 +a=fmtp:119 apt=124 +a=rtpmap:123 H264/90000 +a=rtcp-fb:123 goog-remb +a=rtcp-fb:123 transport-cc +a=rtcp-fb:123 ccm fir +a=rtcp-fb:123 nack +a=rtcp-fb:123 nack pli +a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f +a=rtpmap:118 rtx/90000 +a=fmtp:118 apt=123 +a=rtpmap:114 red/90000 +a=rtpmap:115 rtx/90000 +a=fmtp:115 apt=114 +a=rtpmap:116 ulpfec/90000 +a=rid:q send +a=rid:h send +a=rid:f send +a=simulcast:send q;h;f \ No newline at end of file diff --git a/webrtc/offer.sdp b/webrtc/offer.sdp new file mode 100644 index 00000000..762150d8 --- /dev/null +++ b/webrtc/offer.sdp @@ -0,0 +1,161 @@ +v=0 +o=- 257973874652185302 2 IN IP4 127.0.0.1 +s=- +t=0 0 +a=group:BUNDLE 0 1 +a=extmap-allow-mixed +a=msid-semantic: WMS +m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126 +c=IN IP4 0.0.0.0 +a=rtcp:9 IN IP4 0.0.0.0 +a=ice-ufrag:w2IN +a=ice-pwd:X7kCoPoI2NqW8kxuV9LHRR78 +a=ice-options:trickle +a=fingerprint:sha-256 7A:A7:A4:9A:BC:37:64:68:9C:48:E5:E9:9B:97:BD:88:17:3E:E5:44:29:4D:6D:BB:AB:2C:85:B8:DE:7A:15:B1 +a=setup:actpass +a=mid:0 +a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id +a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id +a=sendrecv +a=msid:- 56049f63-4b19-45c4-aa0a-8895049b5430 +a=rtcp-mux +a=rtpmap:111 opus/48000/2 +a=rtcp-fb:111 transport-cc +a=fmtp:111 minptime=10;useinbandfec=1 +a=rtpmap:103 ISAC/16000 +a=rtpmap:104 ISAC/32000 +a=rtpmap:9 G722/8000 +a=rtpmap:0 PCMU/8000 +a=rtpmap:8 PCMA/8000 +a=rtpmap:106 CN/32000 +a=rtpmap:105 CN/16000 +a=rtpmap:13 CN/8000 +a=rtpmap:110 telephone-event/48000 +a=rtpmap:112 telephone-event/32000 +a=rtpmap:113 telephone-event/16000 +a=rtpmap:126 telephone-event/8000 +a=ssrc:3304267696 cname:sCv+hHL1+2UbfMTB +a=ssrc:3304267696 msid:- 56049f63-4b19-45c4-aa0a-8895049b5430 +a=ssrc:3304267696 mslabel:- +a=ssrc:3304267696 label:56049f63-4b19-45c4-aa0a-8895049b5430 +m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 121 127 120 125 107 108 109 124 119 123 118 114 115 116 +c=IN IP4 0.0.0.0 +a=rtcp:9 IN IP4 0.0.0.0 +a=ice-ufrag:w2IN +a=ice-pwd:X7kCoPoI2NqW8kxuV9LHRR78 +a=ice-options:trickle +a=fingerprint:sha-256 7A:A7:A4:9A:BC:37:64:68:9C:48:E5:E9:9B:97:BD:88:17:3E:E5:44:29:4D:6D:BB:AB:2C:85:B8:DE:7A:15:B1 +a=setup:actpass +a=mid:1 +a=extmap:14 urn:ietf:params:rtp-hdrext:toffset +a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time +a=extmap:13 urn:3gpp:video-orientation +a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01 +a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay +a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type +a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing +a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space +a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid +a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id +a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id +a=sendrecv +a=msid:- a73b3f5f-007a-4a46-ac8b-582ca7fee460 +a=rtcp-mux +a=rtcp-rsize +a=rtpmap:96 VP8/90000 +a=rtcp-fb:96 goog-remb +a=rtcp-fb:96 transport-cc +a=rtcp-fb:96 ccm fir +a=rtcp-fb:96 nack +a=rtcp-fb:96 nack pli +a=rtpmap:97 rtx/90000 +a=fmtp:97 apt=96 +a=rtpmap:98 VP9/90000 +a=rtcp-fb:98 goog-remb +a=rtcp-fb:98 transport-cc +a=rtcp-fb:98 ccm fir +a=rtcp-fb:98 nack +a=rtcp-fb:98 nack pli +a=fmtp:98 profile-id=0 +a=rtpmap:99 rtx/90000 +a=fmtp:99 apt=98 +a=rtpmap:100 VP9/90000 +a=rtcp-fb:100 goog-remb +a=rtcp-fb:100 transport-cc +a=rtcp-fb:100 ccm fir +a=rtcp-fb:100 nack +a=rtcp-fb:100 nack pli +a=fmtp:100 profile-id=2 +a=rtpmap:101 rtx/90000 +a=fmtp:101 apt=100 +a=rtpmap:102 H264/90000 +a=rtcp-fb:102 goog-remb +a=rtcp-fb:102 transport-cc +a=rtcp-fb:102 ccm fir +a=rtcp-fb:102 nack +a=rtcp-fb:102 nack pli +a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f +a=rtpmap:121 rtx/90000 +a=fmtp:121 apt=102 +a=rtpmap:127 H264/90000 +a=rtcp-fb:127 goog-remb +a=rtcp-fb:127 transport-cc +a=rtcp-fb:127 ccm fir +a=rtcp-fb:127 nack +a=rtcp-fb:127 nack pli +a=fmtp:127 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42001f +a=rtpmap:120 rtx/90000 +a=fmtp:120 apt=127 +a=rtpmap:125 H264/90000 +a=rtcp-fb:125 goog-remb +a=rtcp-fb:125 transport-cc +a=rtcp-fb:125 ccm fir +a=rtcp-fb:125 nack +a=rtcp-fb:125 nack pli +a=fmtp:125 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f +a=rtpmap:107 rtx/90000 +a=fmtp:107 apt=125 +a=rtpmap:108 H264/90000 +a=rtcp-fb:108 goog-remb +a=rtcp-fb:108 transport-cc +a=rtcp-fb:108 ccm fir +a=rtcp-fb:108 nack +a=rtcp-fb:108 nack pli +a=fmtp:108 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f +a=rtpmap:109 rtx/90000 +a=fmtp:109 apt=108 +a=rtpmap:124 H264/90000 +a=rtcp-fb:124 goog-remb +a=rtcp-fb:124 transport-cc +a=rtcp-fb:124 ccm fir +a=rtcp-fb:124 nack +a=rtcp-fb:124 nack pli +a=fmtp:124 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=4d001f +a=rtpmap:119 rtx/90000 +a=fmtp:119 apt=124 +a=rtpmap:123 H264/90000 +a=rtcp-fb:123 goog-remb +a=rtcp-fb:123 transport-cc +a=rtcp-fb:123 ccm fir +a=rtcp-fb:123 nack +a=rtcp-fb:123 nack pli +a=fmtp:123 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=64001f +a=rtpmap:118 rtx/90000 +a=fmtp:118 apt=123 +a=rtpmap:114 red/90000 +a=rtpmap:115 rtx/90000 +a=fmtp:115 apt=114 +a=rtpmap:116 ulpfec/90000 +a=ssrc-group:FID 1128910219 3552306261 +a=ssrc:1128910219 cname:sCv+hHL1+2UbfMTB +a=ssrc:1128910219 msid:- a73b3f5f-007a-4a46-ac8b-582ca7fee460 +a=ssrc:1128910219 mslabel:- +a=ssrc:1128910219 label:a73b3f5f-007a-4a46-ac8b-582ca7fee460 +a=ssrc:3552306261 cname:sCv+hHL1+2UbfMTB +a=ssrc:3552306261 msid:- a73b3f5f-007a-4a46-ac8b-582ca7fee460 +a=ssrc:3552306261 mslabel:- +a=ssrc:3552306261 label:a73b3f5f-007a-4a46-ac8b-582ca7fee460 \ No newline at end of file