Android MediaCodec解码h264原始帧

Android MediaCodec解码h264原始帧,android,decode,android-mediacodec,Android,Decode,Android Mediacodec,我正在使用Android MediaCodec API解码h264帧。我可以解码和渲染视图上的帧。我的问题是解码器漏掉了很多帧,尤其是前几帧DecodeMediaCodec.dequeueOutputBuffer()return-1。大约150帧h264帧,刚刚解码了43帧。我找不到问题出在哪里。这是我的密码 /** * init decoder */ private void initDecodeMediaCodec() { mDecodeMediaCodec = MediaCo

我正在使用Android MediaCodec API解码h264帧。我可以解码和渲染视图上的帧。我的问题是解码器漏掉了很多帧,尤其是前几帧DecodeMediaCodec.dequeueOutputBuffer()return-1。大约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();
}
/**
* 
*@param frameData
*/
私有无效解码()
{
新线程(newrunnable())
{
@凌驾
公开募捐
{
while(true)
{
ByteBuffer decodeDataBuffer=null;
尝试
{
//从缓存队列中获取h264帧
decodeDataBuffer=decodeDataQuene.take();
}
捕捉(中断异常e)
{
e、 printStackTrace();
}
BufferInfo=new BufferInfo();
int inputBufferIndex=mDecodeMediaCodec.dequeueInputBuffer(-1);
System.out.println(“inputBufferIndex:+inputBufferIndex”);
如果(inputBufferIndex>=0)
{
ByteBuffer buffer=mDecodeInputBuffers[inputBufferIndex];
buffer.clear();
put(decodeDataBuffer.array());
MDECodemic.queueInputBuffer(inputBufferIndex,
0,
decodeDataBuffer.array().length,
0,
0);
decodeDataBuffer.clear();
decodeDataBuffer=null;
}
int outputBufferIndex=MDECodeic.dequeueOutputBuffer(信息,
1000);
System.out.println(“outputBufferIndex:
+输出缓冲指数);
做
{
如果(outputBufferIndex==MediaCodec.INFO\u请稍后重试)
{
//还没有可用的输出
}
else if(outputBufferIndex==MediaCodec.INFO\u输出\u缓冲区\u已更改)
{
//encodeOutputBuffers=mDecodeMediaCodec.getOutputBuffers();
}
else if(outputBufferIndex==MediaCodec.INFO\u输出\u格式\u更改)
{
MediaFormat formats=mdecodemediadiacodec.getOutputFormat();
//媒体格式已更改
}
else if(outputBufferIndex<0)
{
//编码器的意外结果。dequeueOutputBuffer
}
其他的
{
MDECodemicodec.releaseOutputBuffer(outputBufferIndex,
正确的);
outputBufferIndex=MDECodemic.dequeueOutputBuffer(信息,
0);
System.out.println(“内部输出缓冲索引:”
+输出缓冲指数);
}
}而(outputBufferIndex>0);
}
}
}).start();
}

有人知道为什么吗?我希望你的帮助。我的安卓设备是nexus 7。

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

这并不是说你将
MediaCodec
一个已编码数据的缓冲区交给你,然后立即将一个已解码的缓冲区拿回来。你给它一个数据缓冲区,它被发送到
mediaserver
进程,然后将其送入硬件AVC解码器,该解码器可能仍在初始化中,或者可能只是喜欢坐在几帧上。解码过程完成后,解码后的数据将通过
mediaserver
传回您的应用程序进程

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


您可以在上和中找到各种工作示例。DecodeEditEncodeTest和EncodeDecodeTest示例仅适用于原始H.264,其他示例使用
MediaExtractor
MediaMuxer
来处理MP4文件包装器。

我已经查阅了您提供的资源,对此我有一些问题。1) 有没有办法让解码器快速解码帧?2) 我是否应该将第一个编码帧cds-0添加到解码器格式?3) PresentationTime是否必须?(1)通过提前配置和启动解码器,您可以节省一些时间。我还没有尝试过。你看到了多大的延误?(2) 您可以将CSD添加到
MediaFormat
,也可以将其作为设置了
CODEC\u CONFIG
标志的第一帧提交。不要两者都做。(3) 我认为编解码器在解码时没有注意到PTS。(这在编码时很重要。)如果你从源代码中获取时间戳,最好保留它们——例如,如果你的视频源不能以恒定速率提供帧。Nexus 7上的延迟约为19帧,三星s3上的延迟约为6帧。达赖相对稳定。这似乎和硬件有关,但我不确定。@fadden你介意看看我的问题吗?我知道这是一个非常古老的线程,但介意分享你的代码吗?我正在尝试从实时流中获取原始h264帧,并将其显示在我的android应用程序中。