mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-26 12:37:09 +08:00
rtp使用ntp时间戳作为时间戳,用于实现rtsp音视频同步
This commit is contained in:
parent
eba3758b30
commit
298f6e3864
@ -35,7 +35,8 @@ int64_t DeltaStamp::deltaStamp(int64_t stamp) {
|
|||||||
|
|
||||||
//时间戳增量为负,说明时间戳回环了或回退了
|
//时间戳增量为负,说明时间戳回环了或回退了
|
||||||
_last_stamp = stamp;
|
_last_stamp = stamp;
|
||||||
return 0;
|
//如果时间戳回退不多,那么返回负值
|
||||||
|
return -ret < MAX_CTS ? ret : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stamp::setPlayBack(bool playback) {
|
void Stamp::setPlayBack(bool playback) {
|
||||||
@ -215,4 +216,32 @@ bool DtsGenerator::getDts_l(uint32_t pts, uint32_t &dts){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NtpStamp::setNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate, uint64_t ntp_stamp_ms) {
|
||||||
|
_rtp_stamp_ms = uint64_t(rtp_stamp) * 1000 / sample_rate;
|
||||||
|
_ntp_stamp_ms = ntp_stamp_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t NtpStamp::getNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate) {
|
||||||
|
uint64_t rtp_stamp_ms = uint64_t(rtp_stamp) * 1000 / sample_rate;
|
||||||
|
if (!_rtp_stamp_ms && !_ntp_stamp_ms) {
|
||||||
|
return rtp_stamp_ms;
|
||||||
|
}
|
||||||
|
if (rtp_stamp_ms > _rtp_stamp_ms) {
|
||||||
|
//时间戳正常增长
|
||||||
|
_last_ret = _ntp_stamp_ms + (rtp_stamp_ms - _rtp_stamp_ms);
|
||||||
|
return _last_ret;
|
||||||
|
}
|
||||||
|
if (_rtp_stamp_ms - rtp_stamp_ms < 10 * 1000) {
|
||||||
|
//小于10秒的时间戳回退,说明收到rtp乱序了
|
||||||
|
return _ntp_stamp_ms - (_rtp_stamp_ms - rtp_stamp_ms);
|
||||||
|
}
|
||||||
|
uint64_t max_rtp_ms = uint64_t(UINT32_MAX) * 1000 / sample_rate;
|
||||||
|
if (rtp_stamp_ms < 60 * 1000 && _rtp_stamp_ms > max_rtp_ms - 60 * 1000) {
|
||||||
|
//确定是时间戳溢出
|
||||||
|
return _ntp_stamp_ms + rtp_stamp_ms + (max_rtp_ms - _rtp_stamp_ms);
|
||||||
|
}
|
||||||
|
//不明原因的时间戳回退,直接返回上次值
|
||||||
|
return _last_ret;
|
||||||
|
}
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
@ -114,6 +114,20 @@ private:
|
|||||||
set<uint32_t> _pts_sorter;
|
set<uint32_t> _pts_sorter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class NtpStamp {
|
||||||
|
public:
|
||||||
|
NtpStamp() = default;
|
||||||
|
~NtpStamp() = default;
|
||||||
|
|
||||||
|
void setNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate, uint64_t ntp_stamp_ms);
|
||||||
|
uint64_t getNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t _rtp_stamp_ms = 0;
|
||||||
|
uint64_t _ntp_stamp_ms = 0;
|
||||||
|
uint64_t _last_ret = 0;
|
||||||
|
};
|
||||||
|
|
||||||
}//namespace mediakit
|
}//namespace mediakit
|
||||||
|
|
||||||
#endif //ZLMEDIAKIT_STAMP_H
|
#endif //ZLMEDIAKIT_STAMP_H
|
||||||
|
@ -22,7 +22,7 @@ RtcpContext::RtcpContext(bool is_receiver) {
|
|||||||
_is_receiver = is_receiver;
|
_is_receiver = is_receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, 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) {
|
||||||
if (_is_receiver) {
|
if (_is_receiver) {
|
||||||
//接收者才做复杂的统计运算
|
//接收者才做复杂的统计运算
|
||||||
auto sys_stamp = getCurrentMillisecond();
|
auto sys_stamp = getCurrentMillisecond();
|
||||||
@ -65,6 +65,7 @@ void RtcpContext::onRtp(uint16_t seq, uint32_t stamp, uint32_t sample_rate, size
|
|||||||
++_packets;
|
++_packets;
|
||||||
_bytes += bytes;
|
_bytes += bytes;
|
||||||
_last_rtp_stamp = stamp;
|
_last_rtp_stamp = stamp;
|
||||||
|
_last_ntp_stamp_ms = ntp_stamp_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtcpContext::onRtcp(RtcpHeader *rtcp) {
|
void RtcpContext::onRtcp(RtcpHeader *rtcp) {
|
||||||
@ -154,7 +155,7 @@ Buffer::Ptr RtcpContext::createRtcpSR(uint32_t rtcp_ssrc) {
|
|||||||
throw std::runtime_error("rtp接收者尝试发送sr包");
|
throw std::runtime_error("rtp接收者尝试发送sr包");
|
||||||
}
|
}
|
||||||
auto rtcp = RtcpSR::create(0);
|
auto rtcp = RtcpSR::create(0);
|
||||||
rtcp->setNtpStamp(getCurrentMillisecond(true));
|
rtcp->setNtpStamp(_last_ntp_stamp_ms);
|
||||||
rtcp->rtpts = htonl(_last_rtp_stamp);
|
rtcp->rtpts = htonl(_last_rtp_stamp);
|
||||||
rtcp->ssrc = htonl(rtcp_ssrc);
|
rtcp->ssrc = htonl(rtcp_ssrc);
|
||||||
rtcp->packet_count = htonl((uint32_t) _packets);
|
rtcp->packet_count = htonl((uint32_t) _packets);
|
||||||
|
@ -30,10 +30,11 @@ public:
|
|||||||
* 输出或输入rtp时调用
|
* 输出或输入rtp时调用
|
||||||
* @param seq rtp的seq
|
* @param seq rtp的seq
|
||||||
* @param stamp rtp的时间戳,单位采样数(非毫秒)
|
* @param stamp rtp的时间戳,单位采样数(非毫秒)
|
||||||
|
* @param ntp_stamp_ms ntp时间戳
|
||||||
* @param rtp rtp时间戳采样率,视频一般为90000,音频一般为采样率
|
* @param rtp rtp时间戳采样率,视频一般为90000,音频一般为采样率
|
||||||
* @param bytes rtp数据长度
|
* @param bytes rtp数据长度
|
||||||
*/
|
*/
|
||||||
void onRtp(uint16_t seq, uint32_t stamp, uint32_t sample_rate, size_t bytes);
|
void onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_ms, uint32_t sample_rate, size_t bytes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 输入sr rtcp包
|
* 输入sr rtcp包
|
||||||
@ -110,6 +111,7 @@ private:
|
|||||||
uint16_t _last_rtp_seq = 0;
|
uint16_t _last_rtp_seq = 0;
|
||||||
//上次的rtp时间戳,毫秒
|
//上次的rtp时间戳,毫秒
|
||||||
uint32_t _last_rtp_stamp = 0;
|
uint32_t _last_rtp_stamp = 0;
|
||||||
|
uint64_t _last_ntp_stamp_ms = 0;
|
||||||
//上次的rtp的系统时间戳(毫秒)用于统计抖动
|
//上次的rtp的系统时间戳(毫秒)用于统计抖动
|
||||||
uint64_t _last_rtp_sys_stamp = 0;
|
uint64_t _last_rtp_sys_stamp = 0;
|
||||||
//上次统计的丢包总数
|
//上次统计的丢包总数
|
||||||
|
@ -35,7 +35,7 @@ public:
|
|||||||
void onRecvRtp(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len){
|
void onRecvRtp(const Buffer::Ptr &buf, struct sockaddr *addr, int addr_len){
|
||||||
//统计rtp接受情况,用于发送rr包
|
//统计rtp接受情况,用于发送rr包
|
||||||
auto header = (RtpHeader *) buf->data();
|
auto header = (RtpHeader *) buf->data();
|
||||||
onRtp(ntohs(header->seq), ntohl(header->stamp), _sample_rate, buf->size());
|
onRtp(ntohs(header->seq), ntohl(header->stamp), 0/*不发送sr,所以可以设置为0*/ , _sample_rate, buf->size());
|
||||||
sendRtcp(ntohl(header->ssrc), addr, addr_len);
|
sendRtcp(ntohl(header->ssrc), addr, addr_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,12 +91,19 @@ bool RtpTrack::inputRtp(TrackType type, int sample_rate, uint8_t *ptr, size_t le
|
|||||||
//拷贝rtp
|
//拷贝rtp
|
||||||
memcpy(&data[4], ptr, len);
|
memcpy(&data[4], ptr, len);
|
||||||
|
|
||||||
|
//设置ntp时间戳
|
||||||
|
rtp->ntp_stamp = _ntp_stamp.getNtpStamp(ntohl(rtp->getHeader()->stamp), sample_rate);
|
||||||
|
|
||||||
onBeforeRtpSorted(rtp);
|
onBeforeRtpSorted(rtp);
|
||||||
auto seq = rtp->getSeq();
|
auto seq = rtp->getSeq();
|
||||||
sortPacket(seq, std::move(rtp));
|
sortPacket(seq, std::move(rtp));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RtpTrack::setNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate, uint64_t ntp_stamp_ms){
|
||||||
|
_ntp_stamp.setNtpStamp(rtp_stamp, sample_rate, ntp_stamp_ms);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void RtpTrackImp::setOnSorted(OnSorted cb) {
|
void RtpTrackImp::setOnSorted(OnSorted cb) {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include "RtpCodec.h"
|
#include "RtpCodec.h"
|
||||||
#include "RtspMediaSource.h"
|
#include "RtspMediaSource.h"
|
||||||
|
#include "Common/Stamp.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace toolkit;
|
using namespace toolkit;
|
||||||
|
|
||||||
@ -175,6 +176,7 @@ public:
|
|||||||
void clear();
|
void clear();
|
||||||
uint32_t getSSRC() const;
|
uint32_t getSSRC() const;
|
||||||
bool inputRtp(TrackType type, int sample_rate, uint8_t *ptr, size_t len);
|
bool inputRtp(TrackType type, int sample_rate, uint8_t *ptr, size_t len);
|
||||||
|
void setNtpStamp(uint32_t rtp_stamp, uint32_t sample_rate, uint64_t ntp_stamp_ms);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void onRtpSorted(RtpPacket::Ptr rtp) {}
|
virtual void onRtpSorted(RtpPacket::Ptr rtp) {}
|
||||||
@ -183,6 +185,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
uint32_t _ssrc = 0;
|
uint32_t _ssrc = 0;
|
||||||
Ticker _ssrc_alive;
|
Ticker _ssrc_alive;
|
||||||
|
NtpStamp _ntp_stamp;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RtpTrackImp : public RtpTrack{
|
class RtpTrackImp : public RtpTrack{
|
||||||
@ -236,6 +239,17 @@ public:
|
|||||||
return _track[index].inputRtp(type, sample_rate, ptr, len);
|
return _track[index].inputRtp(type, sample_rate, ptr, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置ntp时间戳,在收到rtcp sender report时设置
|
||||||
|
* @param index track下标索引
|
||||||
|
* @param rtp_stamp rtp时间戳
|
||||||
|
* @param sample_rate 时间戳采样率
|
||||||
|
* @param ntp_stamp_ms ntp时间戳
|
||||||
|
*/
|
||||||
|
void setNtpStamp(int index, uint32_t rtp_stamp, uint32_t sample_rate, uint64_t ntp_stamp_ms){
|
||||||
|
_track[index].setNtpStamp(rtp_stamp, sample_rate, ntp_stamp_ms);
|
||||||
|
}
|
||||||
|
|
||||||
void clear() {
|
void clear() {
|
||||||
for (auto &track : _track) {
|
for (auto &track : _track) {
|
||||||
track.clear();
|
track.clear();
|
||||||
|
@ -530,19 +530,27 @@ RtpHeader* RtpPacket::getHeader(){
|
|||||||
return (RtpHeader *) (data() + RtpPacket::kRtpTcpHeaderSize);
|
return (RtpHeader *) (data() + RtpPacket::kRtpTcpHeaderSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const RtpHeader *RtpPacket::getHeader() const {
|
||||||
|
return (RtpHeader *) (data() + RtpPacket::kRtpTcpHeaderSize);
|
||||||
|
}
|
||||||
|
|
||||||
string RtpPacket::dumpString() const {
|
string RtpPacket::dumpString() const {
|
||||||
return ((RtpPacket *) this)->getHeader()->dumpString(size() - RtpPacket::kRtpTcpHeaderSize);
|
return ((RtpPacket *) this)->getHeader()->dumpString(size() - RtpPacket::kRtpTcpHeaderSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t RtpPacket::getSeq(){
|
uint16_t RtpPacket::getSeq() const {
|
||||||
return ntohs(getHeader()->seq);
|
return ntohs(getHeader()->seq);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RtpPacket::getStampMS(){
|
uint32_t RtpPacket::getStamp() const {
|
||||||
return ntohl(getHeader()->stamp) * uint64_t(1000) / sample_rate;
|
return ntohl(getHeader()->stamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RtpPacket::getSSRC(){
|
uint32_t RtpPacket::getStampMS() const {
|
||||||
|
return ntp_stamp & 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t RtpPacket::getSSRC() const {
|
||||||
return ntohl(getHeader()->ssrc);
|
return ntohl(getHeader()->ssrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,7 +558,7 @@ uint8_t* RtpPacket::getPayload(){
|
|||||||
return getHeader()->getPayloadData();
|
return getHeader()->getPayloadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t RtpPacket::getPayloadSize(){
|
size_t RtpPacket::getPayloadSize() const {
|
||||||
//需除去rtcp over tcp 4个字节长度
|
//需除去rtcp over tcp 4个字节长度
|
||||||
return getHeader()->getPayloadSize(size() - kRtpTcpHeaderSize);
|
return getHeader()->getPayloadSize(size() - kRtpTcpHeaderSize);
|
||||||
}
|
}
|
||||||
|
@ -154,24 +154,29 @@ public:
|
|||||||
|
|
||||||
//获取rtp头
|
//获取rtp头
|
||||||
RtpHeader* getHeader();
|
RtpHeader* getHeader();
|
||||||
|
const RtpHeader* getHeader() const;
|
||||||
|
|
||||||
//打印调试信息
|
//打印调试信息
|
||||||
string dumpString() const;
|
string dumpString() const;
|
||||||
|
|
||||||
//主机字节序的seq
|
//主机字节序的seq
|
||||||
uint16_t getSeq();
|
uint16_t getSeq() const;
|
||||||
|
uint32_t getStamp() const;
|
||||||
//主机字节序的时间戳,已经转换为毫秒
|
//主机字节序的时间戳,已经转换为毫秒
|
||||||
uint32_t getStampMS();
|
uint32_t getStampMS() const;
|
||||||
//主机字节序的ssrc
|
//主机字节序的ssrc
|
||||||
uint32_t getSSRC();
|
uint32_t getSSRC() const;
|
||||||
//有效负载,跳过csrc、ext
|
//有效负载,跳过csrc、ext
|
||||||
uint8_t* getPayload();
|
uint8_t* getPayload();
|
||||||
//有效负载长度,不包括csrc、ext、padding
|
//有效负载长度,不包括csrc、ext、padding
|
||||||
size_t getPayloadSize();
|
size_t getPayloadSize() const;
|
||||||
|
|
||||||
//音视频类型
|
//音视频类型
|
||||||
TrackType type;
|
TrackType type;
|
||||||
//音频为采样率,视频一般为90000
|
//音频为采样率,视频一般为90000
|
||||||
uint32_t sample_rate;
|
uint32_t sample_rate;
|
||||||
|
//ntp时间戳
|
||||||
|
uint64_t ntp_stamp;
|
||||||
|
|
||||||
static Ptr create();
|
static Ptr create();
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ public:
|
|||||||
auto stamp = rtp->getStampMS();
|
auto stamp = rtp->getStampMS();
|
||||||
if (track) {
|
if (track) {
|
||||||
track->_seq = rtp->getSeq();
|
track->_seq = rtp->getSeq();
|
||||||
track->_time_stamp = stamp;
|
track->_time_stamp = rtp->getStamp() * uint64_t(1000) / rtp->sample_rate;
|
||||||
track->_ssrc = rtp->getSSRC();
|
track->_ssrc = rtp->getSSRC();
|
||||||
}
|
}
|
||||||
if (!_ring) {
|
if (!_ring) {
|
||||||
|
@ -13,6 +13,36 @@
|
|||||||
|
|
||||||
namespace mediakit {
|
namespace mediakit {
|
||||||
|
|
||||||
|
class RingDelegateHelper : public RingDelegate<RtpPacket::Ptr> {
|
||||||
|
public:
|
||||||
|
RingDelegateHelper(RtspMuxer *delegate) {
|
||||||
|
_delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWrite(RtpPacket::Ptr in, bool is_key) override {
|
||||||
|
_delegate->onRtp(std::move(in), is_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
RtspMuxer *_delegate;
|
||||||
|
};
|
||||||
|
|
||||||
|
void RtspMuxer::onRtp(RtpPacket::Ptr in, bool is_key) {
|
||||||
|
if (_rtp_stamp[in->type] != in->getHeader()->stamp) {
|
||||||
|
//rtp时间戳变化才计算ntp,节省cpu资源
|
||||||
|
int64_t stamp_ms = in->getStamp() * uint64_t(1000) / in->sample_rate;
|
||||||
|
int64_t stamp_ms_inc;
|
||||||
|
//求rtp时间戳增量
|
||||||
|
_stamp[in->type].revise(stamp_ms, stamp_ms, stamp_ms_inc, stamp_ms_inc);
|
||||||
|
_rtp_stamp[in->type] = in->getHeader()->stamp;
|
||||||
|
_ntp_stamp[in->type] = stamp_ms_inc + _ntp_stamp_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
//rtp拦截入口,此处统一赋值ntp
|
||||||
|
in->ntp_stamp = _ntp_stamp[in->type];
|
||||||
|
_rtpRing->write(std::move(in), is_key);
|
||||||
|
}
|
||||||
|
|
||||||
RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title){
|
RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title){
|
||||||
if(!title){
|
if(!title){
|
||||||
_sdp = std::make_shared<TitleSdp>()->getSdp();
|
_sdp = std::make_shared<TitleSdp>()->getSdp();
|
||||||
@ -20,6 +50,9 @@ RtspMuxer::RtspMuxer(const TitleSdp::Ptr &title){
|
|||||||
_sdp = title->getSdp();
|
_sdp = title->getSdp();
|
||||||
}
|
}
|
||||||
_rtpRing = std::make_shared<RtpRing::RingType>();
|
_rtpRing = std::make_shared<RtpRing::RingType>();
|
||||||
|
_rtpInterceptor = std::make_shared<RtpRing::RingType>();
|
||||||
|
_rtpInterceptor->setDelegate(std::make_shared<RingDelegateHelper>(this));
|
||||||
|
_ntp_stamp_start = getCurrentMillisecond(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspMuxer::addTrack(const Track::Ptr &track) {
|
void RtspMuxer::addTrack(const Track::Ptr &track) {
|
||||||
@ -36,10 +69,18 @@ void RtspMuxer::addTrack(const Track::Ptr &track) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//设置rtp输出环形缓存
|
//设置rtp输出环形缓存
|
||||||
encoder->setRtpRing(_rtpRing);
|
encoder->setRtpRing(_rtpInterceptor);
|
||||||
|
|
||||||
//添加其sdp
|
//添加其sdp
|
||||||
_sdp.append(sdp->getSdp());
|
_sdp.append(sdp->getSdp());
|
||||||
|
trySyncTrack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RtspMuxer::trySyncTrack() {
|
||||||
|
if (_encoder[TrackAudio] && _encoder[TrackVideo]) {
|
||||||
|
//音频时间戳同步于视频,因为音频时间戳被修改后不影响播放
|
||||||
|
_stamp[TrackAudio].syncTo(_stamp[TrackVideo]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RtspMuxer::inputFrame(const Frame::Ptr &frame) {
|
void RtspMuxer::inputFrame(const Frame::Ptr &frame) {
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "Extension/Frame.h"
|
#include "Extension/Frame.h"
|
||||||
#include "Common/MediaSink.h"
|
#include "Common/MediaSink.h"
|
||||||
|
#include "Common/Stamp.h"
|
||||||
#include "RtpCodec.h"
|
#include "RtpCodec.h"
|
||||||
|
|
||||||
namespace mediakit{
|
namespace mediakit{
|
||||||
@ -21,7 +22,8 @@ namespace mediakit{
|
|||||||
*/
|
*/
|
||||||
class RtspMuxer : public MediaSinkInterface{
|
class RtspMuxer : public MediaSinkInterface{
|
||||||
public:
|
public:
|
||||||
typedef std::shared_ptr<RtspMuxer> Ptr;
|
friend class RingDelegateHelper;
|
||||||
|
using Ptr = std::shared_ptr<RtspMuxer>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造函数
|
* 构造函数
|
||||||
@ -57,10 +59,21 @@ public:
|
|||||||
* 重置所有track
|
* 重置所有track
|
||||||
*/
|
*/
|
||||||
void resetTracks() override ;
|
void resetTracks() override ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void onRtp(RtpPacket::Ptr in, bool is_key);
|
||||||
|
void computeNtp(const Frame::Ptr &frame);
|
||||||
|
void trySyncTrack();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t _rtp_stamp[TrackMax]{0};
|
||||||
|
uint64_t _ntp_stamp[TrackMax]{0};
|
||||||
|
uint64_t _ntp_stamp_start;
|
||||||
string _sdp;
|
string _sdp;
|
||||||
|
Stamp _stamp[TrackMax];
|
||||||
RtpCodec::Ptr _encoder[TrackMax];
|
RtpCodec::Ptr _encoder[TrackMax];
|
||||||
RtpRing::RingType::Ptr _rtpRing;
|
RtpRing::RingType::Ptr _rtpRing;
|
||||||
|
RtpRing::RingType::Ptr _rtpInterceptor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -488,6 +488,11 @@ void RtspPlayer::onRtcpPacket(int track_idx, SdpTrack::Ptr &track, uint8_t *data
|
|||||||
auto rtcp_arr = RtcpHeader::loadFromBytes((char *) data, len);
|
auto rtcp_arr = RtcpHeader::loadFromBytes((char *) data, len);
|
||||||
for (auto &rtcp : rtcp_arr) {
|
for (auto &rtcp : rtcp_arr) {
|
||||||
_rtcp_context[track_idx]->onRtcp(rtcp);
|
_rtcp_context[track_idx]->onRtcp(rtcp);
|
||||||
|
if ((RtcpType) rtcp->pt == RtcpType::RTCP_SR) {
|
||||||
|
auto sr = (RtcpSR *) (rtcp);
|
||||||
|
//设置rtp时间戳与ntp时间戳的对应关系
|
||||||
|
setNtpStamp(track_idx, sr->rtpts, track->_samplerate, sr->getNtpUnixStampMS());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -591,7 +596,7 @@ void RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
|
|||||||
|
|
||||||
void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx){
|
void RtspPlayer::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_idx){
|
||||||
auto &rtcp_ctx = _rtcp_context[track_idx];
|
auto &rtcp_ctx = _rtcp_context[track_idx];
|
||||||
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
rtcp_ctx->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||||
|
|
||||||
auto &ticker = _rtcp_send_ticker[track_idx];
|
auto &ticker = _rtcp_send_ticker[track_idx];
|
||||||
if (ticker.elapsedTime() < 3 * 1000) {
|
if (ticker.elapsedTime() < 3 * 1000) {
|
||||||
|
@ -360,7 +360,7 @@ void RtspPusher::updateRtcpContext(const RtpPacket::Ptr &rtp){
|
|||||||
int track_index = getTrackIndexByTrackType(rtp->type);
|
int track_index = getTrackIndexByTrackType(rtp->type);
|
||||||
auto &ticker = _rtcp_send_ticker[track_index];
|
auto &ticker = _rtcp_send_ticker[track_index];
|
||||||
auto &rtcp_ctx = _rtcp_context[track_index];
|
auto &rtcp_ctx = _rtcp_context[track_index];
|
||||||
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
rtcp_ctx->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||||
|
|
||||||
//send rtcp every 5 second
|
//send rtcp every 5 second
|
||||||
if (ticker.elapsedTime() > 5 * 1000) {
|
if (ticker.elapsedTime() > 5 * 1000) {
|
||||||
|
@ -186,6 +186,11 @@ void RtspSession::onRtcpPacket(int track_idx, SdpTrack::Ptr &track, const char *
|
|||||||
auto rtcp_arr = RtcpHeader::loadFromBytes((char *) data, len);
|
auto rtcp_arr = RtcpHeader::loadFromBytes((char *) data, len);
|
||||||
for (auto &rtcp : rtcp_arr) {
|
for (auto &rtcp : rtcp_arr) {
|
||||||
_rtcp_context[track_idx]->onRtcp(rtcp);
|
_rtcp_context[track_idx]->onRtcp(rtcp);
|
||||||
|
if ((RtcpType) rtcp->pt == RtcpType::RTCP_SR) {
|
||||||
|
auto sr = (RtcpSR *) (rtcp);
|
||||||
|
//设置rtp时间戳与ntp时间戳的对应关系
|
||||||
|
setNtpStamp(track_idx, sr->rtpts, track->_samplerate, sr->getNtpUnixStampMS());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1126,12 +1131,14 @@ void RtspSession::onBeforeRtpSorted(const RtpPacket::Ptr &rtp, int track_index){
|
|||||||
void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
|
void RtspSession::updateRtcpContext(const RtpPacket::Ptr &rtp){
|
||||||
int track_index = getTrackIndexByTrackType(rtp->type);
|
int track_index = getTrackIndexByTrackType(rtp->type);
|
||||||
auto &rtcp_ctx = _rtcp_context[track_index];
|
auto &rtcp_ctx = _rtcp_context[track_index];
|
||||||
rtcp_ctx->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
rtcp_ctx->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||||
|
|
||||||
auto &ticker = _rtcp_send_tickers[track_index];
|
auto &ticker = _rtcp_send_tickers[track_index];
|
||||||
//send rtcp every 5 second
|
//send rtcp every 5 second
|
||||||
if (ticker.elapsedTime() > 5 * 1000) {
|
if (ticker.elapsedTime() > 5 * 1000 || (_send_sr_rtcp[track_index] && !_push_src)) {
|
||||||
|
//确保在发送rtp前,先发送一次sender report rtcp(用于播放器同步音视频)
|
||||||
ticker.resetTime();
|
ticker.resetTime();
|
||||||
|
_send_sr_rtcp[track_index] = false;
|
||||||
|
|
||||||
static auto send_rtcp = [](RtspSession *thiz, int index, Buffer::Ptr ptr) {
|
static auto send_rtcp = [](RtspSession *thiz, int index, Buffer::Ptr ptr) {
|
||||||
if (thiz->_rtp_type == Rtsp::RTP_TCP) {
|
if (thiz->_rtp_type == Rtsp::RTP_TCP) {
|
||||||
|
@ -215,6 +215,7 @@ private:
|
|||||||
Ticker _rtcp_send_tickers[2];
|
Ticker _rtcp_send_tickers[2];
|
||||||
//统计rtp并发送rtcp
|
//统计rtp并发送rtcp
|
||||||
vector<RtcpContext::Ptr> _rtcp_context;
|
vector<RtcpContext::Ptr> _rtcp_context;
|
||||||
|
bool _send_sr_rtcp[2] = {true, true};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -600,8 +600,6 @@ public:
|
|||||||
auto seq = ntohs(rtp->seq);
|
auto seq = ntohs(rtp->seq);
|
||||||
//统计rtp接受情况,便于生成nack rtcp包
|
//统计rtp接受情况,便于生成nack rtcp包
|
||||||
_nack_ctx.received(seq);
|
_nack_ctx.received(seq);
|
||||||
//统计rtp收到的情况,好做rr汇报
|
|
||||||
_rtcp_context.onRtp(seq, ntohl(rtp->stamp), sample_rate, len);
|
|
||||||
}
|
}
|
||||||
return RtpTrack::inputRtp(type, sample_rate, ptr, len);
|
return RtpTrack::inputRtp(type, sample_rate, ptr, len);
|
||||||
}
|
}
|
||||||
@ -611,6 +609,14 @@ public:
|
|||||||
return _rtcp_context.createRtcpRR(ssrc, getSSRC());
|
return _rtcp_context.createRtcpRR(ssrc, getSSRC());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void onBeforeRtpSorted(const RtpPacket::Ptr &rtp) override {
|
||||||
|
//统计rtp收到的情况,好做rr汇报
|
||||||
|
_rtcp_context.onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate,
|
||||||
|
rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||||
|
RtpTrackImp::onBeforeRtpSorted(rtp);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NackContext _nack_ctx;
|
NackContext _nack_ctx;
|
||||||
RtcpContext _rtcp_context{true};
|
RtcpContext _rtcp_context{true};
|
||||||
@ -639,6 +645,8 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
|
|||||||
if(!rtp_chn){
|
if(!rtp_chn){
|
||||||
WarnL << "未识别的sr rtcp包:" << rtcp->dumpString();
|
WarnL << "未识别的sr rtcp包:" << rtcp->dumpString();
|
||||||
} else {
|
} else {
|
||||||
|
//设置rtp时间戳与ntp时间戳的对应关系
|
||||||
|
rtp_chn->setNtpStamp(sr->rtpts, track->plan_rtp->sample_rate, sr->getNtpUnixStampMS());
|
||||||
auto rr = rtp_chn->createRtcpRR(sr, track->answer_ssrc_rtp);
|
auto rr = rtp_chn->createRtcpRR(sr, track->answer_ssrc_rtp);
|
||||||
sendRtcpPacket(rr->data(), rr->size(), true);
|
sendRtcpPacket(rr->data(), rr->size(), true);
|
||||||
}
|
}
|
||||||
@ -845,7 +853,7 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r
|
|||||||
}
|
}
|
||||||
if (!rtx) {
|
if (!rtx) {
|
||||||
//统计rtp发送情况,好做sr汇报
|
//统计rtp发送情况,好做sr汇报
|
||||||
track->rtcp_context_send->onRtp(rtp->getSeq(), ntohl(rtp->getHeader()->stamp), rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
track->rtcp_context_send->onRtp(rtp->getSeq(), rtp->getStamp(), rtp->ntp_stamp, rtp->sample_rate, rtp->size() - RtpPacket::kRtpTcpHeaderSize);
|
||||||
track->nack_list.push_back(rtp);
|
track->nack_list.push_back(rtp);
|
||||||
#if 0
|
#if 0
|
||||||
//此处模拟发送丢包
|
//此处模拟发送丢包
|
||||||
|
Loading…
Reference in New Issue
Block a user