Following the BigFlake example there is a comment that states :
// Acquire a new frame of input, and render it to the Surface. If we had a
// GLSurfaceView we could switch EGL contexts and call drawImage() a second
// time to render it on screen. The texture can be shared between contexts by
// passing the GLSurfaceView's EGLContext as eglCreateContext()'s share_context
// argument.
I use EGL14.getCurrentContext()
to query the current context and pass it into the EGL14.eglCreateContext()
share_context parameter, but How do you "switch EGL contexts"?
The GLSurfaceView and MediaCodec.inputSurface have two different surfaces and two different contexts, so I assume you just call eglMakeCurrent()
on each set individually, is that correct? Do you need to eglDestroyContext()
or eglDestroySurface()
?
Added update
Thanks Fadden, I think I figured out this error, instead of drawFrame I was calling drawImage, but you shouldn't have to update the image a second time, right?
Now I am getting an out of memory error glError 1285
when dequeueBuffer is called after EOS has been set??? Maybe I am calling it after the recording has stopped. Thanks for your help.
create EGLSurface in MyEGLWrapper.java
saveToScreenRenderState();
mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], mScreenEglContext,
contextAttribs, 0);
checkEglError("eglCreateContext");
// Create a window surface, and attach it to the Surface we received.
mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
surfaceAttribs, 0);
checkEglError("eglCreateWindowSurface");
...
private void saveToScreenRenderState() {
//System.arraycopy(mProjectionMatrix, 0, mSavedMatrix, 0, mProjectionMatrix.length);
mScreenEglDisplay = EGL14.eglGetCurrentDisplay();
mScreenEglDrawSurface = EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW);
mScreenEglReadSurface = EGL14.eglGetCurrentSurface(EGL14.EGL_READ);
mScreenEglContext = EGL14.eglGetCurrentContext();
}
public void makeCurrent(boolean toScreen, Surface surface) {
if (toScreen) { //as opposed to toEncoder
makeScreenSurfaceCurrent();
return;
}
EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
checkEglError("eglMakeCurrent");
}
private void makeScreenSurfaceCurrent() {
EGL14.eglMakeCurrent(mScreenEglDisplay, mScreenEglDrawSurface,
mScreenEglReadSurface, mScreenEglContext);
checkEglError("eglMakeCurrent");
}
In CaptureManager.java
private void drawFrameOnInputSurface() {
//draw a second time for inputSurface
mEGLWrapper.makeCurrent(false, videoCodec.videoCodecInputSurface);
drawFrame(false);
//ByteBuffer frame = mStManager.drawImage();
videoCodec.runQue(false); // clear que before posting should this be on this thread???
mEGLWrapper.setPresentationTime(mSt.getTimestamp(),!recordingStopped);
mEGLWrapper.swapBuffers(!recordingStopped);
videoHandler.post(new Runnable(){
@Override
public void run(){
videoCodec.updateFrame(!isRecording);
}
});
}
private void drawFrame(boolean updateImage){
mStManager.drawImage(updateImage);
mGLView.mRenderer.drawFrame();
}
In SurfaceTextureManager.java
public ByteBuffer drawImage(boolean updateImage) {
// Latch the data.
if (updateImage){
mTextureRender.checkGlError("before updateTexImage");
mSurfaceTexture.updateTexImage();
}
return mTextureRender.drawFrame(mSurfaceTexture);
}
error in SurfaceTextureManager.java on mSurfaceTexture.updateTexImage();
Yes, use eglMakeCurrent
to switch between the two contexts.
You do not need to destroy the contexts or surfaces you're not currently using (until you're shutting things down, anyway).
For an example of rendering twice with a shared context, see the bigflake Breakout game recorder patch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With