实现部分answer代码

This commit is contained in:
ziyue 2021-03-31 18:32:43 +08:00
parent 7e5cb33395
commit 356a8d1596
5 changed files with 423 additions and 19 deletions

View File

@ -10,7 +10,7 @@ else ()
endif () endif ()
include_directories(./) include_directories(./)
file(GLOB SRC_LIST ./*.*) file(GLOB SRC_LIST ./*.cpp ./*.h ./*.hpp)
add_library(webrtc ${SRC_LIST}) add_library(webrtc ${SRC_LIST})
set(LINK_LIB_LIST ${LINK_LIB_LIST} PARENT_SCOPE) set(LINK_LIB_LIST ${LINK_LIB_LIST} PARENT_SCOPE)

View File

@ -3,12 +3,9 @@
// //
#include "Sdp.h" #include "Sdp.h"
#include "assert.h"
#include "Common/Parser.h" #include "Common/Parser.h"
#include <inttypes.h> #include <inttypes.h>
#define CHECK(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__);
using onCreateSdpItem = function<SdpItem::Ptr(const string &key, const string &value)>; using onCreateSdpItem = function<SdpItem::Ptr(const string &key, const string &value)>;
static map<string, onCreateSdpItem, StrCaseCompare> sdpItemCreator; static map<string, onCreateSdpItem, StrCaseCompare> sdpItemCreator;
@ -1148,7 +1145,6 @@ void RtcConfigure::RtcTrackConfigure::setDefaultSetting(TrackType type){
void RtcConfigure::setDefaultSetting(string ice_ufrag, void RtcConfigure::setDefaultSetting(string ice_ufrag,
string ice_pwd, string ice_pwd,
DtlsRole role,
RtpDirection direction, RtpDirection direction,
const SdpAttrFingerprint &fingerprint) { const SdpAttrFingerprint &fingerprint) {
video.setDefaultSetting(TrackVideo); 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_ufrag = audio.ice_ufrag = application.ice_ufrag = ice_ufrag;
video.ice_pwd = audio.ice_pwd = application.ice_pwd = 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.direction = audio.direction = application.direction = direction;
video.fingerprint = audio.fingerprint = application.fingerprint = fingerprint; video.fingerprint = audio.fingerprint = application.fingerprint = fingerprint;
application.enable = false;
} }
void RtcConfigure::addCandidate(const SdpAttrCandidate &candidate, TrackType type) { void RtcConfigure::addCandidate(const SdpAttrCandidate &candidate, TrackType type) {
@ -1203,5 +1199,100 @@ shared_ptr<RtcSession> RtcConfigure::createOffer(){
} }
shared_ptr<RtcSession> RtcConfigure::createAnswer(const RtcSession &offer){ shared_ptr<RtcSession> RtcConfigure::createAnswer(const RtcSession &offer){
return nullptr; shared_ptr<RtcSession> ret = std::make_shared<RtcSession>();
} 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<RtcSession> &ret, TrackType type, const vector<RtcMedia> &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);
}
}
}

View File

@ -7,10 +7,13 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "assert.h"
#include "Extension/Frame.h" #include "Extension/Frame.h"
using namespace std; using namespace std;
using namespace mediakit; using namespace mediakit;
#define CHECK(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__);
//https://datatracker.ietf.org/doc/rfc4566/?include_text=1 //https://datatracker.ietf.org/doc/rfc4566/?include_text=1
//https://blog.csdn.net/aggresss/article/details/109850434 //https://blog.csdn.net/aggresss/article/details/109850434
//https://aggresss.blog.csdn.net/article/details/106436703 //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相关信息 //ssrc相关信息
class RtcSSRC{ class RtcSSRC{
public: public:
@ -672,7 +666,6 @@ public:
string ice_ufrag; string ice_ufrag;
string ice_pwd; string ice_pwd;
DtlsRole role{DtlsRole::invalid};
RtpDirection direction{RtpDirection::invalid}; RtpDirection direction{RtpDirection::invalid};
SdpAttrFingerprint fingerprint; SdpAttrFingerprint fingerprint;
@ -690,13 +683,16 @@ public:
void setDefaultSetting(string ice_ufrag, void setDefaultSetting(string ice_ufrag,
string ice_pwd, string ice_pwd,
DtlsRole role,
RtpDirection direction, RtpDirection direction,
const SdpAttrFingerprint &fingerprint); const SdpAttrFingerprint &fingerprint);
void addCandidate(const SdpAttrCandidate &candidate, TrackType type = TrackInvalid); void addCandidate(const SdpAttrCandidate &candidate, TrackType type = TrackInvalid);
shared_ptr<RtcSession> createOffer(); shared_ptr<RtcSession> createOffer();
shared_ptr<RtcSession> createAnswer(const RtcSession &offer); shared_ptr<RtcSession> createAnswer(const RtcSession &offer);
private:
void matchMedia(shared_ptr<RtcSession> &ret, TrackType type, const vector<RtcMedia> &medias, const RtcTrackConfigure &configure);
bool onMatchCodecPlan(const RtcCodecPlan &plan, CodecId codec) { return true; }
}; };

156
webrtc/offer-simulcast.sdp Normal file
View File

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

161
webrtc/offer.sdp Normal file
View File

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