完善ssrc处理逻辑

This commit is contained in:
xia-chu 2021-05-10 18:11:12 +08:00
parent d4ce5b0091
commit a42e5f6470
2 changed files with 38 additions and 16 deletions

View File

@ -185,6 +185,9 @@ void WebRtcTransport::onCheckSdp(SdpType type, RtcSession &sdp){
if (sdp.group.mids.empty()) { if (sdp.group.mids.empty()) {
throw std::invalid_argument("只支持group BUNDLE模式"); throw std::invalid_argument("只支持group BUNDLE模式");
} }
if (type == SdpType::offer) {
sdp.checkValidSSRC();
}
} }
void WebRtcTransport::onRtcConfigure(RtcConfigure &configure) const { void WebRtcTransport::onRtcConfigure(RtcConfigure &configure) const {
@ -390,6 +393,16 @@ bool WebRtcTransportImp::canRecvRtp() const{
return _push_src && (sdp.media[0].direction == RtpDirection::sendrecv || sdp.media[0].direction == RtpDirection::recvonly); return _push_src && (sdp.media[0].direction == RtpDirection::sendrecv || sdp.media[0].direction == RtpDirection::recvonly);
} }
const RtcSession& WebRtcTransportImp::getSdpWithSSRC() const{
auto &offer = getSdp(SdpType::offer);
if (offer.haveSSRC()) {
return offer;
}
auto &answer = getSdp(SdpType::answer);
CHECK(answer.haveSSRC());
return answer;
}
void WebRtcTransportImp::onStartWebRTC() { void WebRtcTransportImp::onStartWebRTC() {
//获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息 //获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息
for (auto &m : getSdp(SdpType::offer).media) { for (auto &m : getSdp(SdpType::offer).media) {
@ -398,11 +411,12 @@ void WebRtcTransportImp::onStartWebRTC() {
if (!hit_pan) { if (!hit_pan) {
continue; continue;
} }
auto m_with_ssrc = getSdpWithSSRC().getMedia(m.type);
//获取offer端rtp的ssrc和pt相关信息 //获取offer端rtp的ssrc和pt相关信息
auto &ref = _rtp_info_pt[plan.pt]; auto &ref = _rtp_info_pt[plan.pt];
_rtp_info_ssrc[m.rtp_rtx_ssrc[0].ssrc] = &ref; _rtp_info_ssrc[m_with_ssrc->rtp_rtx_ssrc[0].ssrc] = &ref;
ref.plan = &plan; ref.plan = &plan;
ref.media = &m; ref.media = m_with_ssrc;
ref.is_common_rtp = getCodecId(plan.codec) != CodecInvalid; ref.is_common_rtp = getCodecId(plan.codec) != CodecInvalid;
ref.rtcp_context_recv = std::make_shared<RtcpContext>(ref.plan->sample_rate, true); ref.rtcp_context_recv = std::make_shared<RtcpContext>(ref.plan->sample_rate, true);
ref.rtcp_context_send = std::make_shared<RtcpContext>(ref.plan->sample_rate, false); ref.rtcp_context_send = std::make_shared<RtcpContext>(ref.plan->sample_rate, false);
@ -441,14 +455,16 @@ void WebRtcTransportImp::onStartWebRTC() {
RtcSession rtsp_send_sdp; RtcSession rtsp_send_sdp;
rtsp_send_sdp.loadFrom(_play_src->getSdp(), false); rtsp_send_sdp.loadFrom(_play_src->getSdp(), false);
for (auto &m : getSdp(SdpType::answer).media) { for (auto &m : getSdp(SdpType::answer).media) {
if (m.type == TrackApplication) { if (m.type == TrackApplication) {
continue; continue;
} }
auto rtsp_media = rtsp_send_sdp.getMedia(m.type); auto rtsp_media = rtsp_send_sdp.getMedia(m.type);
if (rtsp_media && getCodecId(rtsp_media->plan[0].codec) == getCodecId(m.plan[0].codec)) { if (rtsp_media && getCodecId(rtsp_media->plan[0].codec) == getCodecId(m.plan[0].codec)) {
//记录发送rtp时约定的pt届时发送rtp时需要修改pt auto it = _rtp_info_pt.find(m.plan[0].pt);
_send_rtp_pt[m.type] = m.plan[0].pt; CHECK(it != _rtp_info_pt.end());
//记录发送rtp时约定的信息届时发送rtp时需要修改pt和ssrc
_send_rtp_info[m.type] = &it->second;
} }
} }
} }
@ -457,10 +473,11 @@ void WebRtcTransportImp::onStartWebRTC() {
void WebRtcTransportImp::onCheckSdp(SdpType type, RtcSession &sdp){ void WebRtcTransportImp::onCheckSdp(SdpType type, RtcSession &sdp){
WebRtcTransport::onCheckSdp(type, sdp); WebRtcTransport::onCheckSdp(type, sdp);
if (type != SdpType::answer) { if (type != SdpType::answer) {
//我们只修改answer sdp
return; return;
} }
//修改sdp的ip、端口信息 //修改answer sdp的ip、端口信息
GET_CONFIG(string, extern_ip, RTC::kExternIP); GET_CONFIG(string, extern_ip, RTC::kExternIP);
for (auto &m : sdp.media) { for (auto &m : sdp.media) {
m.addr.reset(); m.addr.reset();
@ -472,7 +489,8 @@ void WebRtcTransportImp::onCheckSdp(SdpType type, RtcSession &sdp){
sdp.origin.address = m.addr.address; sdp.origin.address = m.addr.address;
} }
if (!canSendRtp()) { if (!canSendRtp() || getSdp(SdpType::offer).haveSSRC()) {
//offer sdp未包含ssrc相关信息那么我们才在answer sdp中回复ssrc相关信息
return; return;
} }
@ -686,20 +704,23 @@ void WebRtcTransportImp::onBeforeSortedRtp(const RtpPayloadInfo &info, const Rtp
} }
void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush){ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush){
auto pt = _send_rtp_pt[rtp->type]; auto info = _send_rtp_info[rtp->type];
if (pt == 0xFF) { if (!info) {
//忽略,对方不支持该编码类型 //忽略,对方不支持该编码类型
return; return;
} }
_bytes_usage += rtp->size() - RtpPacket::kRtpTcpHeaderSize; _bytes_usage += rtp->size() - RtpPacket::kRtpTcpHeaderSize;
sendRtpPacket(rtp->data() + RtpPacket::kRtpTcpHeaderSize, rtp->size() - RtpPacket::kRtpTcpHeaderSize, flush, rtp->type); sendRtpPacket(rtp->data() + RtpPacket::kRtpTcpHeaderSize, rtp->size() - RtpPacket::kRtpTcpHeaderSize, flush, rtp->type);
//统计rtp发送情况好做sr汇报 //统计rtp发送情况好做sr汇报
_rtp_info_pt[pt].rtcp_context_send->onRtp(rtp->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize); _rtp_info_pt[info->plan->pt].rtcp_context_send->onRtp(rtp->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
} }
void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, size_t len, TrackType type) { void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, size_t len, TrackType type) {
auto header = (RtpHeader *)buf; auto header = (RtpHeader *)buf;
header->pt = _send_rtp_pt[type]; auto info = _send_rtp_info[type];
//修改目标pt和ssrc
header->pt = info->plan->pt;
header->ssrc = htons(info->media->rtp_rtx_ssrc[0].ssrc);
changeRtpExtId(header, _rtp_ext_type_to_id); changeRtpExtId(header, _rtp_ext_type_to_id);
} }

View File

@ -188,6 +188,7 @@ private:
SdpAttrCandidate::Ptr getIceCandidate() const; SdpAttrCandidate::Ptr getIceCandidate() const;
bool canSendRtp() const; bool canSendRtp() const;
bool canRecvRtp() const; bool canRecvRtp() const;
const RtcSession& getSdpWithSSRC() const;
class RtpPayloadInfo { class RtpPayloadInfo {
public: public:
@ -215,8 +216,8 @@ private:
Ticker _alive_ticker; Ticker _alive_ticker;
//pli rtcp计时器 //pli rtcp计时器
Ticker _pli_ticker; Ticker _pli_ticker;
//记录协商的rtp的pt类型 //记录协商的发送rtp的pt和ssrc
uint8_t _send_rtp_pt[2] = {0xFF, 0xFF}; RtpPayloadInfo* _send_rtp_info[2] = {nullptr, nullptr};
//复合udp端口接收一切rtp与rtcp //复合udp端口接收一切rtp与rtcp
Socket::Ptr _socket; Socket::Ptr _socket;
//推流的rtsp源 //推流的rtsp源
@ -226,9 +227,9 @@ private:
//播放rtsp源的reader对象 //播放rtsp源的reader对象
RtspMediaSource::RingType::RingReader::Ptr _reader; RtspMediaSource::RingType::RingReader::Ptr _reader;
//根据rtp的pt获取相关信息 //根据rtp的pt获取相关信息
unordered_map<uint8_t, RtpPayloadInfo> _rtp_info_pt; unordered_map<uint8_t/*pt*/, RtpPayloadInfo> _rtp_info_pt;
//根据推流端rtcp的ssrc获取相关信息 //根据rtcp的ssrc获取相关信息
unordered_map<uint32_t, RtpPayloadInfo*> _rtp_info_ssrc; unordered_map<uint32_t/*ssrc*/, RtpPayloadInfo*> _rtp_info_ssrc;
//发送rtp时需要修改rtp ext id //发送rtp时需要修改rtp ext id
map<RtpExtType, uint8_t> _rtp_ext_type_to_id; map<RtpExtType, uint8_t> _rtp_ext_type_to_id;
//接收rtp时需要修改rtp ext id //接收rtp时需要修改rtp ext id