1. 编解码器基础与碎片化背景

1.1 MediaCodec 框架概述

Android 的媒体编解码能力由 android.media.MediaCodec 类集中提供,它是 NDK 与 SDK 两套 API 的底层核心。应用通过 MediaCodec 可以访问设备硬件加速的编码器与解码器,而无需直接操作 OpenMAX IL 或 Codec2 HAL 层。

属性说明
输入/输出缓冲区应用从输入队列提交 ByteBuffer,从输出队列获取已解码/编码的帧
状态机Stopped → Executing → Flushed → End-of-Stream 等状态切换
Codec vs Codec2Android 10 起 Codec2 逐步替代旧 MediaCodec,但仍需同时兼容
异步/同步模式同步:dequeueInputBuffer + queueInputBuffer;异步:setCallback + 回调线程

典型初始化流程(同步模式):

MediaCodec codec = MediaCodec.createDecoderByType(mimeType);
MediaFormat format = MediaFormat.createVideoFormat(mimeType, width, height);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
codec.configure(format, surface, null, 0);
codec.start();
// 循环:dequeueInputBuffer -> 填入数据 -> queueInputBuffer -> dequeueOutputBuffer -> 释放

1.2 厂商差异:HAL 栈实现分裂

Android 编解码器 HAL 存在两套历史实现:

  • OMX(OpenMAX IL) – 早期标准,高通、MTK、三星各自适配,Bug 多
  • Codec2(C2) – Android 10+ 推荐的模块化架构,但旧设备仍使用 OMX

不同 SoC 厂商对 H.264, H.265, VP9, AV1 的支持深度完全不同,即使同样是 H.264,分辨率上限、B‑frame 数量、profile/level 也存在差异。

典型碎片化表现: 一款手机支持 4K H.264 硬解,另一款只能到 1080p;同一台设备在 Android 9 上可正常硬解,升级 Android 11 后偶发解码黑屏。

1.3 碎片化典型表现

分类具体问题影响范围
编解码器列表差异getCodecInfo() 返回不同数量、不同名称的解码器播放器/录制器选型报错
分辨率/帧率上限部分厂商限制 4K 解码仅支持 30fps,或 1080p 编码最高 48fps直播推流、本地回放花屏
颜色格式不兼容COLOR_FormatYUV420Planar vs COLOR_FormatYUV420SemiPlanar 混用纹理上传、GPU 滤镜崩溃
H.265 / VP9 缺失低端机型没有硬件 HEVC/VP9 解码器视频无法播放或回退软解卡顿
B‑frame 排序异常OMX 实现输出解码帧顺序不保证按 PTS 递增timedText 字幕错位
回调线程死锁异步模式下 onOutputBufferAvailable 中调用 releaseOutputBuffer 超时界面无响应
避坑: 不要依赖 MediaCodecList.getCodecInfoAt() 返回的顺序;部分国产机型会隐藏自适应解码器(Adaptive Playback),仅暴露“OMX.google.*”软解,导致硬解降级。

1.4 调试手段:获取设备编解码器能力

使用 adb shell dumpsys media.codec 可以列出所有注册的 Codec 以及每个 Codec 支持的 MIME、分辨率、帧率范围。从 Android 10 开始推荐使用 MediaCodecList.getDetailedCapabilities() 获取更精确的能力。

adb shell dumpsys media.codec
# 输出片段示例:
# OMX.qcom.video.decoder.avc:
#   Component: OMX.qcom.video.decoder.avc
#   Supports: video/avc
#   Max resolution: 4096x2176
#   Max framerate: 60 (per resolution: 1920x1080@60)
#   Color formats: 21, 2130708362
最佳实践: 在应用启动时遍历 MediaCodecList,将支持的编解码器及其能力上报至远端日志中心,用于灰度监控兼容性问题。
Android 编解码器碎片化全景(第1章) 应用层(MediaCodec API) OMX (OpenMAX IL) 栈 Codec2 (C2) 栈 Qualcomm (MSM) HAL MediaTek (MTK) HAL Exynos / Kirin HAL 其它(OEM) 分辨率/帧率上限差异 颜色格式不兼容 HEVC/VP9 缺失 B‑frame 排序错乱 适配策略:探查→降级→兜底(后续章节详解) 虚线箭头表示厂商可能存在自定义扩展或裁剪

1.5 常见错误清单(起步必读)

  • MediaCodec.CodecException(错误码 0xFFFFFFEA): 硬件资源不足,尝试回退软解或降低分辨率
  • IllegalStateException(”No such codec”): MIME 类型不匹配或设备未注册,优先使用 findDecoderForFormat 查询
  • 输出缓冲区格式突变: 更新后的 Android 版本可能改变颜色格式,需在 onOutputFormatChanged 中重建纹理
  • dequeueOutputBuffer 返回 INFO_OUTPUT_FORMAT_CHANGED 后未正确处理: 导致后续帧全部失败
性能起点: 在开发阶段启用 MediaCodec.MetricsConstants 收集编解码耗时,定位厂商特定硬编/硬解瓶颈。

掌握以上基础后,第 2 章将深入 MediaCodec 状态机与同步/异步模式的选择策略,直接指导工程实现。