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字段直接获取宽高。
- H.264:通过
这种方法需要你对视频编码的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
相关产品推荐
相关产品推荐

