Android MediaCodec生成的H.264数据异常及MP4播放报错求助
问题修复方案
一、先修复H.264裸流基础问题(解决Elecard StreamType未知)
- 必须保留SPS/PPS参数集:MediaCodec编码启动时会输出标记为
BUFFER_FLAG_CODEC_CONFIG的CSD数据(包含SPS和PPS),这是解码器识别H.264流的核心依据。你之前大概率只保存了编码帧数据,漏掉了这部分。要优先写入CSD数据到文件,再处理后续编码帧。 - 给每个NALU添加起始码:MediaCodec输出的裸NALU不带起始码,而标准H.264流要求每个NALU以
0x000001或0x00000001开头。需要在写入每帧数据前手动插入这4字节(或3字节)起始码,否则分析工具和播放器无法正确分割帧,导致流类型识别失败。
二、修复MP4封装问题(解决错误0xc00d36c4)
- 禁止直接修改文件后缀为MP4:MP4是有严格容器结构的格式,不是把H.264裸流改个后缀就能用。必须用Android的
MediaMuxer完成标准封装:- 创建
MediaMuxer实例,指定MP4输出路径; - 从MediaCodec的
MediaFormat中提取包含CSD-0、CSD-1的配置,添加视频轨道; - 在
onOutputBufferAvailable回调中,按顺序将CSD数据和编码帧传给MediaMuxer.writeSampleData,注意每一帧都要传入连续递增的presentationTimeUs时间戳,时间戳异常会直接导致播放器解析失败。
- 创建
- 用工具验证封装正确性:如果自行封装的MP4仍有问题,可通过ffmpeg转封装验证:将修复后的H.264裸流执行命令
ffmpeg -i fixed.h264 -c copy valid.mp4生成标准MP4,再尝试播放,以此排除封装逻辑问题。
三、验证修复结果
- 修复后的H.264裸流,用Elecard重新分析,确认StreamType显示为H.264/AVC;
- 用MediaMuxer或ffmpeg封装成MP4后,用系统播放器或VLC尝试播放,检查是否还出现0xc00d36c4错误。
代码细节提示
处理MediaCodec输出时,需区分CSD数据和普通帧:
@Override public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) { ByteBuffer buffer = codec.getOutputBuffer(index); if ((info.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) { // 优先写入CSD数据(SPS/PPS) writeToFile(buffer, info.size); codec.releaseOutputBuffer(index, false); return; } // 给普通编码帧添加起始码后写入 byte[] startCode = {0x00, 0x00, 0x00, 0x01}; FileOutputStream fos = ...; fos.write(startCode); buffer.position(info.offset); buffer.limit(info.offset + info.size); byte[] frameData = new byte[buffer.remaining()]; buffer.get(frameData); fos.write(frameData); codec.releaseOutputBuffer(index, false); }
内容的提问来源于stack exchange,提问作者user666
相关产品推荐
相关产品推荐

