android camera 3A 模式和状态转换

本文深入解析了3A算法(自动对焦、自动曝光、自动白平衡)的工作原理和状态机转换,介绍了如何通过HAL接口控制3A算法,以及在不同模式下3A算法的行为和控件设置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

虽然实际的 3A 算法取决于 HAL 实现,但高级状态机的说明由 HAL 接口定义,以支持 HAL 设备和框架就 3A 的当前状态进行通信并触发 3A 事件。

当设备开启时,所有单独的 3A 状态都必须为 STATE_INACTIVE。流配置不会重置 3A。例如,在整个 configure() 调用期间必须保持焦点锁定。

要触发 3A 操作,只需在下一个请求的设置中设置相关触发条目,以指示触发开始即可。例如,若要触发自动对焦扫描的启动操作,只需将相应请求的 ANDROID_CONTROL_AF_TRIGGER 条目设为 ANDROID_CONTROL_AF_TRIGGER_START 即可;若要触发自动对焦扫描的取消操作,只需将 ANDROID_CONTROL_AF_TRIGGER 设为 ANDROID_CONTRL_AF_TRIGGER_CANCEL 即可。否则,条目将会不存在或被设为 ANDROID_CONTROL_AF_TRIGGER_IDLE。凡是具有已设为非 IDLE 值的触发条目的请求,都会被视为独立的触发事件。

在顶层,3A 由 ANDROID_CONTROL_MODE 设置控制。该设置选项包括关闭 3A (ANDROID_CONTROL_MODE_OFF)、正常自动 (AUTO) 模式 (ANDROID_CONTROL_MODE_AUTO),以及使用取景模式设置 (ANDROID_CONTROL_USE_SCENE_MODE):

  • 在 OFF 模式下,单个的自动对焦 (AF)、自动曝光 (AE) 和自动白平衡 (AWB) 模式都会有效地关闭,且任何拍摄控件都不会被 3A 例程覆盖。
  • 在 AUTO 模式下,AF、AE 和 AWB 模式都会运行各自的独立算法,且具有自己的模式、状态和触发元数据条目,具体如下一节所示。
  • 在 USE_SCENE_MODE 下,必须使用 ANDROID_CONTROL_SCENE_MODE 条目的值来确定 3A 例程的行为。在除 FACE_PRIORITY 以外的 SCENE_MODE 下,HAL 必须将 ANDROID_CONTROL_AE/AWB/AF_MODE 的值替换为它倾向于让所选的 SCENE_MODE 使用的模式。例如,HAL 可能倾向于在 SCENE_MODE_NIGHT 下使用 CONTINUOUS_FOCUS AF 模式。当必须忽略这些取景模式下的场景时,用户可随意选择 AE/AWB/AF_MODE。
  • 对于 SCENE_MODE_FACE_PRIORITY,AE/AWB/AFMODE 控件的工作方式与在 ANDROID_CONTROL_MODE_AUTO 模式下相同,但 3A 例程必须偏向测光,并对焦到场景中任何已检测到的人脸上。

自动对焦设置与结果条目

主要元数据条目
ANDROID_CONTROL_AF_MODE用于选择当前的自动对焦模式的控件。由请求设置中的框架进行设置。
AF_MODE_OFFAF 已停用;框架/应用直接控制镜头位置。
AF_MODE_AUTO单相扫描自动对焦。镜头在该模式下不会移动,除非 AF 被触发。
AF_MODE_MACRO单相扫描近距离自动对焦。镜头在该模式下不会移动,除非 AF 被触发。
AF_MODE_CONTINUOUS_VIDEO流畅连续对焦,用于录制视频。触发后会立刻将焦点锁定在当前位置。取消后即会恢复连续对焦。
AF_MODE_CONTINUOUS_PICTURE快速连续对焦,用于快门零延迟静像拍摄。待当前处于活动状态的扫描结束后,触发即可锁定焦点。取消后即会恢复连续对焦。
AF_MODE_EDOF高级扩展景深对焦。该模式下没有自动对焦扫描,因此触发或取消操作均无效。图像由 HAL 自动对焦。
ANDROID_CONTROL_AF_STATE用于描述当前 AF 算法状态的动态元数据,由结果元数据中的 HAL 报告。
AF_STATE_INACTIVE未进行对焦,或算法被重置。镜头未移动。始终处于 MODE_OFF 或 MODE_EDOF 状态。当设备开启时,必须以此状态启动。
AF_STATE_PASSIVE_SCAN连续对焦算法目前正在扫描理想对焦。镜头正在移动。
AF_STATE_PASSIVE_FOCUSED连续对焦算法认为已良好对焦。镜头未移动。HAL 可能会自发退出此状态。
AF_STATE_PASSIVE_UNFOCUSED连续对焦算法认为未良好对焦。镜头未移动。HAL 可能会自发退出此状态。
AF_STATE_ACTIVE_SCAN用户触发的扫描正在进行中。
AF_STATE_FOCUSED_LOCKEDAF 算法认为已对焦。镜头未移动。
AF_STATE_NOT_FOCUSED_LOCKEDAF 算法无法对焦。镜头未移动。
ANDROID_CONTROL_AFTRIGGER用于启动自动对焦扫描的控件。具体意义取决于模式和状态。由框架在请求设置中进行设置。
AF_TRIGGER_IDLE当前未触发。
AF_TRIGGER_START触发 AF 扫描的启动操作。扫描效果取决于模式和状态。
AF_TRIGGER_CANCEL取消当前 AF 扫描(如有),并将算法重置为默认值。
其他元数据条目
ANDROID_CONTROL_AF_REGIONS用于选择为确定良好对焦而需使用的视野 (FOV) 区域的控件。该控件适用于所有可扫描对焦的 AF 模式。由框架在请求设置中进行设置。

自动曝光设置与结果条目

主要元数据条目
ANDROID_CONTROL_AE_MODE用于选择当前自动曝光模式的控件。由请求设置中的框架进行设置。
AE_MODE_OFF自动曝光已停用;用户控制曝光、增益、帧时长和闪光。
AE_MODE_ON标准自动曝光,闪光灯控件已停用。用户可以将闪光灯设为触发或手电筒模式。
AE_MODE_ON_AUTO_FLASH标准自动曝光,闪光灯听从 HAL 指令开启,以进行预拍摄和静像拍摄。允许用户控制闪光灯的功能已停用。
AE_MODE_ON_ALWAYS_FLASH标准自动曝光,闪光灯始终触发以进行拍摄,并听从 HAL 指令进行预拍摄。允许用户控制闪光灯的功能已停用。
AE_MODE_ON_AUTO_FLASH_REDEYE标准自动曝光,闪光灯听从 HAL 指令开启,以进行预拍摄和静像拍摄。在预拍摄序列结束时使用闪光灯连拍,以减轻最终照片中的红眼现象。允许用户控制闪光灯的功能已停用。
ANDROID_CONTROL_AE_STATE描述当前 AE 算法状态的动态元数据,在结果元数据中由 HAL 报告。
AE_STATE_INACTIVE切换模式后的初始 AE 状态。当设备开启时,必须以此状态启动。
AE_STATE_SEARCHINGAE 没有聚焦到一个理想值,且正在调整曝光参数。
AE_STATE_CONVERGEDAE 已经为当前场景找到了理想曝光值,且曝光参数不会变化。HAL 可能会自发退出此状态,以寻找更好的解决方案。
AE_STATE_LOCKEDAE 已通过 AE_LOCK 控件进行锁定。曝光值不变。
AE_STATE_FLASH_REQUIREDHAL 已聚焦曝光,但认为需要启动闪光灯才能保证照片亮度充足。用于确定是否可使用零快门延迟帧。
AE_STATE_PRECAPTUREHAL 正在处理预拍序列。根据 AE 模式,该模式可能包括触发闪光灯以进行测光,或发出闪光脉冲以减轻红眼现象。
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER用于在拍摄高品质图像之前启动测光序列的控件。由框架在请求设置中进行设置。
PRECAPTURE_TRIGGER_IDLE当前未触发。
PRECAPTURE_TRIGGER_START启动预拍序列。HAL 应使用后续请求进行衡量并达到理想的曝光/白平衡,以便接下来拍摄高分辨率的照片。
其他元数据条目
ANDROID_CONTROL_AE_LOCK用于将 AE 控件锁定到其当前值的控件。
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION用于调整 AE 算法目标亮度点的控件。
ANDROID_CONTROL_AE_TARGET_FPS_RANGE用于为 AE 算法选择目标帧速率范围的控件。AE 例程无法将帧速率变为超出这些范围的值。
ANDROID_CONTROL_AE_REGIONS用于选择应该用于确定良好曝光水平的 FOV 区域的控件。该控件适用于除 OFF 模式外的所有 AE 模式。

自动白平衡设置和结果条目

主要元数据条目
ANDROID_CONTROL_AWB_MODE用于选择当前白平衡模式的控件。
AWB_MODE_OFF自动白平衡已停用。用户控制颜色矩阵。
AWB_MODE_AUTO自动白平衡已启用。3A 控制颜色变换,使用的变换方式可能比简单矩阵更复杂。
AWB_MODE_INCANDESCENT适用于室内白炽灯(钨丝)照明的固定白平衡设置,约为 2700K。
AWB_MODE_FLUORESCENT适用于荧光灯照明的固定白平衡设置,约为 5000K。
AWB_MODE_WARM_FLUORESCENT适用于荧光灯照明的固定白平衡设置,约为 3000K。
AWB_MODE_DAYLIGHT适用于日光的固定白平衡设置,约为 5500K。
AWB_MODE_CLOUDY_DAYLIGHT适用于多云日光的固定白平衡设置,约为 6500K。
AWB_MODE_TWILIGHT适用于近日落/日出的固定白平衡设置,约为 15000K。
AWB_MODE_SHADE适用于非阳光直射区域的固定白平衡设置,约为 7500K。
ANDROID_CONTROL_AWB_STATE描述当前 AWB 算法状态的动态元数据,在结果元数据中由 HAL 报告。
AWB_STATE_INACTIVE切换模式后的初始 AWB 状态。当设备开启时,必须以此状态启动。
AWB_STATE_SEARCHINGAWB 未聚焦为一个理想值,正在改变颜色调整参数。
AWB_STATE_CONVERGEDAWB 已发现适用于当前场景的理想颜色调整值,参数不会更改。HAL 可能会自发退出此状态以寻找更好的解决方案。
AWB_STATE_LOCKEDAWB 已由 AWB_LOCK 控件锁定。颜色调整值不会更改。
其他元数据条目
ANDROID_CONTROL_AWB_LOCK用于将 AWB 颜色调整锁定为当前值的控件。
ANDROID_CONTROL_AWB_REGIONS用于选择应该用于确定良好色彩平衡的 FOV 区域的控件。该模式仅适用于自动白平衡模式。

一般状态机转换说明

在 AF、AE 和 AWB 模式之间进行切换一律会将算法状态重置为 INACTIVE 状态。同样,如果 CONTROL_MODE == USE_SCENE_MODE,在 CONTROL_MODE 和 CONTROL_SCENE_MODE 之间进行切换也会将所有算法状态重置为 INACTIVE 状态。

下表列出了各模式的情况。

AF 状态机

模式 = AF_MODE_OFF 或 AF_MODE_EDOF
状态转换原因新状态备注
INACTIVE  AF 已停用
模式 = AF_MODE_AUTO 或 AF_MODE_MACRO
状态转换原因新状态备注
INACTIVEAF_TRIGGERACTIVE_SCAN

开始 AF 扫描

镜头正在移动

ACTIVE_SCANAF 扫描已完成FOCUSED_LOCKED

若 AF 成功

镜头现已锁定

ACTIVE_SCANAF 扫描已完成NOT_FOCUSED_LOCKED

若 AF 成功

镜头现已锁定

ACTIVE_SCANAF_CANCELINACTIVE

取消/重置 AF

镜头现已锁定

FOCUSED_LOCKEDAF_CANCELINACTIVE取消/重置 AF
FOCUSED_LOCKEDAF_TRIGGERACTIVE_SCAN

开始新的扫描

镜头正在移动

NOT_FOCUSED_LOCKEDAF_CANCELINACTIVE取消/重置 AF
NOT_FOCUSED_LOCKEDAF_TRIGGERACTIVE_SCAN

开始新的扫描

镜头正在移动

所有状态模式更改INACTIVE 
模式 = AF_MODE_CONTINUOUS_VIDEO
状态转换原因新状态备注
INACTIVEHAL 启动新的扫描PASSIVE_SCAN

开始 AF 扫描

镜头正在移动

INACTIVEAF_TRIGGERNOT_FOCUSED_LOCKED

AF 状态查询

镜头现已锁定

PASSIVE_SCANHAL 完成当前扫描PASSIVE_FOCUSED

结束 AF 扫描

镜头现已锁定

PASSIVE_SCANAF_TRIGGERFOCUSED_LOCKED

若对焦理想,则立即转换

镜头现已锁定

PASSIVE_SCANAF_TRIGGERNOT_FOCUSED_LOCKED

若对焦不良,则立即转换

镜头现已锁定

PASSIVE_SCANAF_CANCELINACTIVE

重置镜头位置

镜头现已锁定

PASSIVE_FOCUSEDHAL 启动新的扫描PASSIVE_SCAN

开始 AF 扫描

镜头正在移动

PASSIVE_FOCUSEDAF_TRIGGERFOCUSED_LOCKED

若对焦理想,则立即转换

镜头现已锁定

PASSIVE_FOCUSEDAF_TRIGGERNOT_FOCUSED_LOCKED若对焦不良,则立即转换

镜头现已锁定

FOCUSED_LOCKEDAF_TRIGGERFOCUSED_LOCKED无效果
FOCUSED_LOCKEDAF_CANCELINACTIVE重新启动 AF 扫描
NOT_FOCUSED_LOCKEDAF_TRIGGERNOT_FOCUSED_LOCKED无效果
NOT_FOCUSED_LOCKEDAF_CANCELINACTIVE重新启动 AF 扫描
模式 = AF_MODE_CONTINUOUS_PICTURE
状态转换原因新状态备注
INACTIVEHAL 启动新的扫描PASSIVE_SCAN

开始 AF 扫描

镜头正在移动

INACTIVEAF_TRIGGERNOT_FOCUSED_LOCKED

AF 状态查询

镜头现已锁定

PASSIVE_SCANHAL 完成当前扫描PASSIVE_FOCUSED结束 AF 扫描

镜头现已锁定

PASSIVE_SCANAF_TRIGGERFOCUSED_LOCKED

一旦对焦理想,则进行最终转换

镜头现已锁定

PASSIVE_SCANAF_TRIGGERNOT_FOCUSED_LOCKED

若无法对焦,则进行最终转换

镜头现已锁定

PASSIVE_SCANAF_CANCELINACTIVE

重置镜头位置

镜头现已锁定

PASSIVE_FOCUSEDHAL 启动新的扫描PASSIVE_SCAN

开始 AF 扫描

镜头正在移动

PASSIVE_FOCUSEDAF_TRIGGERFOCUSED_LOCKED

若对焦理想,则立即转换

镜头现已锁定

PASSIVE_FOCUSEDAF_TRIGGERNOT_FOCUSED_LOCKED

若对焦不良,则立即转换

镜头现已锁定

FOCUSED_LOCKEDAF_TRIGGERFOCUSED_LOCKED无效果
FOCUSED_LOCKEDAF_CANCELINACTIVE重新启动 AF 扫描
NOT_FOCUSED_LOCKEDAF_TRIGGERNOT_FOCUSED_LOCKED无效果
NOT_FOCUSED_LOCKEDAF_CANCELINACTIVE重新启动 AF 扫描

AE 和 AWB 状态机

AE 和 AWB 状态机大致上相同,但 AE 具有额外的 FLASH_REQUIRED 和 PRECAPTURE 状态。因此,对于 AWB 状态机,应忽略下表中这两个状态对应的行。

模式 = AE_MODE_OFF/AWB 模式不是 AUTO
状态转换原因新状态备注
INACTIVE  AE/AWB 已停用
模式 = AE_MODE_ON_ * / AWB_MODE_AUTO
状态转换原因新状态备注
INACTIVEHAL 启动 AE/AWB 扫描SEARCHING 
INACTIVEAE/AWB_LOCK 已开启LOCKED值已锁定
SEARCHINGHAL 完成 AE/AWB 扫描CONVERGED理想值,不作改变
SEARCHINGHAL 完成 AE 扫描FLASH_REQUIRED已聚焦,但无闪光灯导致过暗
SEARCHINGAE/AWB_LOCK 已开启LOCKED值已锁定
CONVERGEDHAL 启动 AE/AWB 扫描SEARCHING值已锁定
CONVERGEDAE/AWB_LOCK 已开启LOCKED值已锁定
FLASH_REQUIREDHAL 启动 AE/AWB 扫描SEARCHING值已锁定
FLASH_REQUIREDAE/AWB_LOCK 已开启LOCKED值已锁定
LOCKEDAE/AWB_LOCK 已关闭SEARCHING解锁后值不理想
LOCKEDAE/AWB_LOCK 已关闭CONVERGED解锁后值理想
LOCKEDAE_LOCK 已关闭FLASH_REQUIRED曝光良好但过暗
所有 AE 状态PRECAPTURE_STARTPRECAPTURE开始预拍序列
PRECAPTURE序列完成,AE_LOCK 已关闭CONVERGED高质量拍摄就绪
PRECAPTURE序列完成,AE_LOCK 已开启LOCKED高质量拍摄就绪

启用手动控制

配置设备 3A 块以实现直接应用控制的过程还涉及到多个控件。

用于 3A 控制的 HAL 模式的运作方式为:对于每个请求,HAL 都会检查 3A 控制字段的状态。如果启用了任何 3A 例程,则该例程会覆盖与该例程相关的控制变量,然后这些覆盖值会在该拍摄的结果元数据中提供。例如,如果在请求中启用自动曝光,则 HAL 应覆盖请求的曝光、增益和帧时长字段(还可能包括闪光灯字段,具体取决于 AE 模式)。相关控件如下:

控件名称单位备注
android.control.mode枚举:OFF、AUTO、USE_SCENE_MODE高级 3A 控制。当设为 OFF 时,所有由 HAL 启用的 3A 控件都会被停用。应用必须为拍摄参数本身设置字段。当设为 AUTO 时,android.control.* 中的单个算法控件(例如 android.control.afMode)会生效。当设为 USE_SCENE_MODE 时,android.control.* 中的各控件大都被停用;HAL 根据需要,实现其中的一个场景模式设置(如 ACTION、SUNSET 或 PARTY)。
android.control.afMode枚举OFF 表示使用 android.lens.focusDistance 手动控制镜头对焦。
android.control.aeMode枚举OFF 表示使用 android.sensor.exposureTime / .sensitivity / .frameDuration 手动控制曝光/增益/帧时长。
android.control.awbMode枚举OFF 表示手动控制白平衡。
<think>我们正在分析Android Camera2框架中`startPreview`方法在配流过程中的作用及每行代码的功能。根据之前的上下文,`startPreview`方法是在`onAfterCaptureSessionConfigured`方法中被调用的,用于在会话配置成功后启动预览。 在Camera2 API中,配流步骤一般包括: 1. 打开相机设备(`openCamera`) 2. 创建预览Surface(如通过`SurfaceView`或`TextureView`) 3. 创建`CaptureRequest.Builder`(使用`TEMPLATE_PREVIEW`模板) 4. 创建`CameraCaptureSession`(通过`createCaptureSession`,并传入包含预览Surface的输出目标列表) 5. 在`CameraCaptureSession.StateCallback.onConfigured`回调中,表示会话配置成功,此时可以开始发送重复请求以启动预览。 在给出的`onAfterCaptureSessionConfigured`方法中,我们看到它调用了`startPreview`方法。因此,`startPreview`方法的具体实现(虽然这里没有给出)应该负责构建预览请求并设置重复请求。 由于用户要求分析的是`startPreview`方法,但提供的代码片段中并没有`startPreview`的具体实现,我们只能根据常见的Camera2实现该方法的调用上下文来推测其作用,并分析在`onAfterCaptureSessionConfigured`中调用`startPreview`的代码行。 但是,在用户提供的代码片段中,确实有一行调用了`startPreview`: ```java boolean result = startPreview(!isSyncCalled, unitMode); ``` 因此,我们将重点分析这一行在配流过程中的作用,并尽可能解释`startPreview`方法应该完成的工作。 ### `startPreview`方法在配流过程中的作用 在Camera2的配流流程中,`startPreview`方法通常负责: 1. 创建预览请求(CaptureRequest) 2. 设置预览请求的模板(一般为`TEMPLATE_PREVIEW`) 3. 将预览Surface添加到请求中 4. 设置必要的控制参数(如自动对焦、自动曝光等) 5. 通过`setRepeatingRequest`方法开始持续发送预览请求,从而启动相机预览流。 ### 在`onAfterCaptureSessionConfigured`中调用`startPreview`的代码分析 在`onAfterCaptureSessionConfigured`方法中,调用`startPreview`的代码行是: ```java boolean result = startPreview(!isSyncCalled, unitMode); ``` - **参数分析**: - `!isSyncCalled`: 这个参数可能表示是否异步调用。在之前的日志中,我们看到有“transfer control to main thread”的日志,说明有部分操作被抛到主线程执行。而这里取反可能意味着如果之前是同步调用,那么这里就按异步处理(或者反之),具体逻辑需要看`startPreview`内部实现。 - `unitMode`: 可能表示当前相机的工作模式(比如拍照模式、视频模式等),用于在`startPreview`中根据不同的模式设置不同的参数。 - **返回值**: - 返回一个布尔值,表示启动预览是否成功。 - **上下文**: 在调用`startPreview`之前,方法中执行了以下操作: - 检查并改变预览状态(`changePreviewState`) - 将部分操作(通知UI)抛到主线程执行(`postToHandler`) - 检查模式任务(`checkModeTask`) - 调用`mModeManager.beforeStartPreview()`进行模式相关的预览前准备 - 调用`mModeManager.getCameraSwitcher().watchForPreviewTextureCopied()`,可能是等待预览纹理复制完成(在双摄切换等场景) - **后续操作**: 在`startPreview`调用之后,还有一些操作: - 判断Activity是否正在结束,以及是否需要终止任务(`isTaskNeedTerminatedAfterStartPreview`) - 处理模式切换任务(通过`ModeChangeExecutor`) - 阻塞等待APS服务条件变量(`mApsServiceConditionVariable.block()`),这可能是等待某个服务初始化完成 ### 典型的`startPreview`方法实现 虽然具体实现没有给出,但我们可以参考标准的Camera2预览启动代码: ```java private boolean startPreview(boolean async, String mode) { try { // 1. 创建预览请求构建器 mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); // 2. 添加预览Surface mPreviewRequestBuilder.addTarget(mPreviewSurface); // 3. 设置模式相关的参数(根据mode) // 例如:设置对焦模式、曝光模式等 // 4. 构建请求 CaptureRequest previewRequest = mPreviewRequestBuilder.build(); // 5. 设置重复请求 mCaptureSession.setRepeatingRequest(previewRequest, mCaptureCallback, mHandler); return true; // 成功 } catch (CameraAccessException e) { Log.e(TAG, "Failed to start preview: " + e.getMessage()); return false; // 失败 } } ``` ### 在`onAfterCaptureSessionConfigured`中调用`startPreview`的作用 在配流过程中,`startPreview`的调用标志着相机开始持续捕获图像并输出到预览Surface,用户可以看到相机预览画面。 ### 逐行分析`onAfterCaptureSessionConfigured`中与`startPreview`相关的代码 ```java // ... 省略前面的代码 // 检查模式任务,如果检查到需要处理的任务,则返回(可能是中断当前流程去处理模式切换) if (checkModeTask()) { return false; } // 模式管理器在开始预览前的准备工作 mModeManager.beforeStartPreview(); // 相机切换器监视预览纹理复制(可能用于多摄切换或特殊效果) mModeManager.getCameraSwitcher().watchForPreviewTextureCopied(); // 调用startPreview方法启动预览,传入参数:!isSyncCalled(是否异步)当前模式(unitMode) boolean result = startPreview(!isSyncCalled, unitMode); // 在startPreview之后必须执行的操作 // 如果Activity没有正在结束,并且需要在此后终止任务(根据条件判断) if (!mCameraCore.getActivity().isFinishing() && isTaskNeedTerminatedAfterStartPreview()) { // 获取模式切换执行器 ModeChangeExecutor modeChangeExecutor = mModeManager.getModeChangeExecutor(); // 处理会话配置完成的任务(可能是清理或继续下一个任务) boolean hasTaskPopped = modeChangeExecutor.handleOnSessionConfigured(OneCamera.CAMERA_MAIN_ROLE); // 如果启用了快速模式切换,则处理预览开始后的任务 if (CameraConfig.getConfigBooleanValue(ConfigKey.KEY_ENABLE_QUICK_MODE_SWITCH)) { modeChangeExecutor.handleOnPreviewStarted(OneCamera.CAMERA_MAIN_ROLE, hasTaskPopped); } } // 阻塞等待APS服务条件变量(可能是等待算法服务初始化完成) mApsServiceConditionVariable.block(); // 日志记录Trace结束 CameraLog.v(TAG, () -> "onAfterCaptureSessionConfigured, unlock"); TraceUtil.traceEndSection(() -> "PreviewProcessor.onSessionConfigured"); // 返回startPreview的结果 return result; ``` ### 总结 - `startPreview`方法在Camera2配流流程中负责启动相机预览,即开始持续发送捕获请求,使预览画面可见。 - 在`onAfterCaptureSessionConfigured`中调用`startPreview`是配流成功后的关键一步。 - `startPreview`的调用前后有一些模式相关的准备清理工作,以及可能等待一些服务初始化完成(通过条件变量阻塞)。 注意:由于没有给出`startPreview`的具体实现,以上分析基于Camera2的标准流程常见实现。实际项目中,`startPreview`方法可能会根据不同的模式(拍照、录像、美颜等)设置不同的参数,并可能有更复杂的错误处理逻辑。 ### 相关问题 1. 在`startPreview`方法中如何处理不同的相机模式(如拍照、录像)? 2. 在启动预览时,如何设置相机参数(如对焦模式、曝光补偿)? 3. 在什么情况下`startPreview`会返回false?如何处理这些情况? 4. 条件变量`mApsServiceConditionVariable`的作用是什么?为什么需要在预览启动后阻塞等待它?</think>### `startPreview`方法在Camera2配流流程中的作用 在Android Camera2框架中,`startPreview`方法是**预览启动的核心环节**,位于配流流程的关键位置。它负责在`CameraCaptureSession`配置成功后,向相机硬件发送重复捕获请求以启动预览流[^1][^2]。具体作用包括: 1. **构建预览请求**:创建基于`TEMPLATE_PREVIEW`的捕获请求 2. **设置输出目标**:绑定预览Surface到请求 3. **配置控制参数**:设置对焦/曝光等参数 4. **启动重复请求**:开始持续获取预览帧 --- ### 配流流程中的位置 ```mermaid graph TD A[打开相机 openCamera] --> B[创建预览Surface] B --> C[创建CaptureSession] C --> D[onConfigured回调] D --> E[onAfterCaptureSessionConfigured] E --> F[startPreview] F --> G[setRepeatingRequest] G --> H[预览画面显示] ``` `startPreview`位于`onAfterCaptureSessionConfigured`方法内,是**会话配置完成后**的第一个操作,直接触发预览启动[^2]。 --- ### 逐行代码分析(基于标准实现) ```java boolean result = startPreview(!isSyncCalled, unitMode); ``` #### 1. 参数解析 - **`!isSyncCalled`** 表示是否异步执行预览启动。取反操作可能用于处理同步/异步模式切换,确保在主线程执行关键操作[^2]。 $$ \text{asyncMode} = \neg(\text{isSyncCalled}) $$ - **`unitMode`** 当前相机工作模式标识(如拍照/录像/美颜等),用于加载模式特定的预览参数[^1]。 #### 2. 典型`startPreview`内部实现 ```java private boolean startPreview(boolean async, String mode) { // 1. 检查会话有效性 if (mCaptureSession == null) { CameraLog.e(TAG, "Session is null, abort preview"); return false; // 会话未就绪时中止[^1] } // 2. 创建预览请求构建器 mPreviewRequestBuilder = mCameraDevice.createCaptureRequest( CameraDevice.TEMPLATE_PREVIEW); // 使用预览模板[^1] // 3. 添加预览Surface for (Surface surface : mPreviewSurfaces) { mPreviewRequestBuilder.addTarget(surface); // 绑定输出目标[^2] } // 4. 配置模式参数 applyModeParameters(mode); // 根据unitMode设置参数 // 5. 设置3A控制 mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); // 连续对焦[^1] mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); // 自动曝光 // 6. 构建并发送请求 try { CaptureRequest request = mPreviewRequestBuilder.build(); if (async) { // 异步执行(非阻塞主线程) mCaptureSession.setRepeatingRequest(request, mCaptureCallback, mBackgroundHandler); } else { // 同步执行 mCaptureSession.setRepeatingRequest(request, mCaptureCallback, null); } return true; // 启动成功 } catch (CameraAccessException e) { CameraLog.e(TAG, "Start preview failed: " + e.getMessage()); return false; // 捕获异常[^2] } } ``` #### 3. 关键操作说明 - **`createCaptureRequest(TEMPLATE_PREVIEW)`** 使用系统预定义的预览模板,包含优化的低延迟参数,帧率可达30fps+[^1]。 - **`addTarget(surface)`** 将预览Surface(如`SurfaceTexture`)绑定到输出流,未绑定的Surface不会收到帧数据[^2]。 - **`CONTROL_AF_MODE_CONTINUOUS_PICTURE`** 最适合预览的自动对焦模式,平衡速度精度[^1]。 - **`setRepeatingRequest()`** 核心调用:启动循环捕获请求,相机将持续发送帧到目标Surface[^1][^2]。 --- ### 在配流中的关键作用 1. **状态转换枢纽** 将相机状态从`CONFIGURED`转为`ACTIVE`,标志预览正式开始[^2]。 2. **资源绑定** 完成`Surface`-`CaptureRequest`-`CameraDevice`的最终绑定。 3. **性能优化** 通过`TEMPLATE_PREVIEW`模板启用硬件级优化,降低预览延迟[^1]。 4. **错误处理** 捕获`CameraAccessException`等异常,防止无效状态下的操作[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值