Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use MediaMuxer / MediaCodec InputSurface with GLSurfaceView?

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();

like image 638
HPP Avatar asked Oct 31 '13 06:10

HPP


1 Answers

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.

like image 61
fadden Avatar answered Oct 04 '22 01:10

fadden