在某些设备中解码h.264时未调用MediaCodec.INFO_OUTPUT_FORMAT_CHANGED

时间:2014-01-23 17:22:18

标签: android h.264 decoder mediacodec

我正在使用以下代码来准备硬件解码器。我希望outputBufferIndex为-1,然后是MediaCodec.INFO_OUTPUT_FORMAT_CHANGED。在通知格式改变之前,它不应该> = 0。

我在25个不同的设备中测试了代码,其中7个永远不会返回INFO_OUTPUT_FORMAT_CHANGED。当我得到outputBufferIndex> = 0时,mediaCodec.getOutputFormat()返回了IllegalStateException。我不知道所有设备都没有用的巧合是android 4.2.2和OMX.qcom.video.decoder.avc解码器。 / p>

for (int i = 0; i < videoExtractor.getTrackCount(); i++) {
    MediaFormat mediaFormat = videoExtractor.getTrackFormat(i);
    String mime = mediaFormat.getString(MediaFormat.KEY_MIME);
    if (mime.startsWith("video/")) {
        videoExtractor.selectTrack(i);
        videoCodec = MediaCodec.createDecoderByType(mediaFormat.getString(MediaFormat.KEY_MIME));
        videoCodec.configure(mediaFormat, null, null, 0);
        videoCodec.start();
    }
}
ByteBuffer[] videoInputBuffers = videoCodec.getInputBuffers();
while (true) {
    int sampleTrackIndex = videoExtractor.getSampleTrackIndex();
    if (sampleTrackIndex == -1) {
        break;
    } else { // decode video
        int inputBufferIndex = videoCodec.dequeueInputBuffer(0);
        if (inputBufferIndex >= 0) {
            int bytesRead = videoExtractor.readSampleData(videoInputBuffers[inputBufferIndex], 0);
            if (bytesRead >= 0) {
                videoCodec.queueInputBuffer(inputBufferIndex, 0, bytesRead,
                        videoExtractor.getSampleTime(), 0);
                videoExtractor.advance();
            }
        }
        MediaCodec.BufferInfo videoBufferInfo = new MediaCodec.BufferInfo();
        int outputBufferIndex = videoCodec.dequeueOutputBuffer(videoBufferInfo, 0);
        if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
            MediaFormat format = videoCodec.getOutputFormat();
            Log.w("video format changed: " + videoCodec.getOutputFormat());
            //do something...
            break;
        } else if (outputBufferIndex >= 0) {
            //not supposed to happen!
        }
    }
}

非常感谢您的线索和帮助!

1 个答案:

答案 0 :(得分:0)

在Android 4.3中,一系列MediaCodec测试被添加到CTS中。如果您查看doEncodeDecodeVideoFromBuffer()EncodeDecodeTest中的工作方式,您可以看到它在任何数据之前需要INFO_OUTPUT_FORMAT_CHANGED结果。如果它没有得到它,在尝试获取颜色格式时对checkFrame()的调用将失败。在Android 4.3之前,没有测试,任何行为都是可能的。

话虽如此,我不记得在(基于Qualcomm的)Nexus 4上看到这种行为。

无论如何,除非你能够解码Qualcomm使用的专有缓冲区布局,否则我不确定这实际上会阻止你多少。您可以在同一个checkFrame()函数中看到它在看到OMX_QCOM_COLOR_FormatYUV420PackedSemiPlanar64x32Tile2m8ka时发挥作用。将输出发送到Surface可能是一种可行的替代方案,具体取决于您的目标。

bigflakeGrafika中的大多数MediaCodec代码都是针对API 18(Android 4.3),因为那时行为变得更具可预测性。 (表面输入和MediaMuxer的可用性也具有巨大的价值。)