mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 12:37:09 +08:00
优化rtp统计性能
This commit is contained in:
parent
070bf19cb5
commit
51435d955c
@ -9,65 +9,75 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "RtcpContext.h"
|
#include "RtcpContext.h"
|
||||||
|
#include "Util/logger.h"
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
void RtcpContext::clear(){
|
void RtcpContext::clear() {
|
||||||
memset(this, 0, sizeof(RtcpContext));
|
memset(this, 0, sizeof(RtcpContext));
|
||||||
}
|
}
|
||||||
|
|
||||||
RtcpContext::RtcpContext(uint32_t sample_rate){
|
RtcpContext::RtcpContext(uint32_t sample_rate, bool is_receiver) {
|
||||||
_sample_rate = sample_rate;
|
_sample_rate = sample_rate;
|
||||||
|
_is_receiver = is_receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) {
|
void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) {
|
||||||
_bytes += bytes;
|
if (_is_receiver) {
|
||||||
++_packets;
|
//接收者才做复杂的统计运算
|
||||||
|
auto sys_stamp = getCurrentMillisecond();
|
||||||
auto sys_stamp = getCurrentMillisecond();
|
if (_last_rtp_sys_stamp) {
|
||||||
if (_last_rtp_sys_stamp) {
|
//计算时间戳抖动值
|
||||||
//计算时间戳抖动值
|
double diff = double(
|
||||||
double diff = double(int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp) - int64_t(stamp) + int64_t(_last_rtp_stamp));
|
int64_t(sys_stamp) - int64_t(_last_rtp_sys_stamp) - int64_t(stamp) + int64_t(_last_rtp_stamp));
|
||||||
if (diff < 0) {
|
if (diff < 0) {
|
||||||
diff = -diff;
|
diff = -diff;
|
||||||
|
}
|
||||||
|
//抖动单位为采样次数
|
||||||
|
diff *= (_sample_rate / 1000.0);
|
||||||
|
_jitter += (diff - _jitter) / 16.0;
|
||||||
|
} else {
|
||||||
|
_jitter = 0;
|
||||||
}
|
}
|
||||||
//抖动单位为采样次数
|
|
||||||
diff *= (_sample_rate / 1000.0);
|
if (_last_rtp_seq > 0xFF00 && seq < 0xFF && (!_seq_cycles || _packets - _last_cycle_packets > 0x1FFF)) {
|
||||||
_jitter += (diff - _jitter) / 16.0;
|
//上次seq大于0xFF00且本次seq小于0xFF,
|
||||||
} else {
|
//且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环
|
||||||
_jitter = 0;
|
++_seq_cycles;
|
||||||
}
|
_last_cycle_packets = _packets;
|
||||||
|
_seq_max = seq;
|
||||||
if (_last_rtp_seq > 0xFF00 && seq < 0xFF && (!_seq_cycles || _packets - _last_cycle_packets > 0x1FFF)) {
|
} else if (seq > _seq_max) {
|
||||||
//上次seq大于0xFF00且本次seq小于0xFF,
|
//本次回环前最大seq
|
||||||
//且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环
|
_seq_max = seq;
|
||||||
++_seq_cycles;
|
}
|
||||||
_last_cycle_packets = _packets;
|
|
||||||
_seq_max = seq;
|
if (!_seq_base) {
|
||||||
} else if (seq > _seq_max) {
|
//记录第一个rtp的seq
|
||||||
//本次回环前最大seq
|
_seq_base = seq;
|
||||||
_seq_max = seq;
|
} else if (!_seq_cycles && seq < _seq_base) {
|
||||||
}
|
//未发生回环,那么取最新的seq为基准seq
|
||||||
|
_seq_base = seq;
|
||||||
if (!_seq_base) {
|
}
|
||||||
//记录第一个rtp的seq
|
|
||||||
_seq_base = seq;
|
_last_rtp_seq = seq;
|
||||||
} else if (!_seq_cycles && seq < _seq_base) {
|
_last_rtp_sys_stamp = sys_stamp;
|
||||||
//未发生回环,那么取最新的seq为基准seq
|
|
||||||
_seq_base = seq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
++_packets;
|
||||||
|
_bytes += bytes;
|
||||||
_last_rtp_stamp = stamp;
|
_last_rtp_stamp = stamp;
|
||||||
_last_rtp_sys_stamp = sys_stamp;
|
|
||||||
_last_rtp_seq = seq;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtcpContext::onRtcp(RtcpHeader *rtcp){
|
void RtcpContext::onRtcp(RtcpHeader *rtcp) {
|
||||||
if ((RtcpType) rtcp->pt != RtcpType::RTCP_SR) {
|
if ((RtcpType) rtcp->pt != RtcpType::RTCP_SR) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto rtcp_sr = (RtcpSR *)(rtcp);
|
if (!_is_receiver) {
|
||||||
|
WarnL << "rtp发送者收到sr包";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto rtcp_sr = (RtcpSR *) (rtcp);
|
||||||
/**
|
/**
|
||||||
last SR timestamp (LSR): 32 bits
|
last SR timestamp (LSR): 32 bits
|
||||||
The middle 32 bits out of 64 in the NTP timestamp (as explained in
|
The middle 32 bits out of 64 in the NTP timestamp (as explained in
|
||||||
@ -79,29 +89,38 @@ void RtcpContext::onRtcp(RtcpHeader *rtcp){
|
|||||||
_last_sr_ntp_sys = getCurrentMillisecond();
|
_last_sr_ntp_sys = getCurrentMillisecond();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RtcpContext::getExpectedPackets() const{
|
size_t RtcpContext::getExpectedPackets() const {
|
||||||
|
if (!_is_receiver) {
|
||||||
|
throw std::runtime_error("rtp发送者无法统计应收包数");
|
||||||
|
}
|
||||||
return (_seq_cycles << 16) + _seq_max - _seq_base + 1;
|
return (_seq_cycles << 16) + _seq_max - _seq_base + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RtcpContext::getExpectedPacketsInterval(){
|
size_t RtcpContext::getExpectedPacketsInterval() {
|
||||||
auto expected = getExpectedPackets();
|
auto expected = getExpectedPackets();
|
||||||
auto ret = expected - _last_expected;
|
auto ret = expected - _last_expected;
|
||||||
_last_expected = expected;
|
_last_expected = expected;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RtcpContext::getLost(){
|
size_t RtcpContext::getLost() {
|
||||||
|
if (!_is_receiver) {
|
||||||
|
throw std::runtime_error("rtp发送者无法统计丢包率");
|
||||||
|
}
|
||||||
return getExpectedPackets() - _packets;
|
return getExpectedPackets() - _packets;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RtcpContext::geLostInterval(){
|
size_t RtcpContext::geLostInterval() {
|
||||||
auto lost = getLost();
|
auto lost = getLost();
|
||||||
auto ret = lost - _last_lost;
|
auto ret = lost - _last_lost;
|
||||||
_last_lost = lost;
|
_last_lost = lost;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc){
|
Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) {
|
||||||
|
if (_is_receiver) {
|
||||||
|
throw std::runtime_error("rtp接收者尝试发送sr包");
|
||||||
|
}
|
||||||
auto rtcp = RtcpSR::create(0);
|
auto rtcp = RtcpSR::create(0);
|
||||||
rtcp->ssrc = htonl(rtcp_ssrc);
|
rtcp->ssrc = htonl(rtcp_ssrc);
|
||||||
|
|
||||||
@ -111,12 +130,15 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc){
|
|||||||
|
|
||||||
//转换成rtp时间戳
|
//转换成rtp时间戳
|
||||||
rtcp->rtpts = htonl(uint32_t(_last_rtp_stamp * (_sample_rate / 1000.0)));
|
rtcp->rtpts = htonl(uint32_t(_last_rtp_stamp * (_sample_rate / 1000.0)));
|
||||||
rtcp->packet_count = htonl((uint32_t)_packets);
|
rtcp->packet_count = htonl((uint32_t) _packets);
|
||||||
rtcp->octet_count = htonl((uint32_t)_bytes);
|
rtcp->octet_count = htonl((uint32_t) _bytes);
|
||||||
return RtcpHeader::toBuffer(std::move(rtcp));
|
return RtcpHeader::toBuffer(std::move(rtcp));
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc){
|
Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc) {
|
||||||
|
if (!_is_receiver) {
|
||||||
|
throw std::runtime_error("rtp发送者尝试发送rr包");
|
||||||
|
}
|
||||||
auto rtcp = RtcpRR::create(1);
|
auto rtcp = RtcpRR::create(1);
|
||||||
rtcp->ssrc = htonl(rtcp_ssrc);
|
rtcp->ssrc = htonl(rtcp_ssrc);
|
||||||
|
|
||||||
@ -139,7 +161,7 @@ Buffer::Ptr RtcpContext::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc){
|
|||||||
// now - Last SR time,单位毫秒
|
// now - Last SR time,单位毫秒
|
||||||
auto delay = getCurrentMillisecond() - _last_sr_ntp_sys;
|
auto delay = getCurrentMillisecond() - _last_sr_ntp_sys;
|
||||||
// in units of 1/65536 seconds
|
// 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);
|
item->delay_since_last_sr = htonl(_last_sr_lsr ? dlsr : 0);
|
||||||
return RtcpHeader::toBuffer(rtcp);
|
return RtcpHeader::toBuffer(rtcp);
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* 创建rtcp上下文
|
* 创建rtcp上下文
|
||||||
* @param sample_rate 音频采用率,视频一般为90000
|
* @param sample_rate 音频采用率,视频一般为90000
|
||||||
|
* @param is_receiver 是否为rtp接收者,接收者更消耗性能
|
||||||
*/
|
*/
|
||||||
RtcpContext(uint32_t sample_rate);
|
RtcpContext(uint32_t sample_rate, bool is_receiver);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输出或输入rtp时调用
|
* 输出或输入rtp时调用
|
||||||
@ -82,6 +83,8 @@ private:
|
|||||||
size_t geLostInterval();
|
size_t geLostInterval();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//是否为接收者
|
||||||
|
bool _is_receiver;
|
||||||
//时间戳抖动值
|
//时间戳抖动值
|
||||||
double _jitter = 0;
|
double _jitter = 0;
|
||||||
//视频默认90000,音频为采样率
|
//视频默认90000,音频为采样率
|
||||||
|
@ -204,7 +204,7 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
|
|||||||
throw std::runtime_error("onCheckSDP faied");
|
throw std::runtime_error("onCheckSDP faied");
|
||||||
}
|
}
|
||||||
for (auto &track : _sdp_track) {
|
for (auto &track : _sdp_track) {
|
||||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate));
|
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, true));
|
||||||
}
|
}
|
||||||
sendSetup(0);
|
sendSetup(0);
|
||||||
}
|
}
|
||||||
|
@ -177,7 +177,7 @@ void RtspPusher::sendAnnounce() {
|
|||||||
throw std::runtime_error("无有效的Sdp Track");
|
throw std::runtime_error("无有效的Sdp Track");
|
||||||
}
|
}
|
||||||
for (auto &track : _track_vec) {
|
for (auto &track : _track_vec) {
|
||||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate));
|
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, false));
|
||||||
}
|
}
|
||||||
_on_res_func = std::bind(&RtspPusher::handleResAnnounce, this, placeholders::_1);
|
_on_res_func = std::bind(&RtspPusher::handleResAnnounce, this, placeholders::_1);
|
||||||
sendRtspRequest("ANNOUNCE", _url, {}, src->getSdp());
|
sendRtspRequest("ANNOUNCE", _url, {}, src->getSdp());
|
||||||
|
@ -235,8 +235,9 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) {
|
|||||||
sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err);
|
sendRtspResponse("403 Forbidden", {"Content-Type", "text/plain"}, err);
|
||||||
throw SockException(Err_shutdown,StrPrinter << err << ":" << full_url);
|
throw SockException(Err_shutdown,StrPrinter << err << ":" << full_url);
|
||||||
}
|
}
|
||||||
|
_rtcp_context.clear();
|
||||||
for (auto &track : _sdp_track) {
|
for (auto &track : _sdp_track) {
|
||||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate));
|
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, true));
|
||||||
}
|
}
|
||||||
_push_src = std::make_shared<RtspMediaSourceImp>(_media_info._vhost, _media_info._app, _media_info._streamid);
|
_push_src = std::make_shared<RtspMediaSourceImp>(_media_info._vhost, _media_info._app, _media_info._streamid);
|
||||||
_push_src->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));
|
_push_src->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));
|
||||||
@ -406,7 +407,7 @@ void RtspSession::onAuthSuccess() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (auto &track : strongSelf->_sdp_track) {
|
for (auto &track : strongSelf->_sdp_track) {
|
||||||
strongSelf->_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate));
|
strongSelf->_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, false));
|
||||||
}
|
}
|
||||||
strongSelf->_sessionid = makeRandStr(12);
|
strongSelf->_sessionid = makeRandStr(12);
|
||||||
strongSelf->_play_src = rtsp_src;
|
strongSelf->_play_src = rtsp_src;
|
||||||
|
Loading…
Reference in New Issue
Block a user