实现rtc转rtsp

This commit is contained in:
xiongziliang 2021-04-03 09:34:49 +08:00
parent 130a06897f
commit 2abb5078f9
4 changed files with 80 additions and 16 deletions

View File

@ -82,6 +82,11 @@ string RtcpHeader::dumpString() const {
RtcpSdes *rtcp = (RtcpSdes *)this; RtcpSdes *rtcp = (RtcpSdes *)this;
return rtcp->dumpString(); 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); default: return StrPrinter << dumpHeader() << hexdump((char *)this + sizeof(*this), length << 2);
} }
} }
@ -105,6 +110,12 @@ void RtcpHeader::net2Host(size_t len){
sdes->net2Host(len); sdes->net2Host(len);
break; break;
} }
case RtcpType::RTCP_PSFB: {
RtcpPli *pli = (RtcpPli *)this;
pli->net2Host(len);
break;
}
default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt)); default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt));
} }
} }
@ -121,7 +132,7 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len){
ret.emplace_back(rtcp); ret.emplace_back(rtcp);
} catch (std::exception &ex) { } catch (std::exception &ex) {
//不能处理的rtcp包或者无法解析的rtcp包忽略掉 //不能处理的rtcp包或者无法解析的rtcp包忽略掉
WarnL << ex.what(); WarnL << ex.what() << ",长度为:" << rtcp_len;
} }
ptr += rtcp_len; ptr += rtcp_len;
remain -= rtcp_len; remain -= rtcp_len;
@ -402,4 +413,31 @@ vector<SdesItem *> RtcpSdes::getItemList() {
return ret; return ret;
} }
////////////////////////////////////////////////////////////////////
std::shared_ptr<RtcpPli> 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>((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 }//namespace mediakit

View File

@ -456,6 +456,35 @@ private:
void net2Host(size_t size); void net2Host(size_t size);
} PACKED; } 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<RtcpPli> create();
private:
/**
*
* 使net2Host转换成主机字节序后才可使用此函数
*/
string dumpString() const;
/**
*
* @param size
*/
void net2Host(size_t size);
} PACKED;
#if defined(_WIN32) #if defined(_WIN32)
#pragma pack(pop) #pragma pack(pop)
#endif // defined(_WIN32) #endif // defined(_WIN32)

View File

@ -253,6 +253,9 @@ void WebRtcTransportImp::onStartWebRTC() {
_push_src->setSdp(rtsp_sdp); _push_src->setSdp(rtsp_sdp);
for (auto &m : getSdp(SdpType::offer).media) { for (auto &m : getSdp(SdpType::offer).media) {
if (m.type == TrackVideo) {
_recv_video_ssrc = m.rtp_ssrc.ssrc;
}
for (auto &plan : m.plan) { for (auto &plan : m.plan) {
auto hit_pan = getSdp(SdpType::answer).getMedia(m.type)->getPlan(plan.pt); auto hit_pan = getSdp(SdpType::answer).getMedia(m.type)->getPlan(plan.pt);
if (!hit_pan) { if (!hit_pan) {
@ -416,6 +419,10 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
//todo 此处应该销毁对象 //todo 此处应该销毁对象
break; break;
} }
case RtcpType::RTCP_PSFB: {
// InfoL << rtcp->dumpString();
break;
}
default: 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); 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) { 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) { if (_pli_ticker.elapsedTime() > 2000) {
//todo 定期发送pli //todo 定期发送pli
_pli_ticker.resetTime(); _pli_ticker.resetTime();
char rtcpbuf[12]; auto pli = RtcpPli::create();
makeRtcpPli(rtcpbuf, 12); pli->ssrc = htonl(0);
sendRtcpPacket(rtcpbuf, 12, true); pli->ssrc_media = htonl(_recv_video_ssrc);
sendRtcpPacket((char *) pli.get(), sizeof(RtcpPli), true);
InfoL << "send pli"; InfoL << "send pli";
} }
_push_src->onWrite(std::move(rtp), false); _push_src->onWrite(std::move(rtp), false);

View File

@ -157,6 +157,7 @@ private:
RtspMediaSourceImp::Ptr _push_src; RtspMediaSourceImp::Ptr _push_src;
unordered_map<uint8_t, RtpPayloadInfo> _rtp_receiver; unordered_map<uint8_t, RtpPayloadInfo> _rtp_receiver;
unordered_map<uint32_t, RtpPayloadInfo*> _ssrc_info; unordered_map<uint32_t, RtpPayloadInfo*> _ssrc_info;
uint32_t _recv_video_ssrc;
Ticker _pli_ticker; Ticker _pli_ticker;
}; };