I'm manually reading a RTP/H264 stream and pass the H264 frames to the Android MediaCodec. I use the "markerBit" as a border for the frames. The MediaCodec is tied to a OpenGL Texture (SurfaceTexture). In general everything works fine. But the Decoder appears to buffer frames. If I put a frame in the decoder it is not rendered immediately to the texture. After I put 2-3 frames more in the decoder the first frame is rendered to the texture.
I'm implementing against Android 4.4.4.
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(); ... and
private boolean drainOutputBuffers() { MediaCodec.BufferInfo buffInfo = new MediaCodec.BufferInfo(); int outputBufferIndex = codec.dequeueOutputBuffer(buffInfo, TIMEOUT_OUTPUT_BUFFER_MEDIA_CODEC); if (outputBufferIndex >= 0) { codec.releaseOutputBuffer(outputBufferIndex, true); return true; } switch (outputBufferIndex) { case MediaCodec.INFO_TRY_AGAIN_LATER: LOG.debug("Could not dequeue output buffer. Try again later"); break; case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED: LOG.warn("The output format has changed."); break; case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED: LOG.warn("The output buffers has changed."); break; default: LOG.warn("The output buffer index was negative: {}", outputBufferIndex); } return false; } On the rendering side I use the "onFrameAvailable" callback for checking if I have to update the texture on the openGl Thread. The flag I use for checking is guarded by a lock (synchronized).
I suspect that the presentation timestamp may influence the rendering. But I set it to 0. Thus I assume the frame should be rendered without a delay.
I'd like to have the frame rendered to the texture without having to put additional frames.