0

我正在开发一个具有预览/本地录制/实时流/AI 功能的项目。

所有这些功能都可能随时被激活/停用。

并且每个流在特定的帧速率下都有自己的分辨率,并带有自定义的水印。

所以我正在为此寻找解决方案,

如果解决方案能够在用户体验和效率上取得平衡,那就太好了。

我学到的潜在解决方案。

----

[Android 相机 API2]

通过将不同的目标输出表面激活为相机重复请求。

优点:

  1. 易于拆分为不同的分辨率。

缺点:

  1. 替换重复请求将引入帧间隙和明显的抖动。
  2. 无法控制每个输出表面的 fps,并且可能会减慢整个请求的 fps。(yuv 数据提取的输出表面和 ImageReader 太多)
  3. 支持有限的输出表面。(通常 3 个)
  4. 不知道如何对每个流进行帧后处理,例如添加水印。

[Android Camera API2 + libyuv]

将一个 ImageReader 添加到 Camera API2 并将 ImageReader 的数据复制到多个流中,并使用 libyuv 为每个流进行缩放/水印。

优点:

  1. 每个流的 FPS 可控。
  2. 即时添加/删除流。

缺点:

  1. 使用 libyuv 进行 sacle/water-mark 的 CPU 负载较高。
  2. 用于处理和传输过多数据缓冲区的高 CPU。
  3. 如果涉及 4K 分辨率,则会出现散热问题。

【安卓相机API2+OpenGLES】

  1. 生成纹理对象。
  2. 创建一个 TextureSurface(纹理对象)。
  3. 将 TextureSurface 馈送到 Camera API2。
  4. 当 FrameAvailable 时更新 TexImage。

通过以下方式添加流:

  1. 使用共享的 GlContext 创建一个线程。
  2. 为输出表面创建 EGLSurface。(SurfaceView/MediaCodec/ImageReader..)
  3. 设置一个周期性定时器(fps 控制)来绘制帧。
  4. 当铃声响起。
  5. BindTexture 并绘制到当前的 EGLSurface。
  6. 将位图混合为水印。
  7. 如果流需要 YUV420 输出,我可以rgbaToYuv通过片段着色器实现,然后 glReadPixels()。

通过以下方式删除流:

  1. 释放相关资源。
  2. 终止此线程。

优点:

  1. 动态添加/删除流而不影响其他流。
  2. 简单的fps控制
  3. 轻松添加水印

缺点:

  1. 可能是 GPU 加载过多?

我真的不确定。我对OpenGLES的东西不是很熟悉。

所以请发表评论。

您如何看待上述解决方案?

哪一个更好?

和任何其他方法?

如果我缺乏理解,请原谅我。

4

0 回答 0