mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-10-30 16:27:36 +08:00
完善相对时间戳逻辑, 完善同步机制, 解决相对时间戳不同步的问题
默认禁止时间戳回退并设置最大跳跃幅度为300毫秒 rtsp恢复产生ntp时间戳 由于绝对时间戳可能跳跃回退,之前在求相对时间戳时会导致音视频不同步。 现在求相对时间戳逻辑经过修改,已经支持同步功能,所以恢复rtp ntp时间戳逻辑
This commit is contained in:
parent
bd22c44ee9
commit
0f4e0e1076
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user