安卓相机2 API。设置多个ImageReader表面会导致空白输出。

5
我有一个相机2的实现。当前设置是,它使用纹理视图表面来显示实际的相机视图,并使用一个ImageReader表面来捕获图像。
现在我想要捕获预览帧。所以我尝试添加一个新的ImageReader表面来捕获帧。但是当我将该表面添加到createCaptureSession请求中时,屏幕变空白了。可能出了什么问题?下面是我用来向createCaptureSession添加表面的代码。
val surface = preview.surface
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

val previewIRSurface = previewImageReader?.surface
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

val captureSurface = captureImageReader?.surface
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

try {
    val template = if (zsl) CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG else CameraDevice.TEMPLATE_PREVIEW

    previewRequestBuilder = camera?.createCaptureRequest(template)
            ?.apply { addTarget(surface) }
            ?: throw CameraAccessException(CameraAccessException.CAMERA_ERROR)

    val surfaces: ArrayList<Surface> = arrayListOf(surface, previewIRSurface, captureSurface)

    camera?.createCaptureSession(surfaces, sessionCallback, backgroundHandler)

} catch (e: CameraAccessException) {
    throw RuntimeException("Failed to start camera session")
}

图像读取器的初始化如下所示。
private fun prepareImageReaders() {

    val largestPreview = previewSizes.sizes(aspectRatio).last()

    previewImageReader?.close()

    previewImageReader = ImageReader.newInstance(
            largestPreview.width,
            largestPreview.height,
            internalOutputFormat,
            4 // maxImages
    ).apply { setOnImageAvailableListener(onPreviewImageAvailableListener, backgroundHandler) }

    val largestPicture = pictureSizes.sizes(aspectRatio).last()

    captureImageReader?.close()

    captureImageReader = ImageReader.newInstance(
            largestPicture.width,
            largestPicture.height,
            internalOutputFormat,
            2 // maxImages
    ).apply { setOnImageAvailableListener(onCaptureImageAvailableListener, backgroundHandler) }
}

以上使用的参数的更多澄清:

  • internalOutput 格式为 ImageFormat.JPEGImageFormat.YUV_420_888
  • 图像大小基于最佳可能大小。
  • 单独使用任一图像阅读器均可正常工作,但只要将两者结合起来使用,屏幕就会变成空白!
  • 在安卓 Oreo (8.0) 上的三星 Galaxy S8 进行测试。

原始代码在这里:https://github.com/pvasa/cameraview-ex/blob/development/cameraViewEx/src/main/api21/com/priyankvasa/android/cameraviewex/Camera2.kt

1个回答

2
maxImages == 4 可能太多了,会耗尽您的RAM。此外,不清楚您使用的 internalOutputFormat 是什么,并且它是否与 largestPreview 大小兼容。
总之,请查看长列表,以了解支持的表面列表参数,以便使用 createCaptureSession()。根据您的相机功能,您使用的三个表面可能太多。
从下面的评论中,一个可行的解决方案:"错误本身并没有说太多[...]但是在搜索时发现,JPEG格式不支持多个表面。将其更改为YUV_420_888后,它可以完美运行。"

1
谢谢你的快速回复,Alex。我会在原始帖子中添加关于所有这些的澄清。internalOutputFormatImageFormat.JPEG,我也尝试过使用ImageFormat.YUV_420_888,但结果相同。此外,maxImages = 4在这种情况下是安全的,因为只有在完成当前帧后才会请求下一帧。如果我不使用另一个图像读取器,两个图像读取器都可以单独工作。但是一起使用时只有空白屏幕。我想知道设备是否相关。如果是这样,我正在测试Android 8.0上的Samsung Galaxy S8 - priyank
2
正如Alex所说,您可以添加到捕获会话中的同时输出数量是有限制的。在会话创建或提交第一个捕获请求时应该会出现错误,因此请尝试检查是否有任何捕获错误被报告给您的应用程序。或者检查捕获会话创建是否返回错误回调。 - Eddy Talvala
1
@EddyTalvala 感谢您指出异常。错误本身并没有提供太多信息 Stream configuration failed due to: endConfigure:434,但在搜索后发现,JPEG格式不支持多个表面。将其更改为 YUV_420_888 后,它可以完美地工作。 - priyank
1
是的,JPEG 是图像格式之王。我的意思是,在捕获会话中可能只有一个 JPEG,或者没有。 - Alex Cohn
1
这非常有用!我已经将其中一些评论编辑到答案中,因为它解决了我的问题。 - glenatron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接