如何解决采集和编码速度不一致导致的卡顿问题?丨有问有答
2023-03-07 09:12:19 时间
今天我们要讨论的是关键帧的音视频开发圈的一位朋友在社群里提的问题,如下:
在使用关键帧公众号提供的 Android 视频封装的 Demo 时发现一个问题:相机采集的数据使用 Surface 编码时,如果采集数据输出的纹理和编码器使用的纹理是共享一个纹理,由于采集和编码在两个线程上,如果编码速度跟不上采集速度,就有可能出现编码还在编第 1 帧时,相机已经采集好第 2、3、4、5 帧并把共享纹理的数据更新为第 5 帧了,编码器编码完第一帧后取到的数据是第 5 帧,这样录制的视频看起来就会卡顿,这种情况有什么优化方案吗?
以下是回答,欢迎大家留言讨论补充:
这里先介绍一下这个问题的背景:在我们提供的 Android 视频封装的 Demo 中,使用 KFSurfaceTexture 录制 MP4 文件并使用 Surface 编码时大致过程如下:
- 1、相机采集输出数据,会更新到相机的 OES 纹理上,这个纹理的 id 是
mSurfaceTextureId
。 - 2、当采集完一帧数据时,相机关联的 SurfaceTexture 会回调一次
onFrameAvailable
方法,这里会拼装一帧KFTextureFrame
数据,其中包含了纹理mSurfaceTextureId
。这帧KFTextureFrame
数据一方面会给预览渲染展示,同时也会送给编码器KFVideoSurfaceEncoder
。 - 3、在
KFVideoSurfaceEncoder
中会新起一个线程进行编码,将纹理mSurfaceTextureId
绘制到 MediaCodec 绑定的 Surface,绘制完成后通过mEGLContext.swapBuffers
通知 MediaCodec 数据已经准备好,可以开始编码。
由于整个流程中相机采集模块和编码模块是共用了纹理 mSurfaceTextureId
,而采集和编码又是在不同的线程,所以就可能出现题目中出现的因为采集和编码速度不一致导致最后录制的视频看起来丢帧了所以卡顿的问题。
要优化这个问题可以做一个纹理缓存池给相机和编码器共用:
- 1、创建一个 FBO,通过 FBO 切换绑定纹理来实现将纹理 a 的数据绘制到纹理 b,这里面有两种场景:
- 将相机输出的纹理数据拷贝到纹理缓存池一个空闲纹理上
- 将纹理缓存池中的待编码纹理数据绘制到 MediaCodec 绑定的 Surface 上
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENTO, GL_TEXTURE_2D, textureID, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
// error
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
- 2、纹理缓存池的纹理数量需要设置一个上限,当纹理缓存池没有空闲可用纹理时,则需要做丢帧策略清空某些纹理。这里的丢帧策略可以对缓存池中的待编码纹理做均匀丢帧,尽量提升画面流畅度。
- 3、由于纹理缓存池梳理有上限,所以需要对纹理数据进行封装,增加标记字段用于标记当前纹理是否可用。一个纹理
可用
则表示相机采集来的数据可以拷贝到该纹理中,不可用
则表示该纹理数据在等待编码器拷贝去编码。编码器拷贝完缓存池的某一个纹理后,即标记该纹理为可用状态。
相关文章
- 在 Go 里用 CGO?这 7 个问题你要关注!
- 9款优秀的去中心化通讯软件 Matrix 的客户端
- 求职数据分析,项目经验该怎么写
- 在OKR中,我看到了数据驱动业务的未来
- 火山引擎云原生大数据在金融行业的实践
- OpenHarmony富设备移植指南(二)—从postmarketOS获取移植资源
- 《数据成熟度指数》报告:64%的企业领袖认为大多数员工“不懂数据”
- OpenHarmony 小型系统兼容性测试指南
- 肯睿中国(Cloudera):2023年企业数字战略三大趋势预测
- 适用于 Linux 的十大命令行游戏
- GNOME 截图工具的新旧截图方式
- System76 即将推出的 COSMIC 桌面正在酝酿大变化
- 2GB 内存 8GB 存储即可流畅运行,Windows 11 极致精简版系统 Tiny11 发布
- 迎接 ecode:一个即将推出的具有全新图形用户界面框架的现代、轻量级代码编辑器
- loongarch架构介绍(三)—地址翻译
- Go 语言怎么解决编译器错误“err is shadowed during return”?
- 敏捷:可能被开发人员遗忘的部分
- Denodo预测2023年数据管理和分析的未来
- 利用数据推动可持续发展
- 在 Vue3 中实现 React 原生 Hooks(useState、useEffect),深入理解 React Hooks 的