Android MediaCodec解码H264原始帧 [英] Android MediaCodec decode h264 raw frame
问题描述
我正在使用Android MediaCodec API解码h264帧.我可以解码并渲染视图上的帧.我的问题是解码器会丢失很多帧,尤其是前几帧. DecodeMediaCodec.dequeueOutputBuffer()返回-1.大约150个h264帧,仅解码了43帧.我找不到问题所在.这是我的代码.
I am using Android MediaCodec API to decode h264 frames. I could decode and render the frames on the view. My problem is the decoder miss lots of frames,especially the first some frames. DecodeMediaCodec.dequeueOutputBuffer() return -1. aAbout 150 h264 frames,just decoded 43 frames. I can not find where the problem is. Here is my codes.
/**
* 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());
}
解码器初始化后,我将启动解码器线程.
After decoder initial,I will start decoder thread.
/**
*
* @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();
}
有人知道为什么吗?希望您能帮忙.我的android设备是nexus 7.
Anybody knows why?I hope your help.My android device is nexus 7.
推荐答案
从MediaCodec#dequeueOutputBuffer()
返回-1是正常的.这只是意味着它还没有任何输出准备就绪.
Getting -1 back from MediaCodec#dequeueOutputBuffer()
is normal. It just means it doesn't have any output ready yet.
并非是您将MediaCodec
编码数据的缓冲区交到并立即取回解码后的缓冲区的情况.您将其交给一个数据缓冲区,该缓冲区将被发送到mediaserver
进程,该进程将其馈送到硬件AVC解码器,该解码器可能仍在初始化或可能只是想坐在几帧上.解码过程完成后,解码后的数据将通过mediaserver
传递回您的应用程序进程.
It's not the case that you hand MediaCodec
a buffer of encoded data and immediately get a decoded buffer back. You hand it a buffer of data, which gets sent to the mediaserver
process, which feeds it into the hardware AVC decoder, which may still be initializing or maybe just likes to sit on a few frames. When the decoding process completes, the decoded data gets passed back through mediaserver
to your app process.
诀窍在于,queueInputBuffer()
调用会立即返回.在正常操作中,解码器的输入端将在输出端之前运行几帧.当输入完毕后,您就设置了流结束标志,并且当您看到输出端设置了EOS时,您就知道已经到了结束了.
The trick is, the queueInputBuffer()
call returns immediately. In normal operation the input side of the decoder will run several frames ahead of the output side. When you're done feeding input you set the end-of-stream flag, and when you see EOS set on the output you know you've reached the end.
您可以在 bigflake 和
You can find various working examples on bigflake and in Grafika. The DecodeEditEncodeTest and EncodeDecodeTest examples work exclusively with raw H.264, the others use MediaExtractor
and MediaMuxer
to handle MP4 file wrappers.
这篇关于Android MediaCodec解码H264原始帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!