Android MediaCodec解码h264原始帧

Rea*_*ark 9 android decode mediacodec

我正在使用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());
}
Run Code Online (Sandbox Code Playgroud)

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

 /**
 * 
 * @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();
}
Run Code Online (Sandbox Code Playgroud)

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

fad*_*den 5

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

您不需要MediaCodec提交编码数据缓冲区并立即获得解码缓冲区.你把它交给一个数据缓冲区,然后发送到mediaserver进程,进程将它提供给硬件AVC解码器,这可能仍然在初始化,或者只是喜欢坐在几帧上.解码过程完成后,解码后的数据将传回mediaserver您的应用程序进程.

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

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