Android MediaCodec音视频转码实战:从零构建高效转码Demo
·
在移动端处理音视频时,MediaCodec是Android系统提供的底层编解码利器。相比跨平台的FFmpeg,它直接调用硬件加速,效率能提升3-5倍。今天记录下最近实现的转码Demo,分享关键实现和踩坑经验。

一、为什么选择MediaCodec?
- 硬件加速优势:直接调用芯片的DSP单元,H.264编码速度是软件方案的4倍
- 系统级集成:自动处理安卓版本兼容性问题,API Level 16+全支持
- 低延迟特性:直播推流场景下延迟可控制在200ms内
对比FFmpeg虽然功能全面,但在Android上需要NDK交叉编译,且CPU占用率高。实测转码1080P视频:
// 性能对比数据(Pixel 4 XL测试)
MediaCodec: 45fps CPU占用12%
FFmpeg: 18fps CPU占用65%
二、核心实现四步走
- 初始化编解码器 关键点在于选择合适的MIME类型和颜色格式:
val codec = MediaCodec.createDecoderByType("video/avc")
val format = MediaFormat.createVideoFormat("video/avc", width, height)
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible)
codec.configure(format, surface, null, 0)
- 输入输出缓冲区管理 采用异步回调更高效,注意处理BUFFER_FLAG_END_OF_STREAM:
codec.setCallback(object : MediaCodec.Callback() {
override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
val buffer = codec.getInputBuffer(index)
// 填充原始数据
codec.queueInputBuffer(index, ...)
}
override fun onOutputBufferAvailable(...) {
// 处理转码后数据
codec.releaseOutputBuffer(index, ...)
}
})
- 数据格式转换 YUV420P转NV21的优化写法:
void convertYUV420ToNV21(byte[] yuv420, byte[] nv21, int width, int height) {
// Y分量直接复制
System.arraycopy(yuv420, 0, nv21, 0, width*height);
// UV分量交错处理
for (int i=0; i<width*height/4; i++) {
nv21[width*height + i*2] = yuv420[width*height + i]; // U
nv21[width*height + i*2 +1] = yuv420[width*height*5/4 + i]; // V
}
}
- 异常处理三板斧
- 解码器不支持时fallback到其他MIME类型
- 配置失败检查是否缺少CSD(Codec Specific Data)
- 输出画面绿屏检查颜色格式是否匹配

三、性能优化实战技巧
- 缓冲区黄金法则:
- 输入缓冲区:根据帧率计算,如30fps视频设15帧缓存
-
输出缓冲区:参考分辨率,1080P建议≥2MB
-
异步模式陷阱: 必须处理callback的时序问题,建议用HandlerThread+同步锁:
val handlerThread = HandlerThread("CodecCallback")
handlerThread.start()
codec.setCallback(callback, Handler(handlerThread.looper))
- 硬件加速秘籍: 在Manifest声明硬件加速,并检测设备支持情况:
<application android:hardwareAccelerated="true">
四、常见坑位排查表
| 现象 | 原因 | 解决方案 | |-------|-------|-------| | 初始化崩溃 | 不支持的color format | 改用COLOR_FormatYUV420Flexible | | 输出花屏 | 未设置CSD数据 | 添加sps/pps到format | | 编码延迟高 | 未启用BITRATE_MODE_CBR | 设置目标码率和模式 |
五、扩展方向建议
- 动态码率调整:根据网络状况实时修改KEY_BITRATE
- 多轨道处理:音频同步用presentationTimeUs对齐
- 滤镜集成:结合GLSurfaceView实现实时特效
完整Demo已上传GitHub,包含如下模块:
app/
├── src/main/
│ ├── java/com/example/transcoder/
│ │ ├── VideoTranscoder.kt # 核心转码逻辑
│ │ └── Utils.kt # YUV转换工具
│ └── assets/test.mp4 # 测试视频
通过这次实践,深刻体会到MediaCodec就像精准的手术刀——用对地方威力无穷,但需要严格遵循操作规范。建议新手从官方CTS测试用例学起,逐步掌握这个强大的工具。
更多推荐


所有评论(0)