前言

CameraX 基于 Camera2 构建而成,并且 CameraX 提供了在 Camera2 实现中读取甚至写入属性的方式。如需了解完整详情,请参阅互操作性软件包

那么该如何使用呢

注意:在 CameraX 中,设置底层 Camera2 属性会被标记为“实验性”,因为 Google 希望开发者能了解其使用情况。您设置的值会替换 CameraX 所设置的任何值。我们建议您仅在绝对必要时执行此操作,也建议在您这一端进行其他测试。

Camera2CameraInfo

使用 Camera2CameraInfo 读取底层 CameraCharacteristics

1
2
3
4
5
val c2ci = Camera2CameraInfo.from(cameraInfo)
c2ci.apply {
// 获取设备支持的硬件级别
val level = getCameraCharacteristic(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) ?: INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED
}

Camera2CameraControl

使用 Camera2CameraControl,它让您可以在底层 CaptureRequest 上设置属性,例如自动AWB模式。

1
2
3
4
5
6
val c2cc = Camera2CameraControl.from(cameraControl)
c2cc.captureRequestOptions = CaptureRequestOptions.Builder()
.setCaptureRequestOption(CaptureRequest.CONTROL_AWB_MODE, CaptureRequest.CONTROL_AWB_MODE_OFF)
.setCaptureRequestOption(CaptureRequest.COLOR_CORRECTION_MODE, CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX)
.setCaptureRequestOption(CaptureRequest.COLOR_CORRECTION_GAINS, ColorTemperatureConverter.colorTemperature(2000))
.build()

Camera2Interop.Extender

使用 Camera2Interop.Extender 扩展 CameraX UseCase。这样您就可以在 CaptureRequest 上设置属性,就像使用 Camera2CameraControl 一样。它还提供了一些额外的控件,例如设置数据流用例以根据您的使用场景优化相机。

以下代码示例使用数据流用例来优化视频通话。使用 Camera2CameraInfo 可提取视频通话流用例是否可用。然后,使用 Camera2Interop.Extender 设置底层数据流用例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Set underlying Camera2 stream use case to optimize for video calls.

val videoCallStreamId =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL.toLong()

// Check available CameraInfos to find the first one that supports
// the video call stream use case.
val frontCameraInfo = cameraProvider.getAvailableCameraInfos()
.first { cameraInfo ->
val isVideoCallStreamingSupported = Camera2CameraInfo.from(cameraInfo)
.getCameraCharacteristic(
CameraCharacteristics.SCALER_AVAILABLE_STREAM_USE_CASES
)?.contains(videoCallStreamId)
val isFrontFacing = (cameraInfo.getLensFacing() ==
CameraSelector.LENS_FACING_FRONT)
(isVideoCallStreamingSupported == true) && isFrontFacing
}

val cameraSelector = frontCameraInfo.cameraSelector

// Start with a Preview Builder.
val previewBuilder = Preview.Builder()
.setTargetAspectRatio(screenAspectRatio)
.setTargetRotation(rotation)

// Use Camera2Interop.Extender to set the video call stream use case.
Camera2Interop.Extender(previewBuilder).setStreamUseCase(videoCallStreamId)

// Bind the Preview UseCase and the corresponding CameraSelector.
val preview = previewBuilder.build()
camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Set underlying Camera2 stream use case to optimize for video calls.

Long videoCallStreamId =
CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_CALL.toLong();

// Check available CameraInfos to find the first one that supports
// the video call stream use case.
List<CameraInfo> cameraInfos = cameraProvider.getAvailableCameraInfos();
CameraInfo frontCameraInfo = null;
for (cameraInfo in cameraInfos) {
Long[] availableStreamUseCases = Camera2CameraInfo.from(cameraInfo)
.getCameraCharacteristic(
CameraCharacteristics.SCALER_AVAILABLE_STREAM_USE_CASES
);
boolean isVideoCallStreamingSupported = Arrays.List(availableStreamUseCases)
.contains(videoCallStreamId);
boolean isFrontFacing = (cameraInfo.getLensFacing() ==
CameraSelector.LENS_FACING_FRONT);

if (isVideoCallStreamingSupported && isFrontFacing) {
frontCameraInfo = cameraInfo;
}
}

if (frontCameraInfo == null) {
// Handle case where video call streaming is not supported.
}

CameraSelector cameraSelector = frontCameraInfo.getCameraSelector();

// Start with a Preview Builder.
Preview.Builder previewBuilder = Preview.Builder()
.setTargetAspectRatio(screenAspectRatio)
.setTargetRotation(rotation);

// Use Camera2Interop.Extender to set the video call stream use case.
Camera2Interop.Extender(previewBuilder).setStreamUseCase(videoCallStreamId);

// Bind the Preview UseCase and the corresponding CameraSelector.
Preview preview = previewBuilder.build()
Camera camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview)

参考

Android CameraX 架构