Commit cffc0743 by xiongguangjie

format code use clang-format

parent 602b475a
......@@ -8,55 +8,67 @@
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <stddef.h>
#include <assert.h>
#include "Rtcp.h"
#include "Util/logger.h"
#include "RtcpFCI.h"
#include "Util/logger.h"
#include <assert.h>
#include <stddef.h>
using namespace std;
using namespace toolkit;
namespace mediakit {
const char *rtcpTypeToStr(RtcpType type){
switch (type){
#define SWITCH_CASE(key, value) case RtcpType::key : return #value "(" #key ")";
const char *rtcpTypeToStr(RtcpType type) {
switch (type) {
#define SWITCH_CASE(key, value) \
case RtcpType::key: \
return #value "(" #key ")";
RTCP_PT_MAP(SWITCH_CASE)
#undef SWITCH_CASE
default: return "unknown rtcp pt";
default:
return "unknown rtcp pt";
}
}
const char *sdesTypeToStr(SdesType type){
switch (type){
#define SWITCH_CASE(key, value) case SdesType::key : return #value "(" #key ")";
const char *sdesTypeToStr(SdesType type) {
switch (type) {
#define SWITCH_CASE(key, value) \
case SdesType::key: \
return #value "(" #key ")";
SDES_TYPE_MAP(SWITCH_CASE)
#undef SWITCH_CASE
default: return "unknown source description type";
default:
return "unknown source description type";
}
}
const char *psfbTypeToStr(PSFBType type) {
switch (type){
#define SWITCH_CASE(key, value) case PSFBType::key : return #value "(" #key ")";
switch (type) {
#define SWITCH_CASE(key, value) \
case PSFBType::key: \
return #value "(" #key ")";
PSFB_TYPE_MAP(SWITCH_CASE)
#undef SWITCH_CASE
default: return "unknown payload-specific fb message fmt type";
default:
return "unknown payload-specific fb message fmt type";
}
}
const char *rtpfbTypeToStr(RTPFBType type) {
switch (type){
#define SWITCH_CASE(key, value) case RTPFBType::key : return #value "(" #key ")";
switch (type) {
#define SWITCH_CASE(key, value) \
case RTPFBType::key: \
return #value "(" #key ")";
RTPFB_TYPE_MAP(SWITCH_CASE)
#undef SWITCH_CASE
default: return "unknown transport layer feedback messages fmt type";
default:
return "unknown transport layer feedback messages fmt type";
}
}
static size_t alignSize(size_t bytes) {
return (size_t) ((bytes + 3) >> 2) << 2;
return (size_t)((bytes + 3) >> 2) << 2;
}
static void setupHeader(RtcpHeader *rtcp, RtcpType type, size_t report_count, size_t total_bytes) {
......@@ -65,16 +77,16 @@ static void setupHeader(RtcpHeader *rtcp, RtcpType type, size_t report_count, si
if (report_count > 0x1F) {
throw std::invalid_argument(StrPrinter << "rtcp report_count最大赋值为31,当前为:" << report_count);
}
//items总个数
// items总个数
rtcp->report_count = report_count;
rtcp->pt = (uint8_t) type;
rtcp->pt = (uint8_t)type;
rtcp->setSize(total_bytes);
}
static void setupPadding(RtcpHeader *rtcp, size_t padding_size) {
if (padding_size) {
rtcp->padding = 1;
((uint8_t *) rtcp)[rtcp->getSize() - 1] = padding_size & 0xFF;
((uint8_t *)rtcp)[rtcp->getSize() - 1] = padding_size & 0xFF;
} else {
rtcp->padding = 0;
}
......@@ -91,123 +103,125 @@ string RtcpHeader::dumpHeader() const {
printer << "padding:" << padding << "\r\n";
}
switch ((RtcpType) pt) {
case RtcpType::RTCP_RTPFB : {
printer << "report_count:" << rtpfbTypeToStr((RTPFBType) report_count) << "\r\n";
break;
}
case RtcpType::RTCP_PSFB : {
printer << "report_count:" << psfbTypeToStr((PSFBType) report_count) << "\r\n";
break;
}
default : {
printer << "report_count:" << report_count << "\r\n";
break;
}
switch ((RtcpType)pt) {
case RtcpType::RTCP_RTPFB: {
printer << "report_count:" << rtpfbTypeToStr((RTPFBType)report_count) << "\r\n";
break;
}
case RtcpType::RTCP_PSFB: {
printer << "report_count:" << psfbTypeToStr((PSFBType)report_count) << "\r\n";
break;
}
default: {
printer << "report_count:" << report_count << "\r\n";
break;
}
}
printer << "pt:" << rtcpTypeToStr((RtcpType) pt) << "\r\n";
printer << "pt:" << rtcpTypeToStr((RtcpType)pt) << "\r\n";
printer << "size:" << getSize() << "\r\n";
printer << "--------\r\n";
return std::move(printer);
}
string RtcpHeader::dumpString() const {
switch ((RtcpType) pt) {
case RtcpType::RTCP_SR: {
RtcpSR *rtcp = (RtcpSR *) this;
return rtcp->dumpString();
}
switch ((RtcpType)pt) {
case RtcpType::RTCP_SR: {
RtcpSR *rtcp = (RtcpSR *)this;
return rtcp->dumpString();
}
case RtcpType::RTCP_RR: {
RtcpRR *rtcp = (RtcpRR *) this;
return rtcp->dumpString();
}
case RtcpType::RTCP_RR: {
RtcpRR *rtcp = (RtcpRR *)this;
return rtcp->dumpString();
}
case RtcpType::RTCP_SDES: {
RtcpSdes *rtcp = (RtcpSdes *) this;
return rtcp->dumpString();
}
case RtcpType::RTCP_SDES: {
RtcpSdes *rtcp = (RtcpSdes *)this;
return rtcp->dumpString();
}
case RtcpType::RTCP_RTPFB:
case RtcpType::RTCP_PSFB: {
RtcpFB *rtcp = (RtcpFB *) this;
return rtcp->dumpString();
}
case RtcpType::RTCP_RTPFB:
case RtcpType::RTCP_PSFB: {
RtcpFB *rtcp = (RtcpFB *)this;
return rtcp->dumpString();
}
case RtcpType::RTCP_BYE: {
RtcpBye *rtcp = (RtcpBye *) this;
return rtcp->dumpString();
}
case RtcpType::RTCP_BYE: {
RtcpBye *rtcp = (RtcpBye *)this;
return rtcp->dumpString();
}
default: return StrPrinter << dumpHeader() << hexdump((char *)this + sizeof(*this), getSize() - sizeof(*this));
default:
return StrPrinter << dumpHeader() << hexdump((char *)this + sizeof(*this), getSize() - sizeof(*this));
}
}
size_t RtcpHeader::getSize() const {
//加上rtcp头长度
// 加上rtcp头长度
return (1 + ntohs(length)) << 2;
}
size_t RtcpHeader::getPaddingSize() const{
size_t RtcpHeader::getPaddingSize() const {
if (!padding) {
return 0;
}
return ((uint8_t *) this)[getSize() - 1];
return ((uint8_t *)this)[getSize() - 1];
}
void RtcpHeader::setSize(size_t size) {
//不包含rtcp头的长度
length = htons((uint16_t) ((size >> 2) - 1));
// 不包含rtcp头的长度
length = htons((uint16_t)((size >> 2) - 1));
}
void RtcpHeader::net2Host(size_t len) {
switch ((RtcpType) pt) {
case RtcpType::RTCP_SR: {
RtcpSR *sr = (RtcpSR *) this;
sr->net2Host(len);
break;
}
case RtcpType::RTCP_RR: {
RtcpRR *rr = (RtcpRR *) this;
rr->net2Host(len);
break;
}
case RtcpType::RTCP_SDES: {
RtcpSdes *sdes = (RtcpSdes *) this;
sdes->net2Host(len);
break;
}
case RtcpType::RTCP_RTPFB:
case RtcpType::RTCP_PSFB: {
RtcpFB *fb = (RtcpFB *) this;
fb->net2Host(len);
break;
}
case RtcpType::RTCP_BYE: {
RtcpBye *bye = (RtcpBye *) this;
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;
switch ((RtcpType)pt) {
case RtcpType::RTCP_SR: {
RtcpSR *sr = (RtcpSR *)this;
sr->net2Host(len);
break;
}
case RtcpType::RTCP_RR: {
RtcpRR *rr = (RtcpRR *)this;
rr->net2Host(len);
break;
}
case RtcpType::RTCP_SDES: {
RtcpSdes *sdes = (RtcpSdes *)this;
sdes->net2Host(len);
break;
}
case RtcpType::RTCP_RTPFB:
case RtcpType::RTCP_PSFB: {
RtcpFB *fb = (RtcpFB *)this;
fb->net2Host(len);
break;
}
case RtcpType::RTCP_BYE: {
RtcpBye *bye = (RtcpBye *)this;
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");
}
default: throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType) this->pt));
break;
}
default:
throw std::runtime_error(StrPrinter << "未处理的rtcp包:" << rtcpTypeToStr((RtcpType)this->pt));
}
}
......@@ -215,10 +229,10 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len) {
vector<RtcpHeader *> ret;
ssize_t remain = len;
char *ptr = data;
while (remain > (ssize_t) sizeof(RtcpHeader)) {
RtcpHeader *rtcp = (RtcpHeader *) ptr;
while (remain > (ssize_t)sizeof(RtcpHeader)) {
RtcpHeader *rtcp = (RtcpHeader *)ptr;
auto rtcp_len = rtcp->getSize();
if (remain < (ssize_t) rtcp_len) {
if (remain < (ssize_t)rtcp_len) {
WarnL << "非法的rtcp包,声明的长度超过实际数据长度";
break;
}
......@@ -226,7 +240,7 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len) {
rtcp->net2Host(rtcp_len);
ret.emplace_back(rtcp);
} catch (std::exception &ex) {
//不能处理的rtcp包,或者无法解析的rtcp包,忽略掉
// 不能处理的rtcp包,或者无法解析的rtcp包,忽略掉
WarnL << ex.what() << ",长度为:" << rtcp_len;
}
ptr += rtcp_len;
......@@ -237,19 +251,13 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len) {
class BufferRtcp : public Buffer {
public:
BufferRtcp(std::shared_ptr<RtcpHeader> rtcp) {
_rtcp = std::move(rtcp);
}
BufferRtcp(std::shared_ptr<RtcpHeader> rtcp) { _rtcp = std::move(rtcp); }
~BufferRtcp() override {}
char *data() const override {
return (char *) _rtcp.get();
}
char *data() const override { return (char *)_rtcp.get(); }
size_t size() const override {
return _rtcp->getSize();
}
size_t size() const override { return _rtcp->getSize(); }
private:
std::shared_ptr<RtcpHeader> _rtcp;
......@@ -264,36 +272,34 @@ Buffer::Ptr RtcpHeader::toBuffer(std::shared_ptr<RtcpHeader> rtcp) {
std::shared_ptr<RtcpSR> RtcpSR::create(size_t item_count) {
auto real_size = sizeof(RtcpSR) - sizeof(ReportItem) + item_count * sizeof(ReportItem);
auto bytes = alignSize(real_size);
auto ptr = (RtcpSR *) new char[bytes];
auto ptr = (RtcpSR *)new char[bytes];
setupHeader(ptr, RtcpType::RTCP_SR, item_count, bytes);
setupPadding(ptr, bytes - real_size);
return std::shared_ptr<RtcpSR>(ptr, [](RtcpSR *ptr) {
delete[] (char *) ptr;
});
return std::shared_ptr<RtcpSR>(ptr, [](RtcpSR *ptr) { delete[] (char *)ptr; });
}
string RtcpSR::getNtpStamp() const {
struct timeval tv;
tv.tv_sec = ntpmsw - 0x83AA7E80;
tv.tv_usec = (decltype(tv.tv_usec)) (ntplsw / ((double) (((uint64_t) 1) << 32) * 1.0e-6));
tv.tv_usec = (decltype(tv.tv_usec))(ntplsw / ((double)(((uint64_t)1) << 32) * 1.0e-6));
return LogChannel::printTime(tv);
}
uint64_t RtcpSR::getNtpUnixStampMS() const {
if (ntpmsw < 0x83AA7E80) {
//ntp时间戳起始时间为1900年,但是utc时间戳起始时间为1970年,两者相差0x83AA7E80秒
//ntp时间戳不得早于1970年,否则无法转换为utc时间戳
// ntp时间戳起始时间为1900年,但是utc时间戳起始时间为1970年,两者相差0x83AA7E80秒
// ntp时间戳不得早于1970年,否则无法转换为utc时间戳
return 0;
}
struct timeval tv;
tv.tv_sec = ntpmsw - 0x83AA7E80;
tv.tv_usec = (decltype(tv.tv_usec)) (ntplsw / ((double) (((uint64_t) 1) << 32) * 1.0e-6));
tv.tv_usec = (decltype(tv.tv_usec))(ntplsw / ((double)(((uint64_t)1) << 32) * 1.0e-6));
return 1000 * tv.tv_sec + tv.tv_usec / 1000;
}
void RtcpSR::setNtpStamp(struct timeval tv) {
ntpmsw = htonl(tv.tv_sec + 0x83AA7E80); /* 0x83AA7E80 is the number of seconds from 1900 to 1970 */
ntplsw = htonl((uint32_t) ((double) tv.tv_usec * (double) (((uint64_t) 1) << 32) * 1.0e-6));
ntplsw = htonl((uint32_t)((double)tv.tv_usec * (double)(((uint64_t)1) << 32) * 1.0e-6));
}
void RtcpSR::setNtpStamp(uint64_t unix_stamp_ms) {
......@@ -313,7 +319,7 @@ string RtcpSR::dumpString() const {
printer << "rtpts:" << rtpts << "\r\n";
printer << "packet_count:" << packet_count << "\r\n";
printer << "octet_count:" << octet_count << "\r\n";
auto items = ((RtcpSR *) this)->getItemList();
auto items = ((RtcpSR *)this)->getItemList();
auto i = 0;
for (auto &item : items) {
printer << "---- item:" << i++ << " ----\r\n";
......@@ -322,17 +328,19 @@ string RtcpSR::dumpString() const {
return std::move(printer);
}
#define CHECK_MIN_SIZE(size, kMinSize) \
if (size < kMinSize) { \
throw std::out_of_range(StrPrinter << rtcpTypeToStr((RtcpType)pt) << " 长度不足:" << size << " < " << kMinSize); \
}
#define CHECK_MIN_SIZE(size, kMinSize) \
if (size < kMinSize) { \
throw std::out_of_range( \
StrPrinter << rtcpTypeToStr((RtcpType)pt) << " 长度不足:" << size << " < " << kMinSize); \
}
#define CHECK_REPORT_COUNT(item_count) \
/*修正个数,防止getItemList时内存越界*/ \
if (report_count != item_count) { \
WarnL << rtcpTypeToStr((RtcpType)pt) << " report_count 字段不正确,已修正为:" << (int)report_count << " -> " << item_count; \
report_count = item_count; \
}
#define CHECK_REPORT_COUNT(item_count) \
/*修正个数,防止getItemList时内存越界*/ \
if (report_count != item_count) { \
WarnL << rtcpTypeToStr((RtcpType)pt) << " report_count 字段不正确,已修正为:" << (int)report_count << " -> " \
<< item_count; \
report_count = item_count; \
}
void RtcpSR::net2Host(size_t size) {
static const size_t kMinSize = sizeof(RtcpSR) - sizeof(items);
......@@ -347,7 +355,7 @@ void RtcpSR::net2Host(size_t size) {
ReportItem *ptr = &items;
int item_count = 0;
for (int i = 0; i < (int) report_count && (char *) (ptr) + sizeof(ReportItem) <= (char *) (this) + size; ++i) {
for (int i = 0; i < (int)report_count && (char *)(ptr) + sizeof(ReportItem) <= (char *)(this) + size; ++i) {
ptr->net2Host();
++ptr;
++item_count;
......@@ -358,7 +366,7 @@ void RtcpSR::net2Host(size_t size) {
vector<ReportItem *> RtcpSR::getItemList() {
vector<ReportItem *> ret;
ReportItem *ptr = &items;
for (int i = 0; i < (int) report_count; ++i) {
for (int i = 0; i < (int)report_count; ++i) {
ret.emplace_back(ptr);
++ptr;
}
......@@ -395,19 +403,17 @@ void ReportItem::net2Host() {
std::shared_ptr<RtcpRR> RtcpRR::create(size_t item_count) {
auto real_size = sizeof(RtcpRR) - sizeof(ReportItem) + item_count * sizeof(ReportItem);
auto bytes = alignSize(real_size);
auto ptr = (RtcpRR *) new char[bytes];
auto ptr = (RtcpRR *)new char[bytes];
setupHeader(ptr, RtcpType::RTCP_RR, item_count, bytes);
setupPadding(ptr, bytes - real_size);
return std::shared_ptr<RtcpRR>(ptr, [](RtcpRR *ptr) {
delete[] (char *) ptr;
});
return std::shared_ptr<RtcpRR>(ptr, [](RtcpRR *ptr) { delete[] (char *)ptr; });
}
string RtcpRR::dumpString() const {
_StrPrinter printer;
printer << RtcpHeader::dumpHeader();
printer << "ssrc:" << ssrc << "\r\n";
auto items = ((RtcpRR *) this)->getItemList();
auto items = ((RtcpRR *)this)->getItemList();
auto i = 0;
for (auto &item : items) {
printer << "---- item:" << i++ << " ----\r\n";
......@@ -423,7 +429,7 @@ void RtcpRR::net2Host(size_t size) {
ReportItem *ptr = &items;
int item_count = 0;
for (int i = 0; i < (int) report_count && (char *) (ptr) + sizeof(ReportItem) <= (char *) (this) + size; ++i) {
for (int i = 0; i < (int)report_count && (char *)(ptr) + sizeof(ReportItem) <= (char *)(this) + size; ++i) {
ptr->net2Host();
++ptr;
++item_count;
......@@ -434,7 +440,7 @@ void RtcpRR::net2Host(size_t size) {
vector<ReportItem *> RtcpRR::getItemList() {
vector<ReportItem *> ret;
ReportItem *ptr = &items;
for (int i = 0; i < (int) report_count; ++i) {
for (int i = 0; i < (int)report_count; ++i) {
ret.emplace_back(ptr);
++ptr;
}
......@@ -458,8 +464,8 @@ size_t SdesChunk::minSize() {
string SdesChunk::dumpString() const {
_StrPrinter printer;
printer << "ssrc:" << ssrc << "\r\n";
printer << "type:" << sdesTypeToStr((SdesType) type) << "\r\n";
printer << "txt_len:" << (int) txt_len << "\r\n";
printer << "type:" << sdesTypeToStr((SdesType)type) << "\r\n";
printer << "txt_len:" << (int)txt_len << "\r\n";
printer << "text:" << (txt_len ? string(text, txt_len) : "") << "\r\n";
return std::move(printer);
}
......@@ -469,32 +475,30 @@ string SdesChunk::dumpString() const {
std::shared_ptr<RtcpSdes> RtcpSdes::create(const std::vector<string> &item_text) {
size_t item_total_size = 0;
for (auto &text : item_text) {
//统计所有SdesChunk对象占用的空间
// 统计所有SdesChunk对象占用的空间
item_total_size += alignSize(SdesChunk::minSize() + (0xFF & text.size()));
}
auto real_size = sizeof(RtcpSdes) - sizeof(SdesChunk) + item_total_size;
auto bytes = alignSize(real_size);
auto ptr = (RtcpSdes *) new char[bytes];
auto ptr = (RtcpSdes *)new char[bytes];
memset(ptr, 0x00, bytes);
auto item_ptr = &ptr->chunks;
for (auto &text : item_text) {
item_ptr->txt_len = (0xFF & text.size());
//确保赋值\0为RTCP_SDES_END
// 确保赋值\0为RTCP_SDES_END
memcpy(item_ptr->text, text.data(), item_ptr->txt_len + 1);
item_ptr = (SdesChunk *) ((char *) item_ptr + item_ptr->totalBytes());
item_ptr = (SdesChunk *)((char *)item_ptr + item_ptr->totalBytes());
}
setupHeader(ptr, RtcpType::RTCP_SDES, item_text.size(), bytes);
setupPadding(ptr, bytes - real_size);
return std::shared_ptr<RtcpSdes>(ptr, [](RtcpSdes *ptr) {
delete[] (char *) ptr;
});
return std::shared_ptr<RtcpSdes>(ptr, [](RtcpSdes *ptr) { delete[] (char *)ptr; });
}
string RtcpSdes::dumpString() const {
_StrPrinter printer;
printer << RtcpHeader::dumpHeader();
auto items = ((RtcpSdes *) this)->getChunkList();
auto items = ((RtcpSdes *)this)->getChunkList();
auto i = 0;
for (auto &item : items) {
printer << "---- item:" << i++ << " ----\r\n";
......@@ -508,9 +512,9 @@ void RtcpSdes::net2Host(size_t size) {
CHECK_MIN_SIZE(size, kMinSize);
SdesChunk *ptr = &chunks;
int item_count = 0;
for (int i = 0; i < (int) report_count && (char *) (ptr) + SdesChunk::minSize() <= (char *) (this) + size; ++i) {
for (int i = 0; i < (int)report_count && (char *)(ptr) + SdesChunk::minSize() <= (char *)(this) + size; ++i) {
ptr->net2Host();
ptr = (SdesChunk *) ((char *) ptr + ptr->totalBytes());
ptr = (SdesChunk *)((char *)ptr + ptr->totalBytes());
++item_count;
}
CHECK_REPORT_COUNT(item_count);
......@@ -519,9 +523,9 @@ void RtcpSdes::net2Host(size_t size) {
vector<SdesChunk *> RtcpSdes::getChunkList() {
vector<SdesChunk *> ret;
SdesChunk *ptr = &chunks;
for (int i = 0; i < (int) report_count; ++i) {
for (int i = 0; i < (int)report_count; ++i) {
ret.emplace_back(ptr);
ptr = (SdesChunk *) ((char *) ptr + ptr->totalBytes());
ptr = (SdesChunk *)((char *)ptr + ptr->totalBytes());
}
return ret;
}
......@@ -534,31 +538,29 @@ std::shared_ptr<RtcpFB> RtcpFB::create_l(RtcpType type, int fmt, const void *fci
}
auto real_size = sizeof(RtcpFB) + fci_len;
auto bytes = alignSize(real_size);
auto ptr = (RtcpFB *) new char[bytes];
auto ptr = (RtcpFB *)new char[bytes];
if (fci && fci_len) {
memcpy((char *) ptr + sizeof(RtcpFB), fci, fci_len);
memcpy((char *)ptr + sizeof(RtcpFB), fci, fci_len);
}
setupHeader(ptr, type, fmt, bytes);
setupPadding(ptr, bytes - real_size);
return std::shared_ptr<RtcpFB>((RtcpFB *) ptr, [](RtcpFB *ptr) {
delete[] (char *) ptr;
});
return std::shared_ptr<RtcpFB>((RtcpFB *)ptr, [](RtcpFB *ptr) { delete[] (char *)ptr; });
}
std::shared_ptr<RtcpFB> RtcpFB::create(PSFBType fmt, const void *fci, size_t fci_len) {
return RtcpFB::create_l(RtcpType::RTCP_PSFB, (int) fmt, fci, fci_len);
return RtcpFB::create_l(RtcpType::RTCP_PSFB, (int)fmt, fci, fci_len);
}
std::shared_ptr<RtcpFB> RtcpFB::create(RTPFBType fmt, const void *fci, size_t fci_len) {
return RtcpFB::create_l(RtcpType::RTCP_RTPFB, (int) fmt, fci, fci_len);
return RtcpFB::create_l(RtcpType::RTCP_RTPFB, (int)fmt, fci, fci_len);
}
const void *RtcpFB::getFciPtr() const {
return (uint8_t *) &ssrc_media + sizeof(ssrc_media);
return (uint8_t *)&ssrc_media + sizeof(ssrc_media);
}
size_t RtcpFB::getFciSize() const {
auto fci_len = (ssize_t) getSize() - getPaddingSize() - sizeof(RtcpFB);
auto fci_len = (ssize_t)getSize() - getPaddingSize() - sizeof(RtcpFB);
CHECK(fci_len >= 0);
return fci_len;
}
......@@ -568,58 +570,60 @@ string RtcpFB::dumpString() const {
printer << RtcpHeader::dumpHeader();
printer << "ssrc:" << ssrc << "\r\n";
printer << "ssrc_media:" << ssrc_media << "\r\n";
switch ((RtcpType) pt) {
case RtcpType::RTCP_PSFB : {
switch ((PSFBType) report_count) {
case PSFBType::RTCP_PSFB_SLI : {
auto &fci = getFci<FCI_SLI>();
printer << "fci:" << psfbTypeToStr((PSFBType) report_count) << " " << fci.dumpString();
break;
}
case PSFBType::RTCP_PSFB_PLI : {
getFciSize();
printer << "fci:" << psfbTypeToStr((PSFBType) report_count);
break;
}
case PSFBType::RTCP_PSFB_FIR : {
auto &fci = getFci<FCI_FIR>();
printer << "fci:" << psfbTypeToStr((PSFBType) report_count) << " " << fci.dumpString();
break;
}
case PSFBType::RTCP_PSFB_REMB : {
auto &fci = getFci<FCI_REMB>();
printer << "fci:" << psfbTypeToStr((PSFBType) report_count) << " " << fci.dumpString();
break;
}
default:{
printer << "fci:" << psfbTypeToStr((PSFBType) report_count) << " " << hexdump(getFciPtr(), getFciSize());
break;
}
}
switch ((RtcpType)pt) {
case RtcpType::RTCP_PSFB: {
switch ((PSFBType)report_count) {
case PSFBType::RTCP_PSFB_SLI: {
auto &fci = getFci<FCI_SLI>();
printer << "fci:" << psfbTypeToStr((PSFBType)report_count) << " " << fci.dumpString();
break;
}
case PSFBType::RTCP_PSFB_PLI: {
getFciSize();
printer << "fci:" << psfbTypeToStr((PSFBType)report_count);
break;
}
case PSFBType::RTCP_PSFB_FIR: {
auto &fci = getFci<FCI_FIR>();
printer << "fci:" << psfbTypeToStr((PSFBType)report_count) << " " << fci.dumpString();
break;
}
case RtcpType::RTCP_RTPFB : {
switch ((RTPFBType) report_count) {
case RTPFBType::RTCP_RTPFB_NACK : {
auto &fci = getFci<FCI_NACK>();
printer << "fci:" << rtpfbTypeToStr((RTPFBType) report_count) << " " << fci.dumpString();
break;
}
case RTPFBType::RTCP_RTPFB_TWCC : {
auto &fci = getFci<FCI_TWCC>();
printer << "fci:" << rtpfbTypeToStr((RTPFBType) report_count) << " " << fci.dumpString(getFciSize());
break;
}
default: {
printer << "fci:" << rtpfbTypeToStr((RTPFBType) report_count) << " " << hexdump(getFciPtr(), getFciSize());
break;
}
}
case PSFBType::RTCP_PSFB_REMB: {
auto &fci = getFci<FCI_REMB>();
printer << "fci:" << psfbTypeToStr((PSFBType)report_count) << " " << fci.dumpString();
break;
}
default: /*不可达*/ assert(0); break;
default: {
printer << "fci:" << psfbTypeToStr((PSFBType)report_count) << " " << hexdump(getFciPtr(), getFciSize());
break;
}
}
break;
}
case RtcpType::RTCP_RTPFB: {
switch ((RTPFBType)report_count) {
case RTPFBType::RTCP_RTPFB_NACK: {
auto &fci = getFci<FCI_NACK>();
printer << "fci:" << rtpfbTypeToStr((RTPFBType)report_count) << " " << fci.dumpString();
break;
}
case RTPFBType::RTCP_RTPFB_TWCC: {
auto &fci = getFci<FCI_TWCC>();
printer << "fci:" << rtpfbTypeToStr((RTPFBType)report_count) << " " << fci.dumpString(getFciSize());
break;
}
default: {
printer << "fci:" << rtpfbTypeToStr((RTPFBType)report_count) << " " << hexdump(getFciPtr(), getFciSize());
break;
}
}
break;
}
default: /*不可达*/
assert(0);
break;
}
return std::move(printer);
}
......@@ -637,24 +641,22 @@ std::shared_ptr<RtcpBye> RtcpBye::create(const std::vector<uint32_t> &ssrcs, con
assert(reason.size() <= 0xFF);
auto real_size = sizeof(RtcpHeader) + sizeof(uint32_t) * ssrcs.size() + 1 + reason.size();
auto bytes = alignSize(real_size);
auto ptr = (RtcpBye *) new char[bytes];
auto ptr = (RtcpBye *)new char[bytes];
setupHeader(ptr, RtcpType::RTCP_BYE, ssrcs.size(), bytes);
setupPadding(ptr, bytes - real_size);
int i = 0;
for (auto ssrc : ssrcs) {
((RtcpBye *) ptr)->ssrc[i++] = htonl(ssrc);
((RtcpBye *)ptr)->ssrc[i++] = htonl(ssrc);
}
if (!reason.empty()) {
uint8_t *reason_len_ptr = (uint8_t *) ptr + sizeof(RtcpHeader) + sizeof(uint32_t) * ssrcs.size();
uint8_t *reason_len_ptr = (uint8_t *)ptr + sizeof(RtcpHeader) + sizeof(uint32_t) * ssrcs.size();
*reason_len_ptr = reason.size() & 0xFF;
memcpy(reason_len_ptr + 1, reason.data(), *reason_len_ptr);
}
return std::shared_ptr<RtcpBye>(ptr, [](RtcpBye *ptr) {
delete[] (char *) ptr;
});
return std::shared_ptr<RtcpBye>(ptr, [](RtcpBye *ptr) { delete[] (char *)ptr; });
}
vector<uint32_t *> RtcpBye::getSSRC() {
......@@ -667,16 +669,16 @@ vector<uint32_t *> RtcpBye::getSSRC() {
string RtcpBye::getReason() const {
auto *reason_len_ptr = &reason_len + sizeof(ssrc) * (report_count - 1);
if (reason_len_ptr + 1 >= (uint8_t *) this + getSize()) {
if (reason_len_ptr + 1 >= (uint8_t *)this + getSize()) {
return "";
}
return string((char *) reason_len_ptr + 1, *reason_len_ptr);
return string((char *)reason_len_ptr + 1, *reason_len_ptr);
}
string RtcpBye::dumpString() const {
_StrPrinter printer;
printer << RtcpHeader::dumpHeader();
for (auto ssrc : ((RtcpBye *) this)->getSSRC()) {
for (auto ssrc : ((RtcpBye *)this)->getSSRC()) {
printer << "ssrc:" << *ssrc << "\r\n";
}
printer << "reason:" << getReason();
......@@ -692,35 +694,37 @@ void RtcpBye::net2Host(size_t size) {
ssrc[i] = ntohl(ssrc[i]);
offset += sizeof(ssrc);
}
//修正ssrc个数
// 修正ssrc个数
CHECK_REPORT_COUNT(i);
if (offset < size) {
uint8_t *reason_len_ptr = &reason_len + sizeof(ssrc) * (report_count - 1);
if (reason_len_ptr + 1 + *reason_len_ptr > (uint8_t *) this + size) {
if (reason_len_ptr + 1 + *reason_len_ptr > (uint8_t *)this + size) {
WarnL << "invalid rtcp bye reason length";
//修正reason_len长度
*reason_len_ptr = ((uint8_t *) this + size - reason_len_ptr - 1) & 0xFF;
// 修正reason_len长度
*reason_len_ptr = ((uint8_t *)this + size - reason_len_ptr - 1) & 0xFF;
}
}
}
////////////////////////////////////////////
////////////////////////////////////////////
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";
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);
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);
......@@ -728,14 +732,13 @@ void RtcpXRRRTR::net2Host(size_t size) {
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";
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);
}
......@@ -745,24 +748,23 @@ void RtcpXRDLRRReportItem::net2Host() {
dlrr = ntohl(dlrr);
}
std::vector<RtcpXRDLRRReportItem*> RtcpXRDLRR::getItemList(){
auto count = block_length/3;
std::vector<RtcpXRDLRRReportItem *> RtcpXRDLRR::getItemList() {
auto count = block_length / 3;
RtcpXRDLRRReportItem *ptr = &items;
vector<RtcpXRDLRRReportItem *> ret;
for (int i = 0; i < (int) count; ++i) {
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();
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";
......@@ -778,23 +780,21 @@ void RtcpXRDLRR::net2Host(size_t size) {
ssrc = ntohl(ssrc);
block_length = ntohs(block_length);
auto count = block_length/3;
for (int i = 0; i < (int) count; ++i) {
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){
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];
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;
});
return std::shared_ptr<RtcpXRDLRR>(ptr, [](RtcpXRDLRR *ptr) { delete[] (char *)ptr; });
}
#if 0
......@@ -811,4 +811,4 @@ static toolkit::onceToken token([](){
});
#endif
}//namespace mediakit
\ No newline at end of file
} // namespace mediakit
\ No newline at end of file
......@@ -11,11 +11,11 @@
#ifndef ZLMEDIAKIT_RTCP_H
#define ZLMEDIAKIT_RTCP_H
#include "Common/macros.h"
#include "Network/Buffer.h"
#include "Util/util.h"
#include <stdint.h>
#include <vector>
#include "Util/util.h"
#include "Network/Buffer.h"
#include "Common/macros.h"
namespace mediakit {
......@@ -23,115 +23,115 @@ namespace mediakit {
#pragma pack(push, 1)
#endif // defined(_WIN32)
//http://www.networksorcery.com/enp/protocol/rtcp.htm
#define RTCP_PT_MAP(XX) \
XX(RTCP_FIR, 192) \
XX(RTCP_NACK, 193) \
XX(RTCP_SMPTETC, 194) \
XX(RTCP_IJ, 195) \
XX(RTCP_SR, 200) \
XX(RTCP_RR, 201) \
XX(RTCP_SDES, 202) \
XX(RTCP_BYE, 203) \
XX(RTCP_APP, 204) \
XX(RTCP_RTPFB, 205) \
XX(RTCP_PSFB, 206) \
XX(RTCP_XR, 207) \
XX(RTCP_AVB, 208) \
XX(RTCP_RSI, 209) \
XX(RTCP_TOKEN, 210)
//https://tools.ietf.org/html/rfc3550#section-6.5
#define SDES_TYPE_MAP(XX) \
XX(RTCP_SDES_END, 0) \
XX(RTCP_SDES_CNAME, 1) \
XX(RTCP_SDES_NAME, 2) \
XX(RTCP_SDES_EMAIL, 3) \
XX(RTCP_SDES_PHONE, 4) \
XX(RTCP_SDES_LOC, 5) \
XX(RTCP_SDES_TOOL, 6) \
XX(RTCP_SDES_NOTE, 7) \
XX(RTCP_SDES_PRIVATE, 8)
//https://datatracker.ietf.org/doc/rfc4585/?include_text=1
//6.3. Payload-Specific Feedback Messages
// http://www.networksorcery.com/enp/protocol/rtcp.htm
#define RTCP_PT_MAP(XX) \
XX(RTCP_FIR, 192) \
XX(RTCP_NACK, 193) \
XX(RTCP_SMPTETC, 194) \
XX(RTCP_IJ, 195) \
XX(RTCP_SR, 200) \
XX(RTCP_RR, 201) \
XX(RTCP_SDES, 202) \
XX(RTCP_BYE, 203) \
XX(RTCP_APP, 204) \
XX(RTCP_RTPFB, 205) \
XX(RTCP_PSFB, 206) \
XX(RTCP_XR, 207) \
XX(RTCP_AVB, 208) \
XX(RTCP_RSI, 209) \
XX(RTCP_TOKEN, 210)
// https://tools.ietf.org/html/rfc3550#section-6.5
#define SDES_TYPE_MAP(XX) \
XX(RTCP_SDES_END, 0) \
XX(RTCP_SDES_CNAME, 1) \
XX(RTCP_SDES_NAME, 2) \
XX(RTCP_SDES_EMAIL, 3) \
XX(RTCP_SDES_PHONE, 4) \
XX(RTCP_SDES_LOC, 5) \
XX(RTCP_SDES_TOOL, 6) \
XX(RTCP_SDES_NOTE, 7) \
XX(RTCP_SDES_PRIVATE, 8)
// https://datatracker.ietf.org/doc/rfc4585/?include_text=1
// 6.3. Payload-Specific Feedback Messages
//
// Payload-Specific FB messages are identified by the value PT=PSFB as
// RTCP message type.
// Payload-Specific FB messages are identified by the value PT=PSFB as
// RTCP message type.
//
// Three payload-specific FB messages are defined so far plus an
// application layer FB message. They are identified by means of the
// FMT parameter as follows:
// Three payload-specific FB messages are defined so far plus an
// application layer FB message. They are identified by means of the
// FMT parameter as follows:
//
// 0: unassigned
// 1: Picture Loss Indication (PLI)
// 2: Slice Loss Indication (SLI)
// 3: Reference Picture Selection Indication (RPSI)
// 4: FIR https://tools.ietf.org/html/rfc5104#section-4.3.1.1
// 5: TSTR https://tools.ietf.org/html/rfc5104#section-4.3.2.1
// 6: TSTN https://tools.ietf.org/html/rfc5104#section-4.3.2.1
// 7: VBCM https://tools.ietf.org/html/rfc5104#section-4.3.4.1
// 8-14: unassigned
// 15: REMB / Application layer FB (AFB) message, https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
// 16-30: unassigned
// 31: reserved for future expansion of the sequence number space
#define PSFB_TYPE_MAP(XX) \
XX(RTCP_PSFB_PLI, 1) \
XX(RTCP_PSFB_SLI, 2) \
XX(RTCP_PSFB_RPSI, 3) \
XX(RTCP_PSFB_FIR, 4) \
XX(RTCP_PSFB_TSTR, 5)\
XX(RTCP_PSFB_TSTN, 6)\
XX(RTCP_PSFB_VBCM, 7) \
XX(RTCP_PSFB_REMB, 15)
//https://tools.ietf.org/html/rfc4585#section-6.2
//6.2. Transport Layer Feedback Messages
// 0: unassigned
// 1: Picture Loss Indication (PLI)
// 2: Slice Loss Indication (SLI)
// 3: Reference Picture Selection Indication (RPSI)
// 4: FIR https://tools.ietf.org/html/rfc5104#section-4.3.1.1
// 5: TSTR https://tools.ietf.org/html/rfc5104#section-4.3.2.1
// 6: TSTN https://tools.ietf.org/html/rfc5104#section-4.3.2.1
// 7: VBCM https://tools.ietf.org/html/rfc5104#section-4.3.4.1
// 8-14: unassigned
// 15: REMB / Application layer FB (AFB) message, https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
// 16-30: unassigned
// 31: reserved for future expansion of the sequence number space
#define PSFB_TYPE_MAP(XX) \
XX(RTCP_PSFB_PLI, 1) \
XX(RTCP_PSFB_SLI, 2) \
XX(RTCP_PSFB_RPSI, 3) \
XX(RTCP_PSFB_FIR, 4) \
XX(RTCP_PSFB_TSTR, 5) \
XX(RTCP_PSFB_TSTN, 6) \
XX(RTCP_PSFB_VBCM, 7) \
XX(RTCP_PSFB_REMB, 15)
// https://tools.ietf.org/html/rfc4585#section-6.2
// 6.2. Transport Layer Feedback Messages
//
// Transport layer FB messages are identified by the value RTPFB as RTCP
// message type.
// Transport layer FB messages are identified by the value RTPFB as RTCP
// message type.
//
// A single general purpose transport layer FB message is defined in
// this document: Generic NACK. It is identified by means of the FMT
// parameter as follows:
// A single general purpose transport layer FB message is defined in
// this document: Generic NACK. It is identified by means of the FMT
// parameter as follows:
//
// 0: unassigned
// 1: Generic NACK
// 2: reserved https://tools.ietf.org/html/rfc5104#section-4.2
// 3: TMMBR https://tools.ietf.org/html/rfc5104#section-4.2.1.1
// 4: TMMBN https://tools.ietf.org/html/rfc5104#section-4.2.2.1
// 5-14: unassigned
// 15 transport-cc https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
// 16-30: unassigned
// 31: reserved for future expansion of the identifier number space
#define RTPFB_TYPE_MAP(XX) \
XX(RTCP_RTPFB_NACK, 1) \
XX(RTCP_RTPFB_TMMBR, 3) \
XX(RTCP_RTPFB_TMMBN, 4) \
XX(RTCP_RTPFB_TWCC, 15)
//rtcp类型枚举
// 0: unassigned
// 1: Generic NACK
// 2: reserved https://tools.ietf.org/html/rfc5104#section-4.2
// 3: TMMBR https://tools.ietf.org/html/rfc5104#section-4.2.1.1
// 4: TMMBN https://tools.ietf.org/html/rfc5104#section-4.2.2.1
// 5-14: unassigned
// 15 transport-cc https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01
// 16-30: unassigned
// 31: reserved for future expansion of the identifier number space
#define RTPFB_TYPE_MAP(XX) \
XX(RTCP_RTPFB_NACK, 1) \
XX(RTCP_RTPFB_TMMBR, 3) \
XX(RTCP_RTPFB_TMMBN, 4) \
XX(RTCP_RTPFB_TWCC, 15)
// rtcp类型枚举
enum class RtcpType : uint8_t {
#define XX(key, value) key = value,
RTCP_PT_MAP(XX)
#undef XX
};
//sdes类型枚举
// sdes类型枚举
enum class SdesType : uint8_t {
#define XX(key, value) key = value,
SDES_TYPE_MAP(XX)
#undef XX
};
//psfb类型枚举
// psfb类型枚举
enum class PSFBType : uint8_t {
#define XX(key, value) key = value,
PSFB_TYPE_MAP(XX)
#undef XX
};
//rtpfb类型枚举
// rtpfb类型枚举
enum class RTPFBType : uint8_t {
#define XX(key, value) key = value,
RTPFB_TYPE_MAP(XX)
......@@ -161,26 +161,26 @@ const char *rtpfbTypeToStr(RTPFBType type);
class RtcpHeader {
public:
#if __BYTE_ORDER == __BIG_ENDIAN
//版本号,固定为2
uint32_t version: 2;
//padding,固定为0
uint32_t padding: 1;
//reception report count
uint32_t report_count: 5;
// 版本号,固定为2
uint32_t version : 2;
// padding,固定为0
uint32_t padding : 1;
// reception report count
uint32_t report_count : 5;
#else
//reception report count
uint32_t report_count: 5;
//padding,末尾是否有追加填充
uint32_t padding: 1;
//版本号,固定为2
uint32_t version: 2;
// reception report count
uint32_t report_count : 5;
// padding,末尾是否有追加填充
uint32_t padding : 1;
// 版本号,固定为2
uint32_t version : 2;
#endif
//rtcp类型,RtcpType
uint32_t pt: 8;
// rtcp类型,RtcpType
uint32_t pt : 8;
private:
//长度
uint32_t length: 16;
// 长度
uint32_t length : 16;
public:
/**
......@@ -222,7 +222,6 @@ public:
void setSize(size_t size);
protected:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
......@@ -240,26 +239,26 @@ private:
/////////////////////////////////////////////////////////////////////////////
//ReportBlock
// ReportBlock
class ReportItem {
public:
friend class RtcpSR;
friend class RtcpRR;
uint32_t ssrc;
//Fraction lost
uint32_t fraction: 8;
//Cumulative number of packets lost
uint32_t cumulative: 24;
//Sequence number cycles count
// Fraction lost
uint32_t fraction : 8;
// Cumulative number of packets lost
uint32_t cumulative : 24;
// Sequence number cycles count
uint16_t seq_cycles;
//Highest sequence number received
// Highest sequence number received
uint16_t seq_max;
//Interarrival jitter
// Interarrival jitter
uint32_t jitter;
//Last SR timestamp, NTP timestamp,(ntpmsw & 0xFFFF) << 16 | (ntplsw >> 16) & 0xFFFF)
// Last SR timestamp, NTP timestamp,(ntpmsw & 0xFFFF) << 16 | (ntplsw >> 16) & 0xFFFF)
uint32_t last_sr_stamp;
//Delay since last SR timestamp,expressed in units of 1/65536 seconds
// Delay since last SR timestamp,expressed in units of 1/65536 seconds
uint32_t delay_since_last_sr;
private:
......@@ -273,7 +272,7 @@ private:
* 网络字节序转换为主机字节序
*/
void net2Host();
}PACKED;
} PACKED;
/*
* 6.4.1 SR: Sender Report RTCP Packet
......@@ -329,7 +328,7 @@ public:
uint32_t packet_count;
// sender octet count
uint32_t octet_count;
//可能有很多个
// 可能有很多个
ReportItem items;
public:
......@@ -358,13 +357,13 @@ public:
* 获取ReportItem对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::vector<ReportItem*> getItemList();
std::vector<ReportItem *> getItemList();
private:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::string dumpString() const;
/**
......@@ -406,13 +405,13 @@ block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
//Receiver Report
// Receiver Report
class RtcpRR : public RtcpHeader {
public:
friend class RtcpHeader;
uint32_t ssrc;
//可能有很多个
// 可能有很多个
ReportItem items;
public:
......@@ -420,14 +419,14 @@ public:
* 创建RR包,只赋值了RtcpHeader部分
* @param item_count ReportItem对象个数
* @return RR包
*/
*/
static std::shared_ptr<RtcpRR> create(size_t item_count);
/**
* 获取ReportItem对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::vector<ReportItem*> getItemList();
std::vector<ReportItem *> getItemList();
private:
/**
......@@ -475,20 +474,20 @@ SDES items 定义
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
//Source description Chunk
// Source description Chunk
class SdesChunk {
public:
friend class RtcpSdes;
uint32_t ssrc;
//SdesType
// SdesType
uint8_t type;
//text长度股,可以为0
// text长度股,可以为0
uint8_t txt_len;
//不定长
// 不定长
char text[1];
//最后以RTCP_SDES_END结尾
//只字段为占位字段,不代表真实位置
// 最后以RTCP_SDES_END结尾
// 只字段为占位字段,不代表真实位置
uint8_t end;
public:
......@@ -511,16 +510,16 @@ private:
/**
* 网络字节序转换为主机字节序
*/
*/
void net2Host();
} PACKED;
//Source description
// Source description
class RtcpSdes : public RtcpHeader {
public:
friend class RtcpHeader;
//可能有很多个
// 可能有很多个
SdesChunk chunks;
public:
......@@ -535,13 +534,13 @@ public:
* 获取SdesChunk对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::vector<SdesChunk*> getChunkList();
std::vector<SdesChunk *> getChunkList();
private:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::string dumpString() const;
/**
......@@ -591,11 +590,11 @@ public:
* @tparam Type 对象类型
* @return 对象指针
*/
template<typename Type>
const Type& getFci() const{
template <typename Type>
const Type &getFci() const {
auto fci_data = getFciPtr();
auto fci_len = getFciSize();
Type *fci = (Type *) fci_data;
Type *fci = (Type *)fci_data;
fci->check(fci_len);
return *fci;
}
......@@ -612,9 +611,9 @@ public:
private:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::string dumpString() const;
/**
......@@ -627,7 +626,7 @@ private:
static std::shared_ptr<RtcpFB> create_l(RtcpType type, int fmt, const void *fci, size_t fci_len);
} PACKED;
//BYE
// BYE
/*
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
......@@ -675,9 +674,9 @@ public:
private:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::string dumpString() const;
/**
......@@ -712,8 +711,7 @@ private:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
class RtcpXRRRTR : public RtcpHeader
{
class RtcpXRRRTR : public RtcpHeader {
public:
friend class RtcpHeader;
uint32_t ssrc;
......@@ -722,15 +720,16 @@ public:
uint8_t reserved;
// 2
uint16_t block_length;
// ntp timestamp MSW(in second)
// ntp timestamp MSW(in second)
uint32_t ntpmsw;
// ntp timestamp LSW(in picosecond)
uint32_t ntplsw;
private:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::string dumpString() const;
/**
......@@ -739,7 +738,7 @@ private:
*/
void net2Host(size_t size);
}PACKED;
} PACKED;
/*
......@@ -759,18 +758,18 @@ private:
: ... : 2
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
class RtcpXRDLRRReportItem
{
class RtcpXRDLRRReportItem {
public:
friend class RtcpXRDLRR;
uint32_t ssrc;
uint32_t lrr;
uint32_t dlrr;
private:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::string dumpString() const;
/**
......@@ -778,12 +777,9 @@ private:
* @param size 字节长度,防止内存越界
*/
void net2Host();
}PACKED;
} PACKED;
class RtcpXRDLRR : public RtcpHeader
{
class RtcpXRDLRR : public RtcpHeader {
public:
friend class RtcpHeader;
uint32_t ssrc;
......@@ -799,17 +795,17 @@ public:
*/
static std::shared_ptr<RtcpXRDLRR> create(size_t item_count);
/**
/**
* 获取RtcpXRDLRRReportItem对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::vector<RtcpXRDLRRReportItem*> getItemList();
std::vector<RtcpXRDLRRReportItem *> getItemList();
private:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std::string dumpString() const;
/**
......@@ -818,12 +814,11 @@ private:
*/
void net2Host(size_t size);
}PACKED;
} PACKED;
#if defined(_WIN32)
#pragma pack(pop)
#endif // defined(_WIN32)
} //namespace mediakit
#endif //ZLMEDIAKIT_RTCP_H
} // namespace mediakit
#endif // ZLMEDIAKIT_RTCP_H
......@@ -14,7 +14,8 @@ using namespace toolkit;
namespace mediakit {
void RtcpContext::onRtp(uint16_t /*seq*/, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t /*sample_rate*/, size_t bytes) {
void RtcpContext::onRtp(
uint16_t /*seq*/, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t /*sample_rate*/, size_t bytes) {
++_packets;
_bytes += bytes;
_last_rtp_stamp = stamp;
......@@ -52,43 +53,45 @@ Buffer::Ptr RtcpContext::createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc)
////////////////////////////////////////////////////////////////////////////////////
void RtcpContextForSend::onRtcp(RtcpHeader *rtcp) {
switch ((RtcpType) rtcp->pt) {
case RtcpType::RTCP_RR: {
auto rtcp_rr = (RtcpRR *) rtcp;
for (auto item : rtcp_rr->getItemList()) {
if (!item->last_sr_stamp) {
continue;
}
auto it = _sender_report_ntp.find(item->last_sr_stamp);
if (it == _sender_report_ntp.end()) {
continue;
}
//发送sr到收到rr之间的时间戳增量
auto ms_inc = getCurrentMillisecond() - it->second;
//rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒
auto delay_ms = (uint64_t) item->delay_since_last_sr * 1000 / 65536;
auto rtt = (int) (ms_inc - delay_ms);
if (rtt >= 0) {
//rtt不可能小于0
_rtt[item->ssrc] = rtt;
//InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt;
}
switch ((RtcpType)rtcp->pt) {
case RtcpType::RTCP_RR: {
auto rtcp_rr = (RtcpRR *)rtcp;
for (auto item : rtcp_rr->getItemList()) {
if (!item->last_sr_stamp) {
continue;
}
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;
auto it = _sender_report_ntp.find(item->last_sr_stamp);
if (it == _sender_report_ntp.end()) {
continue;
}
// 发送sr到收到rr之间的时间戳增量
auto ms_inc = getCurrentMillisecond() - it->second;
// rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒
auto delay_ms = (uint64_t)item->delay_since_last_sr * 1000 / 65536;
auto rtt = (int)(ms_inc - delay_ms);
if (rtt >= 0) {
// rtt不可能小于0
_rtt[item->ssrc] = rtt;
// InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt;
}
break;
}
default: 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;
}
}
......@@ -105,21 +108,21 @@ Buffer::Ptr RtcpContextForSend::createRtcpSR(uint32_t rtcp_ssrc) {
rtcp->setNtpStamp(_last_ntp_stamp_ms);
rtcp->rtpts = htonl(_last_rtp_stamp);
rtcp->ssrc = htonl(rtcp_ssrc);
rtcp->packet_count = htonl((uint32_t) _packets);
rtcp->octet_count = htonl((uint32_t) _bytes);
rtcp->packet_count = htonl((uint32_t)_packets);
rtcp->octet_count = htonl((uint32_t)_bytes);
//记录上次发送的sender report信息,用于后续统计rtt
// 记录上次发送的sender report信息,用于后续统计rtt
auto last_sr_lsr = ((ntohl(rtcp->ntpmsw) & 0xFFFF) << 16) | ((ntohl(rtcp->ntplsw) >> 16) & 0xFFFF);
_sender_report_ntp[last_sr_lsr] = getCurrentMillisecond();
if (_sender_report_ntp.size() >= 5) {
//删除最早的sr rtcp
// 删除最早的sr rtcp
_sender_report_ntp.erase(_sender_report_ntp.begin());
}
return RtcpHeader::toBuffer(std::move(rtcp));
}
toolkit::Buffer::Ptr RtcpContextForSend::createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc){
toolkit::Buffer::Ptr RtcpContextForSend::createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) {
auto rtcp = RtcpXRDLRR::create(1);
rtcp->bt = 5;
rtcp->reserved = 0;
......@@ -127,14 +130,14 @@ toolkit::Buffer::Ptr RtcpContextForSend::createRtcpXRDLRR(uint32_t rtcp_ssrc, ui
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()){
if (_xr_xrrtr_recv_last_rr.find(rtp_ssrc) == _xr_xrrtr_recv_last_rr.end()) {
rtcp->items.lrr = 0;
WarnL;
}else{
} 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()){
if (_xr_rrtr_recv_sys_stamp.find(rtp_ssrc) == _xr_rrtr_recv_sys_stamp.end()) {
rtcp->items.dlrr = 0;
WarnL;
} else {
......@@ -149,39 +152,41 @@ toolkit::Buffer::Ptr RtcpContextForSend::createRtcpXRDLRR(uint32_t rtcp_ssrc, ui
////////////////////////////////////////////////////////////////////////////////////
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) {
{
//接收者才做复杂的统计运算
// 接收者才做复杂的统计运算
auto sys_stamp = getCurrentMillisecond();
if (_last_rtp_sys_stamp) {
//计算时间戳抖动值
double diff = double((int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp)) * (sample_rate / double(1000.0))
- (int64_t(stamp) - int64_t(_last_rtp_stamp)));
// 计算时间戳抖动值
double diff = double(
(int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp)) * (sample_rate / double(1000.0))
- (int64_t(stamp) - int64_t(_last_rtp_stamp)));
if (diff < 0) {
diff = -diff;
}
//抖动单位为采样次数
// 抖动单位为采样次数
_jitter += (diff - _jitter) / 16.0;
} else {
_jitter = 0;
}
if (_last_rtp_seq > 0xFF00 && seq < 0xFF && (!_seq_cycles || _packets - _last_cycle_packets > 0x1FFF)) {
//上次seq大于0xFF00且本次seq小于0xFF,
//且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环
// 上次seq大于0xFF00且本次seq小于0xFF,
// 且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环
++_seq_cycles;
_last_cycle_packets = _packets;
_seq_max = seq;
} else if (seq > _seq_max) {
//本次回环前最大seq
// 本次回环前最大seq
_seq_max = seq;
}
if (!_seq_base) {
//记录第一个rtp的seq
// 记录第一个rtp的seq
_seq_base = seq;
} else if (!_seq_cycles && seq < _seq_base) {
//未发生回环,那么取最新的seq为基准seq
// 未发生回环,那么取最新的seq为基准seq
_seq_base = seq;
}
......@@ -192,21 +197,22 @@ void RtcpContextForRecv::onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_
}
void RtcpContextForRecv::onRtcp(RtcpHeader *rtcp) {
switch ((RtcpType) rtcp->pt) {
case RtcpType::RTCP_SR: {
auto rtcp_sr = (RtcpSR *) rtcp;
/**
last SR timestamp (LSR): 32 bits
The middle 32 bits out of 64 in the NTP timestamp (as explained in
Section 4) received as part of the most recent RTCP sender report
(SR) packet from source SSRC_n. If no SR has been received yet,
the field is set to zero.
*/
_last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF);
_last_sr_ntp_sys = getCurrentMillisecond();
break;
}
default: break;
switch ((RtcpType)rtcp->pt) {
case RtcpType::RTCP_SR: {
auto rtcp_sr = (RtcpSR *)rtcp;
/**
last SR timestamp (LSR): 32 bits
The middle 32 bits out of 64 in the NTP timestamp (as explained in
Section 4) received as part of the most recent RTCP sender report
(SR) packet from source SSRC_n. If no SR has been received yet,
the field is set to zero.
*/
_last_sr_lsr = ((rtcp_sr->ntpmsw & 0xFFFF) << 16) | ((rtcp_sr->ntplsw >> 16) & 0xFFFF);
_last_sr_ntp_sys = getCurrentMillisecond();
break;
}
default:
break;
}
}
......@@ -236,7 +242,7 @@ Buffer::Ptr RtcpContextForRecv::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ss
auto rtcp = RtcpRR::create(1);
rtcp->ssrc = htonl(rtcp_ssrc);
ReportItem *item = (ReportItem *) &rtcp->items;
ReportItem *item = (ReportItem *)&rtcp->items;
item->ssrc = htonl(rtp_ssrc);
uint8_t fraction = 0;
......@@ -255,9 +261,9 @@ Buffer::Ptr RtcpContextForRecv::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ss
// now - Last SR time,单位毫秒
auto delay = getCurrentMillisecond() - _last_sr_ntp_sys;
// in units of 1/65536 seconds
auto dlsr = (uint32_t) (delay / 1000.0f * 65536);
auto dlsr = (uint32_t)(delay / 1000.0f * 65536);
item->delay_since_last_sr = htonl(_last_sr_lsr ? dlsr : 0);
return RtcpHeader::toBuffer(rtcp);
}
}//namespace mediakit
\ No newline at end of file
} // namespace mediakit
\ No newline at end of file
......@@ -11,9 +11,9 @@
#ifndef ZLMEDIAKIT_RTCPCONTEXT_H
#define ZLMEDIAKIT_RTCPCONTEXT_H
#include <stdint.h>
#include <stddef.h>
#include "Rtcp.h"
#include <stddef.h>
#include <stdint.h>
namespace mediakit {
......@@ -55,11 +55,10 @@ public:
*/
virtual toolkit::Buffer::Ptr createRtcpSR(uint32_t rtcp_ssrc);
/**
* @brief 创建xr的dlrr包,用于接收者估算rtt
*
* @return toolkit::Buffer::Ptr
*
* @return toolkit::Buffer::Ptr
*/
virtual toolkit::Buffer::Ptr createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc);
......@@ -82,11 +81,11 @@ public:
virtual size_t geLostInterval();
protected:
//收到或发送的rtp的字节数
// 收到或发送的rtp的字节数
size_t _bytes = 0;
//收到或发送的rtp的个数
// 收到或发送的rtp的个数
size_t _packets = 0;
//上次的rtp时间戳,毫秒
// 上次的rtp时间戳,毫秒
uint32_t _last_rtp_stamp = 0;
uint64_t _last_ntp_stamp_ms = 0;
};
......@@ -107,11 +106,11 @@ public:
uint32_t getRtt(uint32_t ssrc) const;
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*/, 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;
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 {
......@@ -125,29 +124,29 @@ public:
void onRtcp(RtcpHeader *rtcp) override;
private:
//时间戳抖动值
// 时间戳抖动值
double _jitter = 0;
//第一个seq的值
// 第一个seq的值
uint16_t _seq_base = 0;
//rtp最大seq
// rtp最大seq
uint16_t _seq_max = 0;
//rtp回环次数
// rtp回环次数
uint16_t _seq_cycles = 0;
//上次回环发生时,记录的rtp包数
// 上次回环发生时,记录的rtp包数
size_t _last_cycle_packets = 0;
//上次的seq
// 上次的seq
uint16_t _last_rtp_seq = 0;
//上次的rtp的系统时间戳(毫秒)用于统计抖动
// 上次的rtp的系统时间戳(毫秒)用于统计抖动
uint64_t _last_rtp_sys_stamp = 0;
//上次统计的丢包总数
// 上次统计的丢包总数
size_t _last_lost = 0;
//上次统计应收rtp包总数
// 上次统计应收rtp包总数
size_t _last_expected = 0;
//上次收到sr包时计算出的Last SR timestamp
// 上次收到sr包时计算出的Last SR timestamp
uint32_t _last_sr_lsr = 0;
//上次收到sr时的系统时间戳,单位毫秒
// 上次收到sr时的系统时间戳,单位毫秒
uint64_t _last_sr_ntp_sys = 0;
};
}//namespace mediakit
#endif //ZLMEDIAKIT_RTCPCONTEXT_H
} // namespace mediakit
#endif // ZLMEDIAKIT_RTCPCONTEXT_H
......@@ -16,16 +16,16 @@ using namespace toolkit;
namespace mediakit {
void FCI_SLI::check(size_t size){
void FCI_SLI::check(size_t size) {
CHECK(size >= kSize);
}
FCI_SLI::FCI_SLI(uint16_t first, uint16_t number, uint8_t pic_id) {
//13 bits
// 13 bits
first &= 0x1FFF;
//13 bits
// 13 bits
number &= 0x1FFF;
//6 bits
// 6 bits
pic_id &= 0x3F;
data = (first << 19) | (number << 6) | pic_id;
data = htonl(data);
......@@ -49,19 +49,19 @@ string FCI_SLI::dumpString() const {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void FCI_FIR::check(size_t size){
void FCI_FIR::check(size_t size) {
CHECK(size >= kSize);
}
uint32_t FCI_FIR::getSSRC() const{
uint32_t FCI_FIR::getSSRC() const {
return ntohl(ssrc);
}
uint8_t FCI_FIR::getSeq() const{
uint8_t FCI_FIR::getSeq() const {
return seq_number;
}
uint32_t FCI_FIR::getReserved() const{
uint32_t FCI_FIR::getReserved() const {
return (reserved[0] << 16) | (reserved[1] << 8) | reserved[2];
}
......@@ -81,7 +81,7 @@ FCI_FIR::FCI_FIR(uint32_t ssrc, uint8_t seq_number, uint32_t reserved) {
static const char kRembMagic[] = "REMB";
void FCI_REMB::check(size_t size){
void FCI_REMB::check(size_t size) {
CHECK(size >= kSize);
CHECK(memcmp(magic, kRembMagic, sizeof(magic)) == 0);
auto num_ssrc = bitrate[0];
......@@ -93,7 +93,7 @@ string FCI_REMB::create(const vector<uint32_t> &ssrcs, uint32_t bitrate) {
CHECK(ssrcs.size() > 0 && ssrcs.size() <= 0xFF);
string ret;
ret.resize(kSize + ssrcs.size() * 4);
FCI_REMB *thiz = (FCI_REMB *) ret.data();
FCI_REMB *thiz = (FCI_REMB *)ret.data();
memcpy(thiz->magic, kRembMagic, sizeof(magic));
/* bitrate --> BR Exp/BR Mantissa */
......@@ -101,7 +101,7 @@ string FCI_REMB::create(const vector<uint32_t> &ssrcs, uint32_t bitrate) {
uint8_t exp = 0;
uint32_t mantissa = 0;
for (b = 0; b < 32; b++) {
if (bitrate <= ((uint32_t) 0x3FFFF << b)) {
if (bitrate <= ((uint32_t)0x3FFFF << b)) {
exp = b;
break;
}
......@@ -110,16 +110,16 @@ string FCI_REMB::create(const vector<uint32_t> &ssrcs, uint32_t bitrate) {
b = 31;
}
mantissa = bitrate >> b;
//Num SSRC (8 bits)
// Num SSRC (8 bits)
thiz->bitrate[0] = ssrcs.size() & 0xFF;
//BR Exp (6 bits)/BR Mantissa (18 bits)
thiz->bitrate[1] = (uint8_t) ((exp << 2) + ((mantissa >> 16) & 0x03));
//BR Mantissa (18 bits)
thiz->bitrate[2] = (uint8_t) (mantissa >> 8);
//BR Mantissa (18 bits)
thiz->bitrate[3] = (uint8_t) (mantissa);
//设置ssrc列表
// BR Exp (6 bits)/BR Mantissa (18 bits)
thiz->bitrate[1] = (uint8_t)((exp << 2) + ((mantissa >> 16) & 0x03));
// BR Mantissa (18 bits)
thiz->bitrate[2] = (uint8_t)(mantissa >> 8);
// BR Mantissa (18 bits)
thiz->bitrate[3] = (uint8_t)(mantissa);
// 设置ssrc列表
int i = 0;
for (auto ssrc : ssrcs) {
thiz->ssrc_feedback[i++] = htonl(ssrc);
......@@ -149,7 +149,7 @@ vector<uint32_t> FCI_REMB::getSSRC() {
string FCI_REMB::dumpString() const {
_StrPrinter printer;
printer << "bitrate:" << getBitRate() << ", ssrc:";
for (auto &ssrc : ((FCI_REMB *) this)->getSSRC()) {
for (auto &ssrc : ((FCI_REMB *)this)->getSSRC()) {
printer << ssrc << " ";
}
return std::move(printer);
......@@ -171,7 +171,7 @@ FCI_NACK::FCI_NACK(uint16_t pid_h, const vector<bool> &type) {
pid = htons(pid_h);
}
void FCI_NACK::check(size_t size){
void FCI_NACK::check(size_t size) {
CHECK(size >= kSize);
}
......@@ -186,7 +186,7 @@ uint16_t FCI_NACK::getBlp() const {
vector<bool> FCI_NACK::getBitArray() const {
vector<bool> ret;
ret.resize(kBitSize + 1);
//nack第一个包丢包
// nack第一个包丢包
ret[0] = true;
auto blp_h = getBlp();
......@@ -220,25 +220,25 @@ public:
// |T| S | Run Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#if __BYTE_ORDER == __BIG_ENDIAN
uint16_t type: 1;
uint16_t symbol: 2;
uint16_t run_length_high: 5;
uint16_t type : 1;
uint16_t symbol : 2;
uint16_t run_length_high : 5;
#else
// Run Length 高5位
uint16_t run_length_high: 5;
//参考SymbolStatus定义
uint16_t symbol: 2;
//固定为0
uint16_t type: 1;
uint16_t run_length_high : 5;
// 参考SymbolStatus定义
uint16_t symbol : 2;
// 固定为0
uint16_t type : 1;
#endif
// Run Length 低8位
uint16_t run_length_low: 8;
uint16_t run_length_low : 8;
//获取Run Length
// 获取Run Length
uint16_t getRunLength() const;
//构造函数
// 构造函数
RunLengthChunk(SymbolStatus status, uint16_t run_length);
//打印本对象
// 打印本对象
string dumpString() const;
} PACKED;
......@@ -254,7 +254,7 @@ uint16_t RunLengthChunk::getRunLength() const {
return run_length_high << 8 | run_length_low;
}
string RunLengthChunk::dumpString() const{
string RunLengthChunk::dumpString() const {
_StrPrinter printer;
printer << "run length chunk, symbol:" << (int)symbol << ", run length:" << getRunLength();
return std::move(printer);
......@@ -271,30 +271,30 @@ public:
// |T|S| symbol list |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#if __BYTE_ORDER == __BIG_ENDIAN
uint16_t type: 1;
uint16_t symbol: 1;
uint16_t symbol_list_high: 6;
uint16_t type : 1;
uint16_t symbol : 1;
uint16_t symbol_list_high : 6;
#else
// symbol_list 高6位
uint16_t symbol_list_high: 6;
//symbol_list中元素是1个还是2个bit
uint16_t symbol: 1;
//固定为1
uint16_t type: 1;
uint16_t symbol_list_high : 6;
// symbol_list中元素是1个还是2个bit
uint16_t symbol : 1;
// 固定为1
uint16_t type : 1;
#endif
// symbol_list 低8位
uint16_t symbol_list_low: 8;
uint16_t symbol_list_low : 8;
//获取symbollist
// 获取symbollist
vector<SymbolStatus> getSymbolList() const;
//构造函数
// 构造函数
StatusVecChunk(bool symbol_bit, const vector<SymbolStatus> &status);
//打印本对象
// 打印本对象
string dumpString() const;
} PACKED;
StatusVecChunk::StatusVecChunk(bool symbol_bit, const vector<SymbolStatus> &status) {
CHECK( status.size() << symbol_bit <= 14);
CHECK(status.size() << symbol_bit <= 14);
uint16_t value = 0;
type = 1;
symbol = symbol_bit;
......@@ -303,31 +303,31 @@ StatusVecChunk::StatusVecChunk(bool symbol_bit, const vector<SymbolStatus> &stat
CHECK(item <= SymbolStatus::reserved);
if (!symbol) {
CHECK(item <= SymbolStatus::small_delta);
value |= (int) item << i;
value |= (int)item << i;
--i;
} else {
value |= (int) item << (i - 1);
value |= (int)item << (i - 1);
i -= 2;
}
}
symbol_list_low = value & 0xFF;
symbol_list_high = (value >> 8 ) & 0x3F;
symbol_list_high = (value >> 8) & 0x3F;
}
vector<SymbolStatus> StatusVecChunk::getSymbolList() const {
CHECK(type == 1);
vector<SymbolStatus> ret;
auto thiz = ntohs(*((uint16_t *) this));
auto thiz = ntohs(*((uint16_t *)this));
if (symbol == 0) {
//s = 0 时,表示symbollist的每一个bit能表示一个数据包的到达状态
// s = 0 时,表示symbollist的每一个bit能表示一个数据包的到达状态
for (int i = 13; i >= 0; --i) {
SymbolStatus status = (SymbolStatus) ((bool) (thiz & (1 << i)));
SymbolStatus status = (SymbolStatus)((bool)(thiz & (1 << i)));
ret.emplace_back(status);
}
} else {
//s = 1 时,表示symbollist每两个bit表示一个数据包的状态
// s = 1 时,表示symbollist每两个bit表示一个数据包的状态
for (int i = 12; i >= 0; i -= 2) {
SymbolStatus status = (SymbolStatus) ((thiz & (3 << i)) >> i);
SymbolStatus status = (SymbolStatus)((thiz & (3 << i)) >> i);
ret.emplace_back(status);
}
}
......@@ -336,17 +336,17 @@ vector<SymbolStatus> StatusVecChunk::getSymbolList() const {
string StatusVecChunk::dumpString() const {
_StrPrinter printer;
printer << "status vector chunk, symbol:" << (int) symbol << ", symbol list:";
printer << "status vector chunk, symbol:" << (int)symbol << ", symbol list:";
auto vec = getSymbolList();
for (auto &item : vec) {
printer << (int) item << " ";
printer << (int)item << " ";
}
return std::move(printer);
}
///////////////////////////////////////////////////////
void FCI_TWCC::check(size_t size){
void FCI_TWCC::check(size_t size) {
CHECK(size >= kSize);
}
......@@ -365,87 +365,87 @@ uint32_t FCI_TWCC::getReferenceTime() const {
ret |= ref_time[2];
return ret;
}
//3.1.5. Receive Delta
// 3.1.5. Receive Delta
//
// Deltas are represented as multiples of 250us:
// Deltas are represented as multiples of 250us:
//
// o If the "Packet received, small delta" symbol has been appended to
// the status list, an 8-bit unsigned receive delta will be appended
// to recv delta list, representing a delta in the range [0, 63.75]
// ms.
// o If the "Packet received, small delta" symbol has been appended to
// the status list, an 8-bit unsigned receive delta will be appended
// to recv delta list, representing a delta in the range [0, 63.75]
// ms.
//
// o If the "Packet received, large or negative delta" symbol has been
// appended to the status list, a 16-bit signed receive delta will be
// appended to recv delta list, representing a delta in the range
// [-8192.0, 8191.75] ms.
// o If the "Packet received, large or negative delta" symbol has been
// appended to the status list, a 16-bit signed receive delta will be
// appended to recv delta list, representing a delta in the range
// [-8192.0, 8191.75] ms.
//
// o If the delta exceeds even the larger limits, a new feedback
// message must be used, where the 24-bit base receive delta can
// cover very large gaps.
// o If the delta exceeds even the larger limits, a new feedback
// message must be used, where the 24-bit base receive delta can
// cover very large gaps.
//
// The smaller receive delta upper bound of 63.75 ms means that this is
// only viable at about 1000/25.5 ~= 16 packets per second and above.
// With a packet size of 1200 bytes/packet that amounts to a bitrate of
// about 150 kbit/s.
// The smaller receive delta upper bound of 63.75 ms means that this is
// only viable at about 1000/25.5 ~= 16 packets per second and above.
// With a packet size of 1200 bytes/packet that amounts to a bitrate of
// about 150 kbit/s.
//
// The 0.25 ms resolution means that up to 4000 packets per second can
// be represented. With a 1200 bytes/packet payload, that amounts to
// 38.4 Mbit/s payload bandwidth.
// The 0.25 ms resolution means that up to 4000 packets per second can
// be represented. With a 1200 bytes/packet payload, that amounts to
// 38.4 Mbit/s payload bandwidth.
static int16_t getRecvDelta(SymbolStatus status, uint8_t *&ptr, const uint8_t *end){
static int16_t getRecvDelta(SymbolStatus status, uint8_t *&ptr, const uint8_t *end) {
int16_t delta = 0;
switch (status) {
case SymbolStatus::not_received : {
//丢包, recv delta为0个字节
break;
}
case SymbolStatus::small_delta : {
CHECK(ptr + 1 <= end);
//时间戳增量小于256, recv delta为1个字节
delta = *ptr;
ptr += 1;
break;
}
case SymbolStatus::large_delta : {
CHECK(ptr + 2 <= end);
//时间戳增量256~65535间,recv delta为2个字节
delta = *ptr << 8 | *(ptr + 1);
ptr += 2;
break;
}
case SymbolStatus::reserved : {
//没有时间戳
break;
}
default:
//这个逻辑分支不可达到
CHECK(0);
break;
case SymbolStatus::not_received: {
// 丢包, recv delta为0个字节
break;
}
case SymbolStatus::small_delta: {
CHECK(ptr + 1 <= end);
// 时间戳增量小于256, recv delta为1个字节
delta = *ptr;
ptr += 1;
break;
}
case SymbolStatus::large_delta: {
CHECK(ptr + 2 <= end);
// 时间戳增量256~65535间,recv delta为2个字节
delta = *ptr << 8 | *(ptr + 1);
ptr += 2;
break;
}
case SymbolStatus::reserved: {
// 没有时间戳
break;
}
default:
// 这个逻辑分支不可达到
CHECK(0);
break;
}
return delta;
}
FCI_TWCC::TwccPacketStatus FCI_TWCC::getPacketChunkList(size_t total_size) const {
TwccPacketStatus ret;
auto ptr = (uint8_t *) this + kSize;
auto end = (uint8_t *) this + total_size;
auto ptr = (uint8_t *)this + kSize;
auto end = (uint8_t *)this + total_size;
CHECK(ptr < end);
auto seq = getBaseSeq();
auto rtp_count = getPacketCount();
for (uint8_t i = 0; i < rtp_count;) {
CHECK(ptr + RunLengthChunk::kSize <= end);
RunLengthChunk *chunk = (RunLengthChunk *) ptr;
RunLengthChunk *chunk = (RunLengthChunk *)ptr;
if (!chunk->type) {
//RunLengthChunk
// RunLengthChunk
for (auto j = 0; j < chunk->getRunLength(); ++j) {
ret.emplace(seq++, std::make_pair((SymbolStatus) chunk->symbol, 0));
ret.emplace(seq++, std::make_pair((SymbolStatus)chunk->symbol, 0));
if (++i >= rtp_count) {
break;
}
}
} else {
//StatusVecChunk
StatusVecChunk *chunk = (StatusVecChunk *) ptr;
// StatusVecChunk
StatusVecChunk *chunk = (StatusVecChunk *)ptr;
for (auto &symbol : chunk->getSymbolList()) {
ret.emplace(seq++, std::make_pair(symbol, 0));
if (++i >= rtp_count) {
......@@ -465,23 +465,29 @@ FCI_TWCC::TwccPacketStatus FCI_TWCC::getPacketChunkList(size_t total_size) const
string FCI_TWCC::dumpString(size_t total_size) const {
_StrPrinter printer;
auto map = getPacketChunkList(total_size);
printer << "twcc fci, base_seq:" << getBaseSeq() << ", pkt_status_count:" << getPacketCount() << ", ref time:" << getReferenceTime() << ", fb count:" << (int)fb_pkt_count << "\n";
printer << "twcc fci, base_seq:" << getBaseSeq() << ", pkt_status_count:" << getPacketCount()
<< ", ref time:" << getReferenceTime() << ", fb count:" << (int)fb_pkt_count << "\n";
for (auto &pr : map) {
printer << "rtp seq:" << pr.first <<", packet status:" << (int)(pr.second.first) << ", delta:" << pr.second.second << "\n";
printer << "rtp seq:" << pr.first << ", packet status:" << (int)(pr.second.first)
<< ", delta:" << pr.second.second << "\n";
}
return std::move(printer);
}
static void appendDeltaString(string &delta_str, FCI_TWCC::TwccPacketStatus &status, int count){
static void appendDeltaString(string &delta_str, FCI_TWCC::TwccPacketStatus &status, int count) {
for (auto it = status.begin(); it != status.end() && count--;) {
switch (it->second.first) {
//large delta模式先写高字节,再写低字节
case SymbolStatus::large_delta: delta_str.push_back((it->second.second >> 8) & 0xFF);
//small delta模式只写低字节
case SymbolStatus::small_delta: delta_str.push_back(it->second.second & 0xFF); break;
default: break;
// large delta模式先写高字节,再写低字节
case SymbolStatus::large_delta:
delta_str.push_back((it->second.second >> 8) & 0xFF);
// small delta模式只写低字节
case SymbolStatus::small_delta:
delta_str.push_back(it->second.second & 0xFF);
break;
default:
break;
}
//移除已经处理过的数据
// 移除已经处理过的数据
it = status.erase(it);
}
}
......@@ -489,7 +495,7 @@ static void appendDeltaString(string &delta_str, FCI_TWCC::TwccPacketStatus &sta
string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatus &status) {
string fci;
fci.resize(FCI_TWCC::kSize);
FCI_TWCC *ptr = (FCI_TWCC *) (fci.data());
FCI_TWCC *ptr = (FCI_TWCC *)(fci.data());
ptr->base_seq = htons(status.begin()->first);
ptr->pkt_status_count = htons(status.size());
ptr->fb_pkt_count = fb_pkt_count;
......@@ -500,21 +506,21 @@ string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatu
string delta_str;
while (!status.empty()) {
{
//第一个rtp的状态
// 第一个rtp的状态
auto symbol = status.begin()->second.first;
int16_t count = 0;
for (auto &pr : status) {
if (pr.second.first != symbol) {
//状态发送变更了,本chunk结束
// 状态发送变更了,本chunk结束
break;
}
if (++count >= (0xFFFF >> 3)) {
//RunLengthChunk 13个bit表明rtp个数,最多可以表述0xFFFF >> 3个rtp状态
// RunLengthChunk 13个bit表明rtp个数,最多可以表述0xFFFF >> 3个rtp状态
break;
}
}
if (count >= 7) {
//连续状态相同个数大于6个时,使用RunLengthChunk模式比较节省带宽
// 连续状态相同个数大于6个时,使用RunLengthChunk模式比较节省带宽
RunLengthChunk chunk(symbol, count);
fci.append((char *)&chunk, RunLengthChunk::kSize);
appendDeltaString(delta_str, status, count);
......@@ -523,20 +529,20 @@ string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatu
}
{
//StatusVecChunk模式
//symbol_list中元素是1个bit
// StatusVecChunk模式
// symbol_list中元素是1个bit
auto symbol = 0;
vector<SymbolStatus> vec;
for (auto &pr : status) {
vec.push_back(pr.second.first);
if (pr.second.first >= SymbolStatus::large_delta) {
//symbol_list中元素是2个bit
// symbol_list中元素是2个bit
symbol = 1;
}
if (vec.size() << symbol >= 14) {
//symbol为0时,最多存放14个rtp的状态
//symbol为1时,最多存放7个rtp的状态
// symbol为0时,最多存放14个rtp的状态
// symbol为1时,最多存放7个rtp的状态
break;
}
}
......@@ -547,9 +553,9 @@ string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatu
}
}
//recv delta部分
// recv delta部分
fci.append(delta_str);
return fci;
}
}//namespace mediakit
\ No newline at end of file
} // namespace mediakit
\ No newline at end of file
......@@ -11,37 +11,37 @@
#ifndef ZLMEDIAKIT_RTCPFCI_H
#define ZLMEDIAKIT_RTCPFCI_H
#include "Rtcp.h"
#include "Common/config.h"
#include "Rtcp.h"
namespace mediakit {
/////////////////////////////////////////// PSFB ////////////////////////////////////////////////////
//PSFB fmt = 2
//https://tools.ietf.org/html/rfc4585#section-6.3.2.2
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | First | Number | PictureID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//First: 13 bits
// The macroblock (MB) address of the first lost macroblock. The MB
// numbering is done such that the macroblock in the upper left
// corner of the picture is considered macroblock number 1 and the
// number for each macroblock increases from left to right and then
// from top to bottom in raster-scan order (such that if there is a
// total of N macroblocks in a picture, the bottom right macroblock
// is considered macroblock number N).
// PSFB fmt = 2
// https://tools.ietf.org/html/rfc4585#section-6.3.2.2
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | First | Number | PictureID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// First: 13 bits
// The macroblock (MB) address of the first lost macroblock. The MB
// numbering is done such that the macroblock in the upper left
// corner of the picture is considered macroblock number 1 and the
// number for each macroblock increases from left to right and then
// from top to bottom in raster-scan order (such that if there is a
// total of N macroblocks in a picture, the bottom right macroblock
// is considered macroblock number N).
//
// Number: 13 bits
// The number of lost macroblocks, in scan order as discussed above.
// Number: 13 bits
// The number of lost macroblocks, in scan order as discussed above.
//
// PictureID: 6 bits
// The six least significant bits of the codec-specific identifier
// that is used to reference the picture in which the loss of the
// macroblock(s) has occurred. For many video codecs, the PictureID
// is identical to the Temporal Reference.
// PictureID: 6 bits
// The six least significant bits of the codec-specific identifier
// that is used to reference the picture in which the loss of the
// macroblock(s) has occurred. For many video codecs, the PictureID
// is identical to the Temporal Reference.
class FCI_SLI {
public:
static size_t constexpr kSize = 4;
......@@ -101,15 +101,15 @@ public:
} PACKED;
#endif
//PSFB fmt = 4
//https://tools.ietf.org/html/rfc5104#section-4.3.1.1
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Seq nr. | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// PSFB fmt = 4
// https://tools.ietf.org/html/rfc5104#section-4.3.1.1
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Seq nr. | Reserved |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class FCI_FIR {
public:
static size_t constexpr kSize = 8;
......@@ -188,34 +188,34 @@ private:
#endif
//PSFB fmt = 15
//https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Unique identifier 'R' 'E' 'M' 'B' |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Num SSRC | BR Exp | BR Mantissa |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC feedback |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ... |
// Num SSRC (8 bits): Number of SSRCs in this message.
// PSFB fmt = 15
// https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Unique identifier 'R' 'E' 'M' 'B' |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | Num SSRC | BR Exp | BR Mantissa |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | SSRC feedback |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | ... |
// Num SSRC (8 bits): Number of SSRCs in this message.
//
// BR Exp (6 bits): The exponential scaling of the mantissa for the
// maximum total media bit rate value, ignoring all packet
// overhead. The value is an unsigned integer [0..63], as
// in RFC 5104 section 4.2.2.1.
// BR Exp (6 bits): The exponential scaling of the mantissa for the
// maximum total media bit rate value, ignoring all packet
// overhead. The value is an unsigned integer [0..63], as
// in RFC 5104 section 4.2.2.1.
//
// BR Mantissa (18 bits): The mantissa of the maximum total media bit
// rate (ignoring all packet overhead) that the sender of
// the REMB estimates. The BR is the estimate of the
// traveled path for the SSRCs reported in this message.
// The value is an unsigned integer in number of bits per
// second.
// BR Mantissa (18 bits): The mantissa of the maximum total media bit
// rate (ignoring all packet overhead) that the sender of
// the REMB estimates. The BR is the estimate of the
// traveled path for the SSRCs reported in this message.
// The value is an unsigned integer in number of bits per
// second.
//
// SSRC feedback (32 bits) Consists of one or more SSRC entries which
// this feedback message applies to.
// SSRC feedback (32 bits) Consists of one or more SSRC entries which
// this feedback message applies to.
class FCI_REMB {
public:
static size_t constexpr kSize = 8;
......@@ -227,9 +227,9 @@ public:
std::vector<uint32_t> getSSRC();
private:
//Unique identifier 'R' 'E' 'M' 'B'
// Unique identifier 'R' 'E' 'M' 'B'
char magic[4];
//Num SSRC (8 bits)/BR Exp (6 bits)/ BR Mantissa (18 bits)
// Num SSRC (8 bits)/BR Exp (6 bits)/ BR Mantissa (18 bits)
uint8_t bitrate[4];
// SSRC feedback (32 bits) Consists of one or more SSRC entries which
// this feedback message applies to.
......@@ -238,13 +238,13 @@ private:
/////////////////////////////////////////// RTPFB ////////////////////////////////////////////////////
//RTPFB fmt = 1
//https://tools.ietf.org/html/rfc4585#section-6.2.1
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | PID | BLP |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// RTPFB fmt = 1
// https://tools.ietf.org/html/rfc4585#section-6.2.1
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | PID | BLP |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class FCI_NACK {
public:
static constexpr size_t kSize = 4;
......@@ -255,8 +255,8 @@ public:
void check(size_t size);
uint16_t getPid() const;
uint16_t getBlp() const;
//返回丢包列表,总长度17,第一个包必丢
// TODO: replace std::bitset
// 返回丢包列表,总长度17,第一个包必丢
// TODO: replace std::bitset
std::vector<bool> getBitArray() const;
std::string dumpString() const;
......@@ -318,47 +318,48 @@ public:
} PACKED;
#endif
enum class SymbolStatus : uint8_t{
//Packet not received
enum class SymbolStatus : uint8_t {
// Packet not received
not_received = 0,
//Packet received, small delta (所谓small detal是指能用一个字节表示的数值)
// Packet received, small delta (所谓small detal是指能用一个字节表示的数值)
small_delta = 1,
// Packet received, large ornegative delta (large即是能用两个字节表示的数值)
large_delta = 2,
//Reserved
// Reserved
reserved = 3
};
//RTPFB fmt = 15
//https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1
//https://zhuanlan.zhihu.com/p/206656654
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | base sequence number | packet status count |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | reference time | fb pkt. count |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | packet chunk | packet chunk |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// . .
// . .
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | packet chunk | recv delta | recv delta |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// . .
// . .
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | recv delta | recv delta | zero padding |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class FCI_TWCC{
// RTPFB fmt = 15
// https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1
// https://zhuanlan.zhihu.com/p/206656654
// 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
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | base sequence number | packet status count |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | reference time | fb pkt. count |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | packet chunk | packet chunk |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// . .
// . .
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | packet chunk | recv delta | recv delta |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// . .
// . .
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | recv delta | recv delta | zero padding |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class FCI_TWCC {
public:
static size_t constexpr kSize = 8;
using TwccPacketStatus = std::map<uint16_t/*rtp ext seq*/, std::pair<SymbolStatus, int16_t/*recv delta,单位为250us*/> >;
using TwccPacketStatus
= std::map<uint16_t /*rtp ext seq*/, std::pair<SymbolStatus, int16_t /*recv delta,单位为250us*/>>;
void check(size_t size);
std::string dumpString(size_t total_size) const;
uint16_t getBaseSeq() const;
//单位64ms
// 单位64ms
uint32_t getReferenceTime() const;
uint16_t getPacketCount() const;
TwccPacketStatus getPacketChunkList(size_t total_size) const;
......@@ -366,15 +367,15 @@ public:
static std::string create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatus &status);
private:
//base sequence number,基础序号,本次反馈的第一个包的序号;也就是RTP扩展头的序列号
// base sequence number,基础序号,本次反馈的第一个包的序号;也就是RTP扩展头的序列号
uint16_t base_seq;
//packet status count, 包个数,本次反馈包含多少个包的状态;从基础序号开始算
// packet status count, 包个数,本次反馈包含多少个包的状态;从基础序号开始算
uint16_t pkt_status_count;
//reference time,基准时间,绝对时间;计算该包中每个媒体包的到达时间都要基于这个基准时间计算
// reference time,基准时间,绝对时间;计算该包中每个媒体包的到达时间都要基于这个基准时间计算
uint8_t ref_time[3];
//feedback packet count,反馈包号,本包是第几个transport-cc包,每次加1 |
// feedback packet count,反馈包号,本包是第几个transport-cc包,每次加1 |
uint8_t fb_pkt_count;
} PACKED;
} //namespace mediakit
#endif //ZLMEDIAKIT_RTCPFCI_H
} // namespace mediakit
#endif // ZLMEDIAKIT_RTCPFCI_H
......@@ -9,11 +9,11 @@
*/
#include "WebRtcTransport.h"
#include <iostream>
#include "RtpExt.h"
#include "Rtcp/Rtcp.h"
#include "Rtcp/RtcpFCI.h"
#include "RtpExt.h"
#include "Rtsp/RtpReceiver.h"
#include <iostream>
#define RTP_SSRC_OFFSET 1
#define RTX_SSRC_OFFSET 2
......@@ -25,17 +25,17 @@
using namespace std;
using namespace mediakit;
//RTC配置项目
// RTC配置项目
namespace RTC {
#define RTC_FIELD "rtc."
//rtp和rtcp接受超时时间
const string kTimeOutSec = RTC_FIELD"timeoutSec";
//服务器外网ip
const string kExternIP = RTC_FIELD"externIP";
//设置remb比特率,非0时关闭twcc并开启remb。该设置在rtc推流时有效,可以控制推流画质
const string kRembBitRate = RTC_FIELD"rembBitRate";
//webrtc单端口udp服务器
const string kPort = RTC_FIELD"port";
// rtp和rtcp接受超时时间
const string kTimeOutSec = RTC_FIELD "timeoutSec";
// 服务器外网ip
const string kExternIP = RTC_FIELD "externIP";
// 设置remb比特率,非0时关闭twcc并开启remb。该设置在rtc推流时有效,可以控制推流画质
const string kRembBitRate = RTC_FIELD "rembBitRate";
// webrtc单端口udp服务器
const string kPort = RTC_FIELD "port";
static onceToken token([]() {
mINI::Instance()[kTimeOutSec] = 15;
......@@ -44,9 +44,9 @@ static onceToken token([]() {
mINI::Instance()[kPort] = 8000;
});
}//namespace RTC
} // namespace RTC
static atomic<uint64_t> s_key{0};
static atomic<uint64_t> s_key { 0 };
static void translateIPFromEnv(std::vector<std::string> &v) {
for (auto iter = v.begin(); iter != v.end();) {
......@@ -69,12 +69,12 @@ WebRtcTransport::WebRtcTransport(const EventPoller::Ptr &poller) {
_packet_pool.setSize(64);
}
void WebRtcTransport::onCreate(){
void WebRtcTransport::onCreate() {
_dtls_transport = std::make_shared<RTC::DtlsTransport>(_poller, this);
_ice_server = std::make_shared<RTC::IceServer>(this, _identifier, makeRandStr(24));
}
void WebRtcTransport::onDestory(){
void WebRtcTransport::onDestory() {
#ifdef ENABLE_SCTP
_sctp = nullptr;
#endif
......@@ -82,7 +82,7 @@ void WebRtcTransport::onDestory(){
_ice_server = nullptr;
}
const EventPoller::Ptr& WebRtcTransport::getPoller() const{
const EventPoller::Ptr &WebRtcTransport::getPoller() const {
return _poller;
}
......@@ -92,8 +92,9 @@ const string &WebRtcTransport::getIdentifier() const {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void WebRtcTransport::OnIceServerSendStunPacket(const RTC::IceServer *iceServer, const RTC::StunPacket *packet, RTC::TransportTuple *tuple) {
sendSockData((char *) packet->GetData(), packet->GetSize(), tuple);
void WebRtcTransport::OnIceServerSendStunPacket(
const RTC::IceServer *iceServer, const RTC::StunPacket *packet, RTC::TransportTuple *tuple) {
sendSockData((char *)packet->GetData(), packet->GetSize(), tuple);
}
void WebRtcTransport::OnIceServerSelectedTuple(const RTC::IceServer *iceServer, RTC::TransportTuple *tuple) {
......@@ -120,16 +121,13 @@ void WebRtcTransport::OnIceServerDisconnected(const RTC::IceServer *iceServer) {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void WebRtcTransport::OnDtlsTransportConnected(
const RTC::DtlsTransport *dtlsTransport,
RTC::SrtpSession::CryptoSuite srtpCryptoSuite,
uint8_t *srtpLocalKey,
size_t srtpLocalKeyLen,
uint8_t *srtpRemoteKey,
size_t srtpRemoteKeyLen,
std::string &remoteCert) {
const RTC::DtlsTransport *dtlsTransport, RTC::SrtpSession::CryptoSuite srtpCryptoSuite, uint8_t *srtpLocalKey,
size_t srtpLocalKeyLen, uint8_t *srtpRemoteKey, size_t srtpRemoteKeyLen, std::string &remoteCert) {
InfoL;
_srtp_session_send = std::make_shared<RTC::SrtpSession>(RTC::SrtpSession::Type::OUTBOUND, srtpCryptoSuite, srtpLocalKey, srtpLocalKeyLen);
_srtp_session_recv = std::make_shared<RTC::SrtpSession>(RTC::SrtpSession::Type::INBOUND, srtpCryptoSuite, srtpRemoteKey, srtpRemoteKeyLen);
_srtp_session_send = std::make_shared<RTC::SrtpSession>(
RTC::SrtpSession::Type::OUTBOUND, srtpCryptoSuite, srtpLocalKey, srtpLocalKeyLen);
_srtp_session_recv = std::make_shared<RTC::SrtpSession>(
RTC::SrtpSession::Type::INBOUND, srtpCryptoSuite, srtpRemoteKey, srtpRemoteKeyLen);
#ifdef ENABLE_SCTP
_sctp = std::make_shared<RTC::SctpAssociationImp>(getPoller(), this, 128, 128, 262144, true);
_sctp->TransportConnected();
......@@ -137,7 +135,8 @@ void WebRtcTransport::OnDtlsTransportConnected(
onStartWebRTC();
}
void WebRtcTransport::OnDtlsTransportSendData(const RTC::DtlsTransport *dtlsTransport, const uint8_t *data, size_t len) {
void WebRtcTransport::OnDtlsTransportSendData(
const RTC::DtlsTransport *dtlsTransport, const uint8_t *data, size_t len) {
sendSockData((char *)data, len, nullptr);
}
......@@ -155,7 +154,8 @@ void WebRtcTransport::OnDtlsTransportClosed(const RTC::DtlsTransport *dtlsTransp
onShutdown(SockException(Err_shutdown, "dtls close notify received"));
}
void WebRtcTransport::OnDtlsTransportApplicationDataReceived(const RTC::DtlsTransport *dtlsTransport, const uint8_t *data, size_t len) {
void WebRtcTransport::OnDtlsTransportApplicationDataReceived(
const RTC::DtlsTransport *dtlsTransport, const uint8_t *data, size_t len) {
#ifdef ENABLE_SCTP
_sctp->ProcessSctpData(data, len);
#else
......@@ -165,63 +165,64 @@ void WebRtcTransport::OnDtlsTransportApplicationDataReceived(const RTC::DtlsTran
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef ENABLE_SCTP
void WebRtcTransport::OnSctpAssociationConnecting(RTC::SctpAssociation* sctpAssociation) {
void WebRtcTransport::OnSctpAssociationConnecting(RTC::SctpAssociation *sctpAssociation) {
TraceL;
}
void WebRtcTransport::OnSctpAssociationConnected(RTC::SctpAssociation* sctpAssociation) {
void WebRtcTransport::OnSctpAssociationConnected(RTC::SctpAssociation *sctpAssociation) {
InfoL << getIdentifier();
}
void WebRtcTransport::OnSctpAssociationFailed(RTC::SctpAssociation* sctpAssociation) {
void WebRtcTransport::OnSctpAssociationFailed(RTC::SctpAssociation *sctpAssociation) {
WarnL << getIdentifier();
}
void WebRtcTransport::OnSctpAssociationClosed(RTC::SctpAssociation* sctpAssociation) {
void WebRtcTransport::OnSctpAssociationClosed(RTC::SctpAssociation *sctpAssociation) {
InfoL << getIdentifier();
}
void WebRtcTransport::OnSctpAssociationSendData(RTC::SctpAssociation* sctpAssociation, const uint8_t* data, size_t len) {
void WebRtcTransport::OnSctpAssociationSendData(
RTC::SctpAssociation *sctpAssociation, const uint8_t *data, size_t len) {
_dtls_transport->SendApplicationData(data, len);
}
void WebRtcTransport::OnSctpAssociationMessageReceived(RTC::SctpAssociation *sctpAssociation, uint16_t streamId,
uint32_t ppid, const uint8_t *msg, size_t len) {
void WebRtcTransport::OnSctpAssociationMessageReceived(
RTC::SctpAssociation *sctpAssociation, uint16_t streamId, uint32_t ppid, const uint8_t *msg, size_t len) {
InfoL << getIdentifier() << " " << streamId << " " << ppid << " " << len << " " << string((char *)msg, len);
RTC::SctpStreamParameters params;
params.streamId = streamId;
//回显数据
// 回显数据
_sctp->SendSctpMessage(params, ppid, msg, len);
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void WebRtcTransport::sendSockData(const char *buf, size_t len, RTC::TransportTuple *tuple){
void WebRtcTransport::sendSockData(const char *buf, size_t len, RTC::TransportTuple *tuple) {
auto pkt = _packet_pool.obtain2();
pkt->assign(buf, len);
onSendSockData(std::move(pkt), true, tuple ? tuple : _ice_server->GetSelectedTuple());
}
RTC::TransportTuple* WebRtcTransport::getSelectedTuple() const{
return _ice_server->GetSelectedTuple();
RTC::TransportTuple *WebRtcTransport::getSelectedTuple() const {
return _ice_server->GetSelectedTuple();
}
void WebRtcTransport::sendRtcpRemb(uint32_t ssrc, size_t bit_rate) {
auto remb = FCI_REMB::create({ssrc}, (uint32_t)bit_rate);
auto remb = FCI_REMB::create({ ssrc }, (uint32_t)bit_rate);
auto fb = RtcpFB::create(PSFBType::RTCP_PSFB_REMB, remb.data(), remb.size());
fb->ssrc = htonl(0);
fb->ssrc_media = htonl(ssrc);
sendRtcpPacket((char *) fb.get(), fb->getSize(), true);
sendRtcpPacket((char *)fb.get(), fb->getSize(), true);
}
void WebRtcTransport::sendRtcpPli(uint32_t ssrc) {
auto pli = RtcpFB::create(PSFBType::RTCP_PSFB_PLI);
pli->ssrc = htonl(0);
pli->ssrc_media = htonl(ssrc);
sendRtcpPacket((char *) pli.get(), pli->getSize(), true);
sendRtcpPacket((char *)pli.get(), pli->getSize(), true);
}
string getFingerprint(const string &algorithm_str, const std::shared_ptr<RTC::DtlsTransport> &transport){
string getFingerprint(const string &algorithm_str, const std::shared_ptr<RTC::DtlsTransport> &transport) {
auto algorithm = RTC::DtlsTransport::GetFingerprintAlgorithm(algorithm_str);
for (auto &finger_prints : transport->GetLocalFingerprints()) {
if (finger_prints.algorithm == algorithm) {
......@@ -231,21 +232,22 @@ string getFingerprint(const string &algorithm_str, const std::shared_ptr<RTC::Dt
throw std::invalid_argument(StrPrinter << "不支持的加密算法:" << algorithm_str);
}
void WebRtcTransport::setRemoteDtlsFingerprint(const RtcSession &remote){
//设置远端dtls签名
void WebRtcTransport::setRemoteDtlsFingerprint(const RtcSession &remote) {
// 设置远端dtls签名
RTC::DtlsTransport::Fingerprint remote_fingerprint;
remote_fingerprint.algorithm = RTC::DtlsTransport::GetFingerprintAlgorithm(_offer_sdp->media[0].fingerprint.algorithm);
remote_fingerprint.algorithm
= RTC::DtlsTransport::GetFingerprintAlgorithm(_offer_sdp->media[0].fingerprint.algorithm);
remote_fingerprint.value = _offer_sdp->media[0].fingerprint.hash;
_dtls_transport->SetRemoteFingerprint(remote_fingerprint);
}
void WebRtcTransport::onRtcConfigure(RtcConfigure &configure) const {
//开启remb后关闭twcc,因为开启twcc后remb无效
// 开启remb后关闭twcc,因为开启twcc后remb无效
GET_CONFIG(size_t, remb_bit_rate, RTC::kRembBitRate);
configure.enableTWCC(!remb_bit_rate);
}
std::string WebRtcTransport::getAnswerSdp(const string &offer){
std::string WebRtcTransport::getAnswerSdp(const string &offer) {
try {
//// 解析offer sdp ////
_offer_sdp = std::make_shared<RtcSession>();
......@@ -259,8 +261,8 @@ std::string WebRtcTransport::getAnswerSdp(const string &offer){
fingerprint.algorithm = _offer_sdp->media[0].fingerprint.algorithm;
fingerprint.hash = getFingerprint(fingerprint.algorithm, _dtls_transport);
RtcConfigure configure;
configure.setDefaultSetting(_ice_server->GetUsernameFragment(), _ice_server->GetPassword(),
RtpDirection::sendrecv, fingerprint);
configure.setDefaultSetting(
_ice_server->GetUsernameFragment(), _ice_server->GetPassword(), RtpDirection::sendrecv, fingerprint);
onRtcConfigure(configure);
//// 生成answer sdp ////
......@@ -279,22 +281,22 @@ static bool is_dtls(char *buf) {
}
static bool is_rtp(char *buf) {
RtpHeader *header = (RtpHeader *) buf;
RtpHeader *header = (RtpHeader *)buf;
return ((header->pt < 64) || (header->pt >= 96));
}
static bool is_rtcp(char *buf) {
RtpHeader *header = (RtpHeader *) buf;
RtpHeader *header = (RtpHeader *)buf;
return ((header->pt >= 64) && (header->pt < 96));
}
static string getPeerAddress(RTC::TransportTuple *tuple){
static string getPeerAddress(RTC::TransportTuple *tuple) {
return SockUtil::inet_ntoa(tuple);
}
void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tuple) {
if (RTC::StunPacket::IsStun((const uint8_t *) buf, len)) {
std::unique_ptr<RTC::StunPacket> packet(RTC::StunPacket::Parse((const uint8_t *) buf, len));
if (RTC::StunPacket::IsStun((const uint8_t *)buf, len)) {
std::unique_ptr<RTC::StunPacket> packet(RTC::StunPacket::Parse((const uint8_t *)buf, len));
if (!packet) {
WarnL << "parse stun error" << std::endl;
return;
......@@ -303,7 +305,7 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
return;
}
if (is_dtls(buf)) {
_dtls_transport->ProcessDtlsData((uint8_t *) buf, len);
_dtls_transport->ProcessDtlsData((uint8_t *)buf, len);
return;
}
if (is_rtp(buf)) {
......@@ -311,7 +313,7 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
WarnL << "received rtp packet when dtls not completed from:" << getPeerAddress(tuple);
return;
}
if (_srtp_session_recv->DecryptSrtp((uint8_t *) buf, &len)) {
if (_srtp_session_recv->DecryptSrtp((uint8_t *)buf, &len)) {
onRtp(buf, len, _ticker.createdTime());
}
return;
......@@ -321,7 +323,7 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
WarnL << "received rtcp packet when dtls not completed from:" << getPeerAddress(tuple);
return;
}
if (_srtp_session_recv->DecryptSrtcp((uint8_t *) buf, &len)) {
if (_srtp_session_recv->DecryptSrtcp((uint8_t *)buf, &len)) {
onRtcp(buf, len);
}
return;
......@@ -331,8 +333,8 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
void WebRtcTransport::sendRtpPacket(const char *buf, int len, bool flush, void *ctx) {
if (_srtp_session_send) {
auto pkt = _packet_pool.obtain2();
//预留rtx加入的两个字节
pkt->setCapacity((size_t) len + SRTP_MAX_TRAILER_LEN + 2);
// 预留rtx加入的两个字节
pkt->setCapacity((size_t)len + SRTP_MAX_TRAILER_LEN + 2);
pkt->assign(buf, len);
onBeforeEncryptRtp(pkt->data(), len, ctx);
if (_srtp_session_send->EncryptRtp(reinterpret_cast<uint8_t *>(pkt->data()), &len)) {
......@@ -345,8 +347,8 @@ void WebRtcTransport::sendRtpPacket(const char *buf, int len, bool flush, void *
void WebRtcTransport::sendRtcpPacket(const char *buf, int len, bool flush, void *ctx) {
if (_srtp_session_send) {
auto pkt = _packet_pool.obtain2();
//预留rtx加入的两个字节
pkt->setCapacity((size_t) len + SRTP_MAX_TRAILER_LEN + 2);
// 预留rtx加入的两个字节
pkt->setCapacity((size_t)len + SRTP_MAX_TRAILER_LEN + 2);
pkt->assign(buf, len);
onBeforeEncryptRtcp(pkt->data(), len, ctx);
if (_srtp_session_send->EncryptRtcp(reinterpret_cast<uint8_t *>(pkt->data()), &len)) {
......@@ -358,29 +360,31 @@ void WebRtcTransport::sendRtcpPacket(const char *buf, int len, bool flush, void
///////////////////////////////////////////////////////////////////////////////////
void WebRtcTransportImp::onCreate(){
void WebRtcTransportImp::onCreate() {
WebRtcTransport::onCreate();
registerSelf();
weak_ptr<WebRtcTransportImp> weak_self = static_pointer_cast<WebRtcTransportImp>(shared_from_this());
GET_CONFIG(float, timeoutSec, RTC::kTimeOutSec);
_timer = std::make_shared<Timer>(timeoutSec / 2, [weak_self]() {
auto strong_self = weak_self.lock();
if (!strong_self) {
return false;
}
if (strong_self->_alive_ticker.elapsedTime() > timeoutSec * 1000) {
strong_self->onShutdown(SockException(Err_timeout, "接受rtp和rtcp超时"));
}
return true;
}, getPoller());
_timer = std::make_shared<Timer>(
timeoutSec / 2,
[weak_self]() {
auto strong_self = weak_self.lock();
if (!strong_self) {
return false;
}
if (strong_self->_alive_ticker.elapsedTime() > timeoutSec * 1000) {
strong_self->onShutdown(SockException(Err_timeout, "接受rtp和rtcp超时"));
}
return true;
},
getPoller());
_twcc_ctx.setOnSendTwccCB([this](uint32_t ssrc, string fci) {
onSendTwcc(ssrc, fci);
});
_twcc_ctx.setOnSendTwccCB([this](uint32_t ssrc, string fci) { onSendTwcc(ssrc, fci); });
}
WebRtcTransportImp::WebRtcTransportImp(const EventPoller::Ptr &poller) : WebRtcTransport(poller) {
WebRtcTransportImp::WebRtcTransportImp(const EventPoller::Ptr &poller)
: WebRtcTransport(poller) {
InfoL << getIdentifier();
}
......@@ -398,14 +402,14 @@ void WebRtcTransportImp::onSendSockData(Buffer::Ptr buf, bool flush, RTC::Transp
WarnL << "send data failed:" << buf->size();
return;
}
//一次性发送一帧的rtp数据,提高网络io性能
// 一次性发送一帧的rtp数据,提高网络io性能
_selected_session->setSendFlushFlag(flush);
_selected_session->send(std::move(buf));
}
///////////////////////////////////////////////////////////////////
bool WebRtcTransportImp::canSendRtp() const{
bool WebRtcTransportImp::canSendRtp() const {
for (auto &m : _answer_sdp->media) {
if (m.direction == RtpDirection::sendrecv || m.direction == RtpDirection::sendonly) {
return true;
......@@ -414,7 +418,7 @@ bool WebRtcTransportImp::canSendRtp() const{
return false;
}
bool WebRtcTransportImp::canRecvRtp() const{
bool WebRtcTransportImp::canRecvRtp() const {
for (auto &m : _answer_sdp->media) {
if (m.direction == RtpDirection::sendrecv || m.direction == RtpDirection::recvonly) {
return true;
......@@ -424,7 +428,7 @@ bool WebRtcTransportImp::canRecvRtp() const{
}
void WebRtcTransportImp::onStartWebRTC() {
//获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息
// 获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息
for (auto &m_answer : _answer_sdp->media) {
if (m_answer.type == TrackApplication) {
continue;
......@@ -441,42 +445,43 @@ void WebRtcTransportImp::onStartWebRTC() {
track->plan_rtx = m_answer.getRelatedRtxPlan(track->plan_rtp->pt);
track->rtcp_context_send = std::make_shared<RtcpContextForSend>();
//rtp track type --> MediaTrack
// rtp track type --> MediaTrack
if (m_answer.direction == RtpDirection::sendonly || m_answer.direction == RtpDirection::sendrecv) {
//该类型的track 才支持发送
// 该类型的track 才支持发送
_type_to_track[m_answer.type] = track;
}
//send ssrc --> MediaTrack
// send ssrc --> MediaTrack
_ssrc_to_track[track->answer_ssrc_rtp] = track;
_ssrc_to_track[track->answer_ssrc_rtx] = track;
//recv ssrc --> MediaTrack
// recv ssrc --> MediaTrack
_ssrc_to_track[track->offer_ssrc_rtp] = track;
_ssrc_to_track[track->offer_ssrc_rtx] = track;
//rtp pt --> MediaTrack
_pt_to_track.emplace(track->plan_rtp->pt, std::unique_ptr<WrappedMediaTrack>(new WrappedRtpTrack(track, _twcc_ctx, *this)));
// rtp pt --> MediaTrack
_pt_to_track.emplace(
track->plan_rtp->pt, std::unique_ptr<WrappedMediaTrack>(new WrappedRtpTrack(track, _twcc_ctx, *this)));
if (track->plan_rtx) {
//rtx pt --> MediaTrack
// rtx pt --> MediaTrack
_pt_to_track.emplace(track->plan_rtx->pt, std::unique_ptr<WrappedMediaTrack>(new WrappedRtxTrack(track)));
}
//记录rtp ext类型与id的关系,方便接收或发送rtp时修改rtp ext id
// 记录rtp ext类型与id的关系,方便接收或发送rtp时修改rtp ext id
track->rtp_ext_ctx = std::make_shared<RtpExtContext>(*m_offer);
weak_ptr<MediaTrack> weak_track = track;
track->rtp_ext_ctx->setOnGetRtp([this, weak_track](uint8_t pt, uint32_t ssrc, const string &rid) {
//ssrc --> MediaTrack
// ssrc --> MediaTrack
auto track = weak_track.lock();
assert(track);
_ssrc_to_track[ssrc] = std::move(track);
InfoL << "get rtp, pt:" << (int) pt << ", ssrc:" << ssrc << ", rid:" << rid;
InfoL << "get rtp, pt:" << (int)pt << ", ssrc:" << ssrc << ", rid:" << rid;
});
size_t index = 0;
for (auto &ssrc : m_offer->rtp_ssrc_sim) {
//记录ssrc对应的MediaTrack
// 记录ssrc对应的MediaTrack
_ssrc_to_track[ssrc.ssrc] = track;
if (m_offer->rtp_rids.size() > index) {
//支持firefox的simulcast, 提前映射好ssrc和rid的关系
// 支持firefox的simulcast, 提前映射好ssrc和rid的关系
track->rtp_ext_ctx->setRid(ssrc.ssrc, m_offer->rtp_rids[index]);
} else {
// SDP munging没有rid, 它通过group-ssrc:SIM给出ssrc列表;
......@@ -493,7 +498,7 @@ void WebRtcTransportImp::onStartWebRTC() {
}
void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
//修改answer sdp的ip、端口信息
// 修改answer sdp的ip、端口信息
GET_CONFIG_FUNC(std::vector<std::string>, extern_ips, RTC::kExternIP, [](string str) {
std::vector<std::string> ret;
if (str.length()) {
......@@ -515,7 +520,7 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
}
if (!canSendRtp()) {
//设置我们发送的rtp的ssrc
// 设置我们发送的rtp的ssrc
return;
}
......@@ -524,13 +529,13 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
continue;
}
if (!m.rtp_rtx_ssrc.empty()) {
//已经生成了ssrc
// 已经生成了ssrc
continue;
}
//添加answer sdp的ssrc信息
// 添加answer sdp的ssrc信息
m.rtp_rtx_ssrc.emplace_back();
auto &ssrc = m.rtp_rtx_ssrc.back();
//发送的ssrc我们随便定义,因为在发送rtp时会修改为此值
// 发送的ssrc我们随便定义,因为在发送rtp时会修改为此值
ssrc.ssrc = m.type + RTP_SSRC_OFFSET;
ssrc.cname = RTP_CNAME;
ssrc.label = RTP_LABEL;
......@@ -538,7 +543,7 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
ssrc.msid = RTP_MSID;
if (m.getRelatedRtxPlan(m.plan[0].pt)) {
//rtx ssrc
// rtx ssrc
ssrc.rtx_ssrc = ssrc.ssrc + RTX_SSRC_OFFSET;
}
}
......@@ -546,20 +551,25 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
void WebRtcTransportImp::onCheckSdp(SdpType type, RtcSession &sdp) {
switch (type) {
case SdpType::answer: onCheckAnswer(sdp); break;
case SdpType::offer: break;
default: /*不可达*/ assert(0); break;
case SdpType::answer:
onCheckAnswer(sdp);
break;
case SdpType::offer:
break;
default: /*不可达*/
assert(0);
break;
}
}
SdpAttrCandidate::Ptr makeIceCandidate(std::string ip, uint16_t port,
uint32_t priority = 100, std::string proto = "udp") {
SdpAttrCandidate::Ptr
makeIceCandidate(std::string ip, uint16_t port, uint32_t priority = 100, std::string proto = "udp") {
auto candidate = std::make_shared<SdpAttrCandidate>();
//rtp端口
// rtp端口
candidate->component = 1;
candidate->transport = proto;
candidate->foundation = proto + "candidate";
//优先级,单candidate时随便
// 优先级,单candidate时随便
candidate->priority = priority;
candidate->address = ip;
candidate->port = port;
......@@ -569,10 +579,10 @@ SdpAttrCandidate::Ptr makeIceCandidate(std::string ip, uint16_t port,
void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const {
WebRtcTransport::onRtcConfigure(configure);
GET_CONFIG(uint16_t, local_port, RTC::kPort);
//添加接收端口candidate信息
GET_CONFIG_FUNC(std::vector<std::string>, extern_ips, RTC::kExternIP, [](string str){
// 添加接收端口candidate信息
GET_CONFIG_FUNC(std::vector<std::string>, extern_ips, RTC::kExternIP, [](string str) {
std::vector<std::string> ret;
if (str.length()) {
ret = split(str, ",");
......@@ -593,19 +603,18 @@ void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const {
}
}
///////////////////////////////////////////////////////////////////
class RtpChannel : public RtpTrackImp, public std::enable_shared_from_this<RtpChannel> {
class RtpChannel
: public RtpTrackImp
, public std::enable_shared_from_this<RtpChannel> {
public:
RtpChannel(EventPoller::Ptr poller, RtpTrackImp::OnSorted cb, function<void(const FCI_NACK &nack)> on_nack) {
_poller = std::move(poller);
_on_nack = std::move(on_nack);
setOnSorted(std::move(cb));
_nack_ctx.setOnNack([this](const FCI_NACK &nack) {
onNack(nack);
});
_nack_ctx.setOnNack([this](const FCI_NACK &nack) { onNack(nack); });
}
~RtpChannel() override = default;
......@@ -618,7 +627,7 @@ public:
auto seq = rtp->getSeq();
_nack_ctx.received(seq, is_rtx);
if (!is_rtx) {
//统计rtp接受情况,便于生成nack rtcp包
// 统计rtp接受情况,便于生成nack rtcp包
_rtcp_context.onRtp(seq, rtp->getStamp(), rtp->ntp_stamp, sample_rate, len);
}
return rtp;
......@@ -630,7 +639,7 @@ public:
}
int getLossRate() {
auto expected = _rtcp_context.getExpectedPacketsInterval();
auto expected = _rtcp_context.getExpectedPacketsInterval();
if (!expected) {
return 0;
}
......@@ -638,7 +647,7 @@ public:
}
private:
void starNackTimer(){
void starNackTimer() {
if (_delay_task) {
return;
}
......@@ -669,7 +678,7 @@ private:
function<void(const FCI_NACK &nack)> _on_nack;
};
std::shared_ptr<RtpChannel> MediaTrack::getRtpChannel(uint32_t ssrc) const{
std::shared_ptr<RtpChannel> MediaTrack::getRtpChannel(uint32_t ssrc) const {
auto it_chn = rtp_channel.find(rtp_ext_ctx->getRid(ssrc));
if (it_chn == rtp_channel.end()) {
return nullptr;
......@@ -693,105 +702,107 @@ int WebRtcTransportImp::getLossRate(mediakit::TrackType type) {
void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
_bytes_usage += len;
auto rtcps = RtcpHeader::loadFromBytes((char *) buf, len);
auto rtcps = RtcpHeader::loadFromBytes((char *)buf, len);
for (auto rtcp : rtcps) {
switch ((RtcpType) rtcp->pt) {
case RtcpType::RTCP_SR : {
//对方汇报rtp发送情况
RtcpSR *sr = (RtcpSR *) rtcp;
auto it = _ssrc_to_track.find(sr->ssrc);
switch ((RtcpType)rtcp->pt) {
case RtcpType::RTCP_SR: {
// 对方汇报rtp发送情况
RtcpSR *sr = (RtcpSR *)rtcp;
auto it = _ssrc_to_track.find(sr->ssrc);
if (it != _ssrc_to_track.end()) {
auto &track = it->second;
auto rtp_chn = track->getRtpChannel(sr->ssrc);
if (!rtp_chn) {
WarnL << "未识别的sr rtcp包:" << rtcp->dumpString();
} else {
// InfoL << "接收丢包率,ssrc:" << sr->ssrc << ",loss rate(%):" << rtp_chn->getLossRate();
// 设置rtp时间戳与ntp时间戳的对应关系
rtp_chn->setNtpStamp(sr->rtpts, sr->getNtpUnixStampMS());
auto rr = rtp_chn->createRtcpRR(sr, track->answer_ssrc_rtp);
sendRtcpPacket(rr->data(), rr->size(), true);
}
} else {
WarnL << "未识别的sr rtcp包:" << rtcp->dumpString();
}
break;
}
case RtcpType::RTCP_RR: {
_alive_ticker.resetTime();
// 对方汇报rtp接收情况
RtcpRR *rr = (RtcpRR *)rtcp;
for (auto item : rr->getItemList()) {
auto it = _ssrc_to_track.find(item->ssrc);
if (it != _ssrc_to_track.end()) {
auto &track = it->second;
auto rtp_chn = track->getRtpChannel(sr->ssrc);
if (!rtp_chn) {
WarnL << "未识别的sr rtcp包:" << rtcp->dumpString();
} else {
//InfoL << "接收丢包率,ssrc:" << sr->ssrc << ",loss rate(%):" << rtp_chn->getLossRate();
//设置rtp时间戳与ntp时间戳的对应关系
rtp_chn->setNtpStamp(sr->rtpts, sr->getNtpUnixStampMS());
auto rr = rtp_chn->createRtcpRR(sr, track->answer_ssrc_rtp);
sendRtcpPacket(rr->data(), rr->size(), true);
}
track->rtcp_context_send->onRtcp(rtcp);
auto sr = track->rtcp_context_send->createRtcpSR(track->answer_ssrc_rtp);
sendRtcpPacket(sr->data(), sr->size(), true);
} else {
WarnL << "未识别的sr rtcp包:" << rtcp->dumpString();
WarnL << "未识别的rr rtcp包:" << rtcp->dumpString();
}
break;
}
case RtcpType::RTCP_RR : {
_alive_ticker.resetTime();
//对方汇报rtp接收情况
RtcpRR *rr = (RtcpRR *) rtcp;
for (auto item : rr->getItemList()) {
auto it = _ssrc_to_track.find(item->ssrc);
if (it != _ssrc_to_track.end()) {
auto &track = it->second;
track->rtcp_context_send->onRtcp(rtcp);
auto sr = track->rtcp_context_send->createRtcpSR(track->answer_ssrc_rtp);
sendRtcpPacket(sr->data(), sr->size(), true);
} else {
WarnL << "未识别的rr rtcp包:" << rtcp->dumpString();
}
break;
}
case RtcpType::RTCP_BYE: {
// 对方汇报停止发送rtp
RtcpBye *bye = (RtcpBye *)rtcp;
for (auto ssrc : bye->getSSRC()) {
auto it = _ssrc_to_track.find(*ssrc);
if (it == _ssrc_to_track.end()) {
WarnL << "未识别的bye rtcp包:" << rtcp->dumpString();
continue;
}
_ssrc_to_track.erase(it);
}
onShutdown(SockException(Err_eof, "rtcp bye message received"));
break;
}
case RtcpType::RTCP_PSFB:
case RtcpType::RTCP_RTPFB: {
if ((RtcpType)rtcp->pt == RtcpType::RTCP_PSFB) {
break;
}
case RtcpType::RTCP_BYE : {
//对方汇报停止发送rtp
RtcpBye *bye = (RtcpBye *) rtcp;
for (auto ssrc : bye->getSSRC()) {
auto it = _ssrc_to_track.find(*ssrc);
if (it == _ssrc_to_track.end()) {
WarnL << "未识别的bye rtcp包:" << rtcp->dumpString();
continue;
}
_ssrc_to_track.erase(it);
// RTPFB
switch ((RTPFBType)rtcp->report_count) {
case RTPFBType::RTCP_RTPFB_NACK: {
RtcpFB *fb = (RtcpFB *)rtcp;
auto it = _ssrc_to_track.find(fb->ssrc_media);
if (it == _ssrc_to_track.end()) {
WarnL << "未识别的 rtcp包:" << rtcp->dumpString();
return;
}
onShutdown(SockException(Err_eof, "rtcp bye message received"));
auto &track = it->second;
auto &fci = fb->getFci<FCI_NACK>();
track->nack_list.forEach(fci, [&](const RtpPacket::Ptr &rtp) {
// rtp重传
onSendRtp(rtp, true, true);
});
break;
}
case RtcpType::RTCP_PSFB:
case RtcpType::RTCP_RTPFB: {
if ((RtcpType) rtcp->pt == RtcpType::RTCP_PSFB) {
break;
}
//RTPFB
switch ((RTPFBType) rtcp->report_count) {
case RTPFBType::RTCP_RTPFB_NACK : {
RtcpFB *fb = (RtcpFB *) rtcp;
auto it = _ssrc_to_track.find(fb->ssrc_media);
if (it == _ssrc_to_track.end()) {
WarnL << "未识别的 rtcp包:" << rtcp->dumpString();
return;
}
auto &track = it->second;
auto &fci = fb->getFci<FCI_NACK>();
track->nack_list.forEach(fci, [&](const RtpPacket::Ptr &rtp) {
//rtp重传
onSendRtp(rtp, true, true);
});
break;
}
default: break;
}
default:
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;
}
case RtcpType::RTCP_XR: {
RtcpXRRRTR *xr = (RtcpXRRRTR *)rtcp;
if (xr->bt != 4) {
break;
}
default: 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;
}
}
}
......@@ -799,18 +810,18 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
///////////////////////////////////////////////////////////////////
void WebRtcTransportImp::createRtpChannel(const string &rid, uint32_t ssrc, MediaTrack &track) {
//rid --> RtpReceiverImp
// rid --> RtpReceiverImp
auto &ref = track.rtp_channel[rid];
weak_ptr<WebRtcTransportImp> weak_self = dynamic_pointer_cast<WebRtcTransportImp>(shared_from_this());
ref = std::make_shared<RtpChannel>(getPoller(), [&track, this, rid](RtpPacket::Ptr rtp) mutable {
onSortedRtp(track, rid, std::move(rtp));
}, [&track, weak_self, ssrc](const FCI_NACK &nack) mutable {
//nack发送可能由定时器异步触发
auto strong_self = weak_self.lock();
if (strong_self) {
strong_self->onSendNack(track, nack, ssrc);
}
});
ref = std::make_shared<RtpChannel>(
getPoller(), [&track, this, rid](RtpPacket::Ptr rtp) mutable { onSortedRtp(track, rid, std::move(rtp)); },
[&track, weak_self, ssrc](const FCI_NACK &nack) mutable {
// nack发送可能由定时器异步触发
auto strong_self = weak_self.lock();
if (strong_self) {
strong_self->onSendNack(track, nack, ssrc);
}
});
InfoL << "create rtp receiver of ssrc:" << ssrc << ", rid:" << rid << ", codec:" << track.plan_rtp->codec;
}
......@@ -822,8 +833,8 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len, uint64_t stamp_ms) {
_bytes_usage += len;
_alive_ticker.resetTime();
RtpHeader *rtp = (RtpHeader *) buf;
//根据接收到的rtp的pt信息,找到该流的信息
RtpHeader *rtp = (RtpHeader *)buf;
// 根据接收到的rtp的pt信息,找到该流的信息
auto it = _pt_to_track.find(rtp->pt);
if (it == _pt_to_track.end()) {
WarnL << "unknown rtp pt:" << (int)rtp->pt;
......@@ -840,10 +851,10 @@ void WrappedRtpTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, R
return;
}
#endif
auto ssrc = ntohl(rtp->ssrc);
//修改ext id至统一
// 修改ext id至统一
string rid;
auto twcc_ext = track->rtp_ext_ctx->changeRtpExtId(rtp, true, &rid, RtpExtType::transport_cc);
......@@ -856,66 +867,67 @@ void WrappedRtpTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, R
_transport.createRtpChannel(rid, ssrc, *track);
}
//解析并排序rtp
ref->inputRtp(track->media->type, track->plan_rtp->sample_rate, (uint8_t *) buf, len, false);
// 解析并排序rtp
ref->inputRtp(track->media->type, track->plan_rtp->sample_rate, (uint8_t *)buf, len, false);
}
void WrappedRtxTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, RtpHeader *rtp) {
//修改ext id至统一
// 修改ext id至统一
string rid;
track->rtp_ext_ctx->changeRtpExtId(rtp, true, &rid, RtpExtType::transport_cc);
auto &ref = track->rtp_channel[rid];
if (!ref) {
//再接收到对应的rtp前,丢弃rtx包
WarnL << "unknown rtx rtp, rid:" << rid << ", ssrc:" << ntohl(rtp->ssrc) << ", codec:" << track->plan_rtp->codec << ", seq:" << ntohs(rtp->seq);
// 再接收到对应的rtp前,丢弃rtx包
WarnL << "unknown rtx rtp, rid:" << rid << ", ssrc:" << ntohl(rtp->ssrc) << ", codec:" << track->plan_rtp->codec
<< ", seq:" << ntohs(rtp->seq);
return;
}
//这里是rtx重传包
// https://datatracker.ietf.org/doc/html/rfc4588#section-4
// 这里是rtx重传包
// https://datatracker.ietf.org/doc/html/rfc4588#section-4
auto payload = rtp->getPayloadData();
auto size = rtp->getPayloadSize(len);
if (size < 2) {
return;
}
//前两个字节是原始的rtp的seq
// 前两个字节是原始的rtp的seq
auto origin_seq = payload[0] << 8 | payload[1];
// rtx 转换为 rtp
rtp->pt = track->plan_rtp->pt;
rtp->seq = htons(origin_seq);
rtp->ssrc = htonl(ref->getSSRC());
memmove((uint8_t *) buf + 2, buf, payload - (uint8_t *) buf);
memmove((uint8_t *)buf + 2, buf, payload - (uint8_t *)buf);
buf += 2;
len -= 2;
ref->inputRtp(track->media->type, track->plan_rtp->sample_rate, (uint8_t *) buf, len, true);
ref->inputRtp(track->media->type, track->plan_rtp->sample_rate, (uint8_t *)buf, len, true);
}
void WebRtcTransportImp::onSendNack(MediaTrack &track, const FCI_NACK &nack, uint32_t ssrc) {
auto rtcp = RtcpFB::create(RTPFBType::RTCP_RTPFB_NACK, &nack, FCI_NACK::kSize);
rtcp->ssrc = htonl(track.answer_ssrc_rtp);
rtcp->ssrc_media = htonl(ssrc);
sendRtcpPacket((char *) rtcp.get(), rtcp->getSize(), true);
sendRtcpPacket((char *)rtcp.get(), rtcp->getSize(), true);
}
void WebRtcTransportImp::onSendTwcc(uint32_t ssrc, const string &twcc_fci) {
auto rtcp = RtcpFB::create(RTPFBType::RTCP_RTPFB_TWCC, twcc_fci.data(), twcc_fci.size());
rtcp->ssrc = htonl(0);
rtcp->ssrc_media = htonl(ssrc);
sendRtcpPacket((char *) rtcp.get(), rtcp->getSize(), true);
sendRtcpPacket((char *)rtcp.get(), rtcp->getSize(), true);
}
///////////////////////////////////////////////////////////////////
void WebRtcTransportImp::onSortedRtp(MediaTrack &track, const string &rid, RtpPacket::Ptr rtp) {
if (track.media->type == TrackVideo && _pli_ticker.elapsedTime() > 2000) {
//定期发送pli请求关键帧,方便非rtc等协议
// 定期发送pli请求关键帧,方便非rtc等协议
_pli_ticker.resetTime();
sendRtcpPli(rtp->getSSRC());
//开启remb,则发送remb包调节比特率
// 开启remb,则发送remb包调节比特率
GET_CONFIG(size_t, remb_bit_rate, RTC::kRembBitRate);
if (remb_bit_rate && _answer_sdp->supportRtcpFb(SdpConst::kRembRtcpFb)) {
sendRtcpRemb(rtp->getSSRC(), remb_bit_rate);
......@@ -930,12 +942,14 @@ void WebRtcTransportImp::onSortedRtp(MediaTrack &track, const string &rid, RtpPa
void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool rtx) {
auto &track = _type_to_track[rtp->type];
if (!track) {
//忽略,对方不支持该编码类型
// 忽略,对方不支持该编码类型
return;
}
if (!rtx) {
//统计rtp发送情况,好做sr汇报
track->rtcp_context_send->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
// 统计rtp发送情况,好做sr汇报
track->rtcp_context_send->onRtp(
rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate,
rtp->size() - RtpPacket::kRtpTcpHeaderSize);
track->nack_list.pushBack(rtp);
#if 0
//此处模拟发送丢包
......@@ -944,45 +958,45 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r
}
#endif
} else {
//发送rtx重传包
//TraceL << "send rtx rtp:" << rtp->getSeq();
// 发送rtx重传包
// TraceL << "send rtx rtp:" << rtp->getSeq();
}
pair<bool/*rtx*/, MediaTrack *> ctx{rtx, track.get()};
pair<bool /*rtx*/, MediaTrack *> ctx { rtx, track.get() };
sendRtpPacket(rtp->data() + RtpPacket::kRtpTcpHeaderSize, rtp->size() - RtpPacket::kRtpTcpHeaderSize, flush, &ctx);
_bytes_usage += rtp->size() - RtpPacket::kRtpTcpHeaderSize;
}
void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, int &len, void *ctx) {
auto pr = (pair<bool/*rtx*/, MediaTrack *> *) ctx;
auto header = (RtpHeader *) buf;
auto pr = (pair<bool /*rtx*/, MediaTrack *> *)ctx;
auto header = (RtpHeader *)buf;
if (!pr->first || !pr->second->plan_rtx) {
//普通的rtp,或者不支持rtx, 修改目标pt和ssrc
// 普通的rtp,或者不支持rtx, 修改目标pt和ssrc
pr->second->rtp_ext_ctx->changeRtpExtId(header, false);
header->pt = pr->second->plan_rtp->pt;
header->ssrc = htonl(pr->second->answer_ssrc_rtp);
} else {
//重传的rtp, rtx
// 重传的rtp, rtx
pr->second->rtp_ext_ctx->changeRtpExtId(header, false);
header->pt = pr->second->plan_rtx->pt;
if (pr->second->answer_ssrc_rtx) {
//有rtx单独的ssrc,有些情况下,浏览器支持rtx,但是未指定rtx单独的ssrc
// 有rtx单独的ssrc,有些情况下,浏览器支持rtx,但是未指定rtx单独的ssrc
header->ssrc = htonl(pr->second->answer_ssrc_rtx);
} else {
//未单独指定rtx的ssrc,那么使用rtp的ssrc
// 未单独指定rtx的ssrc,那么使用rtp的ssrc
header->ssrc = htonl(pr->second->answer_ssrc_rtp);
}
auto origin_seq = ntohs(header->seq);
//seq跟原来的不一样
// seq跟原来的不一样
header->seq = htons(_rtx_seq[pr->second->media->type]);
++_rtx_seq[pr->second->media->type];
auto payload = header->getPayloadData();
auto payload_size = header->getPayloadSize(len);
if (payload_size) {
//rtp负载后移两个字节,这两个字节用于存放osn
//https://datatracker.ietf.org/doc/html/rfc4588#section-4
// rtp负载后移两个字节,这两个字节用于存放osn
// https://datatracker.ietf.org/doc/html/rfc4588#section-4
memmove(payload + 2, payload, payload_size);
}
payload[0] = origin_seq >> 8;
......@@ -991,7 +1005,7 @@ void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, int &len, void *ctx
}
}
void WebRtcTransportImp::onShutdown(const SockException &ex){
void WebRtcTransportImp::onShutdown(const SockException &ex) {
WarnL << ex.what();
unrefSelf();
for (auto &pr : _history_sessions) {
......@@ -1005,8 +1019,9 @@ void WebRtcTransportImp::onShutdown(const SockException &ex){
void WebRtcTransportImp::setSession(Session::Ptr session) {
_history_sessions.emplace(session.get(), session);
if (_selected_session) {
InfoL << "rtc network changed: " << _selected_session->get_peer_ip() << ":" << _selected_session->get_peer_port()
<< " -> " << session->get_peer_ip() << ":" << session->get_peer_port() << ", id:" << getIdentifier();
InfoL << "rtc network changed: " << _selected_session->get_peer_ip() << ":"
<< _selected_session->get_peer_port() << " -> " << session->get_peer_ip() << ":"
<< session->get_peer_port() << ", id:" << getIdentifier();
}
_selected_session = std::move(session);
unrefSelf();
......@@ -1016,18 +1031,18 @@ const Session::Ptr &WebRtcTransportImp::getSession() const {
return _selected_session;
}
uint64_t WebRtcTransportImp::getBytesUsage() const{
uint64_t WebRtcTransportImp::getBytesUsage() const {
return _bytes_usage;
}
uint64_t WebRtcTransportImp::getDuration() const{
uint64_t WebRtcTransportImp::getDuration() const {
return _alive_ticker.createdTime() / 1000;
}
/////////////////////////////////////////////////////////////////////////////////////////////
void WebRtcTransportImp::registerSelf() {
_self = static_pointer_cast<WebRtcTransportImp>(shared_from_this());
_self = static_pointer_cast<WebRtcTransportImp>(shared_from_this());
WebRtcTransportManager::Instance().addItem(getIdentifier(), _self);
}
......@@ -1079,8 +1094,8 @@ void WebRtcPluginManager::registerPlugin(const string &type, Plugin cb) {
_map_creator[type] = std::move(cb);
}
void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, const string &offer, const WebRtcArgs &args,
const onCreateRtc &cb) {
void WebRtcPluginManager::getAnswerSdp(
Session &sender, const string &type, const string &offer, const WebRtcArgs &args, const onCreateRtc &cb) {
lock_guard<mutex> lck(_mtx_creator);
auto it = _map_creator.find(type);
if (it == _map_creator.end()) {
......@@ -1090,17 +1105,20 @@ void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, cons
it->second(sender, offer, args, cb);
}
#include "WebRtcEchoTest.h"
#include "WebRtcPlayer.h"
#include "WebRtcPusher.h"
#include "WebRtcEchoTest.h"
void echo_plugin(Session &sender, const string &offer, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
void echo_plugin(
Session &sender, const string &offer, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
cb(*WebRtcEchoTest::create(EventPollerPool::Instance().getPoller()));
}
void push_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
void push_plugin(
Session &sender, const string &offer_sdp, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
MediaInfo info(args["url"]);
Broadcast::PublishAuthInvoker invoker = [cb, offer_sdp, info](const string &err, const ProtocolOption &option) mutable {
Broadcast::PublishAuthInvoker invoker = [cb, offer_sdp,
info](const string &err, const ProtocolOption &option) mutable {
if (!err.empty()) {
cb(WebRtcException(SockException(Err_other, err)));
return;
......@@ -1112,15 +1130,15 @@ void push_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
auto push_failed = (bool)src;
while (src) {
//尝试断连后继续推流
// 尝试断连后继续推流
auto rtsp_src = dynamic_pointer_cast<RtspMediaSourceImp>(src);
if (!rtsp_src) {
//源不是rtsp推流产生的
// 源不是rtsp推流产生的
break;
}
auto ownership = rtsp_src->getOwnership();
if (!ownership) {
//获取推流源所有权失败
// 获取推流源所有权失败
break;
}
push_src = std::move(rtsp_src);
......@@ -1139,20 +1157,23 @@ void push_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
push_src_ownership = push_src->getOwnership();
push_src->setProtocolOption(option);
}
auto rtc = WebRtcPusher::create(EventPollerPool::Instance().getPoller(), push_src, push_src_ownership, info, option);
auto rtc
= WebRtcPusher::create(EventPollerPool::Instance().getPoller(), push_src, push_src_ownership, info, option);
push_src->setListener(rtc);
cb(*rtc);
};
//rtsp推流需要鉴权
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPublish, MediaOriginType::rtc_push, info, invoker, static_cast<SockInfo &>(sender));
// rtsp推流需要鉴权
auto flag = NoticeCenter::Instance().emitEvent(
Broadcast::kBroadcastMediaPublish, MediaOriginType::rtc_push, info, invoker, static_cast<SockInfo &>(sender));
if (!flag) {
//该事件无人监听,默认不鉴权
// 该事件无人监听,默认不鉴权
invoker("", ProtocolOption());
}
}
void play_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
void play_plugin(
Session &sender, const string &offer_sdp, const WebRtcArgs &args, const WebRtcPluginManager::onCreateRtc &cb) {
MediaInfo info(args["url"]);
auto session_ptr = sender.shared_from_this();
Broadcast::AuthInvoker invoker = [cb, offer_sdp, info, session_ptr](const string &err) mutable {
......@@ -1161,7 +1182,7 @@ void play_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
return;
}
//webrtc播放的是rtsp的源
// webrtc播放的是rtsp的源
info._schema = RTSP_SCHEMA;
MediaSource::findAsync(info, session_ptr, [=](const MediaSource::Ptr &src_in) mutable {
auto src = dynamic_pointer_cast<RtspMediaSource>(src_in);
......@@ -1169,22 +1190,23 @@ void play_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
cb(WebRtcException(SockException(Err_other, "stream not found")));
return;
}
//还原成rtc,目的是为了hook时识别哪种播放协议
// 还原成rtc,目的是为了hook时识别哪种播放协议
info._schema = RTC_SCHEMA;
auto rtc = WebRtcPlayer::create(EventPollerPool::Instance().getPoller(), src, info);
cb(*rtc);
});
};
//广播通用播放url鉴权事件
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, info, invoker, static_cast<SockInfo &>(sender));
// 广播通用播放url鉴权事件
auto flag = NoticeCenter::Instance().emitEvent(
Broadcast::kBroadcastMediaPlayed, info, invoker, static_cast<SockInfo &>(sender));
if (!flag) {
//该事件无人监听,默认不鉴权
// 该事件无人监听,默认不鉴权
invoker("");
}
}
static onceToken s_rtc_auto_register([](){
static onceToken s_rtc_auto_register([]() {
WebRtcPluginManager::Instance().registerPlugin("echo", echo_plugin);
WebRtcPluginManager::Instance().registerPlugin("push", push_plugin);
WebRtcPluginManager::Instance().registerPlugin("play", play_plugin);
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论