Android 如何将相机流拆分为多个具有不同 fps/分辨率/water_marks 的流以进行预览/录制/实时流/AI

问题描述

我正在处理一个具有预览/本地录制/直播/AI 功能的项目。

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

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

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

如果该解决方案能够在用户体验和效率之间取得平衡就好了。

我学到的潜在解决方案。

----

[Android 相机 API2]

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

优点:

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

缺点:

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

[Android 相机 API2 + libyuv]

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

优点:

  1. 每个流的 Fps 可控。
  2. 动态添加/删除流。

缺点:

  1. 使用 libyuv 对 sacle/water-mark 进行高 cpu 负载
  2. cpu 导致过多的数据缓冲区处理和传输。
  3. 如果涉及 4K 分辨率,则存在热问题。

[Android 相机 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 的东西不是很熟悉。

所以请评论

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

哪个更好?

还有其他方法吗?

如果我的理解有欠缺,请见谅。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)