为什么OpenCV计算的帧率是错误的?

本文探讨了OpenCV计算帧率出错的问题,通过分析发现,OpenCV使用AVStream->codec->time_base计算帧率,但在非固定帧率视频中,这个值可能不正确。FFmpeg中,time_base和framerate的计算涉及到H264解码过程中的多个步骤,包括SPS信息和ticks_per_frame。OpenCV未考虑ticks_per_frame导致错误的帧率结果。正确的计算方式应考虑ticks_per_frame。
摘要由CSDN通过智能技术生成

图片

▲扫描图中二维码了解音视频技术大会更多信息▲


作者:王伟

编辑:Alex

引 言

我们有一个平台来周期性地对线上的直播流数据进行某些检测,例如黑/白屏检测、静态画面检测……在检测中,我们会根据提取到的直播流的帧率来预估要计算的帧数量,例如,如果要检测5s的直播流,而该直播流的帧率为20fps,需要计算的帧数量则为100。忽然有一天,我们发现,平台开始大面积的超时,之前只需要2s就能完成的计算,现在却需要30+分钟。查了之后,我们发现,之所以计算超时是因为OpenCV计算的帧率为2000,从而导致需要计算的帧数量从之前的100变为了10000,进而引起了计算超时。

1、OpenCV 如何计算帧率

这个问题的具体描述可以参见 OpenCV Issues 21006[1]。该问题的模拟直播流片段test.ts可以点击链接下载:

https://pan.baidu.com/share/init?surl=RY0Zk5C_DOEwTXYe2SLFEg,下载提取码为x87m。

如果用如下的代码获取test.ts的fps,

const double FPS = cap.get(cv::CAP_PROP_FPS);
std::cout << "fps: " << FPS << std::endl;

可以得到:

$ fps: 2000

用ffprobe对视频进行分析,可以得到:

codec_name=h264
r_frame_rate=30/1
avg_frame_rate=0/0
……

从 opencv/modules/videoio/src/cap_ffmpeg_impl.hpp[2]中,我们发现fps由CvCapture_FFMPEG::get计算而来,其计算逻辑如下:

double fps = r2d(ic->streams[video_stream]->avg_frame_rate);
if (fps < eps_zero) {
    fps = 1.0 / r2d(ic->streams[video_stream]->codec->time_base);
}

2、为什么OpenCV得到的帧率是错的

利用test_time_base.cpp[3],我们可以得到:

time_base: 1/2000
framerate: 0/0
avg_framerate: 0/0
r2d(ic->streams[video_stream]->avg_frame_rate) = 0

所以OpenCV采用了:

1.0 / r2d(ic->streams[video_stream]->codec->time_base)

来计算该视频的fps。而此处的time_base = 1/2000,因此,最终得到的fps是2000。

也就是说,AVStream->codec->time_base的值导致了OpenCV得到一个看起来是错误的fps。那么,AVStream->codec->time_base为什么是这个值呢?FFmpeg是怎么计算这个字段的呢?

3、FFmpeg 如何计算

AVCodecContext.time_base

AVStream->codec->time_baseAVCodecContext中定义的 time_base字段,根据libavcodec/avcodec.h[4] 中的定义可知,对于解码而言,time_base已经被废弃,需要使用framerate来替换 time_base。并且,对于固定帧率而言,time_base = 1/framerate,但并非总是如此。

利用H264Naked[5]对test.ts对应的H.264码流进行分析,我们得到SPS.Vui信息:

timing_info_present_flag :1
num_units_in_tick :1
time_scale :2000
fixed_frame_rate_flag :0

从中可以看到,test.ts是非固定帧率视频。从test_time_base.cpp[3]的结果看,test.ts视频中,framerate = 0/0,而time_base = 1/2000

难道,对于非固定帧率视频而言,time_baseframerate之间没有关联?如果存在关联,那又是怎样的运算才能产生这

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值