Camera onPreviewFrame() 未在某些设备上调用(不存在预览显示)

Camera onPreviewFrame() is not called on some devices (no preview display present)

在我的两个设备之一上,onPreviewFrame 没有被调用,尽管我使用了相同的代码。

我正在尝试获取、处理(使用 OpenCV),然后使用已弃用的相机 API 显示相机帧。 (因为我使用的是 LEGACY 设备并且已弃用的 API 为其提供了更好的性能。)

这意味着我不想直接显示预览帧,但我可以确定在这个设备上,设置显示是进行预览所必需的。这意味着我必须设置某种高性能虚拟显示器。我的选择是:setPreviewDisplay -> SurfaceHoldersetPreviewTexture -> SurfaceTexture.

我了解到的另一件事是 setPreviewCallbackWithBuffer 在此设备上也不起作用:我必须使用 setPreviewCallback.

理想情况下,我想检测是否需要这些额外步骤才能使预览正常工作:如果不需要,我不想在不需要它们的设备上执行这些操作。

我找不到 setPreviewDisplay 方法的虚拟 SurfaceHolder,因此我无法使用它来调用预览回调。另一方面,带有新 SurfaceTexturesetPreviewTexture 确实会调用 onPreviewFrame,但我经常收到 "BufferQueue has been abandoned" 错误,而且预览数据似乎也不正确:虽然我设置了图像格式,从所述数据创建的图像不正确。查看不同的颜色会导致图像显示不同的颜色。同样,相同的代码在另一台设备上工作,我设置了图像格式,因此输出应该有效。

我当前的代码,其中调用了 onPreviewFrame,但数据无效:

camera = Camera.open();
camera.setPreviewTexture(new SurfaceTexture(1));
camera.setPreviewCallback(this);
camera.setParameters(configurator.getParameters()); //sets the resolution (same on both devices), the fps range and the format to ImageFormat.YV12 (or NV21, makes no difference)
camera.startPreview();

不需要预览显示的phone:Doogee X5 MAX
phone 有问题:Samsung Galaxy J3 (2016)

Re: 虚拟预览纹理,这是您可以获得的最佳解决方法。官方 API 要求预览必须在某个地方进行,大多数设备都强制执行此政策。

无法在 运行 时检查设备是否在没有 'sink'(表面或纹理)可供绘制的情况下提供实时预览。在其他类似情况下,我们被迫根据 QA 实验室实验和最终用户投诉维护设备的白名单和黑名单。对于某些功能,技术是在您的应用程序(在特定设备上)的第一个 运行 上尝试最佳设置,如果它崩溃或失败,则在第二次尝试时使用效率较低的替代方案,并且将此标志保留在 SharedPreferences 中以供将来发布。

幸运的是,添加虚拟 SurfaceTexture 不会对性能产生负面影响,即使在没有它也可以工作的设备上也是如此。

为了避免 "BufferQueue has been abandoned" 错误,add 将虚拟 SurfaceTexture 作为字段 activity 或片段。

setPreviewCallbackWithBuffer 没有工作,因为缓冲区太小。在我摆脱 "BufferQueue has been abandoned" 错误之前,我没有看到错误。缓冲区太小的原因是:

  • 我没有查询预览尺寸,我只是用了我设置预览尺寸的值

  • 我调用了 Camera.Parameters#setRecordingHint(true),它将我的分辨率(可能还有其他设置)锁定为硬编码值。这个分辨率和我选择的不一样,所以我的buffer确实太小了