在Camera2中预览callback比在Camera1中显着慢

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

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

这是我如何创buildImageReader

 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() ); 

callback本身做的是尽可能less的工作:

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

我已经检查过类似的答案,比如这个 。 然而,他们的问题是,他们正在使用JPEG图像格式,而不是YUV_420_888

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

Solutions Collecting From Web of "在Camera2中预览callback比在Camera1中显着慢"

这只是一个观察,但我会发布它。

你说你正在注册一个OnImageAvailableListener 。 此侦听器不会传递图像,而是对您订阅的相同ImageReader的引用。 然后,您必须调用acquireLatestImageacquireNextImage来获取实际的图像。

文档中有一段可能有助于理解正在发生的事情:

图像数据被封装在Image对象中,并且可以同时访问多个这样的对象,直到由maxImages构造器参数指定的数目。 发送到ImageReader通过Surface的新图像排队,直到通过acquireLatestImage()acquireNextImage()调用进行访问。 由于内存限制,如果ImageReader没有以等于生产速率的速率获取和释放图像,则图像源将最终在尝试渲染到“表面”时停止或放下图像。

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

  • 在清单中请求大内存
  • 将足够大的maxImagesparameter passing给ImageReader构造函数(如果您使用了队列,则会得到IllegalStateException )。
  • 通过acquireNextImage获取acquireNextImage以进行实时处理。 该方法自动释放较旧的图像,而另一个则不释放,因此错误地使用acquireNextImage将会越来越acquireNextImage地传送图像,直到内存不足。

在支持Camera1和Camera2 API的应用程序上,我遇到了相同的性能问题。 当Android版本高于棒棒糖我用来切换到Camera2 API导致非常糟糕的performance(我有两个目标在时间:ImageReader和表面)。

只有当手机有完整的硬件支持时,我才能使用Camera2 API。 您可以使用CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL进行检查

希望能帮助到你