From 84cfe66da08ae42f09c88bdcd5030ef8a3f045bb Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Sun, 30 Aug 2020 09:15:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=94=B1=E4=BA=8E=E9=9F=B3?= =?UTF-8?q?=E8=A7=86=E9=A2=91=E5=90=8C=E6=AD=A5=E5=AF=BC=E8=87=B4=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E6=88=B3=E5=9B=9E=E9=80=80=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Common/Stamp.cpp | 82 +++++++++++++++++++++++--------------------- src/Common/Stamp.h | 18 +++++++--- 2 files changed, 55 insertions(+), 45 deletions(-) diff --git a/src/Common/Stamp.cpp b/src/Common/Stamp.cpp index d9ab1823..595d147d 100644 --- a/src/Common/Stamp.cpp +++ b/src/Common/Stamp.cpp @@ -44,77 +44,79 @@ void Stamp::setPlayBack(bool playback) { void Stamp::syncTo(Stamp &other){ _sync_master = &other; - _sync_finished = false; } +//限制dts回退 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; } + revise_l(dts, pts, dts_out, pts_out, modifyStamp); + if (_playback) { + //回放允许时间戳回退 return; } - if(_sync_master && _sync_master->_last_dts){ + if (dts_out < _last_dts_out) { + WarnL << "dts回退:" << dts_out << " < " << _last_dts_out; + dts_out = _last_dts_out; + pts_out = _last_pts_out; + return; + } + _last_dts_out = dts_out; + _last_pts_out = pts_out; +} + +//音视频时间戳同步 +void Stamp::revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) { + revise_l2(dts, pts, dts_out, pts_out, modifyStamp); + if (!_sync_master || modifyStamp || _playback) { + //自动生成时间戳或回放或同步完毕 + return; + } + + if (_sync_master && _sync_master->_last_dts_in) { //音视频dts当前时间差 - int64_t dts_diff = _last_dts - _sync_master->_last_dts; - if(ABS(dts_diff) < 5000){ + int64_t dts_diff = _last_dts_in - _sync_master->_last_dts_in; + if (ABS(dts_diff) < 5000) { //如果绝对时间戳小于5秒,那么说明他们的起始时间戳是一致的,那么强制同步 - _last_relativeStamp = _relativeStamp; - _relativeStamp = _sync_master->_relativeStamp + dts_diff; + _relative_stamp = _sync_master->_relative_stamp + 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){ +//求取相对时间戳 +void Stamp::revise_l2(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) { + if (!pts) { //没有播放时间戳,使其赋值为解码时间戳 pts = dts; } - if(_playback){ + if (_playback) { //这是点播 dts_out = dts; pts_out = pts; - _relativeStamp = dts_out; - _last_dts = dts; + _relative_stamp = dts_out; + _last_dts_in = dts; return; } //pts和dts的差值 int pts_dts_diff = pts - dts; - if(_last_dts != dts){ + if (_last_dts_in != dts) { //时间戳发生变更 - if(modifyStamp){ + if (modifyStamp) { //内部自己生产时间戳 - _relativeStamp = _ticker.elapsedTime(); - }else{ - _relativeStamp += deltaStamp(dts); + _relative_stamp = _ticker.elapsedTime(); + } else { + _relative_stamp += deltaStamp(dts); } - _last_dts = dts; + _last_dts_in = dts; } - dts_out = _relativeStamp; + dts_out = _relative_stamp; //////////////以下是播放时间戳的计算////////////////// - if(ABS(pts_dts_diff) > MAX_CTS){ + if (ABS(pts_dts_diff) > MAX_CTS) { //如果差值太大,则认为由于回环导致时间戳错乱了 pts_dts_diff = 0; } @@ -123,11 +125,11 @@ void Stamp::revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_ou } void Stamp::setRelativeStamp(int64_t relativeStamp) { - _relativeStamp = relativeStamp; + _relative_stamp = relativeStamp; } int64_t Stamp::getRelativeStamp() const { - return _relativeStamp; + return _relative_stamp; } bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){ diff --git a/src/Common/Stamp.h b/src/Common/Stamp.h index cf374277..30d41157 100644 --- a/src/Common/Stamp.h +++ b/src/Common/Stamp.h @@ -29,6 +29,7 @@ public: * @return 时间戳增量 */ int64_t deltaStamp(int64_t stamp); + private: int64_t _last_stamp = 0; }; @@ -41,7 +42,7 @@ public: ~Stamp() = default; /** - * 修正时间戳 + * 求取相对时间戳,同时实现了音视频同步、限制dts回退等功能 * @param dts 输入dts,如果为0则根据系统时间戳生成 * @param pts 输入pts,如果为0则等于dts * @param dts_out 输出dts @@ -75,15 +76,20 @@ public: 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); + + //主要实现获取相对时间戳功能 + void revise_l2(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_relativeStamp = 0; - int64_t _last_dts = 0; + int64_t _relative_stamp = 0; + int64_t _last_dts_in = 0; + int64_t _last_dts_out = 0; + int64_t _last_pts_out = 0; SmoothTicker _ticker; bool _playback = false; Stamp *_sync_master = nullptr; - bool _sync_finished = true; }; //dts生成器, @@ -93,8 +99,10 @@ public: DtsGenerator() = default; ~DtsGenerator() = default; bool getDts(uint32_t pts, uint32_t &dts); + private: bool getDts_l(uint32_t pts, uint32_t &dts); + private: uint32_t _dts_pts_offset = 0; uint32_t _last_dts = 0;