完善相对时间戳逻辑, 完善同步机制, 解决相对时间戳不同步的问题

默认禁止时间戳回退并设置最大跳跃幅度为300毫秒
rtsp恢复产生ntp时间戳
由于绝对时间戳可能跳跃回退,之前在求相对时间戳时会导致音视频不同步。
现在求相对时间戳逻辑经过修改,已经支持同步功能,所以恢复rtp ntp时间戳逻辑
This commit is contained in:
xia-chu 2023-11-25 10:43:51 +08:00 committed by 夏楚
parent bd22c44ee9
commit 0f4e0e1076
3 changed files with 75 additions and 17 deletions

View File

@ -20,8 +20,13 @@ using namespace toolkit;
namespace mediakit {
int64_t DeltaStamp::relativeStamp(int64_t stamp) {
_relative_stamp += deltaStamp(stamp);
DeltaStamp::DeltaStamp() {
// 时间戳最大允许跳跃300ms
_max_delta = 300;
}
int64_t DeltaStamp::relativeStamp(int64_t stamp, bool enable_rollback) {
_relative_stamp += deltaStamp(stamp, enable_rollback);
return _relative_stamp;
}
@ -29,7 +34,7 @@ int64_t DeltaStamp::relativeStamp() {
return _relative_stamp;
}
int64_t DeltaStamp::deltaStamp(int64_t stamp) {
int64_t DeltaStamp::deltaStamp(int64_t stamp, bool enable_rollback) {
if (!_last_stamp) {
// 第一次计算时间戳增量,时间戳增量为0
if (stamp) {
@ -43,14 +48,25 @@ int64_t DeltaStamp::deltaStamp(int64_t stamp) {
// 时间戳增量为正,返回之
_last_stamp = stamp;
// 在直播情况下时间戳增量不得大于MAX_DELTA_STAMP否则强制相对时间戳加1
return ret < MAX_DELTA_STAMP ? ret : 1;
if (ret > _max_delta) {
needSync();
return 1;
}
return ret;
}
// 时间戳增量为负,说明时间戳回环了或回退了
_last_stamp = stamp;
if (!enable_rollback || -ret > _max_delta) {
// 不允许回退或者回退太多了, 强制时间戳加1
needSync();
return 1;
}
return ret;
}
// 如果时间戳回退不多那么返回负值否则返回加1
return -ret < MAX_DELTA_STAMP ? ret : 1;
void DeltaStamp::setMaxDelta(size_t max_delta) {
_max_delta = max_delta;
}
void Stamp::setPlayBack(bool playback) {
@ -58,9 +74,18 @@ void Stamp::setPlayBack(bool playback) {
}
void Stamp::syncTo(Stamp &other) {
_need_sync = true;
_sync_master = &other;
}
void Stamp::needSync() {
_need_sync = true;
}
void Stamp::enableRollback(bool flag) {
_enable_rollback = flag;
}
// 限制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);
@ -87,15 +112,26 @@ void Stamp::revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_ou
return;
}
if (_sync_master && _sync_master->_last_dts_in) {
// 需要同步时间戳
if (_sync_master && _sync_master->_last_dts_in && (_need_sync || _sync_master->_need_sync)) {
// 音视频dts当前时间差
int64_t dts_diff = _last_dts_in - _sync_master->_last_dts_in;
if (ABS(dts_diff) < 5000) {
// 如果绝对时间戳小于5秒那么说明他们的起始时间戳是一致的那么强制同步
_relative_stamp = _sync_master->_relative_stamp + dts_diff;
auto target_stamp = _sync_master->_relative_stamp + dts_diff;
if (target_stamp > _relative_stamp || _enable_rollback) {
// 强制同步后,时间戳增加跳跃了,或允许回退
TraceL << "Relative stamp changed: " << _relative_stamp << " -> " << target_stamp;
_relative_stamp = target_stamp;
} else {
// 不允许回退, 则让另外一个Track的时间戳增长
target_stamp = _relative_stamp - dts_diff;
TraceL << "Relative stamp changed: " << _sync_master->_relative_stamp << " -> " << target_stamp;
_sync_master->_relative_stamp = target_stamp;
}
}
// 下次不用再强制同步
_sync_master = nullptr;
_need_sync = false;
_sync_master->_need_sync = false;
}
}
@ -124,7 +160,7 @@ void Stamp::revise_l2(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_o
// 内部自己生产时间戳
_relative_stamp = _ticker.elapsedTime();
} else {
_relative_stamp += deltaStamp(dts);
_relative_stamp += deltaStamp(dts, _enable_rollback);
}
_last_dts_in = dts;
}

View File

@ -19,19 +19,27 @@ namespace mediakit {
class DeltaStamp{
public:
DeltaStamp() = default;
DeltaStamp();
~DeltaStamp() = default;
/**
*
* @param stamp
* @param enable_rollback 退
* @return
*/
int64_t deltaStamp(int64_t stamp);
int64_t relativeStamp(int64_t stamp);
int64_t deltaStamp(int64_t stamp, bool enable_rollback = true);
int64_t relativeStamp(int64_t stamp, bool enable_rollback = true);
int64_t relativeStamp();
private:
// 设置最大允许回退或跳跃幅度
void setMaxDelta(size_t max_delta);
protected:
virtual void needSync() {}
protected:
int _max_delta;
int64_t _last_stamp = 0;
int64_t _relative_stamp = 0;
};
@ -77,6 +85,11 @@ public:
*/
void syncTo(Stamp &other);
/**
* 退
*/
void enableRollback(bool flag);
private:
//主要实现音视频时间戳同步功能
void revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp = false);
@ -84,13 +97,18 @@ private:
//主要实现获取相对时间戳功能
void revise_l2(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp = false);
void needSync() override;
private:
bool _playback = false;
bool _need_sync = false;
// 默认不允许时间戳回滚
bool _enable_rollback = false;
int64_t _relative_stamp = 0;
int64_t _last_dts_in = 0;
int64_t _last_dts_out = 0;
int64_t _last_pts_out = 0;
toolkit::SmoothTicker _ticker;
bool _playback = false;
Stamp *_sync_master = nullptr;
};

View File

@ -14,7 +14,7 @@
using namespace std;
using namespace toolkit;
#define ENABLE_NTP_STAMP 0
#define ENABLE_NTP_STAMP 1
namespace mediakit {
@ -78,6 +78,10 @@ bool RtspMuxer::addTrack(const Track::Ptr &track) {
//添加其sdp
_sdp.append(sdp->getSdp());
trySyncTrack();
// rtp的时间戳是pts允许回退
_stamp[TrackAudio].enableRollback(true);
_stamp[TrackVideo].enableRollback(true);
return true;
}