在 Android 中,我需要一种有效的方法来修改相机流,然后再将其显示在屏幕上。 This post讨论了几种这样做的方法,我能够实现第一种:
- 从onPreviewFrame获取帧缓冲区
- 将帧转换为 YUV
- 修改框架
- 将修改后的帧转换为 jpeg
- 将框架显示到放置在 SurfaceView 上的 ImageView,用于 预览
这确实有效,但将我通过常规相机预览获得的 30 fps 降低到了 5 fps 左右。从不同图像空间来回转换帧也很耗电,这是我不希望的。
是否有关于如何直接访问原始帧而不必经过这么多转换的示例?使用 OpenGL 是执行此操作的正确方法吗?这一定是一件很常见的事情,但我找不到好的例子。
注意:为了向后兼容,我宁愿避免使用 Camera2 API。
最佳答案
基于 CPU 的管道的最有效形式如下所示:
- 从 Surface 上的相机接收帧,而不是以
byte[]
形式接收帧。使用Camera2,您可以将帧直接发送到ImageReader ;这将使您的 CPU 能够访问来自相机的原始 YUV 数据,而无需复制或转换它。 (我不确定如何使用旧的 Camera API 来配置它,因为它需要 SurfaceTexture 或 SurfaceHolder,而 ImageReader 不提供这些。您可以通过 SurfaceTexture 运行帧并从获取 RGB 值glReadPixels()
,但我不知道这是否会给你带来任何东西。) - 对 YUV 数据进行修改。
- 将 YUV 数据转换为 RGB。
- 将 RGB 数据转换为位图或 GLES 纹理。 glTexImage2D会更高效,但 OpenGL ES 的学习曲线很陡峭。如果您决定走这条路,您需要的大部分内容都在 Grafika 中(例如 texture upload benchmark )。
- 渲染图像。根据您在步骤 #4 中所做的操作,您可以通过 custom View 上的 Canvas 渲染位图。 ,或者在 SurfaceView 或 TextureView 上使用 GLES 渲染纹理。
我认为最显着的加速是消除 JPEG 压缩和解压缩,所以您应该从这里开始。将帧编辑器的输出转换为位图,然后将其绘制在 TextureView 或自定义 View 的 Canvas 上,而不是转换为 JPEG 并使用 ImageView。如果这不能让您获得想要的加速,请找出导致您速度减慢的原因,并在管道的该部分上进行工作。
关于android - Android中显示定制视频的高效路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31252840/