在Android API 29中,Camera2用两个物理流替换一个逻辑流。

5
当 Android 9(API 28) 发布时,我很高兴地发现拥有多个相机的手机的物理相机将被公开,我一直很沮丧无法访问它们。今天我偶然发现了 Android Q documentation ,其中提到:
从 API 级别 29 开始,一些或所有物理相机可能不会独立暴露给应用程序,此时物理相机 ID 将不可在 CameraManager.getCameraIdList() 中使用。但是应用程序仍然可以通过调用 CameraManager.getCameraCharacteristics(String) 查询物理相机的特性。
这个声明让我感到困惑,这是否意味着 Android 正在倒退?这个改变的目的是什么?
我对管理相机非常感兴趣,这个改变会阻止我使用 Android 9 能够做的事情吗?
它说ID可能不再列出,但特征仍可查询,那么没有ID,我们该如何获取摄像头的特征?我想我们应该通过逻辑相机上的getPhysicalCameraIds()获取物理相机的ID,但这是否意味着如果我们想使用“隐藏”的相机,我们必须测试一堆随机的ID字符串?

enter image description here

我们是否仍然能够使用SessionConfiguration在未公开的物理相机上创建捕获会话?

有人可以解释一下吗?


你找到从多摄像头中使用特定相机的解决方案了吗?例如最宽的那个?我猜这与camChars.availablePhysicalCameraRequestKeyssetPhysicalCameraKey有关。 - user25
2个回答

4
我尝试使用 Pixel 5(Android 11)第一个逻辑后置摄像头的物理 ID 打开相机,但出现错误:未知的相机 ID...。
因此,Pixel 5 只返回了 2 个逻辑相机 ID,并且只有这两个相机可以使用 cameraManager.openCamera(...) 方法打开... Samsung S10(也是 Android 11)返回 4 个逻辑相机 ID,并且没有任何逻辑相机的物理相机 ID,所有 4 个相机都可以正常使用。 Pixel 5 相机信息:

enter image description here

三星S10 相机信息:

enter image description here

虽然我没有尝试过在Pixel 5上使用setPhysicalCameraId(cameraId)https://developer.android.com/reference/android/hardware/camera2/params/OutputConfiguration.html#setPhysicalCameraId(java.lang.String),但我认为这种方法可以用于在不同的物理相机之间切换(例如,我们可以打开广角相机)

更新

是的,我们可以在Pixel 4、5(以及我猜测还有更多设备和制造商)中使用setPhysicalCameraId方法来设置特定的物理相机

所以逻辑如下:

  1. 您使用相机管理器使用逻辑相机ID打开相机

  2. 然后,如果该逻辑相机支持多摄像头功能,则其应具有非空的物理相机ID列表

  3. 您可以从物理相机ID列表中选择任何ID并将其设置为OutputConfiguration

val outputs = surfaces.map {
    OutputConfiguration(it).apply {
        setPhysicalCameraId(cameraIdx)
    }
}
cameraDevice.createCaptureSessionByOutputConfigurations(
    outputs,
    stateCallback,
    backgroundCameraHandler
)

更新!警告!但是它预览相同的视图,所以看起来这种方法不起作用(尽管没有异常),无论您是否设置物理相机都没有改变。

似乎从Android 10开始出现问题-{{link1:Android 10(api 29)camera2 api regression with wide-angle camera}}。

更新

我还尝试使用SessionConfiguration对象创建捕获会话,而不是过时的方法createCaptureSessionByOutputConfigurations

val config = SessionConfiguration(
    SessionConfiguration.SESSION_REGULAR,
    outputs,
    backgroundCameraExecutor!!,
    stateCallback
)
cameraDevice.createCaptureSession(config)

但仍然没有改变


1
感谢这些更新,虽然它们不符合SO答案的范围,但是它们非常受欢迎。 - Alex Cohn
三星Note 20 Ultra和三星Z Fold 2也提供了4个摄像头ID列表,0表示后置普通(广角)摄像头,1表示前置摄像头,2表示超广角摄像头,3再次表示前置摄像头。这两个设备在摄像头ID列表方面的行为相同。 因此,我想问一下所有具有超广角摄像头的三星设备是否都表现相同(打开摄像头ID-2的超广角摄像头)。 - Saurav_Sharma

1

这不是回溯。实际上,这种概括是提供更好控制复杂相机设置的重要一步。

在 API 29 之前,如果制造商不能为组成复合相机的每个镜头提供单独的 cameraDevice,他们无法向开发人员公开镜头参数。他们唯一的选择是将复合相机作为整体公开。

问题不是

我们是否仍然能够在未公开的物理相机上使用 SessionConfiguration 创建捕获会话?

而是

现在我们可以读取以前无法公开的物理相机的特性‼

通过新的更改,即使没有办法在它们上面启动单独的捕获会话,制造商也可以为您提供有关“后置摄像头1”、“后置摄像头2”等所有可用信息。

getPhysicalCameraIds() 参考说明:

在 API 级别 29 之前,所有返回的 ID 都保证可以通过 CameraManager.getCameraIdList() 直接打开 CameraManager.openCamera()。从 API 级别 29 开始,对于返回的每个 ID,如果它也被 CameraManager.getCameraIdList() 返回,则可以通过 CameraManager.openCamera() 作为单独的相机使用。否则,相机 ID 只能作为当前逻辑相机的一部分使用。
这意味着您可以在CameraManager.getCameraCharacteristics(id)中使用getPhysicalCameraIds()返回的任何ID:

从API 29级开始,此函数还可用于查询仅作为逻辑多相机的一部分使用的物理相机的功能。这些相机无法直接通过openCamera(String, CameraDevice.StateCallback, Handler)打开。


您可以针对CameraManager文档提出错误报告;) 另外,在CameraCharacteristics中,他们使用了这种奇怪的**#**符号,这是懒得复制/粘贴的结果。 - Alex Cohn
那么这是否意味着Pixel 5只允许其他应用程序使用两个摄像头,尽管它的后置摄像头有3个物理摄像头?所以所有这些物理摄像头仅适用于股票相机应用程序? - user924
@user924 对于 Pixel 5,camChars.physicalCameraIds 只返回2个吗? - Alex Cohn
@AlexCohn Pixel 5 返回两个逻辑相机 ID(后置和前置)cameraManager.cameraIdList,对于第一个逻辑后置相机,它包括两个物理相机 ID cameraBackCharacteristics.physicalCameraIds,对于前置逻辑相机,它返回空列表,请查看我的截图 https://dev59.com/qLPma4cB1Zd3GeqPspPM#66569731。 - user924
1
@AlexCohn 我更新了我的答案,说明如何在打开逻辑相机后打开物理相机。 - user924
显示剩余3条评论

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