如何解决采集和编码速度不一致导致的卡顿问题?丨有问有答
编码 问题 如何 解决 速度 导致 采集 一致
2023-06-13 09:16:59 时间
今天我们要讨论的是关键帧的音视频开发圈的一位朋友在社群里提的问题,如下:
在使用关键帧公众号提供的 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、由于纹理缓存池梳理有上限,所以需要对纹理数据进行封装,增加标记字段用于标记当前纹理是否可用。一个纹理
可用
则表示相机采集来的数据可以拷贝到该纹理中,不可用
则表示该纹理数据在等待编码器拷贝去编码。编码器拷贝完缓存池的某一个纹理后,即标记该纹理为可用状态。
相关文章
- PyPDF2 编码问题 PyPDF2.utils.PdfReadError Illegal character in Name Object
- Python 接口测试之处理转义字符的参数和编码问题
- 解决MySQL字符编码问题:基本设置方法(mysql字符编码设置)
- MySQL设置:解决字符编码问题(mysql设置字符编码)
- PHP 换行编码问题详解编程语言
- php 将图片文件转成base64编码的方法详解编程语言
- Linux查询:探寻系统编码之旅(linux查询系统编码)
- 解决Linux环境下的UTF8编码乱码问题(utf8乱码linux)
- MySQL 解决中文编码问题(mysql中文编码)
- MySQL中文字符集编码问题导致的乱码处理(mysql存储的中文乱码)
- 如何正确连接MySQL并设置编码?教你解决编码问题。(连接mysql设置编码)
- 查看MS SQL数据库表编码设置的指南(查看mssql表编码设置)
- MySQL中使用ASCII编码的方法(mysql中上ascii)
- 解决Oracle数据库中全角半角编码问题(oracle全角的问题)
- MySQL编码问题无法存储中文字符(mysql 不能保存汉字)
- vbs或asp采集文章时网页编码问题
- jQueryajax在GBK编码下表单提交终极解决方案(非二次编码方法)
- PHP编码转换
- PHPutf-8编码问题,utf8编码,数据库乱码,页面显示输出乱码
- 解读赫夫曼树编码的问题
- MySql修改数据库编码为UTF8避免造成乱码问题