色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

OpenCV如何計算幀率?為什么OpenCV得到的幀率是錯的

LiveVideoStack ? 來源:LiveVideoStack ? 作者:王偉 ? 2022-07-10 14:11 ? 次閱讀

引言

我們有一個平臺來周期性地對線上的直播流數據進行某些檢測,例如黑/白屏檢測、靜態畫面檢測……在檢測中,我們會根據提取到的直播流的幀率來預估要計算的幀數量,例如,如果要檢測5s的直播流,而該直播流的幀率為20fps,需要計算的幀數量則為100。忽然有一天,我們發現,平臺開始大面積的超時,之前只需要2s就能完成的計算,現在卻需要30+分鐘。查了之后,我們發現,之所以計算超時是因為OpenCV計算的幀率為2000,從而導致需要計算的幀數量從之前的100變為了10000,進而引起了計算超時。

1、OpenCV 如何計算幀率

這個問題的具體描述可以參見 OpenCVIssues 21006。該問題的模擬直播流片段test.ts可以下載。

如果用如下的代碼獲取test.ts的fps,

poYBAGLKbeSAaNopAAAuOVfxEns488.jpg

可以得到:


poYBAGLKbfuAbFs4AAAQYV7WGYo987.jpg

用ffprobe對視頻進行分析,可以得到:

poYBAGLKbhaAKVX2AAAti0_kEmE794.jpg

從 opencv/modules/videoio/src/cap_ffmpeg_impl.hpp[2]中,我們發現fps由CvCapture_FFMPEG::get計算而來,其計算邏輯如下:

poYBAGLKbiuAI6X5AABXELvlcvk539.jpg

2、為什么OpenCV得到的幀率是錯的

利用test_time_base.cpp,我們可以得到:

pYYBAGLKbkuAULEkAABCUgODDTE510.jpg

所以OpenCV采用了:

poYBAGLKbmGAGkZsAAAllRH5Zl8997.jpg

來計算該視頻的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對test.ts對應的H.264碼流進行分析,我們得到SPS.Vui信息

pYYBAGLKbnmACCeeAAA9aIKdKvE771.jpg

從中可以看到,test.ts是非固定幀率視頻。從test_time_base.cpp的結果看,test.ts視頻中,framerate = 0/0,而time_base = 1/2000。

難道,對于非固定幀率視頻而言,time_baseframerate之間沒有關聯?如果存在關聯,那又是怎樣的運算才能產生這種結果?這個 time_base究竟是怎么計算的呢?究竟和framerate有沒有關系呢?一連串的問題隨之而來……

源碼面前,了無秘密。接下來,帶著這個問題,我們來一起分析一下FFmpeg究竟是如何處理time_base的。

3.1 avformat_find_stream_info

在 FFmpeg中,avformat_find_stream_info()對ic->streams[video_stream]->codec進行初始化,因此我們可以從avformat_find_stream_info()開始分析。

從libavformat/avformat.h[6]中,可以得知avformat_open_input()會打開視頻流,從中讀取相關的信息,然后存儲在AVFormatContext中,但是有時候,此處獲取的信息并不完整,因此需要調用avformat_find_stream_info()來獲取更多的信息。

需要注意的是:

avformat_find_stream_info()會嘗試通過解碼部分視頻幀來獲取需要的信息。

pYYBAGLKbpuACU-OAAFvaXlDwMM491.jpg

avformat_find_stream_info()的整體邏輯大致如下圖所示,其中特別需要關注圖中所示的 7 個步驟:

18323f4a-f395-11ec-ba43-dac502259ad0.png

3.2 avformat_find_stream_info()的重要步驟說明

STEP 1 設置線程數,避免H.264多線程解碼時沒有把SPS/PPS信息提取到extradata。

STEP 2 設置AVStream *st,st會在后續的函數調用中一直透傳到try_decode_frame()。

STEP 3比較簡單,這里不再贅述。

STEP 4 設置AVCodecContext *avctx為透傳的st->internal->avctx,在后續的解碼函數調用中,一直透傳的就是這個avctx,因此,從這里開始的執行流程,FFmpeg使用的全部都是st->internal->avctx,而不是st->codec,這里要特別的注意。此處同時會設置解碼的線程數,其目的和STEP 1是一致的。

STEP 5 因為之前設置了解碼線程數為1,所以此處會調用

poYBAGLKbrmAEnYJAAAmOUueAUc640.jpg

來解碼并計算avctx->framerate。注意,此處的avctx實際上是透傳而來的st->internal->avctx。計算 framerate的邏輯會在如何計算framerate部分介紹。

STEP 6 根據解碼器得到的framerate信息來計算 avctx->time_base,注意此處實際上是st->internal->avctx->time_base。根據如何計算framerate可知,此處framerate ={1000, 1}。根據 AVCodecContext.ticks_per_frame的介紹可知,ticks_per_frame = 2。因此,此處avctx->time_base ={1, 2000}

poYBAGLKbtiAEgh1AAAsnPPBFX4256.jpg

STEP 7 這一步可謂是“瞞天過海,明修棧道暗度陳倉”。這一步為了解決API的前向兼容,做了一個替換,把st->internal->avctx->time_base 賦值給了st->codec->time_base,而把st->avg_frame_rate 賦值給了 st->codec->framerate。因此:

poYBAGLKbvGAcVdEAAAujpRKHpU924.jpg

st->codec->time_base 的計算和 st->codec->framerate 之間沒有任何關系,而是和 st->internal->avctx->framerate 有關。究其本質,是和sps.time_scale,sps.num_units_in_tick有關。

poYBAGLKbwiAcIT3AACYM6YWuDM639.jpg

3.3 internal->avctx->time_base &internal->framerate

所以實際上,internal->avctx->time_base為:

poYBAGLKbx2AKVh1AAAnCR3AyEQ492.jpg

internal->avctx->framerate則是:

pYYBAGLKbzWALc5gAAAz1oBC9e8359.jpg

因此,對于 H.264 碼流而言,time_base = 1 / (2 * framerate),而不是1 /framerate。

這也就是為什么

libavcodec/avcodec.h中說:

poYBAGLKb0qALyHaAAAwixex044253.jpg

從如上的分析可以知道:

poYBAGLKb1-ABPUAAAAqzKCjdzc393.jpg

因此,當st->avg_frame_rate = 0時,OpenCV計算fps的邏輯是錯誤的。

在H.265中,ticks_per_frame = 1,因此對于H.265的編碼,OpenCV是沒有這個問題的。可以使用Zond 265 工具來分析一個 H.265的視頻碼流,然后對照OpenCV以及FFmpeg的結果來驗證。

同時,正是如上所示的STEP 7中的移花接木導致了 test_time_base.cpp[3]的結果:

poYBAGLKb3GAT1ZUAAAk58dn75E010.jpg

3.4 ff_h264_decoder

libavcodec/decode.c[8]中的

decode_simple_internal()會調用對應的解碼器來進行解碼(STEP5)。而正如前所示,test.ts為H.264 編碼的視頻流,因此此處會調用 H.264 解碼器來進行解碼。在FFmpeg中,H.264解碼器位于 libavcodec/h264dec.c[9]中定義的

const AVCodec ff_h264_decoder。

pYYBAGLKb4eAY5HlAACFcLzfijE382.jpg

在上文圖中的STEP 5中,

pYYBAGLKb6CATzx4AAAkaD_IIu0097.jpg

實際調用的就是:

poYBAGLKb6uAIwnKAAAowwXYUW8449.jpg

而此處的avctx也就是

try_decode_frame()中透傳下來的st->internal->avctx,即上文圖中的STEP4。

3.5 h264_decode_frame

h264_decode_frame()的整體邏輯如下圖所示:

1843489e-f395-11ec-ba43-dac502259ad0.png

3.6 AVCodecContext.ticks_per_frame

后面會用到ticks_per_frame來計算framerate。在STEP6中計算 time_base的時候也用到了該值。因此,有必要做一下特殊說明。在H.264解碼器中,ticks_per_frame=2,其具體的取值可以從如下幾處得知:

libavcodec/avcodec.h 中的字段說明:
pYYBAGLKcA2AWE2nAAAHKIAypyw750.jpg

pYYBAGLKb_2AaNQIAACWmNuOT3M189.jpg

libavcodec/h264dec.c 中的h264_decode_init():

pYYBAGLKcCyABU9TAAAWlJlnRwA260.jpg

4、如何計算framerate

STEP 1 根據整體的計算流程可知,此處的h實際上就是

avformat_find_stream_info()中的

st->internal->avctx->priv_data。h會一直透傳到之后的所有流程,這個務必要注意。

STEP 2此處會首先獲取到sps的相關信息,以備后續的計算使用,我們可以再次看一下test.ts sps的相關信息。


poYBAGLKcD-AExUjAAA6wl5psTM781.jpg

STEP 3根據sps的相關信息計算framerate,在上文的STEP 6中計算 time_base用到的framerate就是在此處計算的。因為 timing_info_present_flag = 1,因此會執行計算framerate的邏輯:

poYBAGLKcHOASLy5AABTs8_Z5CA584.jpg

因此,


poYBAGLKcIaACzyLAAAiT55R4Bc385.jpg

但是,因為avctx->time_base={1,2000},所以OpenCV計算出來的幀率結果為2000。導致這種不一致的原因在于,OpenCV在使用codec->time_base計算幀率的時候沒有考慮ticks_per_frame。因此,對于OpenCV而言,正確的計算幀率的方式應該為:

pYYBAGLKcLqAQ0NsAABuzSEFKxQ944.jpg


結論

通過上面的分析我們可以知道:

FFmpeg在計算 AVCodecContex 中的frameratetime_base的時候,會用到:

o sps.time_scale

o sps.num_units_in_tick

o AVCodecContex.ticks_per_frame

在 FFmpeg 中,frameratetime_base的關系為:

o framerate = 1 / (time_base *ticks_per_frame)

o time_base = 1 / (framerate *ticks_per_frame)

對于非 H.264/MPEG-2,

ticks_per_frame=1,因此frameratetime_base是互為倒數的關系。而對于H.264/MPEG-2 而言,ticks_per_frame=2,因此,此時二者并非是互為倒數的關系。因而,FFmpeg 中才說,frameratetime_base通常是互為倒數的關系,但并非總是如此。

在OpenCV中,對于H.264/MPEG-2視頻而言,當

AVStream.avg_frame_rate=0時,其計算fps的邏輯存在BUG。

因為在解碼時,

AVCodecContex.time_base已經廢棄,同時 AVStream.avctx也已經廢棄,而

avformat_find_stream_info()中為了兼容老的API,因此會利用 AVStream.internal.avctx和其他的信息來設置AVStream.avctx。而AVStream.avctx.time_base取自AVStream.internal.avctxAVStream.avctx.framerate 則取自 AVStream.framerate。

審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • H.264解碼器
    +關注

    關注

    0

    文章

    2

    瀏覽量

    6319
  • OpenCV
    +關注

    關注

    31

    文章

    635

    瀏覽量

    41343
  • ffmpeg
    +關注

    關注

    0

    文章

    46

    瀏覽量

    7398

原文標題:為什么OpenCV計算的幀率是錯誤的?

文章出處:【微信號:livevideostack,微信公眾號:LiveVideoStack】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    【NanoPC-T4試用體驗】GPU測試+OpenCV配置

    ` 本帖最后由 獵國傾城 于 2018-11-12 13:03 編輯 1.測試OpenGL ES性能這個主要測一下GPU的性能。主要有紋理、渲染,抗鋸齒等方面的測試,每一項測完,都顯示該項的幀率
    發表于 11-12 13:03

    RK3399開發板上linux下qt+opencv通過videocapture調用uvc免驅相機,幀率低且無法更改

    1.通過終端:v4l2-ctl --list-devices顯示:/dev/video0/dev/video1顯示兩個設備,其實只接一個相機,這里猜測可能是兩個視頻格式。2.通過qt配置opencv
    發表于 05-22 10:47

    怎樣去解決RK3588 HDMIin輸入顯示幀率很低的問題呢

    opencv感覺),目測幀率10幀以下  3. 用gstreamer, v4l2src 到 autovideosink,目測幀率也是10幀以下  感覺以rk3588的性能不該如此,目前是最新的固件?;蛟S是我
    發表于 07-20 16:25

    基于OpenCV計算機視覺技術實現

    基于OpenCV計算機視覺技術實現OpencV是用來實現計算機視覺相關技術的開放源碼工作庫,是計算機視覺、圖像處理、模式識別、
    發表于 11-23 21:06 ?0次下載
    基于<b class='flag-5'>OpenCV</b>的<b class='flag-5'>計算</b>機視覺技術實現

    opencv備忘單

    opencv備忘單,opencv_cheatsheet,opencv_tutorials,opencv_user,opencv2refman
    發表于 08-25 15:52 ?0次下載

    opencv基礎的學習手冊

    OpenCV (Open Source Computer Vision Library: http://opencv.org) is an open-source BSD-licensed
    發表于 08-25 15:52 ?0次下載

    The OpenCV User Guide

    The OpenCV User Guide Release 2.4.8.0,英文版OpenCV的用戶指南。
    發表于 08-26 14:12 ?0次下載

    計算機視覺應用之OpenCV基礎教程

    Library,OpenCV)。OpenCV優化了許多功能函數,并在實時的計算機視覺程序中得到應用。但是,由于嵌入式優化策略得天獨厚的優勢,仍然值得大家嘗試利用邏輯硬件來加速
    發表于 11-18 04:45 ?9234次閱讀
    <b class='flag-5'>計算</b>機視覺應用之<b class='flag-5'>OpenCV</b>基礎教程

    如何安裝和配置OpenCVOpenCV的幾個小問題解答

    本文檔的主要內容詳細介紹的是如何安裝和配置OpenCVOpenCV的幾個小問題解答包括了:安裝和配置OpenCV,Highgui.h與CvvImage類的問題:,如何通過攝像頭獲取視頻:,如何播放AVI視頻
    發表于 12-17 17:25 ?9次下載
    如何安裝和配置<b class='flag-5'>OpenCV</b>及<b class='flag-5'>OpenCV</b>的幾個小問題解答

    OpenCV的起源和應用領域

    因此,OpenCV的目的是開發一個普遍可用的計算機視覺庫。在Intel的性能庫團隊的幫助下,OpenCV實現了一些核心代碼以及算法,并發給Intel俄羅斯的庫團隊。
    的頭像 發表于 08-28 10:53 ?7811次閱讀

    基于OpenCV如何提取中心線

    問題 前幾天有個人問了我一個問題,問題是這樣的,他有如下的一張二值圖像: 怎么得到白色Blob中心線,他希望的效果如下: 顯然OpenCV中常見的輪廓分析無法獲得上面的中心紅色線段,本質上這個問題是
    的頭像 發表于 04-26 13:51 ?3770次閱讀

    計算機視覺中如何調用OpenCV

    學習計算機視覺最重要的能力應該就是編程了,為了幫助小伙伴盡快入門計算機視覺,小白準備了【走進OpenCV】系列,主要幫助小伙伴了解如何調用OpenCV庫,涉及到的知識點會做簡單講解。
    的頭像 發表于 09-08 10:26 ?4941次閱讀

    LVGL 優化幀率技巧

    目錄標題前文LVGL幀率限制代碼優化等級前文LVGL——PC模擬器仿真模擬+VS2017f429 discovery開發版 LVGL移植(帶操作系統)首先就個人用過的幾個芯片而言,可能還是要F4系列
    發表于 12-07 13:21 ?15次下載
    LVGL 優化<b class='flag-5'>幀率</b>技巧

    OpenCV配置CUDA以支持GPU加速

    最近在做OpenCV相關的項目時發現,在跑dnn模型時如果單純只使用cpu幀率會非常低,有時甚至一兩秒才刷一幀的圖像出來,需要使用硬件加速,所以在各大論壇等翻閱使用GPU加速的教程,可惜非常雜,而且
    的頭像 發表于 01-09 10:16 ?5204次閱讀

    opencv-python和opencv一樣嗎

    不一樣。OpenCV(Open Source Computer Vision Library)是一個開源的計算機視覺和機器學習軟件庫,它提供了大量的圖像和視頻處理功能。OpenCV
    的頭像 發表于 07-16 10:38 ?1167次閱讀
    主站蜘蛛池模板: 色综合久久久久久| 久久se视频精品视频在线| 被免费网站在线视频| 91国内精品久久久久免费影院| 野花韩国高清完整版在线观看5 | 东北老妇人70OLDMAN| 啊轻点灬大JI巴又大又粗| 99久久精品免费看国产免费| 91久久精品国产亚洲| 2022国产精品不卡a| 3D内射动漫同人资源在线观看| 洲精品无码高潮喷水A片| 中文字幕在线观看网站| 最新无码专区在线视频| 中文字幕无码乱人伦蜜桃| 4388成人| XXXchinese国产HD| 成人无码在线超碰视频| 国产精品大全国产精品| 国产亚洲精品看片在线观看| 好男人好资源在线播放| 久久精品视在线-2| 蜜芽一二三区| 日本亚洲电影| 亚洲h视频在线观看| 在线精品一卡乱码免费| 91天堂国产在线 在线播放| 阿片在线播放| 国产精品99久久久久久AV| 户外插BBBBB| 免费韩国伦理2017最新| 起碰免费公开97在线视频| 偷尝禁果H1V1幸运的山熊| 亚洲精品中文字幕一二三四区| 在线A亚洲老鸭窝天堂AV高清| 99re10久久热| 国产精品高潮呻吟AV久久96| 黄页网站免费视频大全9| 男人天堂999| 偷拍 自怕 亚洲 在线| 一边吃奶一边添P好爽故事|