目錄
前言
chromium是如何支持h265硬解
electron/chromium第一次編譯
electron/chromium第二次編譯
前言
我們的客戶端程序是用electron打包的前端程序,其在rk3588主機上的linux環境運行。之前使用客戶端查看h264編碼的視頻直播是沒有問題的,但視頻源更改為h265編碼后就不能查看了,奇怪的是打包的windows客戶端則可以正常查看,另外rk3588主機上的chromium瀏覽器也是支持播放h265編碼的視頻的,并且是硬件解碼。經過討論我們認為是electron編譯的問題,于是我便開始研究如何重新編譯electron以便在rk3588上支持h265,最終花費10天時間解決了這個問題,在此進行記錄。
chromium是如何支持h265硬解
首先我想先了解下chromium是如何支持h265硬解的,于是我在rk3588主機上手動找到chromium的執行命令,并增加了日志輸出,之后用chromium瀏覽器打開一個h265編碼的視頻并查看輸出的日志。
/usr/lib/chromium/chromium-bin --use-gl=egl --no-sandbox --gpu-sandbox-start-early --ignore-gpu-blacklist --ignore-gpu-blocklist --enable-remote-extensions --no-default-browser-check --enable-webgpu-developer-features --enable-unsafe-webgpu --show-component-extension-options --enable-gpu-rasterization --no-default-browser-check --disable-pings --media-router=0 --enable-accelerated-video-decode --enable-features=VaapiVideoDecoder,VaapiVideoEncoder --enable-logging=stderr --vmodule=*/media/*=5
從下面的日志輸出我們可以看到h265硬解碼是通過系統的v4l2接口來實現的,后面經過查資料,得到了在linux系統下進行視頻解碼的流程大體如下:
1)先嘗試進行硬解碼,硬解碼通過系統的vaapi接口或者v4l2接口實現。
2)硬解碼不支持則調用ffmpeg進行軟解碼。
其中vaapi主要用在x86架構上,v4l2主要用在arm架構上;另外雖然ffmpeg支持h265軟解,但谷歌因為專利原因在添加ffmpeg代碼時移除了h265軟解部分支持,所以chromium如果想支持h265解碼,必須使用h265硬解(當然我們也可以自己修改chromium/ffmpeg部分的代碼來實現軟解h265)。
[3948:4041:0124/150324.813554:VERBOSE4:v4l2_device.cc(2338)] DequeueEvent(): Failed to dequeue event: 沒有那個文件或目錄 (2)[3948:4041:0124/150324.814371:VERBOSE4:v4l2_device.cc(2338)] DequeueEvent(): Failed to dequeue event: 沒有那個文件或目錄 (2)[3948:3948:0124/150324.818244:VERBOSE2:v4l2_video_decode_accelerator.cc(801)] Flush():[3948:4041:0124/150324.819645:VERBOSE2:v4l2_video_decode_accelerator.cc(1628)] FlushTask():[3948:4041:0124/150324.820190:VERBOSE4:v4l2_device.cc(2338)] DequeueEvent(): Failed to dequeue event: 沒有那個文件或目錄 (2)[3948:4041:0124/150324.821289:VERBOSE2:v4l2_video_decode_accelerator.cc(956)] DecodeBufferTask(): enqueued flush buffer[3948:4041:0124/150324.839642:VERBOSE4:v4l2_device.cc(2338)] DequeueEvent(): Failed to dequeue event: 沒有那個文件或目錄 (2)[3948:4041:0124/150324.840585:VERBOSE2:v4l2_video_decode_accelerator.cc(1959)] StopOutputStream():[3948:4041:0124/150325.337913:VERBOSE2:v4l2_video_decode_accelerator.cc(1978)] StopInputStream():[3948:4041:0124/150325.836272:VERBOSE2:v4l2_video_decode_accelerator.cc(1715)] NotifyFlushDone(): returning flush[3948:3948:0124/150341.327350:VERBOSE2:v4l2_video_decode_accelerator.cc(817)] Destroy():[3948:4041:0124/150341.327903:VERBOSE2:v4l2_video_decode_accelerator.cc(1862)] DestroyTask():[3948:4041:0124/150341.328722:VERBOSE2:v4l2_video_decode_accelerator.cc(1959)] StopOutputStream():[3948:4041:0124/150341.328988:VERBOSE2:v4l2_video_decode_accelerator.cc(1978)] StopInputStream():[3948:4041:0124/150341.329202:VERBOSE2:v4l2_video_decode_accelerator.cc(2497)] DestroyInputBuffers():[3948:4041:0124/150341.331171:VERBOSE2:v4l2_video_decode_accelerator.cc(2510)] DestroyOutputBuffers():[3948:3948:0124/150341.336184:VERBOSE2:v4l2_video_decode_accelerator.cc(838)] Destroy(): Destroyed
electron/chromium第一次編譯
因為electron實際上是調用的chromium進行的視頻硬解碼,所以從上面了解了rk3588是通過v4l2接口實現的h265硬解之后我就開始嘗試第一次編譯electron了,編譯步驟參考構建說明 | Electron就不再贅述了。
我發現原來electron編譯時傳遞給chromium的默認參數是沒有打開v4l2的,怪不得rk3588下不支持h265硬解,所以在編譯electron時需要額外包含下面兩個與v4l2相關的參數
use_v4l2_codec = trueuse_v4lplugin=true
當我編完后便信心滿滿的讓前端同事驗證,結果卻仍然不行。之后為了驗證問題,我又用同樣的參數編譯了chromium,果然是無法打開,失落。
electron/chromium第二次編譯
經歷了上面的失敗,我已經做好了梳理chromium進行視頻解碼的代碼流程并打日志來逐步分析了,但我在解決另一個問題時看到了一位大佬給使用rk soc的系統上為chromium打的補丁,我找到了對應版本的chromium補丁后進行chromium和electron的編譯,這次為了驗證electron的支持,我先寫了一個簡單的測試程序test.js,內容如下
const { app, BrowserWindow } = require('electron');
const {execSync} = require('child_process')app.commandLine.appendSwitch('use-gl', 'egl');app.on('ready', () => {const win = new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: false, // 確保安全,不加載 Node.js},});// 加載 chrome://gpu 頁面win.loadURL('chrome://gpu');
});
運行后發現已經支持h265的硬解了,后面讓前端同事驗證,解決。
./electron test.js