mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-10-30 16:27:36 +08:00
for rtc send can receive rtcp xr, player can calculate rtt , for metaRTC player send rtcp xr
This commit is contained in:
parent
14da5ab2d8
commit
602b475a3c
@ -193,7 +193,20 @@ void RtcpHeader::net2Host(size_t len) {
|
||||
bye->net2Host(len);
|
||||
break;
|
||||
}
|
||||
|
||||
case RtcpType::RTCP_XR:{
|
||||
RtcpXRRRTR* xr = (RtcpXRRRTR*)this;
|
||||
if(xr->bt == 4){
|
||||
xr->net2Host(len);
|
||||
//TraceL<<xr->dumpString();
|
||||
}else if(xr->bt == 5){
|
||||
RtcpXRDLRR* dlrr = (RtcpXRDLRR*)this;
|
||||
dlrr->net2Host(len);
|
||||
TraceL<<dlrr->dumpString();
|
||||
}else{
|
||||
throw std::runtime_error(StrPrinter << "rtcp xr bt " << xr->bt<<" not support");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt));
|
||||
}
|
||||
}
|
||||
@ -691,6 +704,98 @@ void RtcpBye::net2Host(size_t size) {
|
||||
}
|
||||
}
|
||||
}
|
||||
////////////////////////////////////////////
|
||||
string RtcpXRRRTR::dumpString() const {
|
||||
_StrPrinter printer;
|
||||
printer << RtcpHeader::dumpHeader();
|
||||
printer << "ssrc :" <<ssrc<<"\r\n";
|
||||
printer << "bt :" <<(int)bt<<"\r\n";
|
||||
printer << "block_length : "<<block_length<<"\r\n";
|
||||
printer << "ntp msw : "<<ntpmsw<<"\r\n";
|
||||
printer << "ntp lsw : "<<ntplsw<<"\r\n";
|
||||
return std::move(printer);
|
||||
}
|
||||
|
||||
void RtcpXRRRTR::net2Host(size_t size) {
|
||||
static const size_t kMinSize = sizeof(RtcpHeader);
|
||||
CHECK_MIN_SIZE(size, kMinSize);
|
||||
if(size != sizeof(RtcpXRRRTR)){
|
||||
throw std::invalid_argument(StrPrinter << "rtcp xr Receiver Reference Time Report Block must is " << sizeof(RtcpXRRRTR)<<" actual size "<<size);
|
||||
}
|
||||
ssrc = ntohl(ssrc);
|
||||
block_length = ntohs(block_length);
|
||||
ntpmsw = ntohl(ntpmsw);
|
||||
ntplsw = ntohl(ntplsw);
|
||||
}
|
||||
|
||||
|
||||
string RtcpXRDLRRReportItem::dumpString() const {
|
||||
_StrPrinter printer;
|
||||
|
||||
printer << "ssrc :" <<ssrc<<"\r\n";
|
||||
printer << "last RR (lrr) :" <<lrr<<"\r\n";
|
||||
printer << "delay since last RR (dlrr): "<<dlrr<<"\r\n";
|
||||
|
||||
return std::move(printer);
|
||||
}
|
||||
|
||||
void RtcpXRDLRRReportItem::net2Host() {
|
||||
ssrc = ntohl(ssrc);
|
||||
lrr = ntohl(lrr);
|
||||
dlrr = ntohl(dlrr);
|
||||
}
|
||||
|
||||
std::vector<RtcpXRDLRRReportItem*> RtcpXRDLRR::getItemList(){
|
||||
auto count = block_length/3;
|
||||
RtcpXRDLRRReportItem *ptr = &items;
|
||||
vector<RtcpXRDLRRReportItem *> ret;
|
||||
for (int i = 0; i < (int) count; ++i) {
|
||||
ret.emplace_back(ptr);
|
||||
++ptr;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
string RtcpXRDLRR::dumpString() const {
|
||||
_StrPrinter printer;
|
||||
printer << RtcpHeader::dumpHeader();
|
||||
printer << "ssrc :" <<ssrc<<"\r\n";
|
||||
printer << "bt :" <<(int)bt<<"\r\n";
|
||||
printer << "block_length : "<<block_length<<"\r\n";
|
||||
auto items_list = ((RtcpXRDLRR *) this)->getItemList();
|
||||
auto i = 0;
|
||||
for (auto &item : items_list) {
|
||||
printer << "---- item:" << i++ << " ----\r\n";
|
||||
printer << item->dumpString();
|
||||
}
|
||||
return std::move(printer);
|
||||
}
|
||||
|
||||
void RtcpXRDLRR::net2Host(size_t size) {
|
||||
static const size_t kMinSize = sizeof(RtcpHeader);
|
||||
CHECK_MIN_SIZE(size, kMinSize);
|
||||
|
||||
ssrc = ntohl(ssrc);
|
||||
block_length = ntohs(block_length);
|
||||
|
||||
auto count = block_length/3;
|
||||
for (int i = 0; i < (int) count; ++i) {
|
||||
RtcpXRDLRRReportItem *ptr = &items;
|
||||
ptr->net2Host();
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<RtcpXRDLRR> RtcpXRDLRR::create(size_t item_count){
|
||||
auto real_size = sizeof(RtcpXRDLRR) - sizeof(RtcpXRDLRRReportItem) + item_count * sizeof(RtcpXRDLRRReportItem);
|
||||
auto bytes = alignSize(real_size);
|
||||
auto ptr = (RtcpXRDLRR *) new char[bytes];
|
||||
setupHeader(ptr, RtcpType::RTCP_XR, 0, bytes);
|
||||
setupPadding(ptr, bytes - real_size);
|
||||
return std::shared_ptr<RtcpXRDLRR>(ptr, [](RtcpXRDLRR *ptr) {
|
||||
delete[] (char *) ptr;
|
||||
});
|
||||
}
|
||||
|
||||
#if 0
|
||||
#include "Util/onceToken.h"
|
||||
|
134
src/Rtcp/Rtcp.h
134
src/Rtcp/Rtcp.h
@ -687,6 +687,140 @@ private:
|
||||
void net2Host(size_t size);
|
||||
} PACKED;
|
||||
|
||||
/*
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|V=2|P|reserved | PT=XR=207 | length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| SSRC |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
: report blocks :
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
*/
|
||||
/*
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| BT=4 | reserved | block length = 2 |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| NTP timestamp, most significant word |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| NTP timestamp, least significant word |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|
||||
*/
|
||||
class RtcpXRRRTR : public RtcpHeader
|
||||
{
|
||||
public:
|
||||
friend class RtcpHeader;
|
||||
uint32_t ssrc;
|
||||
// 4
|
||||
uint8_t bt;
|
||||
uint8_t reserved;
|
||||
// 2
|
||||
uint16_t block_length;
|
||||
// ntp timestamp MSW(in second)
|
||||
uint32_t ntpmsw;
|
||||
// ntp timestamp LSW(in picosecond)
|
||||
uint32_t ntplsw;
|
||||
private:
|
||||
/**
|
||||
* 打印字段详情
|
||||
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||
*/
|
||||
std::string dumpString() const;
|
||||
|
||||
/**
|
||||
* 网络字节序转换为主机字节序
|
||||
* @param size 字节长度,防止内存越界
|
||||
*/
|
||||
void net2Host(size_t size);
|
||||
|
||||
}PACKED;
|
||||
|
||||
/*
|
||||
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| BT=5 | reserved | block length |
|
||||
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
| SSRC_1 (SSRC of first receiver) | sub-
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
|
||||
| last RR (LRR) | 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| delay since last RR (DLRR) |
|
||||
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
| SSRC_2 (SSRC of second receiver) | sub-
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block
|
||||
: ... : 2
|
||||
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
*/
|
||||
class RtcpXRDLRRReportItem
|
||||
{
|
||||
public:
|
||||
friend class RtcpXRDLRR;
|
||||
uint32_t ssrc;
|
||||
uint32_t lrr;
|
||||
uint32_t dlrr;
|
||||
private:
|
||||
/**
|
||||
* 打印字段详情
|
||||
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||
*/
|
||||
std::string dumpString() const;
|
||||
|
||||
/**
|
||||
* 网络字节序转换为主机字节序
|
||||
* @param size 字节长度,防止内存越界
|
||||
*/
|
||||
void net2Host();
|
||||
}PACKED;
|
||||
|
||||
|
||||
|
||||
class RtcpXRDLRR : public RtcpHeader
|
||||
{
|
||||
public:
|
||||
friend class RtcpHeader;
|
||||
uint32_t ssrc;
|
||||
uint8_t bt;
|
||||
uint8_t reserved;
|
||||
uint16_t block_length;
|
||||
RtcpXRDLRRReportItem items;
|
||||
|
||||
/**
|
||||
* 创建RtcpXRDLRR包,只赋值了RtcpHeader部分(网络字节序)
|
||||
* @param item_count RtcpXRDLRRReportItem对象个数
|
||||
* @return RtcpXRDLRR包
|
||||
*/
|
||||
static std::shared_ptr<RtcpXRDLRR> create(size_t item_count);
|
||||
|
||||
/**
|
||||
* 获取RtcpXRDLRRReportItem对象指针列表
|
||||
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||
*/
|
||||
std::vector<RtcpXRDLRRReportItem*> getItemList();
|
||||
|
||||
private:
|
||||
/**
|
||||
* 打印字段详情
|
||||
* 使用net2Host转换成主机字节序后才可使用此函数
|
||||
*/
|
||||
std::string dumpString() const;
|
||||
|
||||
/**
|
||||
* 网络字节序转换为主机字节序
|
||||
* @param size 字节长度,防止内存越界
|
||||
*/
|
||||
void net2Host(size_t size);
|
||||
|
||||
}PACKED;
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
#pragma pack(pop)
|
||||
#endif // defined(_WIN32)
|
||||
|
@ -45,6 +45,10 @@ Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) {
|
||||
throw std::runtime_error("没有实现, rtp发送者尝试发送rr包");
|
||||
}
|
||||
|
||||
Buffer::Ptr RtcpContext::createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) {
|
||||
throw std::runtime_error("没有实现, rtp发送者尝试发送xr dlrr包");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RtcpContextForSend::onRtcp(RtcpHeader *rtcp) {
|
||||
@ -72,6 +76,18 @@ void RtcpContextForSend::onRtcp(RtcpHeader *rtcp) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RtcpType::RTCP_XR:{
|
||||
auto rtcp_xr = (RtcpXRRRTR*)rtcp;
|
||||
if(rtcp_xr->bt == 4){
|
||||
_xr_xrrtr_recv_last_rr[rtcp_xr->ssrc] = ((rtcp_xr->ntpmsw & 0xFFFF) << 16) | ((rtcp_xr->ntplsw >> 16) & 0xFFFF);
|
||||
_xr_rrtr_recv_sys_stamp[rtcp_xr->ssrc] = getCurrentMillisecond();
|
||||
}else if(rtcp_xr->bt == 5){
|
||||
TraceL<<"for sender not recive dlrr";
|
||||
}else{
|
||||
TraceL<<"not support xr bt "<<rtcp_xr->bt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -103,6 +119,34 @@ Buffer::Ptr RtcpContextForSend::createRtcpSR(uint32_t rtcp_ssrc) {
|
||||
return RtcpHeader::toBuffer(std::move(rtcp));
|
||||
}
|
||||
|
||||
toolkit::Buffer::Ptr RtcpContextForSend::createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc){
|
||||
auto rtcp = RtcpXRDLRR::create(1);
|
||||
rtcp->bt = 5;
|
||||
rtcp->reserved = 0;
|
||||
rtcp->block_length = htons(3);
|
||||
rtcp->ssrc = htonl(rtcp_ssrc);
|
||||
rtcp->items.ssrc = htonl(rtp_ssrc);
|
||||
|
||||
if(_xr_xrrtr_recv_last_rr.find(rtp_ssrc) == _xr_xrrtr_recv_last_rr.end()){
|
||||
rtcp->items.lrr = 0;
|
||||
WarnL;
|
||||
}else{
|
||||
rtcp->items.lrr = htonl(_xr_xrrtr_recv_last_rr[rtp_ssrc]);
|
||||
}
|
||||
|
||||
if(_xr_rrtr_recv_sys_stamp.find(rtp_ssrc) == _xr_rrtr_recv_sys_stamp.end()){
|
||||
rtcp->items.dlrr = 0;
|
||||
WarnL;
|
||||
} else {
|
||||
// now - Last SR time,单位毫秒
|
||||
auto delay = getCurrentMillisecond() - _xr_rrtr_recv_sys_stamp[rtp_ssrc];
|
||||
// in units of 1/65536 seconds
|
||||
auto dlsr = (uint32_t)(delay / 1000.0f * 65536);
|
||||
rtcp->items.dlrr = htonl(dlsr);
|
||||
}
|
||||
return RtcpHeader::toBuffer(std::move(rtcp));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RtcpContextForRecv::onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t sample_rate, size_t bytes) {
|
||||
|
@ -55,6 +55,14 @@ public:
|
||||
*/
|
||||
virtual toolkit::Buffer::Ptr createRtcpSR(uint32_t rtcp_ssrc);
|
||||
|
||||
|
||||
/**
|
||||
* @brief 创建xr的dlrr包,用于接收者估算rtt
|
||||
*
|
||||
* @return toolkit::Buffer::Ptr
|
||||
*/
|
||||
virtual toolkit::Buffer::Ptr createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc);
|
||||
|
||||
/**
|
||||
* 创建RR rtcp包
|
||||
* @param rtcp_ssrc rtcp的ssrc
|
||||
@ -86,8 +94,11 @@ protected:
|
||||
class RtcpContextForSend : public RtcpContext {
|
||||
public:
|
||||
toolkit::Buffer::Ptr createRtcpSR(uint32_t rtcp_ssrc) override;
|
||||
|
||||
void onRtcp(RtcpHeader *rtcp) override;
|
||||
|
||||
toolkit::Buffer::Ptr createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) override;
|
||||
|
||||
/**
|
||||
* 获取rtt
|
||||
* @param ssrc rtp ssrc
|
||||
@ -98,6 +109,9 @@ public:
|
||||
private:
|
||||
std::map<uint32_t/*ssrc*/, uint32_t/*rtt*/> _rtt;
|
||||
std::map<uint32_t/*last_sr_lsr*/, uint64_t/*ntp stamp*/> _sender_report_ntp;
|
||||
|
||||
std::map<uint32_t/*ssrc*/,uint64_t/*xr rrtr sys stamp*/> _xr_rrtr_recv_sys_stamp;
|
||||
std::map<uint32_t/*ssrc*/,uint32_t/*last rr */> _xr_xrrtr_recv_last_rr;
|
||||
};
|
||||
|
||||
class RtcpContextForRecv : public RtcpContext {
|
||||
|
@ -774,6 +774,23 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RtcpType::RTCP_XR:{
|
||||
RtcpXRRRTR* xr = (RtcpXRRRTR *) rtcp;
|
||||
if(xr->bt != 4){
|
||||
break;
|
||||
}
|
||||
auto it = _ssrc_to_track.find(xr->ssrc);
|
||||
if (it == _ssrc_to_track.end()) {
|
||||
WarnL << "未识别的 rtcp包:" << rtcp->dumpString();
|
||||
return;
|
||||
}
|
||||
auto &track = it->second;
|
||||
track->rtcp_context_send->onRtcp(rtcp);
|
||||
auto xrdlrr = track->rtcp_context_send->createRtcpXRDLRR(track->answer_ssrc_rtp,track->answer_ssrc_rtp);
|
||||
sendRtcpPacket(xrdlrr->data(), xrdlrr->size(), true);
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user