繁体   English   中英

Android MediaCodec解码h264原始帧

[英]Android MediaCodec decode h264 raw frame

我正在使用Android MediaCodec API来解码h264帧。 我可以在视图上解码和渲染帧。 我的问题是解码器错过了很多帧,特别是前几帧。 DecodeMediaCodec.dequeueOutputBuffer()返回-1。 a约150 h264帧,刚解码43帧。 我找不到问题所在。 这是我的代码。

 /**
 * 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());
}

解码器初始化后,我将启动解码器线程。

 /**
 * 
 * @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();
}

谁知道为什么?我希望你的帮助。我的Android设备是nexus 7。

MediaCodec#dequeueOutputBuffer() -1 MediaCodec#dequeueOutputBuffer()是正常的。 它只是意味着它还没有准备好任何输出。

您不是将MediaCodec作为编码数据缓冲区并立即获得解码缓冲区的情况。 你将它交给数据缓冲区,然后将其发送到mediaserver进程,该进程将其提供给硬件AVC解码器,该解码器可能仍在初始化或者可能只是喜欢坐在几帧上。 解码过程完成后,解码后的数据将通过mediaserver传递回您的应用程序进程。

诀窍是, queueInputBuffer()调用立即返回。 在正常操作中,解码器的输入侧将在输出侧之前运行几帧。 当您完成输入输入时,您可以设置流结束标志,当您在输出上看到EOS设置时,您就知道已经到达终点。

你可以在bigflakeGrafika找到各种工作实例。 DecodeEditEncodeTest和EncodeDecodeTest示例仅使用原始H.264,其他使用MediaExtractorMediaMuxer来处理MP4文件包装器。

暂无
暂无

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

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