mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +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);
|
bye->net2Host(len);
|
||||||
break;
|
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));
|
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
|
#if 0
|
||||||
#include "Util/onceToken.h"
|
#include "Util/onceToken.h"
|
||||||
|
134
src/Rtcp/Rtcp.h
134
src/Rtcp/Rtcp.h
@ -687,6 +687,140 @@ private:
|
|||||||
void net2Host(size_t size);
|
void net2Host(size_t size);
|
||||||
} PACKED;
|
} 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)
|
#if defined(_WIN32)
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
#endif // defined(_WIN32)
|
#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包");
|
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) {
|
void RtcpContextForSend::onRtcp(RtcpHeader *rtcp) {
|
||||||
@ -72,6 +76,18 @@ void RtcpContextForSend::onRtcp(RtcpHeader *rtcp) {
|
|||||||
}
|
}
|
||||||
break;
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,6 +119,34 @@ Buffer::Ptr RtcpContextForSend::createRtcpSR(uint32_t rtcp_ssrc) {
|
|||||||
return RtcpHeader::toBuffer(std::move(rtcp));
|
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) {
|
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);
|
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包
|
* 创建RR rtcp包
|
||||||
* @param rtcp_ssrc rtcp的ssrc
|
* @param rtcp_ssrc rtcp的ssrc
|
||||||
@ -86,8 +94,11 @@ protected:
|
|||||||
class RtcpContextForSend : public RtcpContext {
|
class RtcpContextForSend : public RtcpContext {
|
||||||
public:
|
public:
|
||||||
toolkit::Buffer::Ptr createRtcpSR(uint32_t rtcp_ssrc) override;
|
toolkit::Buffer::Ptr createRtcpSR(uint32_t rtcp_ssrc) override;
|
||||||
|
|
||||||
void onRtcp(RtcpHeader *rtcp) override;
|
void onRtcp(RtcpHeader *rtcp) override;
|
||||||
|
|
||||||
|
toolkit::Buffer::Ptr createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取rtt
|
* 获取rtt
|
||||||
* @param ssrc rtp ssrc
|
* @param ssrc rtp ssrc
|
||||||
@ -98,6 +109,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::map<uint32_t/*ssrc*/, uint32_t/*rtt*/> _rtt;
|
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/*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 {
|
class RtcpContextForRecv : public RtcpContext {
|
||||||
|
@ -774,6 +774,23 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
|
|||||||
}
|
}
|
||||||
break;
|
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;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user