问题: 为什么我...我的意思是,我的解码器发生了什么?当我试图获得丰富的输出数据时,它总是返回超时(-1)!
首先我要说的是我已经阅读了相关主题,但仍然无法解决问题。我真的需要一些指导和帮助。好的,我正在做的是将AVC编码数据传递给我的解码器。编码器工作,从摄像机预览中提取数据,然后在传递给编码器之前从NV21转换到NV12。
编码器提供的第一个数据有codec-specific-data
,我将其传递给ConfigureDecoder(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。
public void offerDecoder(byte[] input, int offset, int size, long presentationTimeUs, int flags)
{
int inputBufIndex = decoder.dequeueInputBuffer(10000);
Log.d(TAG, "Decoder dequeueInputBuffer = " + inputBufIndex);
if(inputBufIndex >= 0)
{
try
{
// Get valid buffer and push into the decoder input buffer
ByteBuffer inputBuf = decoder.getInputBuffer(inputBufIndex);
inputBuf.clear();
inputBuf = ByteBuffer.wrap(input);
decoder.queueInputBuffer(inputBufIndex, 0, size, presentationTimeUs, flags);
}
catch(MediaCodec.CodecException ce)
{
Log.d(TAG, "Decoder adding data error: " + ce.getDiagnosticInfo());
}
}
MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
int outIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
Log.d(TAG, "Decoder dequeueOutputBuffer = " + outIndex);
switch(outIndex)
{
case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
ByteBuffer outputBuffers = decoder.getOutputBuffer(outIndex);
Log.d(TAG, "Decoder dequeueOutputBuffer = INFO_OUTPUT_BUFFERS_CHANGED");
break;
case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
//MediaFormat bufferFormat = decoder.getOutputFormat(outIndex);
Log.d(TAG, "Decoder dequeueOutputBuffer = INFO_OUTPUT_FORMAT_CHANGED");
break;
case MediaCodec.INFO_TRY_AGAIN_LATER:
//Total fail, something is really wrong if you are always receiving -1 from dequeueOutputBuffer
//Log.d(TAG, "Decoder dequeueOutputBuffer = INFO_TRY_AGAIN_LATER");
break;
default:
Log.d(TAG, "Decoder out buffer info-->" + bufferInfo.offset + "--" + bufferInfo.size + "--" + bufferInfo.flags + "--" + bufferInfo.presentationTimeUs);
ByteBuffer buffer = decoder.getOutputBuffer(outIndex);
decoder.releaseOutputBuffer(outIndex, false);
break;
}
}
如果你在帖子中达到这一点,我真的很感谢你的时间:)
答案 0 :(得分:1)
这里的问题似乎是API让你觉得解码是同步的 - 它不是。
当你给解码器一个输入数据包时,它会开始对它进行解码 - 现在你只需要立即检查一次,当解码器返回-1时表示它还没有任何输出(还有)。
您可以增加timeoutUs参数以使其等待一段时间以查看解码器是否返回某些内容,或将其设置为-1以无限期地等待。
但是如果你总是等待每个输入数据包的输出,你会得到相当糟糕的性能(如果输入中断,你可能根本得不到任何输出);您应该为解码器提供迄今为止要解码的数据(直到dequeueInputBuffer指示此时没有可用的输入缓冲区),并使用解码器提供的任何输出缓冲区。如果仅针对Android 5.0及更高版本定位是您的选项,您应该查看回调API(MediaCodec.setCallback
),这更加清晰,无需轮询输出。
答案 1 :(得分:0)
我也面临同样的问题,解决方案就是从代码中删除以下行,
format.setByteBuffer("csd-0", csd0);
format.setByteBuffer("csd-1", csd1);