SurfaceTexture updateTexImage to shared 2 EGLContexts - Android 4.4上的问题

时间:2013-12-05 09:46:44

标签: android textures mediacodec

我指的是如何将摄像机的预览帧直接编码为mp4文件的优秀示例: http://bigflake.com/mediacodec/CameraToMpegTest.java.txt

我采用的方式是我也希望在屏幕上呈现预览图像。因此,我得到了一个类似GLTextureView的东西,它有自己的EGLContext。当我为编码器渲染创建EGLContext时,此Context用作共享EGLContext:

mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], sharedContext == null ? EGL14.EGL_NO_CONTEXT : sharedContext,
                attrib_list, 0);

在我的渲染循环中,我遵循了fadden的提示......对于我执行以下操作的每一帧:

  1. 首先我等待新图像到达SurfaceTexture并带有awaitNewImage()
  2. 然后我将GLTextureView的上下文设置为当前并在其上呈现框架
  3. 之后我将编码器上下文设置为当前并在其上渲染帧
  4. 看起来像这样:

    mFrameWatcher.awaitNewImage();
    mSurfaceTexture.updateTexImage();
    _textureView.getEGLManager().makeCurrent();
    _textureView.requestRender();
    mInputSurface.makeCurrent();
    mInputSurface.requestRender();
    

    虽然我只使用Android 4.3的Nexus 4进行测试,但效果很好。

    然而,由于我使用Android 4.4获得了新的Nexus 5,因此编码器每秒只能从SurfaceTexture获得2个不同的帧...但是这两个帧被重复绘制......所以他编码相同帧的15倍。尽管我的GLTextureView每帧有30个不同的帧,但帧的渲染是正确的。 我首先想到这可能是一个Nexus 5问题 - 所以我将另一个Nexus 4更新为Android 4.4 ......但现在Nexus 4也是如此。

    我玩了一下 - 最后我能够通过在切换时将SurfaceTexture分离并重新附加到不同的上下文来解决问题。这看起来像这样:

    mFrameWatcher.awaitNewImage();
    mSurfaceTexture.updateTexImage();
    _textureView.getEGLManager().makeCurrent();
    _textureView.requestRender();
    mSurfaceTexture.detachFromGLContext();
    mInputSurface.makeCurrent();
    mSurfaceTexture.attachToGLContext(_textureViewRenderer.getTextureId());
    mInputSurface.requestRender();
    mSurfaceTexture.detachFromGLContext();
    _textureView.getEGLManager().makeCurrent();
    mSurfaceTexture.attachToGLContext(_textureViewRenderer.getTextureId());
    

    我现在的问题是:这是正确的方法吗?老实说,当我使用共享上下文时,我认为不需要重新附加SurfaceTexture。此外,重新连接需要相当长的时间...每帧的3-6毫秒,在12毫秒时偷看,这可以更好地用于渲染。我在这里做错了什么?为什么在没有重新连接SurfaceTexture的情况下,它在4.3版本的Nexus 4上有魅力呢?

1 个答案:

答案 0 :(得分:4)

看起来这实际上和this question的问题相同。我在那里写了一些细节;简而言之,您应该能够通过解除绑定和重新绑定纹理来修复它,这实际上就是您使用笨拙的附加/分离序列所做的事情。

在我的代码中,我可以通过更改它来修复它:

GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);

到此:

GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, 0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTextureID);

在我的纹理渲染器中。我稍后会更新bigflake示例。