完善dts计算算法

This commit is contained in:
xiongziliang
2020-04-29 18:05:29 +08:00
parent 3630839bc9
commit 9d9f6e304e
3 changed files with 35 additions and 28 deletions

View File

@@ -95,7 +95,7 @@ int64_t Stamp::getRelativeStamp() const {
bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){
bool ret = false;
if(pts == _last_pts){
//pts未变返回上次结果
//pts未变说明dts也不会变返回上次dts
if(_last_dts){
dts = _last_dts;
ret = true;
@@ -105,44 +105,68 @@ bool DtsGenerator::getDts(uint32_t pts, uint32_t &dts){
ret = getDts_l(pts,dts);
if(ret){
//保存本次结果
//获取到了dts保存本次结果
_last_dts = dts;
}else{
//pts排序列队长度还不知道也就是不知道有没有B帧
//那么先强制dts == pts这样可能导致有B帧的情况下起始画面有几帧回退
dts = pts;
}
//记录上次pts
_last_pts = pts;
return ret;
}
//该算法核心思想是对pts进行排序排序好的pts就是dts。
//排序有一定的滞后性,那么需要加上排序导致的时间戳偏移量
bool DtsGenerator::getDts_l(uint32_t pts, uint32_t &dts){
if(_sorter_max_size == 1){
//没有B帧
//没有B帧dts就等于pts
dts = pts;
return true;
}
if(!_sorter_max_size){
//尚未计算出pts排序列队长度(也就是P帧间B帧个数)
if(pts > _last_max_pts){
//pts时间戳增加了那么说明这帧画面不是B帧(说明是P帧或关键帧)
if(_frames_since_last_max_pts && _count_sorter_max_size++ > 0){
//已经出现多次非B帧的情况那么我们就能知道P帧间B帧的个数
_sorter_max_size = _frames_since_last_max_pts;
//我们记录P帧间时间间隔(也就是多个B帧时间戳增量累计)
_dts_pts_offset = (pts - _last_max_pts) / 2;
}
//遇到P帧或关键帧连续B帧计数清零
_frames_since_last_max_pts = 0;
//记录上次非B帧的pts时间戳(同时也是dts)用于统计连续B帧时间戳增量
_last_max_pts = pts;
}
//如果pts时间戳小于上一个P帧那么断定这个是B帧,我们记录B帧连续个数
++_frames_since_last_max_pts;
}
//pts放入排序缓存列队缓存列队最大等于连续B帧个数
_pts_sorter.emplace(pts);
if(_sorter_max_size && _pts_sorter.size() > _sorter_max_size){
//如果启用了pts排序(意味着存在B帧)并且pts排序缓存列队长度大于连续B帧个数
//意味着后续的pts都会比最早的pts大那么说明可以取出最早的pts了这个pts将当做该帧的dts基准
auto it = _pts_sorter.begin();
//由于该pts是前面偏移了个_sorter_max_size帧的pts(也就是那帧画面的dts),
//那么我们加上时间戳偏移量基本等于该帧的dts
dts = *it + _dts_pts_offset;
if(dts > pts){
//dts不能大于pts(基本不可能到达这个逻辑)
dts = pts;
}
//pts排序缓存出列
_pts_sorter.erase(it);
return true;
}
//排序缓存尚未满
return false;
}