我需要对实时摄像机数据(仅来自Y平面)执行CPU端只读过程,然后在GPU上进行渲染.在处理完成之前不应渲染帧(因此我并不总是希望从摄像机渲染最新帧,只是CPU端已完成处理的最新帧).渲染与相机处理分离,即使相机帧以低于此速率的速度到达,目标也是60 FPS.
在Android上有一个相关但更高级别的问题:最低开销的相机到CPU到GPU的方法
更详细地描述当前设置:我们有一个用于摄像机数据的应用程序端缓冲池,其中缓冲区是"空闲","显示"或"待处理显示".当来自摄像机的新帧到达时,我们获取一个空闲缓冲区,在那里存储帧(或者如果实际数据在某个系统提供的缓冲池中,则对它进行引用),进行处理并将结果存储在缓冲区中,然后设置缓冲区"待处理显示".在渲染器线程中,如果在渲染循环开始处有任何缓冲区"待处理显示",我们将其锁定为"显示"中的一个,渲染相机,并使用从其计算的处理信息渲染其他内容相机框架.
感谢@ fadden对上面链接的问题的回复,我现在明白了android camera2 API的"并行输出"功能在各种输出队列之间共享缓冲区,因此不应该涉及数据上的任何副本,至少在现代android上.
在评论中有一个建议,我可以同时锁定SurfaceTexture和ImageReader输出,只是"坐在缓冲区",直到处理完成.不幸的是,我不认为这适用于我的情况,因为我们仍然希望以60 FPS驱动的解耦渲染,并且仍然需要访问前一帧,同时处理新帧以确保无法获得不同步.
我想到的一个解决方案是拥有多个SurfaceTextures - 我们每个应用程序端缓冲区中都有一个(我们目前使用3个).使用该方案,当我们获得一个新的相机帧时,我们将从我们的应用程序池中获得一个空闲缓冲区.然后我们调用acquireLatestImage()ImageReader获取要处理的数据,并updateTexImage()在空闲缓冲区中调用SurfaceTexture.在渲染时我们只需要确保来自"in display"缓冲区的SufaceTexture是绑定到GL的那个,并且所有内容都应该在大多数时间同步(因为@fadden评论说在调用updateTexImage()和之间存在争用acquireLatestImage()但是时间窗口应该足够小以使其变得罕见,并且无论如何使用缓冲区中的时间戳可能是可行的和可修复的).
我注意到文档updateTexImage()只能在SurfaceTexture绑定到GL上下文时调用,这表明我在相机处理线程中也需要GL上下文,因此相机线程可以updateTexImage()在"免费"缓冲区中的SurfaceTexture上执行而渲染线程仍然能够从"显示"缓冲区中的SurfaceTexture渲染.
所以,对于问题:
这听起来很有希望,我会试一试; 但是,如果有人(基本上是@fadden!)知道任何我忽略的内部细节会让这个想法变得糟糕,那么我觉得值得一试.