Android NDK开发详解相机之Camera2 Extensions API
注意:本页介绍的是 Camera2 软件包。除非您的应用需要 Camera2 的特定低层级功能,否则我们建议您使用 CameraX。CameraX 和 Camera2 都支持 Android 5.0(API 级别 21)及更高版本。
Camera2 提供了一个 Extensions API,用于访问设备制造商在各种 Android 设备上实现的扩展。如需查看支持的扩展模式列表,请参阅相机扩展。
如需查看支持扩展的设备列表,请参阅支持的设备。
扩展架构
下图显示了相机扩展程序架构。
图 1. 相机扩展架构
Camera2 应用可以通过 Camera2 API 使用扩展。Camera2 API 提供了查询可用扩展、配置扩展相机会话以及与相机扩展 OEM 库通信的方法。这样,您的应用就可以使用夜间、HDR、自动、焦外成像或脸部照片修复等扩展程序。
测试相机设备的 Camera2 Extensions API 兼容性
以下代码段会检查设备是否支持 Camera2 Extensions API。并非所有设备都支持扩展,或者设备可能支持一部分扩展。该代码段会返回支持相机扩展的兼容相机 ID 的列表。
Kotlin
private fun getExtensionCameraIds(cameraManager: CameraManager): List =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
cameraManager.cameraIdList.filter { cameraId ->
val characteristics = cameraManager.getCameraCharacteristics(cameraId)
val extensionCharacteristics =
cameraManager.getCameraExtensionCharacteristics(cameraId)
val capabilities =
characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)
extensionCharacteristics.supportedExtensions.isNotEmpty() &&
capabilities?.contains(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
) ?: false
}
} else emptyList()
Java
private List getExtensionCameraIds(CameraManager cameraManager)
throws CameraAccessException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
return Arrays.stream(cameraManager.getCameraIdList()).filter(cameraId -> {
try {
CameraCharacteristics characteristics =
cameraManager.getCameraCharacteristics(cameraId);
CameraExtensionCharacteristics extensionCharacteristics =
cameraManager.getCameraExtensionCharacteristics(cameraId);
IntStream capabilities =
Arrays.stream(
characteristics.get(
CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES
)
);
return !extensionCharacteristics.getSupportedExtensions().isEmpty() &&
capabilities.anyMatch(capability -> capability == CameraCharacteristics
.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
);
} catch (CameraAccessException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
} else {
return Collections.emptyList();
}
}
使用 Camera2 Extensions API 创建 CameraExtensionSession
与兼容的设备搭配使用时,Camera2 Extensions API 可让您访问某些相机扩展。以下代码段举例说明了如何创建 CameraExtensionSession,以便为现有 Camera2 应用使用夜间拍摄模式。
Kotlin
private val captureCallbacks = object : CameraExtensionSession.ExtensionCaptureCallback() {
// Implement Capture Callbacks
}
private val extensionSessionStateCallback = object : CameraExtensionSession.StateCallback() {
override fun onConfigured(session: CameraExtensionSession) {
cameraExtensionSession = session
try {
val captureRequest =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(previewSurface)
}.build()
session.setRepeatingRequest(
captureRequest,
Dispatchers.IO.asExecutor(),
captureCallbacks
)
} catch (e: CameraAccessException) {
Snackbar.make(
previewView,
"Failed to preview capture request",
Snackbar.LENGTH_SHORT
).show()
requireActivity().finish()
}
}
override fun onClosed(session: CameraExtensionSession) {
super.onClosed(session)
cameraDevice.close()
}
override fun onConfigureFailed(session: CameraExtensionSession) {
Snackbar.make(
previewView,
"Failed to start camera extension preview",
Snackbar.LENGTH_SHORT
).show()
requireActivity().finish()
}
}
private fun startExtensionSession() {
val outputConfig = arrayListOf(
OutputConfiguration(stillImageReader.surface),
OutputConfiguration(previewSurface)
)
val extensionConfiguration = ExtensionSessionConfiguration(
CameraExtensionCharacteristics.EXTENSION_NIGHT,
outputConfig,
Dispatchers.IO.asExecutor(),
extensionSessionStateCallback
)
cameraDevice.createExtensionSession(extensionConfiguration)
}
Java
private CameraExtensionSession.ExtensionCaptureCallback captureCallbacks =
new CameraExtensionSession.ExtensionCaptureCallback() {
// Implement Capture Callbacks
};
private CameraExtensionSession.StateCallback extensionSessionStateCallback =
new CameraExtensionSession.StateCallback() {
@Override
public void onConfigured(@NonNull CameraExtensionSession session) {
cameraExtensionSession = session;
try {
CaptureRequest.Builder captureRequestBuilder =
cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
captureRequestBuilder.addTarget(previewSurface);
CaptureRequest captureRequest = captureRequestBuilder.build();
session.setRepeatingRequest(captureRequest, backgroundExecutor, captureCallbacks);
} catch (CameraAccessException e) {
Snackbar.make(
previewView,
"Failed to preview capture request",
Snackbar.LENGTH_SHORT
).show();
requireActivity().finish();
}
}
@Override
public void onClosed(@NonNull CameraExtensionSession session) {
super.onClosed(session);
cameraDevice.close();
}
@Override
public void onConfigureFailed(@NonNull CameraExtensionSession session) {
Snackbar.make(
previewView,
"Failed to start camera extension preview",
Snackbar.LENGTH_SHORT
).show();
requireActivity().finish();
}
};
private void startExtensionSession() {
ArrayList outputConfig = new ArrayList<>();
outputConfig.add(new OutputConfiguration(stillImageReader.getSurface()));
outputConfig.add(new OutputConfiguration(previewSurface));
ExtensionSessionConfiguration extensionConfiguration = new ExtensionSessionConfiguration(
CameraExtensionCharacteristics.EXTENSION_NIGHT,
outputConfig,
backgroundExecutor,
extensionSessionStateCallback
);
}
其他资源
如需了解详情,请参阅 CameraExtensionCharacteristics 并查看公开 Camera2 Extensions API 示例。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2023-11-09。