mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-23 03:10:04 +08:00
修复由于音视频同步导致时间戳回退的问题
This commit is contained in:
parent
29fcf3eb3b
commit
84cfe66da0
@ -44,46 +44,48 @@ void Stamp::setPlayBack(bool playback) {
|
|||||||
|
|
||||||
void Stamp::syncTo(Stamp &other){
|
void Stamp::syncTo(Stamp &other){
|
||||||
_sync_master = &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) {
|
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);
|
revise_l(dts, pts, dts_out, pts_out, modifyStamp);
|
||||||
if(_sync_finished || modifyStamp || _playback){
|
if (_playback) {
|
||||||
//自动生成时间戳或回放或同步完毕
|
//回放允许时间戳回退
|
||||||
if(dts_out < 0) { dts_out = 0; }
|
|
||||||
if(pts_out < 0) { pts_out = 0; }
|
|
||||||
return;
|
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当前时间差
|
//音视频dts当前时间差
|
||||||
int64_t dts_diff = _last_dts - _sync_master->_last_dts;
|
int64_t dts_diff = _last_dts_in - _sync_master->_last_dts_in;
|
||||||
if (ABS(dts_diff) < 5000) {
|
if (ABS(dts_diff) < 5000) {
|
||||||
//如果绝对时间戳小于5秒,那么说明他们的起始时间戳是一致的,那么强制同步
|
//如果绝对时间戳小于5秒,那么说明他们的起始时间戳是一致的,那么强制同步
|
||||||
_last_relativeStamp = _relativeStamp;
|
_relative_stamp = _sync_master->_relative_stamp + dts_diff;
|
||||||
_relativeStamp = _sync_master->_relativeStamp + dts_diff;
|
|
||||||
}
|
}
|
||||||
//下次不用再强制同步
|
//下次不用再强制同步
|
||||||
_sync_master = nullptr;
|
_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_l2(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp) {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
@ -93,25 +95,25 @@ void Stamp::revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_ou
|
|||||||
//这是点播
|
//这是点播
|
||||||
dts_out = dts;
|
dts_out = dts;
|
||||||
pts_out = pts;
|
pts_out = pts;
|
||||||
_relativeStamp = dts_out;
|
_relative_stamp = dts_out;
|
||||||
_last_dts = dts;
|
_last_dts_in = dts;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//pts和dts的差值
|
//pts和dts的差值
|
||||||
int pts_dts_diff = pts - dts;
|
int pts_dts_diff = pts - dts;
|
||||||
|
|
||||||
if(_last_dts != dts){
|
if (_last_dts_in != dts) {
|
||||||
//时间戳发生变更
|
//时间戳发生变更
|
||||||
if (modifyStamp) {
|
if (modifyStamp) {
|
||||||
//内部自己生产时间戳
|
//内部自己生产时间戳
|
||||||
_relativeStamp = _ticker.elapsedTime();
|
_relative_stamp = _ticker.elapsedTime();
|
||||||
} else {
|
} else {
|
||||||
_relativeStamp += deltaStamp(dts);
|
_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) {
|
||||||
@ -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) {
|
void Stamp::setRelativeStamp(int64_t relativeStamp) {
|
||||||
_relativeStamp = relativeStamp;
|
_relative_stamp = relativeStamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t Stamp::getRelativeStamp() const {
|
int64_t Stamp::getRelativeStamp() const {
|
||||||
return _relativeStamp;
|
return _relative_stamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){
|
bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){
|
||||||
|
@ -29,6 +29,7 @@ public:
|
|||||||
* @return 时间戳增量
|
* @return 时间戳增量
|
||||||
*/
|
*/
|
||||||
int64_t deltaStamp(int64_t stamp);
|
int64_t deltaStamp(int64_t stamp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int64_t _last_stamp = 0;
|
int64_t _last_stamp = 0;
|
||||||
};
|
};
|
||||||
@ -41,7 +42,7 @@ public:
|
|||||||
~Stamp() = default;
|
~Stamp() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修正时间戳
|
* 求取相对时间戳,同时实现了音视频同步、限制dts回退等功能
|
||||||
* @param dts 输入dts,如果为0则根据系统时间戳生成
|
* @param dts 输入dts,如果为0则根据系统时间戳生成
|
||||||
* @param pts 输入pts,如果为0则等于dts
|
* @param pts 输入pts,如果为0则等于dts
|
||||||
* @param dts_out 输出dts
|
* @param dts_out 输出dts
|
||||||
@ -75,15 +76,20 @@ public:
|
|||||||
void syncTo(Stamp &other);
|
void syncTo(Stamp &other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//主要实现音视频时间戳同步功能
|
||||||
void revise_l(int64_t dts, int64_t pts, int64_t &dts_out, int64_t &pts_out,bool modifyStamp = false);
|
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:
|
private:
|
||||||
int64_t _relativeStamp = 0;
|
int64_t _relative_stamp = 0;
|
||||||
int64_t _last_relativeStamp = 0;
|
int64_t _last_dts_in = 0;
|
||||||
int64_t _last_dts = 0;
|
int64_t _last_dts_out = 0;
|
||||||
|
int64_t _last_pts_out = 0;
|
||||||
SmoothTicker _ticker;
|
SmoothTicker _ticker;
|
||||||
bool _playback = false;
|
bool _playback = false;
|
||||||
Stamp *_sync_master = nullptr;
|
Stamp *_sync_master = nullptr;
|
||||||
bool _sync_finished = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//dts生成器,
|
//dts生成器,
|
||||||
@ -93,8 +99,10 @@ public:
|
|||||||
DtsGenerator() = default;
|
DtsGenerator() = default;
|
||||||
~DtsGenerator() = default;
|
~DtsGenerator() = default;
|
||||||
bool getDts(uint32_t pts, uint32_t &dts);
|
bool getDts(uint32_t pts, uint32_t &dts);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getDts_l(uint32_t pts, uint32_t &dts);
|
bool getDts_l(uint32_t pts, uint32_t &dts);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32_t _dts_pts_offset = 0;
|
uint32_t _dts_pts_offset = 0;
|
||||||
uint32_t _last_dts = 0;
|
uint32_t _last_dts = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user