mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2026-06-30 23:02:24 +08:00
for mergen
This commit is contained in:
@@ -68,7 +68,6 @@ bool H265Frame::isKeyFrame(int type, const char *ptr) {
|
||||
return (((*((uint8_t *) ptr + 2)) >> 7) & 0x01) == 1 && (type == NAL_IDR_N_LP || type == NAL_IDR_W_RADL);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
H265Frame::H265Frame(){
|
||||
|
||||
@@ -18,8 +18,7 @@ void RtcpContext::clear() {
|
||||
memset(this, 0, sizeof(RtcpContext));
|
||||
}
|
||||
|
||||
RtcpContext::RtcpContext(uint32_t sample_rate, bool is_receiver) {
|
||||
_sample_rate = sample_rate;
|
||||
RtcpContext::RtcpContext(bool is_receiver) {
|
||||
_is_receiver = is_receiver;
|
||||
}
|
||||
|
||||
@@ -35,7 +34,6 @@ void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, size_t bytes) {
|
||||
diff = -diff;
|
||||
}
|
||||
//抖动单位为采样次数
|
||||
diff *= (_sample_rate / 1000.0);
|
||||
_jitter += (diff - _jitter) / 16.0;
|
||||
} else {
|
||||
_jitter = 0;
|
||||
@@ -129,7 +127,7 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) {
|
||||
rtcp->setNtpStamp(tv);
|
||||
|
||||
//转换成rtp时间戳
|
||||
rtcp->rtpts = htonl(uint32_t(_last_rtp_stamp * (_sample_rate / 1000.0)));
|
||||
rtcp->rtpts = htonl(_last_rtp_stamp);
|
||||
rtcp->packet_count = htonl((uint32_t) _packets);
|
||||
rtcp->octet_count = htonl((uint32_t) _bytes);
|
||||
return RtcpHeader::toBuffer(std::move(rtcp));
|
||||
|
||||
@@ -22,15 +22,14 @@ public:
|
||||
using Ptr = std::shared_ptr<RtcpContext>;
|
||||
/**
|
||||
* 创建rtcp上下文
|
||||
* @param sample_rate 音频采用率,视频一般为90000
|
||||
* @param is_receiver 是否为rtp接收者,接收者更消耗性能
|
||||
*/
|
||||
RtcpContext(uint32_t sample_rate, bool is_receiver);
|
||||
RtcpContext(bool is_receiver);
|
||||
|
||||
/**
|
||||
* 输出或输入rtp时调用
|
||||
* @param seq rtp的seq
|
||||
* @param stamp rtp的时间戳,单位毫秒
|
||||
* @param stamp rtp的时间戳,单位采样数(非毫秒)
|
||||
* @param bytes rtp数据长度
|
||||
*/
|
||||
void onRtp(uint16_t seq, uint32_t stamp, size_t bytes);
|
||||
@@ -87,8 +86,6 @@ private:
|
||||
bool _is_receiver;
|
||||
//时间戳抖动值
|
||||
double _jitter = 0;
|
||||
//视频默认90000,音频为采样率
|
||||
uint32_t _sample_rate;
|
||||
//收到或发送的rtp的字节数
|
||||
size_t _bytes = 0;
|
||||
//收到或发送的rtp的个数
|
||||
|
||||
@@ -24,36 +24,23 @@ static inline bool checkTS(const uint8_t *packet, size_t bytes){
|
||||
return bytes % TS_PACKET_SIZE == 0 && packet[0] == TS_SYNC_BYTE;
|
||||
}
|
||||
|
||||
class RtpReceiverImp : public RtpReceiver {
|
||||
class RtpReceiverImp : public RtpTrackImp {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<RtpReceiverImp>;
|
||||
RtpReceiverImp(int sample_rate, function<void(RtpPacket::Ptr rtp)> cb, function<void(const RtpPacket::Ptr &rtp)> cb_before = nullptr){
|
||||
RtpReceiverImp(int sample_rate, RtpTrackImp::OnSorted cb, RtpTrackImp::BeforeSorted cb_before = nullptr){
|
||||
_sample_rate = sample_rate;
|
||||
_on_sort = std::move(cb);
|
||||
_on_before_sort = std::move(cb_before);
|
||||
setOnSorted(std::move(cb));
|
||||
setBeforeSorted(std::move(cb_before));
|
||||
}
|
||||
|
||||
~RtpReceiverImp() override = default;
|
||||
|
||||
bool inputRtp(TrackType type, uint8_t *ptr, size_t len){
|
||||
return handleOneRtp((int) type, type, _sample_rate, ptr, len);
|
||||
}
|
||||
|
||||
protected:
|
||||
void onRtpSorted(RtpPacket::Ptr rtp, int track_index) override {
|
||||
_on_sort(std::move(rtp));
|
||||
}
|
||||
|
||||
void onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index) override {
|
||||
if (_on_before_sort) {
|
||||
_on_before_sort(rtp);
|
||||
}
|
||||
return RtpTrack::inputRtp(type, _sample_rate, ptr, len);
|
||||
}
|
||||
|
||||
private:
|
||||
int _sample_rate;
|
||||
function<void(RtpPacket::Ptr rtp)> _on_sort;
|
||||
function<void(const RtpPacket::Ptr &rtp)> _on_before_sort;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -27,7 +27,7 @@ class RtcpHelper : public RtcpContext, public std::enable_shared_from_this<RtcpH
|
||||
public:
|
||||
using Ptr = std::shared_ptr<RtcpHelper>;
|
||||
|
||||
RtcpHelper(Socket::Ptr rtcp_sock, uint32_t sample_rate) : RtcpContext(sample_rate, true){
|
||||
RtcpHelper(Socket::Ptr rtcp_sock, uint32_t sample_rate) : RtcpContext(true){
|
||||
_rtcp_sock = std::move(rtcp_sock);
|
||||
_sample_rate = sample_rate;
|
||||
}
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
void onRecvRtp(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len){
|
||||
//统计rtp接受情况,用于发送rr包
|
||||
auto header = (RtpHeader *) buf->data();
|
||||
onRtp(ntohs(header->seq), ntohl(header->stamp) * uint64_t(1000) / _sample_rate, buf->size());
|
||||
onRtp(ntohs(header->seq), ntohl(header->stamp), buf->size());
|
||||
sendRtcp(ntohl(header->ssrc), addr, addr_len);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ void RtpSession::onRtpPacket(const char *data, size_t len) {
|
||||
}
|
||||
try {
|
||||
_process->inputRtp(false, getSock(), data, len, &_addr);
|
||||
} catch (RtpReceiver::BadRtpException &ex) {
|
||||
} catch (RtpTrack::BadRtpException &ex) {
|
||||
if (!_is_udp) {
|
||||
WarnL << ex.what() << ",开始搜索ssrc以便恢复上下文";
|
||||
_search_rtp = true;
|
||||
|
||||
@@ -15,19 +15,23 @@
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
RtpReceiver::RtpReceiver() {
|
||||
int index = 0;
|
||||
for (auto &sortor : _rtp_sortor) {
|
||||
sortor.setOnSort([this, index](uint16_t seq, RtpPacket::Ptr &packet) {
|
||||
onRtpSorted(std::move(packet), index);
|
||||
});
|
||||
++index;
|
||||
}
|
||||
RtpTrack::RtpTrack() {
|
||||
setOnSort([this](uint16_t seq, RtpPacket::Ptr &packet) {
|
||||
onRtpSorted(std::move(packet));
|
||||
});
|
||||
}
|
||||
|
||||
RtpReceiver::~RtpReceiver() {}
|
||||
uint32_t RtpTrack::getSSRC() const {
|
||||
return _ssrc;
|
||||
}
|
||||
|
||||
bool RtpReceiver::handleOneRtp(int index, TrackType type, int sample_rate, uint8_t *ptr, size_t len) {
|
||||
void RtpTrack::clear() {
|
||||
_ssrc = 0;
|
||||
_ssrc_alive.resetTime();
|
||||
PacketSortor<RtpPacket::Ptr>::clear();
|
||||
}
|
||||
|
||||
bool RtpTrack::inputRtp(TrackType type, int sample_rate, uint8_t *ptr, size_t len) {
|
||||
if (len < RtpPacket::kRtpHeaderSize) {
|
||||
WarnL << "rtp包太小:" << len;
|
||||
return false;
|
||||
@@ -52,23 +56,23 @@ bool RtpReceiver::handleOneRtp(int index, TrackType type, int sample_rate, uint8
|
||||
//比对缓存ssrc
|
||||
auto ssrc = ntohl(header->ssrc);
|
||||
|
||||
if (!_ssrc[index]) {
|
||||
if (!_ssrc) {
|
||||
//记录并锁定ssrc
|
||||
_ssrc[index] = ssrc;
|
||||
_ssrc_alive[index].resetTime();
|
||||
} else if (_ssrc[index] == ssrc) {
|
||||
_ssrc = ssrc;
|
||||
_ssrc_alive.resetTime();
|
||||
} else if (_ssrc == ssrc) {
|
||||
//ssrc匹配正确,刷新计时器
|
||||
_ssrc_alive[index].resetTime();
|
||||
_ssrc_alive.resetTime();
|
||||
} else {
|
||||
//ssrc错误
|
||||
if (_ssrc_alive[index].elapsedTime() < 3 * 1000) {
|
||||
if (_ssrc_alive.elapsedTime() < 3 * 1000) {
|
||||
//接受正确ssrc的rtp在10秒内,那么我们认为存在多路rtp,忽略掉ssrc不匹配的rtp
|
||||
WarnL << "ssrc不匹配,rtp已丢弃:" << ssrc << " != " << _ssrc[index];
|
||||
WarnL << "ssrc不匹配,rtp已丢弃:" << ssrc << " != " << _ssrc;
|
||||
return false;
|
||||
}
|
||||
InfoL << "rtp流ssrc切换:" << _ssrc[index] << " -> " << ssrc;
|
||||
_ssrc[index] = ssrc;
|
||||
_ssrc_alive[index].resetTime();
|
||||
InfoL << "rtp流ssrc切换:" << _ssrc << " -> " << ssrc;
|
||||
_ssrc = ssrc;
|
||||
_ssrc_alive.resetTime();
|
||||
}
|
||||
|
||||
auto rtp = RtpPacket::create();
|
||||
@@ -87,29 +91,32 @@ bool RtpReceiver::handleOneRtp(int index, TrackType type, int sample_rate, uint8
|
||||
//拷贝rtp
|
||||
memcpy(&data[4], ptr, len);
|
||||
|
||||
onBeforeRtpSorted(rtp, index);
|
||||
onBeforeRtpSorted(rtp);
|
||||
auto seq = rtp->getSeq();
|
||||
_rtp_sortor[index].sortPacket(seq, std::move(rtp));
|
||||
sortPacket(seq, std::move(rtp));
|
||||
return true;
|
||||
}
|
||||
|
||||
void RtpReceiver::clear() {
|
||||
CLEAR_ARR(_ssrc);
|
||||
for (auto &sortor : _rtp_sortor) {
|
||||
sortor.clear();
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void RtpTrackImp::setOnSorted(OnSorted cb) {
|
||||
_on_sorted = std::move(cb);
|
||||
}
|
||||
|
||||
void RtpTrackImp::setBeforeSorted(BeforeSorted cb) {
|
||||
_on_before_sorted = std::move(cb);
|
||||
}
|
||||
|
||||
void RtpTrackImp::onRtpSorted(RtpPacket::Ptr rtp) {
|
||||
if (_on_sorted) {
|
||||
_on_sorted(std::move(rtp));
|
||||
}
|
||||
}
|
||||
|
||||
size_t RtpReceiver::getJitterSize(int index) const{
|
||||
return _rtp_sortor[index].getJitterSize();
|
||||
}
|
||||
|
||||
size_t RtpReceiver::getCycleCount(int index) const{
|
||||
return _rtp_sortor[index].getCycleCount();
|
||||
}
|
||||
|
||||
uint32_t RtpReceiver::getSSRC(int index) const{
|
||||
return _ssrc[index];
|
||||
void RtpTrackImp::onBeforeRtpSorted(const RtpPacket::Ptr &rtp) {
|
||||
if (_on_before_sorted) {
|
||||
_on_before_sorted(rtp);
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
@@ -160,11 +160,8 @@ private:
|
||||
function<void(SEQ seq, T &packet)> _cb;
|
||||
};
|
||||
|
||||
class RtpReceiver {
|
||||
class RtpTrack : private PacketSortor<RtpPacket::Ptr>{
|
||||
public:
|
||||
RtpReceiver();
|
||||
virtual ~RtpReceiver();
|
||||
|
||||
class BadRtpException : public invalid_argument {
|
||||
public:
|
||||
template<typename Type>
|
||||
@@ -172,7 +169,60 @@ public:
|
||||
~BadRtpException() = default;
|
||||
};
|
||||
|
||||
RtpTrack();
|
||||
virtual ~RtpTrack() = default;
|
||||
|
||||
void clear();
|
||||
uint32_t getSSRC() const;
|
||||
bool inputRtp(TrackType type, int sample_rate, uint8_t *ptr, size_t len);
|
||||
|
||||
protected:
|
||||
virtual void onRtpSorted(RtpPacket::Ptr rtp) {}
|
||||
virtual void onBeforeRtpSorted(const RtpPacket::Ptr &rtp) {}
|
||||
|
||||
private:
|
||||
uint32_t _ssrc = 0;
|
||||
Ticker _ssrc_alive;
|
||||
};
|
||||
|
||||
class RtpTrackImp : public RtpTrack{
|
||||
public:
|
||||
using OnSorted = function<void(RtpPacket::Ptr)>;
|
||||
using BeforeSorted = function<void(const RtpPacket::Ptr &)>;
|
||||
|
||||
RtpTrackImp() = default;
|
||||
~RtpTrackImp() override = default;
|
||||
|
||||
void setOnSorted(OnSorted cb);
|
||||
void setBeforeSorted(BeforeSorted cb);
|
||||
|
||||
protected:
|
||||
void onRtpSorted(RtpPacket::Ptr rtp) override;
|
||||
void onBeforeRtpSorted(const RtpPacket::Ptr &rtp) override;
|
||||
|
||||
private:
|
||||
OnSorted _on_sorted;
|
||||
BeforeSorted _on_before_sorted;
|
||||
};
|
||||
|
||||
template<int kCount = 2>
|
||||
class RtpMultiReceiver {
|
||||
public:
|
||||
RtpMultiReceiver() {
|
||||
int index = 0;
|
||||
for (auto &track : _track) {
|
||||
track.setOnSorted([this, index](RtpPacket::Ptr rtp) {
|
||||
onRtpSorted(std::move(rtp), index);
|
||||
});
|
||||
track.setBeforeSorted([this, index](const RtpPacket::Ptr &rtp) {
|
||||
onBeforeRtpSorted(rtp, index);
|
||||
});
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~RtpMultiReceiver() = default;
|
||||
|
||||
/**
|
||||
* 输入数据指针生成并排序rtp包
|
||||
* @param index track下标索引
|
||||
@@ -182,34 +232,49 @@ protected:
|
||||
* @param len rtp数据指针长度
|
||||
* @return 解析成功返回true
|
||||
*/
|
||||
bool handleOneRtp(int index, TrackType type, int samplerate, uint8_t *ptr, size_t len);
|
||||
bool handleOneRtp(int index, TrackType type, int sample_rate, uint8_t *ptr, size_t len){
|
||||
return _track[index].inputRtp(type, sample_rate, ptr, len);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
for (auto &track : _track) {
|
||||
track.clear();
|
||||
}
|
||||
}
|
||||
|
||||
size_t getJitterSize(int index) const {
|
||||
return _track[index].getJitterSize();
|
||||
}
|
||||
|
||||
size_t getCycleCount(int index) const {
|
||||
return _track[index].getCycleCount();
|
||||
}
|
||||
|
||||
uint32_t getSSRC(int index) const {
|
||||
return _track[index].getSSRC();
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* rtp数据包排序后输出
|
||||
* @param rtp rtp数据包
|
||||
* @param track_index track索引
|
||||
*/
|
||||
virtual void onRtpSorted(RtpPacket::Ptr rtp, int track_index) {}
|
||||
virtual void onRtpSorted(RtpPacket::Ptr rtp, int index) {}
|
||||
|
||||
/**
|
||||
* 解析出rtp但还未排序
|
||||
* @param rtp rtp数据包
|
||||
* @param track_index track索引
|
||||
*/
|
||||
virtual void onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index) {}
|
||||
|
||||
void clear();
|
||||
size_t getJitterSize(int track_index) const;
|
||||
size_t getCycleCount(int track_index) const;
|
||||
uint32_t getSSRC(int track_index) const;
|
||||
virtual void onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int index) {}
|
||||
|
||||
private:
|
||||
uint32_t _ssrc[2] = {0, 0};
|
||||
Ticker _ssrc_alive[2];
|
||||
//rtp排序缓存,根据seq排序
|
||||
PacketSortor<RtpPacket::Ptr> _rtp_sortor[2];
|
||||
RtpTrackImp _track[kCount];
|
||||
};
|
||||
|
||||
using RtpReceiver = RtpMultiReceiver<2>;
|
||||
|
||||
}//namespace mediakit
|
||||
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
|
||||
}
|
||||
_rtcp_context.clear();
|
||||
for (auto &track : _sdp_track) {
|
||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, true));
|
||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(true));
|
||||
}
|
||||
sendSetup(0);
|
||||
}
|
||||
@@ -591,7 +591,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->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||
|
||||
auto &ticker = _rtcp_send_ticker[track_idx];
|
||||
if (ticker.elapsedTime() < 3 * 1000) {
|
||||
|
||||
@@ -179,7 +179,7 @@ void RtspPusher::sendAnnounce() {
|
||||
}
|
||||
_rtcp_context.clear();
|
||||
for (auto &track : _track_vec) {
|
||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, false));
|
||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(false));
|
||||
}
|
||||
_on_res_func = std::bind(&RtspPusher::handleResAnnounce, this, placeholders::_1);
|
||||
sendRtspRequest("ANNOUNCE", _url, {}, src->getSdp());
|
||||
@@ -360,7 +360,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->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||
|
||||
//send rtcp every 5 second
|
||||
if (ticker.elapsedTime() > 5 * 1000) {
|
||||
|
||||
@@ -252,7 +252,7 @@ void RtspSession::handleReq_ANNOUNCE(const Parser &parser) {
|
||||
}
|
||||
_rtcp_context.clear();
|
||||
for (auto &track : _sdp_track) {
|
||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, true));
|
||||
_rtcp_context.emplace_back(std::make_shared<RtcpContext>(true));
|
||||
}
|
||||
_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()));
|
||||
@@ -413,7 +413,7 @@ void RtspSession::onAuthSuccess() {
|
||||
}
|
||||
strongSelf->_rtcp_context.clear();
|
||||
for (auto &track : strongSelf->_sdp_track) {
|
||||
strongSelf->_rtcp_context.emplace_back(std::make_shared<RtcpContext>(track->_samplerate, false));
|
||||
strongSelf->_rtcp_context.emplace_back(std::make_shared<RtcpContext>(false));
|
||||
}
|
||||
strongSelf->_sessionid = makeRandStr(12);
|
||||
strongSelf->_play_src = rtsp_src;
|
||||
@@ -1126,7 +1126,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->getSeq(), rtp->getStampMS(), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||
|
||||
auto &ticker = _rtcp_send_tickers[track_index];
|
||||
//send rtcp every 5 second
|
||||
|
||||
Reference in New Issue
Block a user