目录
前言
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 = true
use_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