Encoding MediaCodec解码器与出列输出缓冲区调用有关的问题(H.264)

Encoding MediaCodec解码器与出列输出缓冲区调用有关的问题(H.264),encoding,h.264,android-mediacodec,Encoding,H.264,Android Mediacodec,问题: 我为什么…我是说,我的解码器怎么了?当我试图获取它丰富的输出数据时,它总是返回超时(-1) 让我先说我已经阅读了相关的线程,但仍然不能解决问题。我真的需要一些指导和帮助。好的,我现在做的是把AVC编码的数据传递给我的解码器。编码器工作,从相机预览中提取数据,在那里我在传递到编码器之前从NV21转换到NV12 编码器提供的第一个数据具有编解码器特定数据,我将其传递给配置解码器(ByteBuffer csd0,ByteBuffer csd1)函数,以创建和配置解码器,该解码器不会引发任何错误

问题: 我为什么…我是说,我的解码器怎么了?当我试图获取它丰富的输出数据时,它总是返回超时(-1)

让我先说我已经阅读了相关的线程,但仍然不能解决问题。我真的需要一些指导和帮助。好的,我现在做的是把AVC编码的数据传递给我的解码器。编码器工作,从相机预览中提取数据,在那里我在传递到编码器之前从NV21转换到NV12

编码器提供的第一个数据具有
编解码器特定数据
,我将其传递给
配置解码器(ByteBuffer csd0,ByteBuffer csd1)
函数,以创建和配置解码器,该解码器不会引发任何错误

public void ConfigureDecoder(ByteBuffer csd0, ByteBuffer csd1)
{
    try
    {
        decoder = MediaCodec.createDecoderByType(MIME_TYPE);
    }
    catch(IOException e)
    {
        Log.d(TAG, "Decoder codec creation failed: " + e.toString());
    }

    MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, 320, 240);
    format.setByteBuffer("csd-0", csd0);
    format.setByteBuffer("csd-1", csd1);
    decoder.configure(format, null, null, 0);

    try
    {
        decoder.start();
        Log.d(TAG, "Decoder configured");
    }
    catch(CodecException e)
    {
        Log.d(TAG, "Decoder config start failed: " + e.getDiagnosticInfo());
    }
}

一旦编码器通知有编码数据可用(在编解码器特定数据之后),将调用以下函数。首先,我得到一个可用的解码器输入缓冲区,若成功,我用编码数据(验证)填充它并将其添加到解码器队列。然后一切都糟透了,我尝试使用
dequeueOutputBuffer(bufferInfo,0)从解码器检索数据始终返回-1



如果你在文章中说到这一点,我真的很感谢你的时间:)

这里的问题似乎是API给了你一种错觉,认为解码是同步的——事实并非如此

当您给解码器一个输入数据包时,它将开始对其进行解码-现在您只需在之后立即检查一次,当解码器返回-1时,表示它没有任何更多的输出(尚未)

您可以增加timeoutUs参数,使其等待更长的时间,以查看解码器是否返回某些内容,或者将其设置为-1以无限期等待


但是,如果您总是立即等待每个输入数据包的输出,您将获得非常糟糕的性能(并且在输入中断的情况下,您可能根本得不到任何输出);您应该向解码器提供到目前为止需要解码的尽可能多的数据(直到dequeueInputBuffer指示此时没有可用的输入缓冲区),并使用解码器提供的任何输出缓冲区。如果只针对Android 5.0及更高版本是您的一个选择,那么您应该研究回调API(
MediaCodec.setCallback
),这更清楚,不必轮询输出。

我也面临同样的问题,解决方案是从代码中删除以下行

format.setByteBuffer("csd-0", csd0);
format.setByteBuffer("csd-1", csd1);

IIRC,AVC编解码器在开始做任何事情之前,需要输入大约四个接入单元。我希望这在不同的设备之间有所不同。
format.setByteBuffer("csd-0", csd0);
format.setByteBuffer("csd-1", csd1);