Android MediaCodec似乎缓冲了H264帧

时间:2016-07-05 09:05:25

标签: android opengl-es h.264 mediacodec

我手动读取RTP / H264流并将H264帧传递给Android MediaCodec。我使用" markerBit"作为框架的边框。 MediaCodec与OpenGL纹理(SurfaceTexture)相关联。 总的来说一切正常。但解码器似乎缓冲帧。如果我在解码器中放置一个帧,它不会立即渲染到纹理。在解码器中放入2-3帧后,第一帧渲染到纹理。

我正在针对Android 4.4.4实施。

DateInterval {#727
     +"y": 0,
     +"m": 0,
     +"d": 0,
     +"h": 22,
     +"i": 59,
     +"s": 6,
     +"weekday": 0,
     +"weekday_behavior": 0,
     +"first_last_day_of": 0,
     +"invert": 1,
     +"days": 0,
     +"special_type": 0,
     +"special_amount": 0,
     +"have_weekday_relative": 0,
     +"have_special_relative": 0,
   }

private static final int INFINITE_TIMEOUT = -1;
private static final int TIMEOUT_OUTPUT_BUFFER_MEDIA_CODEC = 1000;
...
int bufferIndex = codec.dequeueInputBuffer(INFINITE_TIMEOUT);
if (bufferIndex < 0) {
  throw new RuntimeException("Error");
}

ByteBuffer inputBuffer = inputBuffers[bufferIndex];
inputBuffer.clear();

// Copy H264 data to inputBuffer
h264Frame.fill(inputBuffer);

codec.queueInputBuffer(bufferIndex, 0, inputBuffer.position(), 0, 0);
drainOutputBuffers();
...

在渲染方面,我使用&#34; onFrameAvailable&#34;用于检查是否必须更新openGl线程上的纹理的回调。我用来检查的标志由锁(同步)保护。

我怀疑演示时间戳可能会影响渲染。但是我把它设置为0.因此我假设帧应该没有延迟地渲染。

我希望将帧渲染到纹理而不必添加其他帧。

2 个答案:

答案 0 :(得分:1)

来自MediaCodec documentation

  

执行状态有三个子状态:Flushed,Running和   结束流。在start()编解码器处于刷新状态之后   子状态,它包含所有缓冲区。第一次输入   缓冲区出列后,编解码器移动到正在运行的子状态   花费大部分时间。 使用。排队输入缓冲区时   流末尾标记,编解码器转换为End-of-Stream   子状态即可。在这种状态下,编解码器不再接受进一步的输入   缓冲区,但仍然生成输出缓冲区,直到流结束为止   达到了输出。您可以返回到Flushed子状态   使用flush()处于执行状态时的任何时间。

您需要“使用end-of-stream标记对输入缓冲区进行排队”。使用您提供给解码器的第一帧执行此操作(确保它是关键帧)。

这一点是告诉解码器不要再期待帧了,因此立即开始播放。否则在看到任何东西之前喂3或4帧是正常的。这是所有MPEG解码器的期望,与Android无关。

答案 1 :(得分:-1)

Mediacodec解码器在输出第一个解码输出帧之前缓冲6-7帧。它似乎在mediacodec中有缺陷。这将是流应用程序中的问题。 到目前为止,我的调试显示解码H264与mediacodec在流启动期间有6-7帧延迟。