安卓MediaCodec解码h264原始帧



我正在使用Android MediaCodec API解码h264帧。我可以解码并渲染视图中的帧。我的问题是解码器错过了很多帧,尤其是前几帧解码媒体编解码器.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();
}

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

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

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

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

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

最新更新