3. MediaFormat 配置关键:视频尺寸、比特率、帧率、颜色格式、关键帧间隔
MediaFormat 是 Android 多媒体框架中描述编码/解码器输入输出格式的核心对象。正确配置 MediaFormat 的五个关键参数——视频尺寸、比特率、帧率、颜色格式、关键帧间隔——直接决定编码质量、码率稳定性、兼容性与实时性。每个参数都有物理意义、取值范围和典型约束,配置错误会导致编码失败、花屏、延迟过高或文件损坏。
3.1 核心参数速查表
| 参数 | MediaFormat Key | 类型 | 典型值范围 | 单位/说明 |
|---|---|---|---|---|
| 视频宽度 | KEY_WIDTH |
int | 16–3840 | 像素,必须为 2 的倍数 |
| 视频高度 | KEY_HEIGHT |
int | 16–2160 | 像素,必须为 2 的倍数 |
| 比特率 | KEY_BIT_RATE |
int | 100 kbps – 50 Mbps | bits per second |
| 帧率 | KEY_FRAME_RATE |
int | 1–60(常见 15/24/30/60) | fps |
| 颜色格式 | KEY_COLOR_FORMAT |
int | COLOR_FormatYUV420SemiPlanar / COLOR_FormatYUV420Planar | CodecSpecific 值 |
| 关键帧间隔 | KEY_I_FRAME_INTERVAL |
int | 0 / 1–10(秒) | 0 表示全 IDR,负数表示 GDR |
3.2 参数含义与原理
- 视频尺寸 (Width × Height)
- 编码器输出分辨率。必须和输入 Surface 或 ByteBuffer 提供的分辨率一致。非对称缩放(如 720×1280 竖屏)通常支持,但需硬件兼容。尺寸需为 2 的倍数,部分编码器要求 16 或 8 对齐。
- 比特率 (Bitrate)
- 单位时间编码数据量,决定视频清晰度与文件大小。过高比特率可能超出编码器/网络能力,过低则产生块效应。通常结合码率控制模式(CQ/CBR/VBR)使用。
- 帧率 (Frame Rate)
- 编码器期望的输入帧率。实际输入帧率需与此匹配,否则编码器内部会丢帧或插入重复帧,导致时间戳混乱。常见值为 15、24、30、60。
- 颜色格式 (Color Format)
- 输入图像的像素数据排列方式。Android 推荐
COLOR_FormatYUV420SemiPlanar(NV12)或COLOR_FormatYUV420Planar(I420)。Surface 输入时无需设置,由框架自动匹配;ByteBuffer 输入时必须正确配置。 - 关键帧间隔 (Key Frame Interval)
- 两个 IDR 帧(关键帧)之间的时间间隔(秒)。0 表示每个帧均为 IDR,适合低延迟场景;1–10 是常见范围,间隔越短码流越随机访问,但压缩效率降低。
3.3 配置流程
- 创建
MediaFormat对象:MediaFormat.createVideoFormat(mimeType, width, height)。 - 通过各
setInteger/setString方法填入所需参数。 - 设置颜色格式(ByteBuffer 输入时)或使用 Surface 输入(自动省略)。
- 调用
configure(mediaFormat, surface, flags, mediacodecInfo)应用到编码器。
3.4 代码示例:配置 H.264 编码器
MediaFormat format = MediaFormat.createVideoFormat(
MediaFormat.MIMETYPE_VIDEO_AVC, 1280, 720);
format.setInteger(MediaFormat.KEY_BIT_RATE, 2_000_000); // 2 Mbps
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar);
format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2); // 每2秒一个IDR
MediaCodec encoder = MediaCodec.createByCodecName("OMX.google.h264.encoder");
encoder.configure(format, null, MediaCodec.CONFIGURE_FLAG_ENCODE, null);
3.5 调试与验证
- 输出 MediaCodec 配置报告: 编码器启动后调用
getOutputFormat()查看实际采用的参数。 - 日志观察: 使用
adb logcat -s MediaCodec过滤编码器相关的 INFO/WARNING 信息,确认配置是否被降级或拒绝。
// 编码器输出 MediaFormat 示例(logcat 可见)
OutputFormat: {mime=video/avc, width=1280, height=720, bitrate=2000000, frame-rate=30, i-frame-interval=2, color-format=21}
3.6 常见错误
| 错误症状 | 可能原因 | 解决方案 |
|---|---|---|
configure 抛出 MediaCodec.CodecException |
分辨率或颜色格式不被硬件支持 | 通过 MediaCodecList 查询支持能力,回退到软件编码器 |
| 编码后视频花屏、绿屏 | 颜色格式与实际输入数据不匹配 | 确保 ByteBuffer 输入采用与 KEY_COLOR_FORMAT 一致的 YUV 排列 |
| 输出帧时间戳错乱 | 实际输入帧率与 KEY_FRAME_RATE 偏差过大 |
使用 PresentationTimeUs 严格按 1/fps 递增,或关闭帧率限制(设为 -1) |
| 码率波动超出预期 | 未设置码率控制模式,默认使用 CQ | 使用 KEY_BITRATE_MODE 设置为 BITRATE_MODE_CBR 或 VBR |
3.7 性能与稳定性优化
- 码率控制模式: 直播场景使用
BITRATE_MODE_CBR保持恒定码率;本地录制使用BITRATE_MODE_VBR提升画质;低延时场景使用BITRATE_MODE_CQ。 - 颜色格式选择: 优先使用
COLOR_FormatYUV420SemiPlanar,大多数现代编码器支持更佳;老设备可能需要COLOR_FormatYUV420Planar。 - 关键帧间隔优化: 即时通信场景设为 0~1 秒减少抖动;视频点播场景可设为 2~5 秒提升压缩率。
- 分辨率对齐: 始终对宽高执行
width += (width % 2 != 0) ? 1 : 0和height += (height % 2 != 0) ? 1 : 0,避免未知编码器报错。
3.8 MediaFormat 参数配置流程
上图展示了从创建 MediaFormat 到启动编码器的完整配置路径,重点标注五个关键参数的数据类型与配置时机。红色节点为必须配置项,绿色节点为可省略项(Surface 输入时颜色格式自动匹配)。
3.9 部署建议
在正式应用中将 MediaFormat 配置封装为 VideoEncoderConfig 数据类,支持从服务器下发或用户偏好动态调整。使用 MediaCodecInfo.CodecCapabilities 查询具体编码器的 getSupportedPerformances() 匹配最佳参数,避免硬编码导致兼容性故障。
本章节全部代码示例、参数速查表与调试技巧已归档至课程仓库的 /chapter03 目录,可结合 Android Studio 项目直接运行验证。