You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android MediaCodec:如何获取待解码帧的宽高信息

问题

通常如果我们已通过元数据获取到帧的宽高信息,会通过如下方式定义MediaFormat对象以解码帧:

mediaFormat = MediaFormat.createVideoFormat(
        MediaFormat.MIMETYPE_VIDEO_MPEG4,
        720, 1024
    )

随后执行:

mediaCodec.configure(mediaFormat, Surface(textureView.surfaceTexture), null, 0)

但如果仅持有编码后的帧,而无相关元数据了解其分辨率,请问是否有方法获取该帧的宽高信息?

解决方案

当然有办法获取编码帧的宽高信息,以下是几种实用方案:

1. 解析视频帧的NALU单元(针对H.264/H.265编码)

大部分常见视频编码(如H.264/AVC、H.265/HEVC)的SPS(序列参数集)帧中包含了分辨率的核心信息,你可以直接从编码帧中提取SPS并解析:

  • 首先定位SPS的起始码:H.264的起始码是0x000001或0x00000001,找到后提取后续的SPS数据;
  • 解析SPS中的关键字段:
    • H.264:通过pic_width_in_mbs_minus1和pic_height_in_map_units_minus1计算基础宽高,再结合frame_mbs_only_flag、mb_adaptive_frame_field_flag等字段修正最终分辨率;
    • H.265:解析pic_width_in_luma_samples和pic_height_in_luma_samples字段直接获取宽高。

这种方法需要你对视频编码的NALU结构有一定了解,适合需要轻量解析、不想依赖额外库的场景。

2. 利用MediaCodec自动推导格式

Android的MediaCodec支持在不预先指定MediaFormat的情况下,自动从输入的编码帧中推导格式信息,步骤如下:

// 以H.264为例创建解码器
val mediaCodec = MediaCodec.createDecoderByType(MediaFormat.MIMETYPE_VIDEO_AVC)

// 设置异步回调监听格式变化
mediaCodec.setCallback(object : MediaCodec.Callback() {
    override fun onInputBufferAvailable(codec: MediaCodec, index: Int) {
        // 将编码帧数据写入输入缓冲区
        val inputBuffer = codec.getInputBuffer(index) ?: return
        inputBuffer.clear()
        inputBuffer.put(encodedFrameData) // encodedFrameData是你的编码帧字节数组
        codec.queueInputBuffer(index, 0, encodedFrameData.size, 0, 0)
    }

    override fun onOutputBufferAvailable(codec: MediaCodec, index: Int, info: MediaCodec.BufferInfo) {
        // 释放输出缓冲区(若不需要渲染可直接释放)
        codec.releaseOutputBuffer(index, false)
    }

    override fun onOutputFormatChanged(codec: MediaCodec, format: MediaFormat) {
        // 在这里获取自动推导的宽高信息
        val width = format.getInteger(MediaFormat.KEY_WIDTH)
        val height = format.getInteger(MediaFormat.KEY_HEIGHT)
        // 后续可根据这个format做进一步处理,比如重新配置解码器或记录分辨率
    }

    override fun onError(codec: MediaCodec, e: MediaCodec.CodecException) {
        e.printStackTrace()
    }
})

// 传入null的MediaFormat,让解码器自动推导
mediaCodec.configure(null, null, null, 0)
mediaCodec.start()

这种方法兼容性好,无需手动解析编码结构,依赖系统原生解码器处理,是Android平台推荐的方案。

3. 使用第三方解析库

如果不想自己处理编码细节,可以借助成熟的开源库:

  • ExoPlayer:可以使用其Extractor模块,将编码帧包装成ByteArrayDataSource后,提取媒体格式信息;
  • FFmpeg:通过FFmpeg的API直接解析编码帧的流信息,获取宽高。

这类库封装了复杂的编码解析逻辑,适合需要快速开发、处理多种编码格式的场景。


内容的提问来源于stack exchange,提问作者Ali Has

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 11:17:31