同步摄像头预览和处理

时间:2013-08-26 16:58:25

标签: android opengl-es

我正在设计一个具有OpenGL处理​​管道(着色器集合)的应用程序,同时要求最终用户查看未处理的相机预览。

为了举例,假设您要向用户显示相机预览,同时计算从相机接收的场景中的红色对象数,但是您使用任何着色器来计算对象,例如用户不应该看到色调过滤等。

我该如何正确设置?

我知道我可以设置摄像头预览然后在回调上接收YUV格式的相机帧数据,然后将其转储到OpenGL纹理中并以这种方式处理帧,但这会产生与之相关的性能问题。我必须将数据从摄像头硬件往返到VM,然后将其传递回GPU内存。我正在使用SurfaceTexture直接以OpenGL可理解的格式从摄像机获取数据,并将其传递给我的着色器以解决此问题。

我以为我能够向最终用户显示相同的未处理SurfaceTexture,但TextureView没有构造函数或setter,我可以将SurfaceTexture传递给它我希望它呈现。它总是创造自己的。

这是我当前设置的概述:

  • GLRenderThread:此类从Thread扩展,设置OpenGL上下文,显示等,并使用SurfaceTexture作为表面(eglCreateWindowSurface的第3个参数)。
  • GLFilterChain:对输入纹理执行检测的着色器集合。
  • 相机:使用单独的SurfaceTexture作为GLFilterChain的输入并抓取相机的预览
  • 最后是一个显示GLRenderThread的SurfaceTexture
  • 的TextureView

显然,通过这种设置,我向用户显示处理过的帧,这不是我想要的。此外,帧的处理不是实时的。基本上,我从Camera通过链运行输入一次,所有过滤器完成后,我调用updateTexImage从相机抓取下一帧。我在Nexus 4上的处理速度约为每秒10帧。

我觉得我可能需要使用2个GL上下文,一个用于实时预览,一个用于处理,但我不确定。我希望有人能把我推向正确的方向。

2 个答案:

答案 0 :(得分:0)

你能上传一些你正在使用的代码吗?

您可以在为最初显示预览时使用的曲面视图创建的纹理上调用glDrawArrays,然后将其刷新并将单独的纹理与其他纹理绑定以进行分析?

之类的东西
GLES20.glUseProgram(simpleProgram);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[0]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

GLES20.glUseProgram(crazyProgram);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textures[1]);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

将相机的预览表面纹理绑定到纹理[0],然后为纹理创建单独的表面纹理[1]

可能?

答案 1 :(得分:0)

除非您的处理速度比实时慢,否则答案很简单:只保持原始相机纹理不变,将处理后的图像计算为不同的纹理,并在单个GLView中并排显示给用户。保持一个线程,因为无论如何所有处理都发生在GPU上。多线程只会使问题复杂化。

处理步骤的数量并不重要,因为可以有任意数量的中间纹理(也见乒乓)从未向用户显示 - 没有人也没有任何东西迫使你去。

实时概念在这里可能令人困惑。只需将框架视为不可分割的时间快照。通过这样做,您将忽略图像从相机到屏幕所需的延迟,但如果您可以将其保持在交互式帧速率(例如每秒至少20帧),那么这主要是忽略。

另一方面,如果你的处理速度慢得多,你需要在相机输入中引入延迟并仅在每第N帧处理之间做出选择,或者交替地实时显示每个相机帧并让下一个处理过框架滞后。要做到这一点,您可能需要两个单独的渲染上下文来启用异步处理,这可能在Android上很难做到(或者可能就像创建第二个GLView一样简单,因为您可以在没有上下文之间的数据共享的情况下生存)。

相关问题