完善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;
}

View File

@ -191,19 +191,10 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
}
void H264RtpDecoder::onGetH264(const H264Frame::Ptr &frame) {
auto flag = _dts_generator.getDts(frame->_pts,frame->_dts);
if(!flag){
if(frame->configFrame() || frame->keyFrame()){
flag = true;
frame->_dts = frame->_pts;
}
}
//根据pts计算dts
if(flag){
//写入环形缓存
RtpCodec::inputFrame(frame);
}
//rtsp没有dts那么根据pts排序算法生成dts
_dts_generator.getDts(frame->_pts,frame->_dts);
//写入环形缓存
RtpCodec::inputFrame(frame);
_h264frame = obtainFrame();
}

View File

@ -127,18 +127,10 @@ bool H265RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
}
void H265RtpDecoder::onGetH265(const H265Frame::Ptr &frame) {
//计算dts
auto flag = _dts_generator.getDts(frame->_pts,frame->_dts);
if(!flag){
if(frame->configFrame() || frame->keyFrame()){
flag = true;
frame->_dts = frame->_pts;
}
}
if(flag){
//写入环形缓存
RtpCodec::inputFrame(frame);
}
//rtsp没有dts那么根据pts排序算法生成dts
_dts_generator.getDts(frame->_pts,frame->_dts);
//写入环形缓存
RtpCodec::inputFrame(frame);
_h265frame = obtainFrame();
}