rtmp播放时,取相对时间戳逻辑确保时间戳同步

This commit is contained in:
xiongziliang 2020-05-06 18:54:28 +08:00
parent 920f06a996
commit a4d7b3463e
4 changed files with 54 additions and 4 deletions

View File

@ -42,7 +42,40 @@ void Stamp::setPlayBack(bool playback) {
_playback = playback; _playback = playback;
} }
void Stamp::makeRelation(Stamp &other){
_related = &other;
}
void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) { void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) {
revise_l(dts,pts,dts_out,pts_out,modifyStamp);
if(modifyStamp || _playback){
//自动生成时间戳或回放,不需要做音视频同步
return;
}
if(_related && _related->_last_dts){
//音视频dts当前时间差
int64_t dts_diff = _last_dts - _related->_last_dts;
if(ABS(dts_diff) < 5000){
//如果绝对时间戳小于5秒那么说明他们的起始时间戳是一致的那么强制同步
_last_relativeStamp = _relativeStamp;
_relativeStamp = _related->_relativeStamp + dts_diff;
dts_out += dts_diff;
pts_out += dts_diff;
// DebugL << "音视频同步事件差:" << dts_diff;
}
//下次不用再强制同步
_related = nullptr;
}
if(dts_out < 0){
//相对时间戳小于0那么说明是同步时间戳导致的,在这个过渡期内,我们一直返回上次的结果(目的是为了防止时间戳回退)
pts_out = _last_relativeStamp + (pts_out - dts_out);
dts_out = _last_relativeStamp;
}
}
void Stamp::revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) {
if(!pts){ if(!pts){
//没有播放时间戳,使其赋值为解码时间戳 //没有播放时间戳,使其赋值为解码时间戳
pts = dts; pts = dts;
@ -53,6 +86,7 @@ void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,
dts_out = dts; dts_out = dts;
pts_out = pts; pts_out = pts;
_relativeStamp = dts_out; _relativeStamp = dts_out;
_last_dts = dts;
return; return;
} }
@ -62,6 +96,7 @@ void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,
if(_last_dts != dts){ if(_last_dts != dts){
//时间戳发生变更 //时间戳发生变更
if(modifyStamp){ if(modifyStamp){
//内部自己生产时间戳
_relativeStamp = _ticker.elapsedTime(); _relativeStamp = _ticker.elapsedTime();
}else{ }else{
_relativeStamp += deltaStamp(dts); _relativeStamp += deltaStamp(dts);

View File

@ -32,6 +32,7 @@ public:
private: private:
int64_t _last_stamp = 0; int64_t _last_stamp = 0;
}; };
//该类解决时间戳回环、回退问题 //该类解决时间戳回环、回退问题
//计算相对时间戳或者产生平滑时间戳 //计算相对时间戳或者产生平滑时间戳
class Stamp : public DeltaStamp{ class Stamp : public DeltaStamp{
@ -66,14 +67,25 @@ public:
* @param playback * @param playback
*/ */
void setPlayBack(bool playback = true); void setPlayBack(bool playback = true);
/**
* ,
*/
void makeRelation(Stamp &other);
private:
void revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp = false);
private: private:
int64_t _relativeStamp = 0; int64_t _relativeStamp = 0;
int64_t _last_dts = -1; int64_t _last_relativeStamp = 0;
int64_t _last_dts = 0;
SmoothTicker _ticker; SmoothTicker _ticker;
bool _playback = false; bool _playback = false;
Stamp *_related = nullptr;
}; };
//dts生成器
//pts排序后就是dts
class DtsGenerator{ class DtsGenerator{
public: public:
DtsGenerator() = default; DtsGenerator() = default;
@ -90,8 +102,6 @@ private:
int _sorter_max_size = 0; int _sorter_max_size = 0;
int _count_sorter_max_size = 0; int _count_sorter_max_size = 0;
set<uint32_t> _pts_sorter; set<uint32_t> _pts_sorter;
}; };
}//namespace mediakit }//namespace mediakit

View File

@ -50,6 +50,9 @@ void FlvMuxer::start(const EventPoller::Ptr &poller,const RtmpMediaSource::Ptr &
} }
strongSelf->onDetach(); strongSelf->onDetach();
}); });
//音频同步于视频
_stamp[0].makeRelation( _stamp[1]);
_ring_reader->setReadCB([weakSelf](const RtmpMediaSource::RingDataType &pkt){ _ring_reader->setReadCB([weakSelf](const RtmpMediaSource::RingDataType &pkt){
auto strongSelf = weakSelf.lock(); auto strongSelf = weakSelf.lock();
if(!strongSelf){ if(!strongSelf){

View File

@ -266,6 +266,8 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
onSendMedia(pkt); onSendMedia(pkt);
}); });
//音频同步于视频
_stamp[0].makeRelation( _stamp[1]);
_pRingReader = src->getRing()->attach(getPoller()); _pRingReader = src->getRing()->attach(getPoller());
weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this()); weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this());
_pRingReader->setReadCB([weakSelf](const RtmpMediaSource::RingDataType &pkt) { _pRingReader->setReadCB([weakSelf](const RtmpMediaSource::RingDataType &pkt) {