mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 04:31:37 +08:00
初步实现webrtc datachannel sdp握手
This commit is contained in:
parent
03dfcbad36
commit
1ed793fe97
@ -372,9 +372,7 @@ void SdpMedia::parse(const string &str) {
|
|||||||
port = atoi(vec[1].data());
|
port = atoi(vec[1].data());
|
||||||
proto = vec[2];
|
proto = vec[2];
|
||||||
for (size_t i = 3; i < vec.size(); ++i) {
|
for (size_t i = 3; i < vec.size(); ++i) {
|
||||||
auto pt = atoi(vec[i].data());
|
fmts.emplace_back(vec[i]);
|
||||||
CHECK_SDP(type == TrackApplication || pt <= 0xFF);
|
|
||||||
fmts.emplace_back(pt);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,7 +381,7 @@ string SdpMedia::toString() const {
|
|||||||
value = string(getTrackString(type)) + " " + to_string(port) + " " + proto;
|
value = string(getTrackString(type)) + " " + to_string(port) + " " + proto;
|
||||||
for (auto fmt : fmts) {
|
for (auto fmt : fmts) {
|
||||||
value += ' ';
|
value += ' ';
|
||||||
value += to_string(fmt);
|
value += fmt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SdpItem::toString();
|
return SdpItem::toString();
|
||||||
@ -921,7 +919,9 @@ void RtcSession::loadFrom(const string &str) {
|
|||||||
//添加失败,有多条
|
//添加失败,有多条
|
||||||
CHECK(fmtp_map.emplace(fmtp.pt, fmtp).second, "该pt存在多条a=fmtp:", (int)fmtp.pt);
|
CHECK(fmtp_map.emplace(fmtp.pt, fmtp).second, "该pt存在多条a=fmtp:", (int)fmtp.pt);
|
||||||
}
|
}
|
||||||
for (auto &pt : mline.fmts) {
|
for (auto &item : mline.fmts) {
|
||||||
|
auto pt = atoi(item.c_str());
|
||||||
|
CHECK(pt < 0xFF, "invalid payload type: ", item);
|
||||||
//遍历所有编码方案的pt
|
//遍历所有编码方案的pt
|
||||||
rtc_media.plan.emplace_back();
|
rtc_media.plan.emplace_back();
|
||||||
auto &plan = rtc_media.plan.back();
|
auto &plan = rtc_media.plan.back();
|
||||||
@ -1078,10 +1078,10 @@ RtcSessionSdp::Ptr RtcSession::toRtcSessionSdp() const{
|
|||||||
mline->port = m.port;
|
mline->port = m.port;
|
||||||
mline->proto = m.proto;
|
mline->proto = m.proto;
|
||||||
for (auto &p : m.plan) {
|
for (auto &p : m.plan) {
|
||||||
mline->fmts.emplace_back(p.pt);
|
mline->fmts.emplace_back(to_string(p.pt));
|
||||||
}
|
}
|
||||||
if (m.type == TrackApplication) {
|
if (m.type == TrackApplication) {
|
||||||
mline->fmts.emplace_back(m.sctp_port);
|
mline->fmts.emplace_back("webrtc-datachannel");
|
||||||
}
|
}
|
||||||
sdp_media.items.emplace_back(std::move(mline));
|
sdp_media.items.emplace_back(std::move(mline));
|
||||||
sdp_media.items.emplace_back(std::make_shared<SdpConnection>(m.addr));
|
sdp_media.items.emplace_back(std::make_shared<SdpConnection>(m.addr));
|
||||||
@ -1201,7 +1201,9 @@ RtcSessionSdp::Ptr RtcSession::toRtcSessionSdp() const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpAttrSctpMap>(m.sctpmap)));
|
if (!m.sctpmap.empty()) {
|
||||||
|
sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpAttrSctpMap>(m.sctpmap)));
|
||||||
|
}
|
||||||
sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpCommon>("sctp-port", to_string(m.sctp_port))));
|
sdp_media.items.emplace_back(wrapSdpAttr(std::make_shared<SdpCommon>("sctp-port", to_string(m.sctp_port))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1567,6 +1569,15 @@ static RtpDirection matchDirection(RtpDirection offer_direction, RtpDirection su
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DtlsRole mathDtlsRole(DtlsRole role){
|
||||||
|
switch (role) {
|
||||||
|
case DtlsRole::actpass:
|
||||||
|
case DtlsRole::active: return DtlsRole::passive;
|
||||||
|
case DtlsRole::passive: return DtlsRole::active;
|
||||||
|
default: CHECK(0, "invalid role:", getDtlsRoleString(role)); return DtlsRole::passive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RtcConfigure::matchMedia(const shared_ptr<RtcSession> &ret, TrackType type, const vector<RtcMedia> &medias, const RtcTrackConfigure &configure){
|
void RtcConfigure::matchMedia(const shared_ptr<RtcSession> &ret, TrackType type, const vector<RtcMedia> &medias, const RtcTrackConfigure &configure){
|
||||||
bool check_profile = true;
|
bool check_profile = true;
|
||||||
bool check_codec = true;
|
bool check_codec = true;
|
||||||
@ -1577,6 +1588,14 @@ RETRY:
|
|||||||
if (offer_media.type != type) {
|
if (offer_media.type != type) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (type == TrackApplication) {
|
||||||
|
RtcMedia answer_media = offer_media;
|
||||||
|
answer_media.role = mathDtlsRole(offer_media.role);
|
||||||
|
answer_media.direction = matchDirection(offer_media.direction, configure.direction);
|
||||||
|
answer_media.candidate = configure.candidate;
|
||||||
|
ret->media.emplace_back(answer_media);
|
||||||
|
return;
|
||||||
|
}
|
||||||
for (auto &codec : configure.preferred_codec) {
|
for (auto &codec : configure.preferred_codec) {
|
||||||
if (offer_media.ice_lite && configure.ice_lite) {
|
if (offer_media.ice_lite && configure.ice_lite) {
|
||||||
WarnL << "answer sdp配置为ice_lite模式,与offer sdp中的ice_lite模式冲突";
|
WarnL << "answer sdp配置为ice_lite模式,与offer sdp中的ice_lite模式冲突";
|
||||||
@ -1617,18 +1636,7 @@ RETRY:
|
|||||||
answer_media.ice_lite = configure.ice_lite;
|
answer_media.ice_lite = configure.ice_lite;
|
||||||
answer_media.candidate = configure.candidate;
|
answer_media.candidate = configure.candidate;
|
||||||
answer_media.rtp_rids = offer_media.rtp_rids;
|
answer_media.rtp_rids = offer_media.rtp_rids;
|
||||||
switch (offer_media.role) {
|
answer_media.role = mathDtlsRole(offer_media.role);
|
||||||
case DtlsRole::actpass :
|
|
||||||
case DtlsRole::active : {
|
|
||||||
answer_media.role = DtlsRole::passive;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DtlsRole::passive : {
|
|
||||||
answer_media.role = DtlsRole::active;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//如果codec匹配失败,那么禁用该track
|
//如果codec匹配失败,那么禁用该track
|
||||||
answer_media.direction = check_codec ? matchDirection(offer_media.direction, configure.direction)
|
answer_media.direction = check_codec ? matchDirection(offer_media.direction, configure.direction)
|
||||||
|
@ -196,7 +196,7 @@ public:
|
|||||||
//RTP/AVPF: 应用场景为视频/音频的 RTP 协议,支持 RTCP-based Feedback。参考 RFC 4585
|
//RTP/AVPF: 应用场景为视频/音频的 RTP 协议,支持 RTCP-based Feedback。参考 RFC 4585
|
||||||
//RTP/SAVPF: 应用场景为视频/音频的 SRTP 协议,支持 RTCP-based Feedback。参考 RFC 5124
|
//RTP/SAVPF: 应用场景为视频/音频的 SRTP 协议,支持 RTCP-based Feedback。参考 RFC 5124
|
||||||
std::string proto;
|
std::string proto;
|
||||||
std::vector<uint32_t> fmts;
|
std::vector<std::string> fmts;
|
||||||
|
|
||||||
void parse(const std::string &str) override;
|
void parse(const std::string &str) override;
|
||||||
std::string toString() const override;
|
std::string toString() const override;
|
||||||
@ -426,12 +426,13 @@ public:
|
|||||||
//https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-05
|
//https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-05
|
||||||
//a=sctpmap:5000 webrtc-datachannel 1024
|
//a=sctpmap:5000 webrtc-datachannel 1024
|
||||||
//a=sctpmap: sctpmap-number media-subtypes [streams]
|
//a=sctpmap: sctpmap-number media-subtypes [streams]
|
||||||
uint16_t port;
|
uint16_t port = 0;
|
||||||
std::string subtypes;
|
std::string subtypes;
|
||||||
uint32_t streams;
|
uint32_t streams = 0;
|
||||||
void parse(const std::string &str) override;
|
void parse(const std::string &str) override;
|
||||||
std::string toString() const override;
|
std::string toString() const override;
|
||||||
const char* getKey() const override { return "sctpmap";}
|
const char* getKey() const override { return "sctpmap";}
|
||||||
|
bool empty() const { return port == 0 && subtypes.empty() && streams == 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class SdpAttrCandidate : public SdpItem {
|
class SdpAttrCandidate : public SdpItem {
|
||||||
|
@ -368,6 +368,9 @@ bool WebRtcTransportImp::canRecvRtp() const{
|
|||||||
void WebRtcTransportImp::onStartWebRTC() {
|
void WebRtcTransportImp::onStartWebRTC() {
|
||||||
//获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息
|
//获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息
|
||||||
for (auto &m_answer : _answer_sdp->media) {
|
for (auto &m_answer : _answer_sdp->media) {
|
||||||
|
if (m_answer.type == TrackApplication) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
auto m_offer = _offer_sdp->getMedia(m_answer.type);
|
auto m_offer = _offer_sdp->getMedia(m_answer.type);
|
||||||
auto track = std::make_shared<MediaTrack>();
|
auto track = std::make_shared<MediaTrack>();
|
||||||
|
|
||||||
@ -376,7 +379,7 @@ void WebRtcTransportImp::onStartWebRTC() {
|
|||||||
track->answer_ssrc_rtx = m_answer.getRtxSSRC();
|
track->answer_ssrc_rtx = m_answer.getRtxSSRC();
|
||||||
track->offer_ssrc_rtp = m_offer->getRtpSSRC();
|
track->offer_ssrc_rtp = m_offer->getRtpSSRC();
|
||||||
track->offer_ssrc_rtx = m_offer->getRtxSSRC();
|
track->offer_ssrc_rtx = m_offer->getRtxSSRC();
|
||||||
track->plan_rtp = &m_answer.plan[0];;
|
track->plan_rtp = &m_answer.plan[0];
|
||||||
track->plan_rtx = m_answer.getRelatedRtxPlan(track->plan_rtp->pt);
|
track->plan_rtx = m_answer.getRelatedRtxPlan(track->plan_rtp->pt);
|
||||||
track->rtcp_context_send = std::make_shared<RtcpContextForSend>();
|
track->rtcp_context_send = std::make_shared<RtcpContextForSend>();
|
||||||
|
|
||||||
@ -399,28 +402,26 @@ void WebRtcTransportImp::onStartWebRTC() {
|
|||||||
//rtx pt --> MediaTrack
|
//rtx pt --> MediaTrack
|
||||||
_pt_to_track.emplace(track->plan_rtx->pt, std::unique_ptr<WrappedMediaTrack>(new WrappedRtxTrack(track)));
|
_pt_to_track.emplace(track->plan_rtx->pt, std::unique_ptr<WrappedMediaTrack>(new WrappedRtxTrack(track)));
|
||||||
}
|
}
|
||||||
if (m_offer->type != TrackApplication) {
|
//记录rtp ext类型与id的关系,方便接收或发送rtp时修改rtp ext id
|
||||||
//记录rtp ext类型与id的关系,方便接收或发送rtp时修改rtp ext id
|
track->rtp_ext_ctx = std::make_shared<RtpExtContext>(*m_offer);
|
||||||
track->rtp_ext_ctx = std::make_shared<RtpExtContext>(*m_offer);
|
weak_ptr<MediaTrack> weak_track = track;
|
||||||
weak_ptr<MediaTrack> weak_track = track;
|
track->rtp_ext_ctx->setOnGetRtp([this, weak_track](uint8_t pt, uint32_t ssrc, const string &rid) {
|
||||||
track->rtp_ext_ctx->setOnGetRtp([this, weak_track](uint8_t pt, uint32_t ssrc, const string &rid) {
|
//ssrc --> MediaTrack
|
||||||
//ssrc --> MediaTrack
|
auto track = weak_track.lock();
|
||||||
auto track = weak_track.lock();
|
assert(track);
|
||||||
assert(track);
|
_ssrc_to_track[ssrc] = std::move(track);
|
||||||
_ssrc_to_track[ssrc] = std::move(track);
|
InfoL << "get rtp, pt:" << (int) pt << ", ssrc:" << ssrc << ", rid:" << rid;
|
||||||
InfoL << "get rtp, pt:" << (int) pt << ", ssrc:" << ssrc << ", rid:" << rid;
|
});
|
||||||
});
|
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
for (auto &ssrc : m_offer->rtp_ssrc_sim) {
|
for (auto &ssrc : m_offer->rtp_ssrc_sim) {
|
||||||
//记录ssrc对应的MediaTrack
|
//记录ssrc对应的MediaTrack
|
||||||
_ssrc_to_track[ssrc.ssrc] = track;
|
_ssrc_to_track[ssrc.ssrc] = track;
|
||||||
if (m_offer->rtp_rids.size() > index) {
|
if (m_offer->rtp_rids.size() > index) {
|
||||||
//支持firefox的simulcast, 提前映射好ssrc和rid的关系
|
//支持firefox的simulcast, 提前映射好ssrc和rid的关系
|
||||||
track->rtp_ext_ctx->setRid(ssrc.ssrc, m_offer->rtp_rids[index]);
|
track->rtp_ext_ctx->setRid(ssrc.ssrc, m_offer->rtp_rids[index]);
|
||||||
}
|
|
||||||
++index;
|
|
||||||
}
|
}
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user