用Qt5的Qpainter畫視頻解碼的圖像,發現CPU佔用極高(50%),有方法能夠降低cpu佔用嗎?

使用Qt5畫解碼的視頻圖像,通過槽函數運行update方法觸發paintevent重繪,CPU佔用率極高,有沒有方法降低CPU使用率,能否使用QOpenGL的硬體加速渲染來降低CPU佔用?


qt widgets用的是cpu渲染,而不是gpu,性能並不優秀,只適合用來做界面,而不是做多媒體。

做多媒體的話,qt有專門封裝的QtMultiMedia類庫。其中包含了音頻、視頻、攝像解碼、處理、播放。其中有專門用於播放的控制項。

總之,盡量不要手擼paintEvent

——————————

另,還可以借用第三方更專業的庫。比如ffmpeg+opencv。

qt+opencv聯合開發gui是很常見的,網上不難搜到教程

最後,另一位答主推薦的方法是最好的,用QOpenGlWidget,這個類的繪製操作是通過opengl渲染,走的就是gpu,而不是常規QWidget那樣走cpu


用QOpenGLWidget(不要用QGLWidget,高DPI有坑),在它的paintEvent中以smooth模式畫drawImage,定時update,最簡單高效


使用QPainter繪製視頻圖像不是一個好的解決方案:

1、YUV / RGB 轉換費CPU

2、QPainter大面積繪製效率不高

OpenGL是一個不錯的選擇,目前移動設備上很多都是用GLES實現視頻渲染。

大概思路是:

創建一個texture

實現一個shader用於YUV / RGB 轉換

每次渲染將視頻數據update到texture

將texture繪到一個表面


50% 還極高啊……我還見過 2000% 的呢。

視頻的話,上專業工具試試?


正如依雲所說的一樣,佔用50%的cup不能肯定是演算法沒有優化。

圖形的東西就是耗費cup,所以很多qt的模擬器軟體都上幾百個cpu的。


qt creator自己有profile,跑一下看看是不是繪製函數耗時。

qt自帶圖形繪製的效率本來就比較差,甚至在幾百個表格控制項刷新的情況下就開始卡了。

不過就我的經驗,僅僅貼圖上去不解碼,我覺得qt自帶引擎的性能還是應該夠的。當然得看你的解析度了,以及update的頻率了。

另外qt有opengl widget,嘗試直接用opengl代替你的繪製看看。


QPainter 不是用來渲染視頻的,是用來自繪 GUI 的,它在 Windows 中底層應該使用了 GDI,缺乏顯卡加速,性能達不到繪製視頻的要求。另外,視頻繪製也不應該使用事件驅動,使用事件驅動會讓繪製操作運行在主線程里,這有可能阻塞 UI 事件響應,顯然是不合理的。

使用 Qt 繪製視頻有兩個選擇,要麼使用 QGLWidget,要麼拿到 widget 的窗口句柄(好像是 winid() 這個函數的返回值)或者窗口位置,配合其他工具(opengl、directx等,在 linux 中我推薦試試 SDL,介面比較友好)自行繪製。


RGB/YUV變換在手機端還有個問題就是費時

例如1280*960的圖像做yuv-&>rgb變換,在普通android手機上約需30ms~100ms

具體到使用opengl直接渲染yuv數據,大致步驟上面有答主已經答了,我來上一點具體代碼

1. shader部分可以參考webrtc 的render實現部分,open_gles20.mm (鏈接需翻牆),在shader中做YUV -&> RGB565變換。(需要注意Y/U/V uniform的綁定)

這部分代碼是基於GLES20的,可以直接搬到Qt中。

2. Qt中QOpenGLWidget 支持GLES20,參考Qt中的example程序即可


請問樓主是如何顯示cpu佔用的呢


解碼後的數據,是否是通過memcpy放到緩存中,然後paintEvent再通過緩存中畫到屏幕上QPainter?

memcpy會耗很多CPU的。QT並沒有想VC那種雙緩衝機制,這樣數據必須在paintEvent中準備好,不需要拷貝數據等,才能節省CPU,很難辦到。


沒有人提到用gstreamer嗎?難道就我一個人這麼干?

用Qt做了界面,用Gst做的後端,看視頻,放電影,聽音樂,一樣都不少。

Qt 5以後也有多媒體的支持了,沒用過。我還是用的4.8,所以只能自己找個後台啦


推薦閱讀:

如何用 C++ 在 GUI 中畫出各種平衡樹插入刪除的動態變化?
Qt多線程編程中子線程如何調用主線程中的成員變數?
MFC、Qt、WPF?該用哪個?

TAG:編程 | QtC開發框架 | QtProject |