简体   繁体   English

Android MediaCodec解码h264原始帧

[英]Android MediaCodec decode h264 raw frame

I am using Android MediaCodec API to decode h264 frames. 我正在使用Android MediaCodec API来解码h264帧。 I could decode and render the frames on the view. 我可以在视图上解码和渲染帧。 My problem is the decoder miss lots of frames,especially the first some frames. 我的问题是解码器错过了很多帧,特别是前几帧。 DecodeMediaCodec.dequeueOutputBuffer() return -1. DecodeMediaCodec.dequeueOutputBuffer()返回-1。 aAbout 150 h264 frames,just decoded 43 frames. a约150 h264帧,刚解码43帧。 I can not find where the problem is. 我找不到问题所在。 Here is my codes. 这是我的代码。

 /**
 * init decoder
 */
private void initDecodeMediaCodec()
{
    mDecodeMediaCodec = MediaCodec.createDecoderByType(MIME_TYPE);
    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE,
            VIDEO_WIDTH_640,
            VIDEO_HEIGHT_480);

    mDecodeMediaCodec.configure(format,
            new Surface(mRemoteVideoView.getSurfaceTexture()),
            null,
            0);
    mDecodeMediaCodec.start();
    mDecodeInputBuffers = mDecodeMediaCodec.getInputBuffers();
    System.out.println("decode-----"
            + mDecodeMediaCodec.getCodecInfo().getName());
}

After decoder initial,I will start decoder thread. 解码器初始化后,我将启动解码器线程。

 /**
 * 
 * @param frameData
 */
private void decode()
{
    new Thread(new Runnable()
    {
        @Override
        public void run()
        {
            while (true)
            {
                ByteBuffer decodeDataBuffer = null;
                try
                {
                    //take h264 frame from cache queue
                    decodeDataBuffer = decodeDataQuene.take();
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }


                BufferInfo info = new BufferInfo();
                int inputBufferIndex = mDecodeMediaCodec.dequeueInputBuffer(-1);
                System.out.println("inputBufferIndex: " + inputBufferIndex);
                if (inputBufferIndex >= 0)
                {
                    ByteBuffer buffer = mDecodeInputBuffers[inputBufferIndex];
                    buffer.clear();
                    buffer.put(decodeDataBuffer.array());
                    mDecodeMediaCodec.queueInputBuffer(inputBufferIndex,
                            0,
                            decodeDataBuffer.array().length,
                            0,
                            0);
                    decodeDataBuffer.clear();
                    decodeDataBuffer = null;
                }

                int outputBufferIndex = mDecodeMediaCodec.dequeueOutputBuffer(info,
                       1000);
                System.out.println("outputBufferIndex: "
                        + outputBufferIndex);
                do
                {

                    if (outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER)
                    {
                        //no output available yet
                    }
                    else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED)
                    {
                        //encodeOutputBuffers = mDecodeMediaCodec.getOutputBuffers();
                    }
                    else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED)
                    {
                        MediaFormat formats = mDecodeMediaCodec.getOutputFormat();
                        //mediaformat changed
                    }
                    else if (outputBufferIndex < 0)
                    {
                        //unexpected result from encoder.dequeueOutputBuffer
                    }
                    else
                    {
                        mDecodeMediaCodec.releaseOutputBuffer(outputBufferIndex,
                                true);

                        outputBufferIndex = mDecodeMediaCodec.dequeueOutputBuffer(info,
                                0);
                        System.out.println("inner outputBufferIndex: "
                                + outputBufferIndex);
                    }
                } while (outputBufferIndex > 0);
            }
        }
    }).start();
}

Anybody knows why?I hope your help.My android device is nexus 7. 谁知道为什么?我希望你的帮助。我的Android设备是nexus 7。

Getting -1 back from MediaCodec#dequeueOutputBuffer() is normal. MediaCodec#dequeueOutputBuffer() -1 MediaCodec#dequeueOutputBuffer()是正常的。 It just means it doesn't have any output ready yet. 它只是意味着它还没有准备好任何输出。

It's not the case that you hand MediaCodec a buffer of encoded data and immediately get a decoded buffer back. 您不是将MediaCodec作为编码数据缓冲区并立即获得解码缓冲区的情况。 You hand it a buffer of data, which gets sent to the mediaserver process, which feeds it into the hardware AVC decoder, which may still be initializing or maybe just likes to sit on a few frames. 你将它交给数据缓冲区,然后将其发送到mediaserver进程,该进程将其提供给硬件AVC解码器,该解码器可能仍在初始化或者可能只是喜欢坐在几帧上。 When the decoding process completes, the decoded data gets passed back through mediaserver to your app process. 解码过程完成后,解码后的数据将通过mediaserver传递回您的应用程序进程。

The trick is, the queueInputBuffer() call returns immediately. 诀窍是, queueInputBuffer()调用立即返回。 In normal operation the input side of the decoder will run several frames ahead of the output side. 在正常操作中,解码器的输入侧将在输出侧之前运行几帧。 When you're done feeding input you set the end-of-stream flag, and when you see EOS set on the output you know you've reached the end. 当您完成输入输入时,您可以设置流结束标志,当您在输出上看到EOS设置时,您就知道已经到达终点。

You can find various working examples on bigflake and in Grafika . 你可以在bigflakeGrafika找到各种工作实例。 The DecodeEditEncodeTest and EncodeDecodeTest examples work exclusively with raw H.264, the others use MediaExtractor and MediaMuxer to handle MP4 file wrappers. DecodeEditEncodeTest和EncodeDecodeTest示例仅使用原始H.264,其他使用MediaExtractorMediaMuxer来处理MP4文件包装器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM