我正在开发一个具有预览/本地录制/实时流/AI 功能的项目。
所有这些功能都可能随时被激活/停用。
并且每个流在特定的帧速率下都有自己的分辨率,并带有自定义的水印。
所以我正在为此寻找解决方案,
如果解决方案能够在用户体验和效率上取得平衡,那就太好了。
我学到的潜在解决方案。
----
[Android 相机 API2]
通过将不同的目标输出表面激活为相机重复请求。
优点:
- 易于拆分为不同的分辨率。
缺点:
- 替换重复请求将引入帧间隙和明显的抖动。
- 无法控制每个输出表面的 fps,并且可能会减慢整个请求的 fps。(yuv 数据提取的输出表面和 ImageReader 太多)
- 支持有限的输出表面。(通常 3 个)
- 不知道如何对每个流进行帧后处理,例如添加水印。
[Android Camera API2 + libyuv]
将一个 ImageReader 添加到 Camera API2 并将 ImageReader 的数据复制到多个流中,并使用 libyuv 为每个流进行缩放/水印。
优点:
- 每个流的 FPS 可控。
- 即时添加/删除流。
缺点:
- 使用 libyuv 进行 sacle/water-mark 的 CPU 负载较高。
- 用于处理和传输过多数据缓冲区的高 CPU。
- 如果涉及 4K 分辨率,则会出现散热问题。
【安卓相机API2+OpenGLES】
- 生成纹理对象。
- 创建一个 TextureSurface(纹理对象)。
- 将 TextureSurface 馈送到 Camera API2。
- 当 FrameAvailable 时更新 TexImage。
通过以下方式添加流:
- 使用共享的 GlContext 创建一个线程。
- 为输出表面创建 EGLSurface。(SurfaceView/MediaCodec/ImageReader..)
- 设置一个周期性定时器(fps 控制)来绘制帧。
- 当铃声响起。
- BindTexture 并绘制到当前的 EGLSurface。
- 将位图混合为水印。
- 如果流需要 YUV420 输出,我可以
rgbaToYuv
通过片段着色器实现,然后 glReadPixels()。
通过以下方式删除流:
- 释放相关资源。
- 终止此线程。
优点:
- 动态添加/删除流而不影响其他流。
- 简单的fps控制
- 轻松添加水印
缺点:
- 可能是 GPU 加载过多?
我真的不确定。我对OpenGLES的东西不是很熟悉。
所以请发表评论。
您如何看待上述解决方案?
哪一个更好?
和任何其他方法?
如果我缺乏理解,请原谅我。