I ran into the same problem, and the solution I'm using is to set the timestamp via EGL, like RecordFBOActivity # doFrame . To do this, an intermediate distribution is used to bridge the gap between RenderScript and OpenGL / EGL.
Let you view the data stream as a processing pipeline with steps.
Original pipeline
[Camera] --> [ImageAllocation] --> [RenderScript] --> [MediaCodecSurfaceAllocationForEncoder] --> [MediaCodec]
In the source pipeline, all buffers are RS allocations.
MediaCodecSurfaceAllocation based on the Surface returned from the encoder, i.e. MediaCodec#getSurface() .
New pipeline
[Camera] --> [ImageAllocation] --> [RenderScript] --> [IntermediateAllocation] --> [EglWindowSurfaceForEncoder] --> [MediaCodec]
There are two big changes in the new pipeline: IntermediateAllocation and EglWindowSurfaceForEncoder
IntermediateAllocation is a SurfaceTexture-based distribution, similar to the flickering glitter of a screen texture used in CameraCaptureActivity .
EglWindowSurfaceForEncoder wraps an encoder input surface similar to RecordFBOActivity # startEncoder
The key point here is setting your own OnFrameAvailableListener .
Installation code
void setup() { mEglWindowSurfaceForEncoder= new WindowSurface(mEglCore, encoderCore.getInputSurface(), true); mFullScreen = new FullFrameRect( new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT)); mTextureId = mFullScreen.createTextureObject(); mSurfaceTexture = new SurfaceTexture(mTextureId); Type renderType = new Type.Builder(renderScript, Element.RGBA_8888(renderScript)) .setX(width) .setY(height) .create(); mIntermediateAllocation = Allocation.createTyped( renderScript, renderType, Allocation.USAGE_SCRIPT | Allocation.USAGE_IO_OUTPUT); mIntermediateAllocation .setSurface(surface); mAllocationFromCamera = ... }
OnNewCameraImage
mIntermediateAllocation.copyFrom(mAllocationFromCamera);
OnFrameAvailableListener
mSurfaceTexture.setOnFrameAvailableListener( new SurfaceTexture.OnFrameAvailableListener() { public void onFrameAvailableListener(SurfaceTexture) {
The above code should be executed in the context of the EGL (i.e. in the OpenGl rendering thread).