diff --git a/src/Rtcp/Rtcp.cpp b/src/Rtcp/Rtcp.cpp index 2e0b21db..220a8439 100644 --- a/src/Rtcp/Rtcp.cpp +++ b/src/Rtcp/Rtcp.cpp @@ -82,6 +82,11 @@ string RtcpHeader::dumpString() const { RtcpSdes *rtcp = (RtcpSdes *)this; return rtcp->dumpString(); } + + case RtcpType::RTCP_PSFB: { + RtcpPli *rtcp = (RtcpPli *)this; + return rtcp->dumpString(); + } default: return StrPrinter << dumpHeader() << hexdump((char *)this + sizeof(*this), length << 2); } } @@ -105,6 +110,12 @@ void RtcpHeader::net2Host(size_t len){ sdes->net2Host(len); break; } + + case RtcpType::RTCP_PSFB: { + RtcpPli *pli = (RtcpPli *)this; + pli->net2Host(len); + break; + } default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt)); } } @@ -121,7 +132,7 @@ vector RtcpHeader::loadFromBytes(char *data, size_t len){ ret.emplace_back(rtcp); } catch (std::exception &ex) { //不能处理的rtcp包,或者无法解析的rtcp包,忽略掉 - WarnL << ex.what(); + WarnL << ex.what() << ",长度为:" << rtcp_len; } ptr += rtcp_len; remain -= rtcp_len; @@ -402,4 +413,31 @@ vector RtcpSdes::getItemList() { return ret; } +//////////////////////////////////////////////////////////////////// + +std::shared_ptr RtcpPli::create() { + auto bytes = alignSize(sizeof(RtcpPli)); + auto ptr = (RtcpRR *) new char[bytes]; + setupHeader(ptr, RtcpType::RTCP_PSFB, 1, bytes); + return std::shared_ptr((RtcpPli *) ptr, [](RtcpPli *ptr) { + delete[] (char *) ptr; + }); +} + +string RtcpPli::dumpString() const { + _StrPrinter printer; + printer << RtcpHeader::dumpHeader(); + printer << "ssrc:" << ssrc << "\r\n"; + printer << "ssrc_media:" << ssrc_media; + return std::move(printer); +} + +void RtcpPli::net2Host(size_t size) { + static const size_t kMinSize = sizeof(RtcpPli); + CHECK_MIN_SIZE(size, kMinSize); + RtcpHeader::net2Host(); + ssrc = ntohl(ssrc); + ssrc_media = ntohl(ssrc_media); +} + }//namespace mediakit \ No newline at end of file diff --git a/src/Rtcp/Rtcp.h b/src/Rtcp/Rtcp.h index dbf4c769..8fcc1a1a 100644 --- a/src/Rtcp/Rtcp.h +++ b/src/Rtcp/Rtcp.h @@ -456,6 +456,35 @@ private: void net2Host(size_t size); } PACKED; +//PLI +class RtcpPli : public RtcpHeader { +public: + friend class RtcpHeader; + uint32_t ssrc; + uint32_t ssrc_media; + +public: + /** + * 创建SDES包,只赋值了RtcpHeader以及SdesItem对象的length和text部分 + * @param item_text SdesItem列表,只赋值length和text部分 + * @return SDES包 + */ + static std::shared_ptr create(); + +private: + /** + * 打印字段详情 + * 使用net2Host转换成主机字节序后才可使用此函数 + */ + string dumpString() const; + + /** + * 网络字节序转换为主机字节序 + * @param size 字节长度,防止内存越界 + */ + void net2Host(size_t size); +} PACKED; + #if defined(_WIN32) #pragma pack(pop) #endif // defined(_WIN32) diff --git a/webrtc/WebRtcTransport.cpp b/webrtc/WebRtcTransport.cpp index 69a4003a..23dc13e0 100644 --- a/webrtc/WebRtcTransport.cpp +++ b/webrtc/WebRtcTransport.cpp @@ -253,6 +253,9 @@ void WebRtcTransportImp::onStartWebRTC() { _push_src->setSdp(rtsp_sdp); for (auto &m : getSdp(SdpType::offer).media) { + if (m.type == TrackVideo) { + _recv_video_ssrc = m.rtp_ssrc.ssrc; + } for (auto &plan : m.plan) { auto hit_pan = getSdp(SdpType::answer).getMedia(m.type)->getPlan(plan.pt); if (!hit_pan) { @@ -416,6 +419,10 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) { //todo 此处应该销毁对象 break; } + case RtcpType::RTCP_PSFB: { +// InfoL << rtcp->dumpString(); + break; + } default: break; } } @@ -434,18 +441,6 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len) { info.receiver->inputRtp(info.media->type, info.plan->sample_rate, (uint8_t *) buf, len); } -int makeRtcpPli(char *packet, int len) { - if (packet == NULL || len != 12) - return -1; - memset(packet, 0, len); - RtcpHeader *rtcp = (RtcpHeader *) packet; - rtcp->version = 2; - rtcp->pt = (uint8_t) RtcpType::RTCP_PSFB; - rtcp->report_count = 1; - rtcp->length = htons((len / 4) - 1); - return 12; -} - /////////////////////////////////////////////////////////////////// void WebRtcTransportImp::onSortedRtp(const RtpPayloadInfo &info, RtpPacket::Ptr rtp) { @@ -457,9 +452,10 @@ void WebRtcTransportImp::onSortedRtp(const RtpPayloadInfo &info, RtpPacket::Ptr if (_pli_ticker.elapsedTime() > 2000) { //todo 定期发送pli _pli_ticker.resetTime(); - char rtcpbuf[12]; - makeRtcpPli(rtcpbuf, 12); - sendRtcpPacket(rtcpbuf, 12, true); + auto pli = RtcpPli::create(); + pli->ssrc = htonl(0); + pli->ssrc_media = htonl(_recv_video_ssrc); + sendRtcpPacket((char *) pli.get(), sizeof(RtcpPli), true); InfoL << "send pli"; } _push_src->onWrite(std::move(rtp), false); diff --git a/webrtc/WebRtcTransport.h b/webrtc/WebRtcTransport.h index 74a00b81..f8d4f6b7 100644 --- a/webrtc/WebRtcTransport.h +++ b/webrtc/WebRtcTransport.h @@ -157,6 +157,7 @@ private: RtspMediaSourceImp::Ptr _push_src; unordered_map _rtp_receiver; unordered_map _ssrc_info; + uint32_t _recv_video_ssrc; Ticker _pli_ticker; };