重写rtp框架

This commit is contained in:
xiongziliang 2021-01-31 19:19:24 +08:00
parent 5175c52abe
commit 070bf19cb5
21 changed files with 395 additions and 322 deletions

View File

@ -195,8 +195,6 @@ sslport=19350
#音频mtu大小该参数限制rtp最大字节数推荐不要超过1400
#加大该值会明显增加直播延时
audioMtuSize=600
#rtp时间戳回环时间单位毫秒
cycleMS=46800000
#视频mtu大小该参数限制rtp最大字节数推荐不要超过1400
videoMtuSize=1400

View File

@ -194,15 +194,12 @@ const string kAudioMtuSize = RTP_FIELD"audioMtuSize";
const string kMaxRtpCount = RTP_FIELD"maxRtpCount";
//如果RTP序列正确次数累计达到该数字就启动清空排序缓存
const string kClearCount = RTP_FIELD"clearCount";
//最大RTP时间为13个小时每13小时回环一次
const string kCycleMS = RTP_FIELD"cycleMS";
onceToken token([](){
mINI::Instance()[kVideoMtuSize] = 1400;
mINI::Instance()[kAudioMtuSize] = 600;
mINI::Instance()[kMaxRtpCount] = 50;
mINI::Instance()[kClearCount] = 10;
mINI::Instance()[kCycleMS] = 13*60*60*1000;
},nullptr);
} //namespace Rtsp

View File

@ -251,8 +251,6 @@ extern const string kAudioMtuSize;
extern const string kMaxRtpCount;
//如果RTP序列正确次数累计达到该数字就启动清空排序缓存
extern const string kClearCount;
//最大RTP时间为13个小时每13小时回环一次
extern const string kCycleMS;
} //namespace Rtsp
////////////组播配置///////////

View File

@ -25,32 +25,30 @@ AACRtpEncoder::AACRtpEncoder(uint32_t ui32Ssrc,
}
void AACRtpEncoder::inputFrame(const Frame::Ptr &frame) {
GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS);
auto uiStamp = frame->dts();
auto pcData = frame->data() + frame->prefixSize();
auto iLen = frame->size() - frame->prefixSize();
uiStamp %= cycleMS;
auto *ptr = (char *) pcData;
auto iSize = iLen;
while (iSize > 0) {
if (iSize <= _ui32MtuSize - 20) {
_aucSectionBuf[0] = 0;
_aucSectionBuf[1] = 16;
_aucSectionBuf[2] = (iLen >> 5) & 0xFF;
_aucSectionBuf[3] = ((iLen & 0x1F) << 3) & 0xFF;
memcpy(_aucSectionBuf + 4, ptr, iSize);
makeAACRtp(_aucSectionBuf, iSize + 4, true, uiStamp);
auto stamp = frame->dts();
auto data = frame->data() + frame->prefixSize();
auto len = frame->size() - frame->prefixSize();
auto ptr = (char *) data;
auto remain_size = len;
auto max_size = getMaxSize() - 4;
while (remain_size > 0) {
if (remain_size <= max_size) {
_section_buf[0] = 0;
_section_buf[1] = 16;
_section_buf[2] = (len >> 5) & 0xFF;
_section_buf[3] = ((len & 0x1F) << 3) & 0xFF;
memcpy(_section_buf + 4, ptr, remain_size);
makeAACRtp(_section_buf, remain_size + 4, true, stamp);
break;
}
_aucSectionBuf[0] = 0;
_aucSectionBuf[1] = 16;
_aucSectionBuf[2] = ((iLen) >> 5) & 0xFF;
_aucSectionBuf[3] = ((iLen & 0x1F) << 3) & 0xFF;
memcpy(_aucSectionBuf + 4, ptr, _ui32MtuSize - 20);
makeAACRtp(_aucSectionBuf, _ui32MtuSize - 16, false, uiStamp);
ptr += (_ui32MtuSize - 20);
iSize -= (_ui32MtuSize - 20);
_section_buf[0] = 0;
_section_buf[1] = 16;
_section_buf[2] = ((len) >> 5) & 0xFF;
_section_buf[3] = ((len & 0x1F) << 3) & 0xFF;
memcpy(_section_buf + 4, ptr, max_size);
makeAACRtp(_section_buf, max_size + 4, false, stamp);
ptr += max_size;
remain_size -= max_size;
}
}
@ -82,15 +80,16 @@ void AACRtpDecoder::obtainFrame() {
_frame->_codec_id = CodecAAC;
}
bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) {
auto stamp = rtp->getStampMS();
//rtp数据开始部分
uint8_t *ptr = (uint8_t *) rtppack->data() + rtppack->offset;
auto ptr = rtp->getPayload();
//rtp数据末尾
uint8_t *end = (uint8_t *) rtppack->data() + rtppack->size();
auto end = ptr + rtp->getPayloadSize();
//首2字节表示Au-Header的个数单位bit所以除以16得到Au-Header个数
uint16_t au_header_count = ((ptr[0] << 8) | ptr[1]) >> 4;
auto au_header_count = ((ptr[0] << 8) | ptr[1]) >> 4;
//记录au_header起始指针
uint8_t *au_header_ptr = ptr + 2;
auto au_header_ptr = ptr + 2;
ptr = au_header_ptr + au_header_count * 2;
if (end < ptr) {
@ -100,11 +99,11 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
if (!_last_dts) {
//记录第一个时间戳
_last_dts = rtppack->timeStamp;
_last_dts = stamp;
}
//每个audio unit时间戳增量
auto dts_inc = (rtppack->timeStamp - _last_dts) / au_header_count;
auto dts_inc = (stamp - _last_dts) / au_header_count;
if (dts_inc < 0 && dts_inc > 100) {
//时间戳增量异常,忽略
dts_inc = 0;
@ -129,7 +128,7 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
}
}
//记录上次时间戳
_last_dts = rtppack->timeStamp;
_last_dts = stamp;
return false;
}

View File

@ -80,7 +80,7 @@ private:
void makeAACRtp(const void *pData, size_t uiLen, bool bMark, uint32_t uiStamp);
private:
unsigned char _aucSectionBuf[1600];
unsigned char _section_buf[1600];
};
}//namespace mediakit

View File

@ -29,14 +29,16 @@ void CommonRtpDecoder::obtainFrame() {
}
bool CommonRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool){
auto payload = rtp->data() + rtp->offset;
auto size = rtp->size() - rtp->offset;
auto payload = rtp->getPayload();
auto size = rtp->getPayloadSize();
auto stamp = rtp->getStampMS();
auto seq = rtp->getSeq();
if (size <= 0) {
//无实际负载
return false;
}
if (_frame->_dts != rtp->timeStamp || _frame->_buffer.size() > _max_frame_size) {
if (_frame->_dts != stamp || _frame->_buffer.size() > _max_frame_size) {
//时间戳发生变化或者缓存超过MAX_FRAME_SIZE则清空上帧数据
if (!_frame->_buffer.empty()) {
//有有效帧,则输出
@ -45,20 +47,20 @@ bool CommonRtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool){
//新的一帧数据
obtainFrame();
_frame->_dts = rtp->timeStamp;
_frame->_dts = stamp;
_drop_flag = false;
} else if (_last_seq != 0 && (uint16_t)(_last_seq + 1) != rtp->sequence) {
} else if (_last_seq != 0 && (uint16_t)(_last_seq + 1) != seq) {
//时间戳未发生变化但是seq却不连续说明中间rtp丢包了那么整帧应该废弃
WarnL << "rtp丢包:" << _last_seq << " -> " << rtp->sequence;
WarnL << "rtp丢包:" << _last_seq << " -> " << seq;
_drop_flag = true;
_frame->_buffer.clear();
}
if (!_drop_flag) {
_frame->_buffer.append(payload, size);
_frame->_buffer.append((char *)payload, size);
}
_last_seq = rtp->sequence;
_last_seq = seq;
return false;
}
@ -70,18 +72,17 @@ CommonRtpEncoder::CommonRtpEncoder(CodecId codec, uint32_t ssrc, uint32_t mtu_si
}
void CommonRtpEncoder::inputFrame(const Frame::Ptr &frame){
GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS);
auto stamp = frame->dts() % cycleMS;
auto stamp = frame->dts();
auto ptr = frame->data() + frame->prefixSize();
auto len = frame->size() - frame->prefixSize();
auto remain_size = len;
const auto max_rtp_size = _ui32MtuSize - 20;
auto max_size = getMaxSize();
bool mark = false;
while (remain_size > 0) {
size_t rtp_size;
if (remain_size > max_rtp_size) {
rtp_size = max_rtp_size;
if (remain_size > max_size) {
rtp_size = max_size;
} else {
rtp_size = remain_size;
mark = true;

View File

@ -46,7 +46,7 @@ bool H264RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool key_pos) {
return decodeRtp(rtp);
}
bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtp) {
/**
* h264帧类型
* Type==1:P/B frame
@ -71,8 +71,11 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
29 FU-B Fragmentation unit 5.8
30-31 undefined -
*/
const uint8_t *frame = (uint8_t *) rtppack->data() + rtppack->offset;
auto length = rtppack->size() - rtppack->offset;
auto frame = rtp->getPayload();
auto length = rtp->getPayloadSize();
auto stamp = rtp->getStampMS();
auto seq = rtp->getSeq();
int nal_type = *frame & 0x1F;
int nal_suffix = *frame & (~0x1F);
@ -80,7 +83,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
//a full frame
_h264frame->_buffer.assign("\x0\x0\x0\x1", 4);
_h264frame->_buffer.append((char *) frame, length);
_h264frame->_pts = rtppack->timeStamp;
_h264frame->_pts = stamp;
auto key = _h264frame->keyFrame();
onGetH264(_h264frame);
return (key); //i frame
@ -107,7 +110,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
//有有效数据
_h264frame->_buffer.assign("\x0\x0\x0\x1", 4);
_h264frame->_buffer.append((char *) ptr, len);
_h264frame->_pts = rtppack->timeStamp;
_h264frame->_pts = stamp;
if ((ptr[0] & 0x1F) == H264Frame::NAL_IDR) {
haveIDR = true;
}
@ -127,16 +130,16 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
_h264frame->_buffer.assign("\x0\x0\x0\x1", 4);
_h264frame->_buffer.push_back(nal_suffix | fu.type);
_h264frame->_buffer.append((char *) frame + 2, length - 2);
_h264frame->_pts = rtppack->timeStamp;
_h264frame->_pts = stamp;
//该函数return时保存下当前sequence,以便下次对比seq是否连续
_lastSeq = rtppack->sequence;
_lastSeq = seq;
return _h264frame->keyFrame();
}
if (rtppack->sequence != (uint16_t)(_lastSeq + 1) && rtppack->sequence != 0) {
if (seq != (uint16_t)(_lastSeq + 1) && seq != 0) {
//中间的或末尾的rtp包其seq必须连续(如果回环了则判定为连续)否则说明rtp丢包那么该帧不完整必须得丢弃
_h264frame->_buffer.clear();
WarnL << "rtp丢包: " << rtppack->sequence << " != " << _lastSeq << " + 1,该帧被废弃";
WarnL << "rtp丢包: " << seq << " != " << _lastSeq << " + 1,该帧被废弃";
return false;
}
@ -144,13 +147,13 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
//该帧的中间rtp包 FU-A mid
_h264frame->_buffer.append((char *) frame + 2, length - 2);
//该函数return时保存下当前sequence,以便下次对比seq是否连续
_lastSeq = rtppack->sequence;
_lastSeq = seq;
return false;
}
//该帧最后一个rtp包 FU-A end
_h264frame->_buffer.append((char *) frame + 2, length - 2);
_h264frame->_pts = rtppack->timeStamp;
_h264frame->_pts = stamp;
onGetH264(_h264frame);
return false;
}
@ -163,7 +166,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
// 0 udef
// 30 udef
// 31 udef
WarnL << "不支持的rtp类型:" << (int) nal_type << " " << rtppack->sequence;
WarnL << "不支持的rtp类型:" << (int) nal_type << " " << seq;
return false;
}
}
@ -193,15 +196,14 @@ H264RtpEncoder::H264RtpEncoder(uint32_t ui32Ssrc,
}
void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
GET_CONFIG(uint32_t,cycleMS,Rtp::kCycleMS);
auto ptr = frame->data() + frame->prefixSize();
auto len = frame->size() - frame->prefixSize();
auto pts = frame->pts() % cycleMS;
auto pts = frame->pts();
auto nal_type = H264_TYPE(ptr[0]);
size_t payload_size = _ui32MtuSize - 2;
auto max_size = getMaxSize() - 2;
//超过MTU则按照FU-A模式打包
if (len > payload_size + 1) {
if (len > max_size + 1) {
//最高位bit为forbidden_zero_bit,
//后面2bit为nal_ref_idc(帧重要程度),00:可以丢,11:不能丢
//末尾5bit为nalu type固定为28(FU-A)
@ -211,10 +213,10 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
bool mark_bit = false;
size_t offset = 1;
while (!mark_bit) {
if (len <= offset + payload_size) {
if (len <= offset + max_size) {
//FU-A end
mark_bit = true;
payload_size = len - offset;
max_size = len - offset;
s_e_r_flags = (1 << 6) | nal_type;
} else if (fu_a_start) {
//FU-A start
@ -226,19 +228,19 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
{
//传入nullptr先不做payload的内存拷贝
auto rtp = makeRtp(getTrackType(), nullptr, payload_size + 2, mark_bit, pts);
auto rtp = makeRtp(getTrackType(), nullptr, max_size + 2, mark_bit, pts);
//rtp payload 负载部分
uint8_t *payload = (uint8_t*)rtp->data() + rtp->offset;
uint8_t *payload = rtp->getPayload();
//FU-A 第1个字节
payload[0] = nal_fu_a;
//FU-A 第2个字节
payload[1] = s_e_r_flags;
//H264 数据
memcpy(payload + 2, (unsigned char *) ptr + offset, payload_size);
memcpy(payload + 2, (unsigned char *) ptr + offset, max_size);
//输入到rtp环形缓存
RtpCodec::inputRtp(rtp, fu_a_start && nal_type == H264Frame::NAL_IDR);
}
offset += payload_size;
offset += max_size;
fu_a_start = false;
}
} else {

View File

@ -168,9 +168,11 @@ bool H265RtpDecoder::mergeFu(const uint8_t *ptr, ssize_t size, uint16_t seq, uin
return false;
}
bool H265RtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool ) {
const uint8_t *frame = (uint8_t *) rtppack->data() + rtppack->offset;
auto length = rtppack->size() - rtppack->offset;
bool H265RtpDecoder::inputRtp(const RtpPacket::Ptr &rtp, bool ) {
auto frame = rtp->getPayload();
auto length = rtp->getPayloadSize();
auto stamp = rtp->getStampMS();
auto seq = rtp->getSeq();
int nal = H265_TYPE(frame[0]);
if (nal > 50){
@ -185,13 +187,13 @@ bool H265RtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool ) {
return false;
case 48:
// aggregated packet (AP) - with two or more NAL units
return unpackAp(frame, length, rtppack->timeStamp);
return unpackAp(frame, length, stamp);
case 49:
// fragmentation unit (FU)
return mergeFu(frame, length, rtppack->sequence, rtppack->timeStamp);
return mergeFu(frame, length, seq, stamp);
default:
// 4.4.1. Single NAL Unit Packets (p24)
return singleFrame(frame, length, rtppack->timeStamp);
return singleFrame(frame, length, stamp);
}
}
@ -228,25 +230,24 @@ H265RtpEncoder::H265RtpEncoder(uint32_t ui32Ssrc,
}
void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) {
GET_CONFIG(uint32_t, cycleMS, Rtp::kCycleMS);
auto ptr = (uint8_t *) frame->data() + frame->prefixSize();
auto len = frame->size() - frame->prefixSize();
auto pts = frame->pts() % cycleMS;
auto pts = frame->pts();
auto nal_type = H265_TYPE(ptr[0]); //获取NALU的5bit 帧类型
size_t payload_size = _ui32MtuSize - 3;
auto max_size = getMaxSize() - 3;
//超过MTU,按照FU方式打包
if (len > payload_size + 2) {
if (len > max_size + 2) {
//获取帧头数据1byte
unsigned char s_e_flags;
bool fu_start = true;
bool mark_bit = false;
size_t offset = 2;
while (!mark_bit) {
if (len <= offset + payload_size) {
if (len <= offset + max_size) {
//FU end
mark_bit = true;
payload_size = len - offset;
max_size = len - offset;
s_e_flags = (1 << 6) | nal_type;
} else if (fu_start) {
//FU start
@ -258,9 +259,9 @@ void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) {
{
//传入nullptr先不做payload的内存拷贝
auto rtp = makeRtp(getTrackType(), nullptr, payload_size + 3, mark_bit, pts);
auto rtp = makeRtp(getTrackType(), nullptr, max_size + 3, mark_bit, pts);
//rtp payload 负载部分
uint8_t *payload = (uint8_t *) rtp->data() + rtp->offset;
uint8_t *payload = rtp->getPayload();
//FU 第1个字节表明为FU
payload[0] = 49 << 1;
//FU 第2个字节貌似固定为1
@ -268,12 +269,12 @@ void H265RtpEncoder::inputFrame(const Frame::Ptr &frame) {
//FU 第3个字节
payload[2] = s_e_flags;
//H265 数据
memcpy(payload + 3, ptr + offset, payload_size);
memcpy(payload + 3, ptr + offset, max_size);
//输入到rtp环形缓存
RtpCodec::inputRtp(rtp, fu_start && H265Frame::isKeyFrame(nal_type));
}
offset += payload_size;
offset += max_size;
fu_start = false;
}
} else {

View File

@ -35,8 +35,9 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
}
void GB28181Process::onRtpSorted(const RtpPacket::Ptr &rtp, int) {
auto pt = rtp->getHeader()->pt;
if (!_rtp_decoder) {
switch (rtp->PT) {
switch (pt) {
case 98: {
//H264负载
_rtp_decoder = std::make_shared<H264RtpDecoder>();
@ -44,8 +45,8 @@ void GB28181Process::onRtpSorted(const RtpPacket::Ptr &rtp, int) {
break;
}
default: {
if (rtp->PT != 33 && rtp->PT != 96) {
WarnL << "rtp payload type未识别(" << (int) rtp->PT << "),已按ts或ps负载处理";
if (pt != 33 && pt != 96) {
WarnL << "rtp payload type未识别(" << (int) pt << "),已按ts或ps负载处理";
}
//ts或ps负载
_rtp_decoder = std::make_shared<CommonRtpDecoder>(CodecInvalid, 32 * 1024);

View File

@ -28,7 +28,7 @@ void RtpCache::input(uint64_t stamp, Buffer::Ptr buffer) {
void RtpCachePS::onRTP(Buffer::Ptr buffer) {
auto rtp = static_pointer_cast<RtpPacket>(buffer);
auto stamp = rtp->timeStamp;
auto stamp = rtp->getStampMS();
input(stamp, std::move(buffer));
}

View File

@ -13,43 +13,37 @@
namespace mediakit{
RtpPacket::Ptr RtpInfo::makeRtp(TrackType type, const void* data, size_t len, bool mark, uint32_t stamp) {
uint16_t payload_len = (uint16_t)(len + 12);
uint32_t ts = htonl((_ui32SampleRate / 1000) * stamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
uint16_t payload_len = (uint16_t) (len + RtpPacket::kRtpHeaderSize);
auto rtp = ResourcePoolHelper<RtpPacket>::obtainObj();
rtp->setCapacity(payload_len + RtpPacket::kRtpTcpHeaderSize);
rtp->setSize(payload_len + RtpPacket::kRtpTcpHeaderSize);
rtp->sample_rate = _sample_rate;
rtp->type = type;
auto rtp_ptr = ResourcePoolHelper<RtpPacket>::obtainObj();
rtp_ptr->setCapacity(len + 16);
rtp_ptr->setSize(len + 16);
//rtsp over tcp 头
auto ptr = (uint8_t *) rtp->data();
ptr[0] = '$';
ptr[1] = _interleaved;
ptr[2] = payload_len >> 8;
ptr[3] = payload_len & 0xFF;
auto *rtp = (unsigned char *)rtp_ptr->data();
rtp[0] = '$';
rtp[1] = _ui8Interleaved;
rtp[2] = payload_len >> 8;
rtp[3] = payload_len & 0xFF;
rtp[4] = 0x80;
rtp[5] = (mark << 7) | _ui8PayloadType;
memcpy(&rtp[6], &sq, 2);
memcpy(&rtp[8], &ts, 4);
//ssrc
memcpy(&rtp[12], &sc, 4);
//rtp头
auto header = rtp->getHeader();
header->version = RtpPacket::kRtpVersion;
header->padding = 0;
header->ext = 0;
header->csrc = 0;
header->mark = mark;
header->pt = _pt;
header->seq = htons(_seq++);
header->stamp = htonl(uint64_t(stamp) * _sample_rate / 1000);
header->ssrc = htonl(_ssrc);
if(data){
//payload
memcpy(&rtp[16], data, len);
//有效负载
if (data) {
memcpy(&ptr[RtpPacket::kRtpHeaderSize + RtpPacket::kRtpTcpHeaderSize], data, len);
}
rtp_ptr->PT = _ui8PayloadType;
rtp_ptr->interleaved = _ui8Interleaved;
rtp_ptr->mark = mark;
rtp_ptr->sequence = _ui16Sequence;
rtp_ptr->timeStamp = stamp;
rtp_ptr->ssrc = _ui32Ssrc;
rtp_ptr->type = type;
rtp_ptr->offset = 16;
_ui16Sequence++;
_ui32TimeStamp = stamp;
return rtp_ptr;
return rtp;
}
}//namespace mediakit

View File

@ -58,63 +58,41 @@ protected:
RingType::Ptr _rtpRing;
};
class RtpInfo : public ResourcePoolHelper<RtpPacket>{
public:
typedef std::shared_ptr<RtpInfo> Ptr;
RtpInfo(uint32_t ui32Ssrc,
uint32_t ui32MtuSize,
uint32_t ui32SampleRate,
uint8_t ui8PayloadType,
uint8_t ui8Interleaved) {
if(ui32Ssrc == 0){
ui32Ssrc = ((uint64_t)this) & 0xFFFFFFFF;
RtpInfo(uint32_t ssrc, size_t mtu_size, uint32_t sample_rate, uint8_t pt, uint8_t interleaved) {
if (ssrc == 0) {
ssrc = ((uint64_t) this) & 0xFFFFFFFF;
}
_ui32Ssrc = ui32Ssrc;
_ui32SampleRate = ui32SampleRate;
_ui32MtuSize = ui32MtuSize;
_ui8PayloadType = ui8PayloadType;
_ui8Interleaved = ui8Interleaved;
_pt = pt;
_ssrc = ssrc;
_mtu_size = mtu_size;
_sample_rate = sample_rate;
_interleaved = interleaved;
}
virtual ~RtpInfo(){}
~RtpInfo() override {}
int getInterleaved() const {
return _ui8Interleaved;
}
int getPayloadType() const {
return _ui8PayloadType;
}
int getSampleRate() const {
return _ui32SampleRate;
//返回rtp负载最大长度
size_t getMaxSize() const {
return _mtu_size - RtpPacket::kRtpHeaderSize;
}
uint32_t getSsrc() const {
return _ui32Ssrc;
return _ssrc;
}
uint16_t getSeqence() const {
return _ui16Sequence;
}
uint32_t getTimestamp() const {
return _ui32TimeStamp;
}
uint32_t getMtuSize() const {
return _ui32MtuSize;
}
RtpPacket::Ptr makeRtp(TrackType type,const void *data, size_t len, bool mark, uint32_t stamp);
protected:
uint32_t _ui32Ssrc;
uint32_t _ui32SampleRate;
uint32_t _ui32MtuSize;
uint8_t _ui8PayloadType;
uint8_t _ui8Interleaved;
uint16_t _ui16Sequence = 0;
uint32_t _ui32TimeStamp = 0;
private:
uint8_t _pt;
uint8_t _interleaved;
uint16_t _seq = 0;
uint32_t _ssrc;
uint32_t _sample_rate;
size_t _mtu_size;
};
class RtpCodec : public RtpRing, public FrameDispatcher , public CodecInfo{

View File

@ -11,10 +11,6 @@
#include "Common/config.h"
#include "RtpReceiver.h"
#define AV_RB16(x) \
((((const uint8_t*)(x))[0] << 8) | \
((const uint8_t*)(x))[1])
#define RTP_MAX_SIZE (10 * 1024)
namespace mediakit {
@ -28,122 +24,67 @@ RtpReceiver::RtpReceiver() {
++index;
}
}
RtpReceiver::~RtpReceiver() {}
bool RtpReceiver::handleOneRtp(int track_index, TrackType type, int samplerate, uint8_t *rtp_raw_ptr, size_t rtp_raw_len) {
if (rtp_raw_len < 12) {
WarnL << "rtp包太小:" << rtp_raw_len;
bool RtpReceiver::handleOneRtp(int index, TrackType type, int sample_rate, uint8_t *ptr, size_t len) {
if (len < RtpPacket::kRtpHeaderSize) {
WarnL << "rtp包太小:" << len;
return false;
}
uint32_t version = rtp_raw_ptr[0] >> 6;
uint8_t padding = 0;
uint8_t ext = rtp_raw_ptr[0] & 0x10;
uint8_t csrc = rtp_raw_ptr[0] & 0x0f;
if (rtp_raw_ptr[0] & 0x20) {
//获取padding大小
padding = rtp_raw_ptr[rtp_raw_len - 1];
//移除padding flag
rtp_raw_ptr[0] &= ~0x20;
//移除padding字节
rtp_raw_len -= padding;
if (len > RTP_MAX_SIZE) {
WarnL << "超大的rtp包:" << len << " > " << RTP_MAX_SIZE;
return false;
}
if (version != 2) {
throw std::invalid_argument("非法的rtpversion != 2");
}
auto rtp_ptr = _rtp_pool.obtain();
auto &rtp = *rtp_ptr;
rtp.type = type;
rtp.interleaved = 2 * type;
rtp.mark = rtp_raw_ptr[1] >> 7;
rtp.PT = rtp_raw_ptr[1] & 0x7F;
//序列号,内存对齐
memcpy(&rtp.sequence, rtp_raw_ptr + 2, 2);
rtp.sequence = ntohs(rtp.sequence);
//时间戳,内存对齐
memcpy(&rtp.timeStamp, rtp_raw_ptr + 4, 4);
rtp.timeStamp = ntohl(rtp.timeStamp);
if (!samplerate) {
if (!sample_rate) {
//无法把时间戳转换成毫秒
return false;
}
//时间戳转换成毫秒
rtp.timeStamp = rtp.timeStamp * 1000LL / samplerate;
//ssrc,内存对齐
memcpy(&rtp.ssrc, rtp_raw_ptr + 8, 4);
rtp.ssrc = ntohl(rtp.ssrc);
if (_ssrc[track_index] != rtp.ssrc) {
if (_ssrc[track_index] == 0) {
//保存SSRC至track对象
_ssrc[track_index] = rtp.ssrc;
} else {
//ssrc错误
WarnL << "ssrc错误:" << rtp.ssrc << " != " << _ssrc[track_index];
if (_ssrc_err_count[track_index]++ > 10) {
//ssrc切换后清除老数据
WarnL << "ssrc更换:" << _ssrc[track_index] << " -> " << rtp.ssrc;
_rtp_sortor[track_index].clear();
_ssrc[track_index] = rtp.ssrc;
RtpHeader *header = (RtpHeader *) ptr;
if (header->version != RtpPacket::kRtpVersion) {
throw std::invalid_argument("非法的rtpversion字段非法");
}
return false;
}
}
//ssrc匹配正确不匹配计数清零
_ssrc_err_count[track_index] = 0;
//rtp 12个固定字节头
rtp.offset = 12;
//rtp有csrc
rtp.offset += 4 * csrc;
if (ext) {
//rtp有ext
uint16_t reserved = AV_RB16(rtp_raw_ptr + rtp.offset);
uint16_t extlen = AV_RB16(rtp_raw_ptr + rtp.offset + 2) << 2;
rtp.offset += extlen + 4;
}
if (rtp_raw_len <= rtp.offset) {
if (!header->getPayloadSize(len)) {
//无有效负载的rtp包
return false;
}
if (rtp_raw_len > RTP_MAX_SIZE) {
WarnL << "超大的rtp包:" << rtp_raw_len << " > " << RTP_MAX_SIZE;
//比对缓存ssrc
auto ssrc = ntohl(header->ssrc);
if (!_ssrc[index]) {
//保存SSRC至track对象
_ssrc[index] = ssrc;
} else if (_ssrc[index] != ssrc) {
//ssrc错误
WarnL << "ssrc错误:" << ssrc << " != " << _ssrc[index];
return false;
}
//设置rtp负载长度
rtp.setCapacity(rtp_raw_len + 4);
rtp.setSize(rtp_raw_len + 4);
uint8_t *payload_ptr = (uint8_t *) rtp.data();
payload_ptr[0] = '$';
payload_ptr[1] = rtp.interleaved;
payload_ptr[2] = (rtp_raw_len >> 8) & 0xFF;
payload_ptr[3] = rtp_raw_len & 0xFF;
//添加rtp over tcp前4个字节的偏移量
rtp.offset += 4;
//拷贝rtp负载
memcpy(payload_ptr + 4, rtp_raw_ptr, rtp_raw_len);
//排序rtp
auto seq = rtp_ptr->sequence;
onBeforeRtpSorted(rtp_ptr, track_index);
_rtp_sortor[track_index].sortPacket(seq, std::move(rtp_ptr));
auto rtp = _rtp_pool.obtain();
//需要添加4个字节的rtp over tcp头
rtp->setCapacity(RtpPacket::kRtpTcpHeaderSize + len);
rtp->setSize(RtpPacket::kRtpTcpHeaderSize + len);
rtp->sample_rate = sample_rate;
rtp->type = type;
//赋值4个字节的rtp over tcp头
uint8_t *data = (uint8_t *) rtp->data();
data[0] = '$';
data[1] = 2 * type;
data[2] = (len >> 8) & 0xFF;
data[3] = len & 0xFF;
//拷贝rtp
memcpy(&data[4], ptr, len);
onBeforeRtpSorted(rtp, index);
auto seq = rtp->getSeq();
_rtp_sortor[index].sortPacket(seq, std::move(rtp));
return true;
}
void RtpReceiver::clear() {
CLEAR_ARR(_ssrc);
CLEAR_ARR(_ssrc_err_count);
for (auto &sortor : _rtp_sortor) {
sortor.clear();
}
@ -153,16 +94,16 @@ void RtpReceiver::setPoolSize(size_t size) {
_rtp_pool.setSize(size);
}
size_t RtpReceiver::getJitterSize(int track_index) const{
return _rtp_sortor[track_index].getJitterSize();
size_t RtpReceiver::getJitterSize(int index) const{
return _rtp_sortor[index].getJitterSize();
}
size_t RtpReceiver::getCycleCount(int track_index) const{
return _rtp_sortor[track_index].getCycleCount();
size_t RtpReceiver::getCycleCount(int index) const{
return _rtp_sortor[index].getCycleCount();
}
uint32_t RtpReceiver::getSSRC(int track_index) const{
return _ssrc[track_index];
uint32_t RtpReceiver::getSSRC(int index) const{
return _ssrc[index];
}
}//namespace mediakit

View File

@ -168,14 +168,14 @@ public:
protected:
/**
* rtp包
* @param track_index track下标索引
* @param index track下标索引
* @param type track类型
* @param samplerate rtp时间戳基准时钟90000
* @param rtp_raw_ptr rtp数据指针
* @param rtp_raw_len rtp数据指针长度
* @param ptr rtp数据指针
* @param len rtp数据指针长度
* @return true
*/
bool handleOneRtp(int track_index, TrackType type, int samplerate, uint8_t *rtp_raw_ptr, size_t rtp_raw_len);
bool handleOneRtp(int index, TrackType type, int samplerate, uint8_t *ptr, size_t len);
/**
* rtp数据包排序后输出
@ -199,8 +199,6 @@ protected:
private:
uint32_t _ssrc[2] = {0, 0};
//ssrc不匹配计数
size_t _ssrc_err_count[2] = {0, 0};
//rtp排序缓存根据seq排序
PacketSortor<RtpPacket::Ptr> _rtp_sortor[2];
//rtp循环池

View File

@ -415,14 +415,101 @@ string printSSRC(uint32_t ui32Ssrc) {
}
Buffer::Ptr makeRtpOverTcpPrefix(uint16_t size, uint8_t interleaved){
auto rtp_tcp = std::make_shared<BufferRaw>(4);
auto rtp_tcp = std::make_shared<BufferRaw>(RtpPacket::kRtpTcpHeaderSize);
rtp_tcp->setSize(RtpPacket::kRtpTcpHeaderSize);
auto ptr = rtp_tcp->data();
ptr[0] = '$';
ptr[1] = interleaved;
ptr[2] = (size >> 8) & 0xFF;
ptr[3] = size & 0xFF;
rtp_tcp->setSize(4);
return rtp_tcp;
}
#define AV_RB16(x) \
((((const uint8_t*)(x))[0] << 8) | \
((const uint8_t*)(x))[1])
size_t RtpHeader::getCsrcSize() const {
//每个csrc占用4字节
return csrc << 2;
}
uint8_t *RtpHeader::getCsrcData() {
if (!csrc) {
return nullptr;
}
return &payload;
}
size_t RtpHeader::getExtSize() const {
//rtp有ext
if (!ext) {
return 0;
}
auto ext_ptr = &payload + getCsrcSize();
uint16_t reserved = AV_RB16(ext_ptr);
//每个ext占用4字节
return AV_RB16(ext_ptr + 2) << 2;
}
uint8_t *RtpHeader::getExtData() {
if (!ext) {
return nullptr;
}
auto ext_ptr = &payload + getCsrcSize();
//多出的4个字节分别为reserved、ext_len
return ext_ptr + 4 + getExtSize();
}
size_t RtpHeader::getPayloadOffset() const {
//有ext时还需要忽略reserved、ext_len 4个字节
return getCsrcSize() + (ext ? (4 + getExtSize()) : 0);
}
uint8_t *RtpHeader::getPayloadData() {
return &payload + getPayloadOffset();
}
size_t RtpHeader::getPaddingSize(size_t rtp_size) const {
if (!padding) {
return 0;
}
auto end = (uint8_t *) this + rtp_size;
return *end;
}
size_t RtpHeader::getPayloadSize(size_t rtp_size){
auto invalid_size = getPayloadOffset() + getPaddingSize(rtp_size);
if (invalid_size + RtpPacket::kRtpHeaderSize >= rtp_size) {
return 0;
}
return rtp_size - invalid_size - RtpPacket::kRtpHeaderSize;
}
RtpHeader* RtpPacket::getHeader(){
//需除去rtcp over tcp 4个字节长度
return (RtpHeader*)(data() + RtpPacket::kRtpTcpHeaderSize);
}
uint16_t RtpPacket::getSeq(){
return ntohs(getHeader()->seq);
}
uint32_t RtpPacket::getStampMS(){
return ntohl(getHeader()->stamp) * uint64_t(1000) / sample_rate;
}
uint32_t RtpPacket::getSSRC(){
return ntohl(getHeader()->ssrc);
}
uint8_t* RtpPacket::getPayload(){
return getHeader()->getPayloadData();
}
size_t RtpPacket::getPayloadSize(){
//需除去rtcp over tcp 4个字节长度
return getHeader()->getPayloadSize(size() - kRtpTcpHeaderSize);
}
}//namespace mediakit

View File

@ -15,8 +15,9 @@
#include <string>
#include <memory>
#include <unordered_map>
#include "Common/config.h"
#include "Util/util.h"
#include "Common/config.h"
#include "Common/macros.h"
#include "Extension/Frame.h"
using namespace std;
@ -68,18 +69,101 @@ typedef enum {
};
#if defined(_WIN32)
#pragma pack(push, 1)
#endif // defined(_WIN32)
class RtpHeader {
public:
#if __BYTE_ORDER == __BIG_ENDIAN
//版本号固定为2
uint32_t version: 2;
//padding
uint32_t padding: 1;
//扩展
uint32_t ext: 1;
//csrc
uint32_t csrc: 4;
//mark
uint32_t mark: 1;
//负载类型
uint32_t pt: 7;
#else
//csrc
uint32_t csrc: 4;
//扩展
uint32_t ext: 1;
//padding
uint32_t padding: 1;
//版本号固定为2
uint32_t version: 2;
//负载类型
uint32_t pt: 7;
//mark
uint32_t mark: 1;
#endif
//序列号
uint32_t seq: 16;
//时间戳
uint32_t stamp;
//ssrc
uint32_t ssrc;
//负载如果有csrc和ext前面为 4 * csrc + (4 + 4 * ext_len)
uint8_t payload;
public:
//返回csrc字段字节长度
size_t getCsrcSize() const;
//返回csrc字段首地址不存在时返回nullptr
uint8_t *getCsrcData();
//返回ext字段字节长度
size_t getExtSize() const;
//返回ext段首地址不存在时返回nullptr
uint8_t *getExtData();
//返回有效负载指针,跳过csrc、ext
uint8_t* getPayloadData();
//返回有效负载总长度,不包括csrc、ext、padding
size_t getPayloadSize(size_t rtp_size);
private:
//返回有效负载偏移量
size_t getPayloadOffset() const;
//返回padding长度
size_t getPaddingSize(size_t rtp_size) const;
} PACKED;
#if defined(_WIN32)
#pragma pack(pop)
#endif // defined(_WIN32)
//此rtp为rtp over tcp形式需要忽略前4个字节
class RtpPacket : public BufferRaw{
public:
typedef std::shared_ptr<RtpPacket> Ptr;
bool mark;
uint8_t interleaved;
uint8_t PT;
using Ptr = std::shared_ptr<RtpPacket>;
enum {
kRtpVersion = 2,
kRtpHeaderSize = 12,
kRtpTcpHeaderSize = 4
};
RtpHeader* getHeader();
//主机字节序的seq
uint16_t getSeq();
//主机字节序的时间戳,已经转换为毫秒
uint32_t getStampMS();
//主机字节序的ssrc
uint32_t getSSRC();
//有效负载跳过csrc、ext
uint8_t* getPayload();
//有效负载长度不包括csrc、ext、padding
size_t getPayloadSize();
//音视频类型
TrackType type;
uint16_t sequence;
//时间戳,单位毫秒
uint32_t timeStamp;
uint32_t ssrc;
size_t offset;
//音频为采样率视频一般为90000
uint32_t sample_rate;
};
Buffer::Ptr makeRtpOverTcpPrefix(uint16_t size, uint8_t interleaved);

View File

@ -160,10 +160,11 @@ public:
_speed[rtp->type] += rtp->size();
assert(rtp->type >= 0 && rtp->type < TrackMax);
auto &track = _tracks[rtp->type];
auto stamp = rtp->getStampMS();
if (track) {
track->_seq = rtp->sequence;
track->_time_stamp = rtp->timeStamp;
track->_ssrc = rtp->ssrc;
track->_seq = rtp->getSeq();
track->_time_stamp = stamp;
track->_ssrc = rtp->getSSRC();
}
if (!_ring) {
weak_ptr<RtspMediaSource> weakSelf = dynamic_pointer_cast<RtspMediaSource>(shared_from_this());
@ -183,7 +184,6 @@ public:
}
}
bool is_video = rtp->type == TrackVideo;
auto stamp = rtp->timeStamp;
PacketCache<RtpPacket>::inputPacket(stamp, is_video, std::move(rtp), keyPos);
}

View File

@ -478,10 +478,10 @@ void RtspPlayer::onRtpPacket(const char *data, size_t len) {
uint8_t interleaved = data[1];
if(interleaved %2 == 0){
trackIdx = getTrackIndexByInterleaved(interleaved);
handleOneRtp(trackIdx, _sdp_track[trackIdx]->_type, _sdp_track[trackIdx]->_samplerate, (uint8_t *)data + 4, len - 4);
handleOneRtp(trackIdx, _sdp_track[trackIdx]->_type, _sdp_track[trackIdx]->_samplerate, (uint8_t *)data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
}else{
trackIdx = getTrackIndexByInterleaved(interleaved - 1);
onRtcpPacket(trackIdx, _sdp_track[trackIdx], (uint8_t *) data + 4, len - 4);
onRtcpPacket(trackIdx, _sdp_track[trackIdx], (uint8_t *) data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
}
}
@ -494,7 +494,7 @@ void RtspPlayer::onRtcpPacket(int track_idx, SdpTrack::Ptr &track, uint8_t *data
}
void RtspPlayer::onRtpSorted(const RtpPacket::Ptr &rtppt, int trackidx){
_stamp[trackidx] = rtppt->timeStamp;
_stamp[trackidx] = rtppt->getStampMS();
_rtp_recv_ticker.resetTime();
onRecvRTP(rtppt, _sdp_track[trackidx]);
}
@ -593,7 +593,7 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx){
auto &rtcp_ctx = _rtcp_context[track_idx];
rtcp_ctx->onRtp(rtp->sequence, rtp->timeStamp, rtp->size() - 4);
rtcp_ctx->onRtp(rtp->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
auto &ticker = _rtcp_send_ticker[track_idx];
if (ticker.elapsedTime() < 3 * 1000) {
@ -627,10 +627,11 @@ void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx){
}
};
auto rtcp = rtcp_ctx->createRtcpRR(rtp->ssrc + 1, rtp->ssrc);
auto ssrc = rtp->getSSRC();
auto rtcp = rtcp_ctx->createRtcpRR(ssrc + 1, ssrc);
auto rtcp_sdes = RtcpSdes::create({SERVER_NAME});
rtcp_sdes->items.type = (uint8_t) SdesType::RTCP_SDES_CNAME;
rtcp_sdes->items.ssrc = htonl(rtp->ssrc);
rtcp_sdes->items.ssrc = htonl(ssrc);
send_rtcp(this, track_idx, std::move(rtcp));
send_rtcp(this, track_idx, RtcpHeader::toBuffer(rtcp_sdes));
ticker.resetTime();

View File

@ -154,7 +154,7 @@ void RtspPusher::onRtpPacket(const char *data, size_t len) {
uint8_t interleaved = data[1];
if (interleaved % 2 != 0) {
trackIdx = getTrackIndexByInterleaved(interleaved - 1);
onRtcpPacket(trackIdx, _track_vec[trackIdx], (uint8_t *) data + 4, len - 4);
onRtcpPacket(trackIdx, _track_vec[trackIdx], (uint8_t *) data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
}
}
@ -361,7 +361,7 @@ void RtspPusher::updateRtcpContext(const RtpPacket::Ptr &rtp){
int track_index = getTrackIndexByTrackType(rtp->type);
auto &ticker = _rtcp_send_ticker[track_index];
auto &rtcp_ctx = _rtcp_context[track_index];
rtcp_ctx->onRtp(rtp->sequence, rtp->timeStamp, rtp->size() - 4);
rtcp_ctx->onRtp(rtp->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
//send rtcp every 5 second
if (ticker.elapsedTime() > 5 * 1000) {
@ -376,10 +376,11 @@ void RtspPusher::updateRtcpContext(const RtpPacket::Ptr &rtp){
}
};
auto rtcp = rtcp_ctx->createRtcpSR(rtp->ssrc + 1);
auto ssrc = rtp->getSSRC();
auto rtcp = rtcp_ctx->createRtcpSR(ssrc + 1);
auto rtcp_sdes = RtcpSdes::create({SERVER_NAME});
rtcp_sdes->items.type = (uint8_t) SdesType::RTCP_SDES_CNAME;
rtcp_sdes->items.ssrc = htonl(rtp->ssrc);
rtcp_sdes->items.ssrc = htonl(ssrc);
send_rtcp(this, track_index, std::move(rtcp));
send_rtcp(this, track_index, RtcpHeader::toBuffer(rtcp_sdes));
}

View File

@ -15,7 +15,6 @@
#include "RtspSession.h"
#include "Util/MD5.h"
#include "Util/base64.h"
#include "Rtcp/Rtcp.h"
using namespace std;
using namespace toolkit;
@ -171,10 +170,10 @@ void RtspSession::onRtpPacket(const char *data, size_t len) {
return;
}
auto track_idx = getTrackIndexByInterleaved(interleaved);
handleOneRtp(track_idx, _sdp_track[track_idx]->_type, _sdp_track[track_idx]->_samplerate, (uint8_t *) data + 4, len - 4);
handleOneRtp(track_idx, _sdp_track[track_idx]->_type, _sdp_track[track_idx]->_samplerate, (uint8_t *) data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
} else {
auto track_idx = getTrackIndexByInterleaved(interleaved - 1);
onRtcpPacket(track_idx, _sdp_track[track_idx], data + 4, len - 4);
onRtcpPacket(track_idx, _sdp_track[track_idx], data + RtpPacket::kRtpTcpHeaderSize, len - RtpPacket::kRtpTcpHeaderSize);
}
}
@ -913,12 +912,6 @@ void RtspSession::send_NotAcceptable() {
}
void RtspSession::onRtpSorted(const RtpPacket::Ptr &rtp, int track_idx) {
if (_start_stamp[track_idx] == -1) {
//记录起始时间戳
_start_stamp[track_idx] = rtp->timeStamp;
}
//时间戳增量
rtp->timeStamp -= _start_stamp[track_idx];
_push_src->onWrite(rtp, false);
}
@ -1130,7 +1123,7 @@ void RtspSession::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index){
void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
int track_index = getTrackIndexByTrackType(rtp->type);
auto &rtcp_ctx = _rtcp_context[track_index];
rtcp_ctx->onRtp(rtp->sequence, rtp->timeStamp, rtp->size() - 4);
rtcp_ctx->onRtp(rtp->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
auto &ticker = _rtcp_send_tickers[track_index];
//send rtcp every 5 second
@ -1147,10 +1140,11 @@ void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
}
};
auto rtcp = _push_src ? rtcp_ctx->createRtcpRR(rtp->ssrc + 1, rtp->ssrc) : rtcp_ctx->createRtcpSR(rtp->ssrc + 1);
auto ssrc = rtp->getSSRC();
auto rtcp = _push_src ? rtcp_ctx->createRtcpRR(ssrc + 1, ssrc) : rtcp_ctx->createRtcpSR(ssrc + 1);
auto rtcp_sdes = RtcpSdes::create({SERVER_NAME});
rtcp_sdes->items.type = (uint8_t)SdesType::RTCP_SDES_CNAME;
rtcp_sdes->items.ssrc = htonl(rtp->ssrc);
rtcp_sdes->items.ssrc = htonl(ssrc);
send_rtcp(this, track_index, std::move(rtcp));
send_rtcp(this, track_index, RtcpHeader::toBuffer(rtcp_sdes));
}

View File

@ -171,8 +171,6 @@ private:
Rtsp::eRtpType _rtp_type = Rtsp::RTP_Invalid;
//收到的seq回复时一致
int _cseq = 0;
//rtsp推流起始时间戳目的是为了同步
int32_t _start_stamp[2] = {-1, -1};
//消耗的总流量
uint64_t _bytes_usage = 0;
//ContentBase