Skip to end of metadata Go to start of metadata
1 背景
Mesa对 Linux 内核 DRM/KMS 标准化图形架构的适配和其规范统一的底层接口能力,使得其成为了 Linux 平台默认图形栈。在此基础上,各大主流 GPU 厂商纷纷跟进适配 Mesa,进一步巩固了其在 Linux 图形生态的主导地位。依托 Android 开源社区的持续适配迭代,Mesa 及其配套 GBM 缓存管理组件已完整移植至 Android 生态,这也使得所有采用 Mesa GPU 方案的 PC 端 Android 适配项目,均无法绕开该套图形架构,OpenFDE 同样沿用该通用技术方案。但这套方案和Android原生图形栈设计存在一定的架构差异。GBM 框架的设计定位主要面向 3D 图形渲染场景,原生仅支持渲染专用格式,并未适配视频编解码所需的 YUV 等视频格式。而Android图形缓存框架为一体化设计,统一兼顾3D图形渲染与视频编解码两类场景的缓存分配。为适配 Android 视频业务需求,当前 GBM Gralloc 模块采用的方案是通过 GR88 格式模拟 YUV12 视频缓存,以此勉强兼容 Android 视频编解码流程。 这种格式模拟的兼容方式存在严重的底层适配问题,引发了两类典型故障:一是显存未按要求gpu要求的字节宽度对齐,导致系统内核与 GPU 驱动异常、内核卡死;二是视频缓存格式解析错乱,直接造成视频画面花屏、色彩异常等问题,极大影响 Android 视频编解码业务的稳定性与可用性。
2. 缓存申请流程分析
下面以抖音app为例子分析YUV12 图形缓存申请、使用和合成显示流程
图1 视频缓存申请与显示流程示意图
- 抖音通过调用dequeue_buffer 向gbm gralloc申请YUV格式的buffer
- gbm gralloc分配buffer,将fd句柄返回给抖音。
- 抖音调用lock_ycbcr方法,将解码后的YUV视频数据,存入buffer
- vsync到来后,surfaceflinger对这个buffer做合成,
- 合成结果最终存入到Frame buffer。
- frame buffer送到显示器进行显示。
3 缓存宽度256字节对齐问题解决方案
从以上流程可以看到,要做到字节宽度对齐,我们需要在gbm gralloc中来完成。
图2 gbm未做对齐 图3 主动做256字节对齐
4 抖音视频花屏问题解决方案
如上图所示的花屏问题在数据对齐后依然存在。一开始我们以为这是因为应用未能适配stride参数导致的。因为我们尝试抓取一帧buffer数据,放到7yuv工具中查看,且设置视频宽度为1024(256对齐后),则能看到左半边正常,右半边花屏的数据,
如下图所示。
左半边正常,右半边花屏示意图
分析到这里,以为app的数据存放忽略了stride导致。所以我们曾在sf的合成逻辑中,主动做了一些对齐再裁剪来解决该问题。但是最终发现其实是gbm gralloc的lock_ycbcr方法中stride的赋值未按照hnd句柄的实际值返回给应用,
而是做了一个16字节的对齐。
正是由于这个原因,app未能接收到正确的stride值。从而导致数据存放错误,引发了视频花屏问题。此处是修复stride值的代码提交链接。
5 总结
代码维护者在日志中提及16字节对齐的测试只在medaswcodec 的software上进行了。所以现在也不确定我们的这种修改是否对其他gpu兼容。如果有兼容问题,欢迎大家往我们的仓库--github.com/openfde/har…提pr。