I have recently been modifying Grafika's TextureMovieEncoder
to create a recording of what I displayed onscreen: two Sprite2ds which are overlapping. Using the CameraCaptureActivity
example as a reference point, I effectively ported what I created for my rendering thread into the TextureMovieEncoder
but the output is jagged lines across the screen. I think I understand what's wrong, but I don't know how to fix it:
Some code:
private void prepareEncoder(EGLContext sharedContext, int width, int height, int bitRate,
File outputFile) {
try {
mVideoEncoder = new VideoEncoderCore(width, height, bitRate, outputFile);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
mEglCore = new EglCore(sharedContext, EglCore.FLAG_RECORDABLE);
mInputWindowSurface = new WindowSurface(mEglCore, mVideoEncoder.getInputSurface(), true);
mInputWindowSurface.makeCurrent();
textureProgram = new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT);
backgroundDrawable = new Drawable2d(Drawable2d.Prefab.RECTANGLE);
backgroundRect = new Sprite2d(backgroundDrawable);
frontDrawable = new Drawable2d(Drawable2d.Prefab.RECTANGLE);
frontRect = new Sprite2d(frontDrawable);
backgroundRect.setTexture(backTextureId);
frontRect.setTexture(frontTextureId);
updateGeometry();
}
private void handleFrameAvailable(Transform transform, long timestampNanos) {
if (VERBOSE) Log.d(TAG, "handleFrameAvailable tr=" + transform);
mVideoEncoder.drainEncoder(false);
backgroundRect.draw(textureProgram, transform.movieMatrix);
frontRect.draw(textureProgram, transform.cameraMatrix);
mInputWindowSurface.setPresentationTime(timestampNanos);
mInputWindowSurface.swapBuffers();
}
I think the problem comes down to my lack of understanding of how to establish the right projection onto the WindowSurface
for the VideoEncoder
. In the Grafika example, FullFrameRect
is used, which is easier since you can just use the identity matrix to stretch a given texture to the surface area. However, since I want to create the overlapping effect, I needed to use Sprite2d. Is the problem the shared EGLContext? Do I need to create a new one so that I can set the viewport to match the WindowSurface
size? A bit lost on where to go from here.
Turns out the functionality of the code above was fine. The problem was the interaction between the TextureEncoder and the calling parent.
I was initializing the member variables backTextureId
and frontTextureId
after prepareEncoder and it was therefore recording garbage data into the output.