Android --camera2(CameraDevice)

1,698 阅读11分钟

总结

CameraDevice相当于单个摄像头;
不同级别相机支持的能力:

  • LEGACY==具有最低的 camera2 API 功能\
  • LIMITED ==功能与Camera1API类似\
  • EXTERNAL == 外接的摄像头,功能少于Camera1API\
  • FULLLEVEL3 == 功能大大提高
    应该一个模板用例使用一个CaptureRequest:\
  • CameraDevice.TEMPLATE_MANUAL:用于直接应用控制捕获参数的基本模板\
  • CameraDevice.TEMPLATE_PREVIEW: 创建适合相机预览窗口的请求\
  • CameraDevice.TEMPLATE_RECORD:创建适合视频录制的请求\
  • CameraDevice.TEMPLATE_STILL_CAPTURE:创建适合静态图像捕获的请求\
  • CameraDevice.TEMPLATE_VIDEO_SNAPSHOT:在录制视频时创建适合静态图像捕获的请求\
  • CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG:创建适用于零快门延迟静态捕获的请求
    流程步骤: 在CameraManageropenCamera中设置 CameraDevice.StateCallback,在CameraDevice.StateCallback onOpened回调中得到CameraDevice实例,使用这个CameraDevice调用createCaptureSession创建一个新CameraCaptureSession捕获会话对象,创建好的CameraCaptureSessionCameraCaptureSession.StateCallbackonConfigured中返回,然后可以调用CameraCaptureSessioncapture, captureBurst, setRepeatingRequest,或 setRepeatingBurst方法提交由CameraDevice调用createCaptureRequest创建的捕获请求CaptureRequest

CameraDevice

CameraDevice 类是连接到 Android 设备的单个摄像头的表示,允许以高帧速率对图像捕获和后处理进行细粒度控制。
您的应用程序必须在清单中声明Camera权限才能访问相机设备。\

给定的相机设备可以在CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL中定义的多个级别之一提供支持。如果设备支持LEGACYlevel,则相机设备以向后兼容模式运行,并且具有最低的 camera2 API 支持。如果设备支持LIMITED 级别,则 Camera2 会公开一个与旧CameraAPI大致等效的功能集 ,但具有更清晰、更高效的界面。如果设备支持EXTERNAL 级别,则该设备是一个可移动的相机,提供与LIMITED级别类似但略少的功能。实现FULL或的 设备LEVEL3与旧Camera API 相比,支持级别提供了显着改进的功能。如果您的应用程序需要完整级别的设备才能正常运行,请在清单中声明“android.hardware.camera.level.full”功能。

关闭

public abstract void close ()

尽快关闭与此相机设备的连接。
在调用close()之后,所有对CameraDevicesession接口的调用都会抛出IllegalStateException,对 close() 的调用除外。一旦设备完全关闭,StateCallback#onClosed将被调用,并且可以自由地重新打开相机。
在调用close()之后,除了最终会调用StateCallback#onClosed之外,不会发生来自CameraDevicesession的进一步回调,所有剩余提交的捕获请求都将被丢弃,就像调用了CameraCaptureSession#abortCaptures一样,但不会调用成功或失败回调。

创建捕获请求

public CaptureRequest.Builder createCaptureRequest (int templateType, Set<String> physicalCameraIdSet)

为新的捕获请求创建一个CaptureRequest.Builder,使用目标用例的模板初始化。
此方法允许客户端传递物理相机 ID,可用于自定义对特定物理相机的请求。这些设置被选择为特定逻辑相机设备的最佳选项。如果传递了额外的物理相机 ID,那么它们也将使用相同的设置模板。客户可以通过调用CaptureRequest.Builder#setPhysicalCameraKey进一步修改单个相机设置。
单独的物理相机设置将仅适用于使用相应物理相机 id 输出配置OutputConfiguration#setPhysicalCameraId初始化的相机会话,相同的输出目标也会通过CaptureRequest.Builder#addTarget附加到请求中。
如果附加了有效的物理相机设置,则任何逻辑相机流的输出都是未定义的。

创建捕获请求

public abstract CaptureRequest.Builder createCaptureRequest (int templateType)

为新的捕获请求创建一个CaptureRequest.Builder,使用目标用例的模板初始化。设置选择为特定相机设备的最佳选项,因此不建议对不同的相机设备重复使用相同的请求;为该设备和模板创建一个特定的构建器,并根据需要覆盖设置。

创建捕获会话(新)

public void createCaptureSession (SessionConfiguration config)

创建一个新CameraCaptureSession对象,使用SessionConfiguration 对象聚合所有支持参数。
活动捕获会话为每个捕获请求确定相机设备的潜在输出表面集。给定的请求可以使用全部或仅部分输出。一旦CameraCaptureSession创建,请求可以被capture, captureBurst, setRepeatingRequest,或 setRepeatingBurst提交。

创建捕获会话(旧)

public abstract void createCaptureSession (List<Surface> outputs, CameraCaptureSession.StateCallback callback, Handler handler)

通过向相机设备提供 Surface 的目标输出集来创建新的相机捕获会话。

创建捕获会话(旧)

public abstract void createCaptureSessionByOutputConfigurations (List<OutputConfiguration> outputConfigurations, CameraCaptureSession.StateCallback callback,  Handler handler)

通过向相机设备提供表面的目标输出集及其相应的表面配置来创建新的相机捕获会话。

创建捕获会话(旧)

public abstract void createConstrainedHighSpeedCaptureSession (List<Surface> outputs, 
                CameraCaptureSession.StateCallback callback, 
                Handler handler)

创建一个新的受约束的高速捕获会话。

创建扩展会话

public void createExtensionSession (ExtensionSessionConfiguration extensionConfiguration)

初始化特定于特定设备的扩展增强相机捕获会话。
扩展会话可用于启用特定于设备的操作模式,例如 CameraExtensionCharacteristics#EXTENSION_NIGHT或 CameraExtensionCharacteristics#EXTENSION_HDR。这些模式不如完整的相机 API 灵活,但可以访问更复杂的处理算法,这些算法可以捕获多帧连拍以生成单个输出图像。要查询此设备上的可用扩展,请调用 CameraExtensionCharacteristics#getSupportedExtensions()
此方法还将触发用于扩展增强预览和多帧静态捕获的内部处理管道的设置。
如果调用此方法时先前的 CameraCaptureSession 已存在,则先前的会话将无法再接受新的捕获请求并将关闭。在前一个会话上发出的任何正在进行的捕获请求都将在它关闭之前完成。
CameraExtensionSession 将一直处于活动状态,直到客户端调用 CameraExtensionSession.close() 或创建新的相机捕获会话。在这两种情况下,所有内部资源都将被释放,连续重复请求停止并刷新任何挂起的多帧捕获请求。
请注意,CameraExtensionSession 目前最多支持两种多帧捕获表面格式:所有扩展都支持 ImageFormat.JPEG,可能支持也可能不支持 ImageFormat.YUV_420_888。客户端必须使用 CameraExtensionCharacteristics#getExtensionSupportedSizes(int, int) 查询多帧捕获格式支持情况. 对于重复请求,CameraExtensionSession 仅支持 SurfaceTexture作为输出。客户端可以使用 getExtensionSupportedSizes(..., Class)查询重复请求输出的支持分辨率。
初始化至少需要一个用于重复的有效输出表面,或者用于在扩展配置参数的输出参数中注册的高质量单个请求的有效输出。初始化最多将接受两个有效的输出表面,一个用于重复,另一个用于单个请求。传递给 ExtensionSessionConfiguration 的其他不受支持的表面将导致 IllegalArgumentException抛出 。

创建重新处理捕获请求

public abstract CaptureRequest.Builder createReprocessCaptureRequest (TotalCaptureResult inputResult)

从 TotalCaptureResult为一个新的reprocess CaptureRequest创建CaptureRequest.Builder
每个reprocessCaptureRequest处理从 CameraCaptureSession的输入Surface到包含重新处理捕获请求中包含的所有输出表面的缓冲区。重新处理输入图像必须从从同一相机设备捕获的一个或多个输出图像生成。该应用程序可以通过ImageWriter.queueInputImage(Image)向相机设备提供输入图像。应用程序必须使用这些输出图像之一的捕获结果来创建重新处理捕获请求,以便相机设备可以使用该信息来实现最佳的重新处理图像质量。对于仅支持 1 个输出 Surface的相机设备,提交具有多个输出目标的重新处理CaptureRequest将导致CaptureFailure.

创建ReprocessableCaptureSession

public abstract void createReprocessableCaptureSession (InputConfiguration inputConfig, 
                List<Surface> outputs, 
                CameraCaptureSession.StateCallback callback, 
                Handler handler)

通过向相机设备提供所需的重新处理输入表面配置和表面的目标输出集,创建新的可重新处理相机捕获会话。

createReprocessableCaptureSessionByConfigurations

public abstract void createReprocessableCaptureSessionByConfigurations (InputConfiguration inputConfig, 
                List<OutputConfiguration> outputs, 
                CameraCaptureSession.StateCallback callback, 
                Handler handler)

通过向OutputConfiguration 相机设备提供所需的重新处理输入配置和输出,创建新的可重新处理相机捕获会话。

获取相机音频限制

public int getCameraAudioRestriction ()

获取当前应用的全局相机音频限制模式。
应用程序可以使用此方法来检索setCameraAudioRestriction(int)中描述的系统范围的相机音频限制设置

获取ID

public abstract String getId ()

获取此相机设备的 ID。
这与CameraManager#openCamera用于实例化此相机设备的 ID 匹配。
这个ID可以使用CameraManager.getCameraCharacteristics(String)来查询相机设备的fixed properties
即使设备已关闭或遇到严重错误,也可以调用此方法。

isSessionConfigurationSupported

public boolean isSessionConfigurationSupported (SessionConfiguration sessionConfig)

检查特定SessionConfiguration相机设备是否支持。
此方法执行对给定的SessionConfiguration运行时检查。结果确认传递的会话配置是否可以成功用于使用 CameraDevice#createCaptureSession( android.hardware.camera2.params.SessionConfiguration)创建的摄影机捕获会话.
可以在活动捕获会话之前、期间和之后的任何时候调用该方法。它不得以任何方式影响正常的相机行为,并且必须比创建常规或受限制的捕获会话快得多。
尽管此方法比创建新的捕获会话更快,但它并不打算用于探索支持的流组合的整个空间。可用的强制流组合 MandatoryStreamCombination更适合于此目的。
请注意,会话参数将被忽略,并且SessionConfiguration#setSessionParameters不需要调用 。

设置相机音频限制

public void setCameraAudioRestriction (int mode)

使用此 CameraDevice 时设置音频限制模式。
某些相机硬件(例如具有光学图像稳定支持的设备)对设备振动很敏感,并且视频录制可能会被意外的声音破坏。应用程序可以使用此方法来抑制来自铃声、警报或通知的振动或声音。其他振动或声音(例如媒体播放或辅助功能)不会被静音。
静音模式是系统范围的设置。当多个 CameraDevice 对象设置不同的模式时,系统将选择一个由 CameraDevice 设置的所有模式联合的模式。应用程序还可以 getCameraAudioRestriction()用于查询当前有效的系统范围相机静音模式。
当 CameraDevice 关闭或应用程序与相机断开连接时,此 CameraDevice 的静音设置将自动删除。

CameraDevice.StateCallback

用于接收有关相机设备状态的更新的回调对象。
必须CameraManager#openCamera为打开相机设备的方法提供回调实例。
这些状态更新包括有关设备完成启动(允许CameraDevice.createCaptureSession(SessionConfiguration)被调用)、设备断开或关闭以及意外设备错误的通知。
关于具体的进步活动CaptureRequests通过提供CameraCaptureSession.CaptureCallback给定的 CameraCaptureSession#captureCameraCaptureSession#captureBurst, CameraCaptureSession#setRepeatingRequest,或 CameraCaptureSession#setRepeatingBurst方法.\

关闭

public void onClosed (CameraDevice camera)

使用CameraDevice#close关闭相机设备时调用的方法。
将来任何在此 CameraDevice 上调用方法的尝试都将抛出IllegalStateException.\

断开连接

public abstract void onDisconnected (CameraDevice camera)

当相机设备不再可用时调用的方法。
如果打开相机失败,可能会调用此回调而不是onOpened(CameraDevice)
任何在此 CameraDevice 上调用方法的尝试都将抛出一个 CameraAccessException. 断开连接可能是由于安全策略或权限的更改;可移动相机设备的物理断开连接;或更高优先级的相机 API 客户端所需的相机。
调用此方法后可能仍会调用捕获回调,或者传递到活动输出的新图像缓冲区。
默认实现会在系统日志中记录有关断开连接的通知。
发生这种情况后,您应该调用CameraDevice#close清理相机,因为在再次打开相机之前无法恢复。对于大多数用例,这将是相机再次变为 available.

出错时

public abstract void onError (CameraDevice camera, int error)

当相机设备遇到严重错误时调用的方法。
如果打开相机失败,可能会调用此回调而不是onOpened(CameraDevice)
这表示摄像机设备或摄像机服务以某种方式出现故障。将来任何调用此CameraDevice上的方法的尝试都将抛出CameraAccessException,并带有CAMERA_错误原因。
在收到此错误后,可能仍会调用捕获完成或相机流回调。
发生这种情况后,您应该调用CameraDevice#close清理相机。进一步的恢复尝试是特定于错误代码的。

打开

public abstract void onOpened (CameraDevice camera)

当相机设备完成打开时调用的方法。
此时,摄像头设备已准备就绪,可以调用CameraDevice#createCaptureSession来设置第一个捕获会话。