Android使用ImageReader YUV_420_888曲面并行显示预览并进行处理

时间:2019-11-04 17:07:48

标签: android

背景

我编写了一个使用Camera2并且基本上使用两个输出的库项目:使用SurfaceTexture的预览和使用YUV_420_888 ImageReader的处理输出。 通过将CaptureRequest.SCALER_CROP_REGION设置为匹配所选的输出大小,可以避免对处理图像进行任何放大/缩小操作。

此输出组合当前适用于所有硬件级别,因为我当前使用4倍数码变焦。

目标

我希望能够设置不同的缩放级别(可能是1倍,起初未知),并尽可能保留当前的性能。

问题

为了支持硬件级别低于FULL的设备,我唯一的选择似乎是使用一个输出目标(传感器大小的ImageReader YUV_420_888,保证为LEGACY级别),并以某种方式手动填充预览。 目标尺寸MAXIMUM,因为我不希望进行任何放大/缩小操作,并且一开始不会知道缩放,因此会 ==> 实际的用户感知缩放必须是提供给预览的裁剪。

现在只有一个输出,我必须找到一种有效的方式:

  1. 格式化+裁剪YUV数据。
  2. 将结果传递到预览图。

我花了很多时间寻找解决方案,例如herehere

最初,我想使用RenderScript,但由于它在库项目中不起作用,因此不得不放弃它。然后我尝试使用NDK,但这涉及处理YUV到RGB的转换(比Java快,但对于大图像仍然很慢)。

所以我现在正在考虑MediaCodec / EGL方法。但是,我没有太多经验,所以我有点迷路。我已经阅读了很多有关MediaCodec的信息,据推测它可以使您skip the format conversion,但是我在解决这些CTS示例和理解如何链接ImageReader表面时遇到了问题和预览表面(由SurfaceTexture制成)。 This example被认为是相关的,但是我不知道如何交互。 大概我应该从YUV曲面创建一个InputSurface,然后创建一个编码器,然后从预览曲面创建一个OutputSurface,并分配一个进行裁剪的着色器,并为其配置解码器。

这是正确的方法吗?是否需要像here中那样管理所有缓冲区?我可以真正跳过转换吗?

会使用eglCreateWindowSurfaceas mentioned by Eddy Talvala be better吗?有人有很好的榜样吗?

编辑

在发现无法使用我想要的尺寸(UHD being the max, when available...)之前,我曾尝试(失败)以下列方式使用MediaCodec(以减轻颜色格式转换的负担):

  • SurfaceSurface ==>将ImageReader表面设置为input surface,将SurfaceTexture制成的表面设置为输出。

  • BufferSurface ==>将Camera2 Images馈送到解码器。

    • 编解码器大小限制显然仍然是一个问题。但是,即使图像较小:
      • 我从没能获得getInputImage(onInputBufferAvailable)返回非空图像
      • 将Camera2 Image转换为连续的YUV I420字节缓冲区并将其馈送到解码器需要花费时间(本机代码),与直接使用本机方法相比,我不确定这是一个大胜利。

0 个答案:

没有答案