From 05a65d4961e99486ec58c210b6f157f9298c8d0f Mon Sep 17 00:00:00 2001 From: baiyfcu Date: Wed, 17 Jun 2020 15:51:02 +0800 Subject: [PATCH] merge stamp --- src/Common/Stamp.cpp | 54 ++++++++++++++++++++++++++++++++++++-------- src/Common/Stamp.h | 23 +++++++++++++------ 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index 0bbaf958..e5fd631c 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -42,7 +42,48 @@ void Stamp::setPlayBack(bool playback) { _playback = playback; } +void Stamp::syncTo(Stamp &other){ + _sync_master = &other; + _sync_finished = false; +} + 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(_sync_finished || modifyStamp || _playback){ + //自动生成时间戳或回放或同步完毕 + if(dts_out < 0) { dts_out = 0; } + if(pts_out < 0) { pts_out = 0; } + return; + } + + if(_sync_master && _sync_master->_last_dts){ + //音视频dts当前时间差 + int64_t dts_diff = _last_dts - _sync_master->_last_dts; + if(ABS(dts_diff) < 5000){ + //如果绝对时间戳小于5秒,那么说明他们的起始时间戳是一致的,那么强制同步 + _last_relativeStamp = _relativeStamp; + _relativeStamp = _sync_master->_relativeStamp + dts_diff; + } + //下次不用再强制同步 + _sync_master = nullptr; + } + + if (dts_out < 0 || dts_out < _last_relativeStamp) { + //相对时间戳小于0,或者小于上次的时间戳, + //那么说明是同步时间戳导致的,在这个过渡期内,我们一直返回上次的结果(目的是为了防止时间戳回退) + pts_out = _last_relativeStamp + (pts_out - dts_out); + dts_out = _last_relativeStamp; + } else if(!_sync_master){ + //音视频同步过渡期完毕 + _sync_finished = true; + } + + if(pts_out < 0){ + pts_out = dts_out; + } +} + +void Stamp::revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) { if(!pts){ //没有播放时间戳,使其赋值为解码时间戳 pts = dts; @@ -52,10 +93,8 @@ void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out, //这是点播 dts_out = dts; pts_out = pts; + _relativeStamp = dts_out; _last_dts = dts; - if (_dts_base == -1) - _dts_base = dts; - _relativeStamp = _npt_base + dts - _dts_base; return; } @@ -65,6 +104,7 @@ void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out, if(_last_dts != dts){ //时间戳发生变更 if(modifyStamp){ + //内部自己生产时间戳 _relativeStamp = _ticker.elapsedTime(); }else{ _relativeStamp += deltaStamp(dts); @@ -80,15 +120,9 @@ void Stamp::revise(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out, } pts_out = dts_out + pts_dts_diff; - if(pts_out < 0){ - //时间戳不能小于0 - pts_out = 0; - } } void Stamp::setRelativeStamp(int64_t relativeStamp) { - _dts_base = _last_dts; - _npt_base = relativeStamp; _relativeStamp = relativeStamp; } @@ -141,7 +175,7 @@ bool DtsGenerator::getDts_l(uint32_t pts, uint32_t &dts){ //已经出现多次非B帧的情况,那么我们就能知道P帧间B帧的个数 _sorter_max_size = _frames_since_last_max_pts; //我们记录P帧间时间间隔(也就是多个B帧时间戳增量累计) - _dts_pts_offset = (pts - _last_max_pts) / 2; + _dts_pts_offset = (pts - _last_max_pts); } //遇到P帧或关键帧,连续B帧计数清零 _frames_since_last_max_pts = 0; diff --git a/src/Common/Stamp.h b/src/Common/Stamp.h index 5d3897bf..cf374277 100644 --- a/src/Common/Stamp.h +++ b/src/Common/Stamp.h @@ -32,6 +32,7 @@ public: private: int64_t _last_stamp = 0; }; + //该类解决时间戳回环、回退问题 //计算相对时间戳或者产生平滑时间戳 class Stamp : public DeltaStamp{ @@ -66,17 +67,27 @@ public: * @param playback 是否为回放模式 */ void setPlayBack(bool playback = true); + + /** + * 音视频同步用,音频应该同步于视频(只修改音频时间戳) + * 因为音频时间戳修改后不影响播放速度 + */ + void syncTo(Stamp &other); + +private: + void revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp = false); private: int64_t _relativeStamp = 0; - int64_t _last_dts = -1; + int64_t _last_relativeStamp = 0; + int64_t _last_dts = 0; SmoothTicker _ticker; bool _playback = false; - - int64_t _dts_base = 0; - int64_t _npt_base = 0; + Stamp *_sync_master = nullptr; + bool _sync_finished = true; }; - +//dts生成器, +//pts排序后就是dts class DtsGenerator{ public: DtsGenerator() = default; @@ -93,8 +104,6 @@ private: int _sorter_max_size = 0; int _count_sorter_max_size = 0; set _pts_sorter; - - }; }//namespace mediakit