欢迎关注微信公众号:FSA全栈行动 👋
项目需要在低端 Android 设备上驱动相机获取 YUV 图像,同时,还需要进行录像,YUV 图像的获取与处理之前已经趟过去了,总体感觉只要掌握了相机与 YUV 原理等知识点后,结合 libyuv 这个牛逼的库基本就没什么了,而录像这一块则是使用 MediaCodec + MediaMuxer
来处理,本篇就是我在使用原生 MediaCodec
编码 mp4 文件的踩杭记要,主要有两个问题:
- 录像变色 (video wrong color)
- 录像时长缩水(play too fast)
注:低端的 Android 设备硬件条件有多差呢?大概就是 2014 年 Android4.x 手机那种水平吧,CPU 处理速度很感人,对此,唯有硬编码才是王道。
一、录像变色
在探究该问题前,先来了解一下 MediaCodec
的两种编码模式:
ByteBuffer 模式
(手动档):- 格式:
COLOR_FORMAT
对应的值是MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar
(图像格式 NV21)。 - 操作:通过
MediaCodec.dequeueInputBuffer()
获取数据输入缓冲区,再通过MediaCodec.queueInputBuffer()
手动将 YUV 图像传给MediaCodec
。 Surface 模式
(自动档):- 格式:
COLOR_FORMAT
对应的值是MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
。 - 操作:通过
MediaCodec.createInputSurface()
创建编码数据源 Surface,再通过 OpenGL 纹理,将相机预览图像绘制到该 Surface 上。
1、现象
相机预览正常,但是录制出来的 mp4 视频颜色很阴间。
说明:就跟 YUV 图像把 u/v 颠倒之后的效果一样。
2、分析
ByteBuffer 模式
下,从相机处获取到原始的 NV21 图像,交给设置了 COLOR_FORMAT
为 COLOR_FormatYUV420SemiPlanar
的 MediaCodec
,结果在不同的 Android 设备上,有的正常,有的不正常(少数),刚开始以为是个别设备上不支持这种 COLOR_FORMAT