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

Dmi*_*sev 27 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()
);
Run Code Online (Sandbox Code Playgroud)

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

Image image = reader.acquireNextImage();
image.close();
Run Code Online (Sandbox Code Playgroud)

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

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

Mis*_*ith 2

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

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

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

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

所以一些可能有帮助的事情:

  • 在清单中请求大内存
  • 将足够大的maxImages参数传递给构造函数(无论如何,如果您耗尽队列,ImageReader您就会得到)。IllegalStateException
  • acquireLatestImage更喜欢acquireNextImage实时处理。此方法会自动释放较旧的图像,而另一种方法则不会,因此acquireNextImage错误使用会逐渐减慢图像传输速度,直到内存耗尽。

  • 感谢您的回答。不幸的是,我已经尝试了所有这些,并且它对性能没有丝毫影响(尽管我期望“maxImages”有一些改进,但实际上没有)。 (3认同)