Android 相机 2 api。设置多个 ImageReader 表面会产生空白输出
Android camera2 api. Setting multiple ImageReader surfaces gives blank output
我有一个 camera2 实现。当前的设置是,它使用纹理视图表面来显示实际的相机视图,并使用 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")
}
ImageReader的初始化是这样的
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.JPEG
或 ImageFormat.YUV_420_888
.
- 图像尺寸基于最佳尺寸
- 它可以单独与任何一个图像阅读器一起使用,但一旦我将两者加在一起,就会出现黑屏!
- 使用 Android Oreo (8.0)
在 Samsung Galaxy S8 上进行测试
maxImages == 4 可能太多了,会耗尽您的 RAM。另外,不清楚你用的是什么internalOutputFormat,是否兼容largestPreview尺寸。
最重要的是,研究 createCaptureSession() 支持的表面列表参数的长表列表。根据您的相机功能,您使用的三个表面可能太多了。
根据下面的评论,一个可行的解决方案:"The error itself doesn't say much [...] but upon searching, it is found that multiple surfaces are not supported for JPEG format. Upon changing it to YUV_420_888 it works flawlessly."
我有一个 camera2 实现。当前的设置是,它使用纹理视图表面来显示实际的相机视图,并使用 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")
}
ImageReader的初始化是这样的
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.JPEG
或ImageFormat.YUV_420_888
.- 图像尺寸基于最佳尺寸
- 它可以单独与任何一个图像阅读器一起使用,但一旦我将两者加在一起,就会出现黑屏!
- 使用 Android Oreo (8.0) 在 Samsung Galaxy S8 上进行测试
maxImages == 4 可能太多了,会耗尽您的 RAM。另外,不清楚你用的是什么internalOutputFormat,是否兼容largestPreview尺寸。
最重要的是,研究 createCaptureSession() 支持的表面列表参数的长表列表。根据您的相机功能,您使用的三个表面可能太多了。
根据下面的评论,一个可行的解决方案:"The error itself doesn't say much [...] but upon searching, it is found that multiple surfaces are not supported for JPEG format. Upon changing it to YUV_420_888 it works flawlessly."