我手动读取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.因此我假设帧应该没有延迟地渲染。
我希望将帧渲染到纹理而不必添加其他帧。
答案 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帧延迟。