限时福利领取


最近在项目中需要处理视频转码功能,调研了多种方案后最终选择使用 Android 原生的 MediaCodec API。今天就来分享一下我的实战经验,希望能帮助到同样需要做视频重编码的开发者。

视频处理示意图

为什么选择 MediaCodec?

在移动端处理视频时,我们常常遇到以下痛点:

  • 性能问题:软件编码器(如 FFmpeg)CPU 占用率高
  • 功耗问题:长时间编码导致手机发热严重
  • 兼容性问题:不同厂商设备表现差异大

MediaCodec 作为 Android 系统提供的硬件编解码接口,相比 FFmpeg 有三个明显优势:

  1. 硬件加速:直接调用芯片厂商的编解码器
  2. 低功耗:专用电路处理,CPU 占用低
  3. 系统级优化:Google 和厂商共同维护

核心实现步骤

1. 初始化编解码器

// 创建编码器
val encoder = MediaCodec.createEncoderByType("video/avc")
val format = MediaFormat.createVideoFormat("video/avc", width, height)
format.setInteger(MediaFormat.KEY_BIT_RATE, bitrate)
format.setInteger(MediaFormat.KEY_FRAME_RATE, fps)
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval)
format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface)
encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)

2. 输入输出缓冲区管理

MediaCodec 有两种工作模式:

  1. 同步模式:适合简单场景
  2. 异步模式:性能更好,推荐使用

缓冲区处理流程

// 异步模式示例
encoder.setCallback(object : MediaCodec.Callback() {
    override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
        val buffer = codec.getInputBuffer(index)
        // 填充视频数据
        codec.queueInputBuffer(index, ...)
    }

    override fun onOutputBufferAvailable(codec: MediaCodec, index: Int, info: MediaCodec.BufferInfo) {
        val buffer = codec.getOutputBuffer(index)
        // 处理编码后的数据
        codec.releaseOutputBuffer(index, false)
    }
})

性能优化技巧

经过多次测试,我总结了几个关键优化点:

  1. 色彩空间转换
  2. 优先使用 COLOR_FormatYUV420Flexible
  3. 避免多次色彩空间转换

  4. 内存复用

  5. 复用 ByteBuffer 对象
  6. 使用 Surface 输入避免内存拷贝

  7. 参数调优

  8. 根据设备性能动态调整 BITRATE_MODE
  9. 合理设置 KEY_FRAME_RATE

常见坑点

在适配不同 Android 版本时,我遇到了这些问题:

  • Android 5.0 以下:某些 COLOR_FORMAT 不支持
  • 华为设备:需要特殊处理编解码器名称
  • 三星设备:Surface 输入有时会丢帧

解决方案是做好设备检测和降级处理:

fun isFormatSupported(codecInfo: MediaCodecInfo, mime: String, format: Int): Boolean {
    return codecInfo.getCapabilitiesForType(mime)
        .colorFormats.any { it == format }
}

测试建议

最后分享下我的性能测试方法:

  1. 使用 adb shell dumpsys media.codec 查看实际使用的编解码器
  2. 通过 Systrace 分析帧处理耗时
  3. 监控温度变化和 CPU 使用率

对于想进一步优化的同学,可以研究下:

  • 使用 MediaCodec 的异步模式
  • 尝试 H265 编码
  • 结合 MediaMuxer 实现流式输出

希望这些经验对你有所帮助,欢迎在评论区交流你遇到的问题和解决方案!

Logo

音视频技术社区,一个全球开发者共同探讨、分享、学习音视频技术的平台,加入我们,与全球开发者一起创造更加优秀的音视频产品!

更多推荐