Android MediaCodec解码初始帧返回INFO_OUTPT_FORMAT_CHNAGED无法渲染如何处理
问题根因
dequeueOutputBuffer返回的负值为状态通知,不是合法的输出缓冲区索引,当前代码未做判断直接传入releaseOutputBuffer会抛出异常,导致前两次解码调用直接失败,无法正常输出首帧INFO_OUTPUT_FORMAT_CHANGED(返回值-2)代表解码器输出格式发生变更,需要确认新格式后才能继续后续解码流程INFO_OUTPUT_BUFFERS_CHANGED(返回值-3)代表输出缓冲区集合发生变更,低版本Android需要重新获取输出缓冲区,高版本虽已废弃该状态但仍需兼容处理避免报错- 代码中注释掉了SPS/PPS的配置逻辑,如果是H.264/H.265这类编码格式,解码器必须拿到SPS/PPS参数才能正常解码:如果是带外传输SPS/PPS就打开注释配置到
csd-0/csd-1字段,如果是带内传输就确保送入解码器的第一帧数据携带SPS/PPS头 - 代码中重复定义了
init方法,需要删除冗余的一个
修复后代码
init方法
public void init(int width, int height, Surface surface, byte[] sps, byte[] pps) { mPts = 0; format = MediaFormat.createVideoFormat(FORMAT, width, height); // 带外传输SPS/PPS时打开以下两行配置 //format.setByteBuffer("csd-0", ByteBuffer.wrap(sps)); //format.setByteBuffer("csd-1", ByteBuffer.wrap(pps)); mDecoder.configure(format, surface, null, 0); mDecoder.start(); }
decodeSample方法
public void decodeSample(byte[] data) { try { Log.e(TAG, Arrays.toString(data)); int index = mDecoder.dequeueInputBuffer(TIMEOUT); Log.e(TAG, String.valueOf(index)); if (index >= 0) { ByteBuffer buffer = mDecoder.getInputBuffer(index); if (buffer != null) { buffer.clear(); buffer.put(data, 0, data.length); mDecoder.queueInputBuffer(index, 0, data.length, mPts, 0); } } mPts++; int outIndex = mDecoder.dequeueOutputBuffer(info, 1000000); Log.e(TAG, "decodeSample: " + outIndex); // 增加返回值状态判断 if (outIndex >= 0) { // 仅合法索引才调用渲染逻辑 Log.d("DecodeActivity", "ready to render....."); mDecoder.releaseOutputBuffer(outIndex, true); } else if (outIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { // 输出格式变更,可按需获取新格式参数 MediaFormat newOutputFormat = mDecoder.getOutputFormat(); Log.d(TAG, "output format changed: " + newOutputFormat); } else if (outIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) { // 低版本兼容逻辑,Android 5.0+无需额外处理 Log.d(TAG, "output buffers changed"); } } catch (Exception exception) { Log.e(TAG, "Exception*********: " + exception.getMessage()); exception.printStackTrace(); } }
补充说明
- 建议pts不要使用简单自增,最好填入帧对应的实际时间戳,避免播放速度不符合预期
- 若解码后仍出现花屏/首帧不显示问题,优先检查送入的第一帧数据是否携带SPS/PPS头,或者configure前是否正确配置了
csd-0/csd-1参数
内容的提问来源于stack exchange,提问作者Madhukar
相关产品推荐
相关产品推荐

