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 配置流程

  1. 创建 MediaFormat 对象:MediaFormat.createVideoFormat(mimeType, width, height)。
  2. 通过各 setInteger / setString 方法填入所需参数。
  3. 设置颜色格式(ByteBuffer 输入时)或使用 Surface 输入(自动省略)。
  4. 调用 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 输入时颜色格式自动匹配)。
MediaFormat 配置流程 创建 MediaFormat KEY_WIDTH + KEY_HEIGHT KEY_BIT_RATE (int) KEY_FRAME_RATE (int) KEY_COLOR_FORMAT (int) KEY_I_FRAME_INTERVAL (int) configure() 启动编码器 Surface 输入时自动匹配 ByteBuffer 输入必须显式设置 0 = 全 IDR 帧 负数表示 GDR 模式 宽高必须为2的倍数 否则 configure 报错

3.9 部署建议

在正式应用中将 MediaFormat 配置封装为 VideoEncoderConfig 数据类,支持从服务器下发或用户偏好动态调整。使用 MediaCodecInfo.CodecCapabilities 查询具体编码器的 getSupportedPerformances() 匹配最佳参数,避免硬编码导致兼容性故障。

本章节全部代码示例、参数速查表与调试技巧已归档至课程仓库的 /chapter03 目录,可结合 Android Studio 项目直接运行验证。