Camera2中的预览回调明显慢于Camera1

时间:2017-04-28 19:29:43

标签: android android-camera2

2017年,我终于开始从Camera1切换到Camera2。在Camera1中,我非常依赖setPreviewCallbackWithBuffer()来执行实时帧处理,但是在Camera2中,它的工作速度要慢得多,几乎无法使用。

相比之下,在Moto G3上Camera1可以很容易地产生30-40 FPS,而在Camera2上我的速度不会超过10-15 FPS。

以下是我创建ImageReader

的方法
imageReader = ImageReader
  .newInstance(
    previewSize.width,        // size is around 1280x720
    previewSize.height,
    ImageFormat.YUV_420_888,  // note, it is not JPEG
    2 // max number of images, does not really affect performance
  );

imageReader.setOnImageAvailableListener(
  callback,
  CameraThread.getInstance().createHandler()
);

回调本身可以完成最小的工作:

Image image = reader.acquireNextImage();
image.close();

我已经检查了类似的答案,例如this one。但问题是,他们使用的是JPEG图片格式,而不是YUV_420_888

如何实现与Camera1类似的性能?

2 个答案:

答案 0 :(得分:3)

我在支持Camera1和Camera2 API的应用上遇到了相同的性能问题。当Android版本高于Lollipop时,我曾经切换到Camera2 API导致非常糟糕的表现(我有两个目标:ImageReader和Surface)。

我最终只在手机有完整的硬件支持时才使用Camera2 API。您可以使用 CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL

进行检查

希望有所帮助

答案 1 :(得分:2)

这只是一个观察,但无论如何我都会发布它。

您说您正在注册OnImageAvailableListener。此侦听器不提供图像,而是对您订阅的同一ImageReader的引用。然后,您必须拨打acquireLatestImageacquireNextImage来获取实际图片。

the docs中有一段可能有助于了解正在发生的事情:

  

图像数据封装在Image个对象中,可以同时访问多个此类对象,最多可达maxImages构造函数参数指定的数量。通过其Surface发送到ImageReader的新图像会排队,直到通过acquireLatestImage()acquireNextImage()调用进行访问。 由于内存限制,如果ImageReader无法以等于生产率的速率获取和释放图像,则图像源最终会在尝试渲染到Surface时停止或丢弃图像。

所以有些事情可能会有所帮助:

  • 在清单中请求大内存
  • 将足够大的maxImages参数传递给ImageReader构造函数(如果你耗尽了队列,你会得到IllegalStateException。)
  • 首选acquireLatestImage超过acquireNextImage 进行实时处理。此方法会自动释放旧图像,而另一个则不会,因此错误地使用acquireNextImage会减慢图像传输速度,直到内存不足为止。