我正在使用Android MediaCodec API来解码h264帧。我可以在视图上解码和渲染帧。我的问题是解码器错过了很多帧,特别是前几帧。 DecodeMediaCodec.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();
}
有谁知道为什么?我希望你的帮助。我的Android设备是nexus 7.
答案 0 :(得分:5)
从MediaCodec#dequeueOutputBuffer()
获取-1是正常的。这只是意味着它还没有准备好任何输出。
并非您将MediaCodec
一个编码数据缓冲区并立即返回解码缓冲区。你把它交给一个数据缓冲区,然后发送到mediaserver
进程,它将它提供给硬件AVC解码器,它可能仍在初始化,或者只是喜欢坐在几帧上。解码过程完成后,解码后的数据将通过mediaserver
传递回您的应用程序进程。
诀窍是,queueInputBuffer()
调用立即返回。在正常操作中,解码器的输入侧将在输出侧之前运行几帧。当您完成输入输入时,您可以设置流结束标志,当您在输出上看到EOS设置时,您知道已经到达终点。
您可以在bigflake和Grafika找到各种工作示例。 DecodeEditEncodeTest和EncodeDecodeTest示例仅使用原始H.264,其他人使用MediaExtractor
和MediaMuxer
来处理MP4文件包装。