同时进行相机预览和处理

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

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

我将如何正确设置这个?

我知道我可以设置一个摄像头预览,然后在YUV格式的callback接收摄像头帧数据,然后转储成OpenGL纹理,然后处理框架,但是,它有相关的性能问题。 我必须将数据从相机硬件传送到虚拟机,然后将其传回到GPU内存。 我正在使用SurfaceTexture从OpenGL直观的数据获取可理解的格式,并将其传递给我的着色器来解决这个问题。

我以为我能够向最终用户展示同样的未处理的SurfaceTexture ,但是TextureView没有一个构造函数或一个setter,我可以将它传递SurfaceTexture我想要渲染的SurfaceTexture 。 它总是创造自己的。

这是我目前的设置的概述:

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

显然,通过这个设置,我向用户显示了处理过的帧,这不是我想要的。 此外,帧的处理不是实时的。 基本上,我通过链路运行来自摄像头的input,一旦完成所有filter,我调用updateTexImage从摄像头抓取下一帧。 Nexus 4上的处理速度为每秒10帧左右。

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

Solutions Collecting From Web of "同时进行相机预览和处理"

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

你可能能够调用glDrawArrays的纹理创build和绑定到你正在使用的表面视图最初显示预览,然后刷新它,绑定一个单独的纹理与其他纹理进行分析? 就像是

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

其中您的相机的预览surfacetexture绑定到纹理[0],然后为纹理[1]创build一个单独的surfacetexture

也许?

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

处理步骤的数量并不重要,因为可以有任意数量的中间纹理(也可以参见乒乓),这些纹理永远不会显示给用户 – 没有人会强迫你。

实时的概念可能在这里混淆。 只要把一个框架看作是一个不可分割的时间快照。 通过这样做,您将忽略图像从相机到屏幕所需的延迟,但是如果您可以保持交互式帧速率(例如每秒至less20帧),那么这可能主要是忽略。

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