如何在GLSurfaceView中使用MediaMuxer / MediaCodec InputSurface?

时间:2013-10-31 06:19:28

标签: java android opengl-es egl mediacodec

BigFlake示例之后,有一条评论声明:

// 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.

我使用EGL14.getCurrentContext()查询当前上下文并将其传递给EGL14.eglCreateContext() share_context参数,但是如何“切换EGL上下文”?

GLSurfaceView和MediaCodec.inputSurface有两个不同的表面和两个不同的上下文,所以我假设你只是在每个集上单独调用eglMakeCurrent(),这是正确的吗?您需要eglDestroyContext()还是eglDestroySurface()

已添加更新

谢谢Fadden,我想我发现了这个错误,而不是drawFrame我调用了drawImage,但你不应该再次更新图像,对吧?

现在我在设置EOS后调用dequeueBuffer时出现内存不足错误glError 1285 ???也许我在录音停止后调用它。谢谢你的帮助。

在MyEGLWrapper.java中创建EGLSurface

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");
}

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

在SurfaceTextureManager.java

public ByteBuffer drawImage(boolean updateImage) {
    // Latch the data.
    if (updateImage){
        mTextureRender.checkGlError("before updateTexImage");
        mSurfaceTexture.updateTexImage();
    }
    return mTextureRender.drawFrame(mSurfaceTexture);
}
mSurfaceTexture.updateTexImage(); SurfaceTextureManager.java 中的

错误

1 个答案:

答案 0 :(得分:5)

是的,使用eglMakeCurrent在两个上下文之间切换。

你不需要破坏你当前没有使用的上下文或表面(无论如何你要关闭它们。)

有关使用共享上下文呈现两次的示例,请参阅bigflake Breakout game recorder patch