4. Preview Request 流程详解:从 Framework 下发 CaptureRequest 到 HAL 的完整路径
Preview 流程的起点是 Android Framework 的 Camera 应用层,终点是 HAL 层的硬件处理单元。本章将深入剖析 CaptureRequest 从 Framework 下发到 HAL 的完整路径,并详细解析核心数据结构 camera3_capture_request_t 的每个字段。
4.1 整体流程概览
一个 Preview Request 的生命周期跨越 Framework、Camera Service、Camera Provider 和 HAL 四个层级。下图展示了从应用层调用 capture 到 HAL 接收 process_capture_request 的完整路径。
4.2 关键路径步骤详解
从 Framework 到 HAL 的完整路径包含以下关键步骤:
- 应用层发起请求:应用通过
CameraCaptureSession.capture()或setRepeatingRequest()提交CaptureRequest。 - Framework 层封装:
CameraDeviceImpl将请求封装为CaptureRequest对象,包含 metadata 和 target surfaces。 - Camera Service 调度:
Camera3Device的RequestThread将请求加入队列,按优先级和帧号调度。 - 跨进程传输:通过 Binder 将
CaptureRequest序列化后传输到 Camera Provider 进程。 - HAL 层转换:Camera Provider 调用
convertRequestToHAL()将 Framework 请求转换为camera3_capture_request_t。 - HAL 回调:调用
process_capture_request()将请求下发到 HAL 实现。
4.3 核心数据结构:camera3_capture_request_t 字段解析
camera3_capture_request_t 是 HAL 层接收请求的核心数据结构,定义在 hardware/libhardware/include/hardware/camera3.h 中。下表详细解析每个字段的含义和用途:
| 字段名 | 类型 | 描述 | Preview 场景典型值 |
|---|---|---|---|
frame_number |
uint32_t | 帧序号,单调递增,用于追踪请求和结果对应关系 | 0, 1, 2, ... |
settings |
const camera_metadata_t* | 请求的 metadata,包含 3A 参数、AE/AF/AWB 设置、输出尺寸等 | 预览模式的 metadata |
input_buffer |
const camera3_stream_buffer_t* | 输入 buffer,用于 reprocessing 场景;Preview 通常为 NULL | NULL |
num_output_buffers |
uint32_t | 输出 buffer 数量,对应 target surfaces 个数 | 1(预览 Surface)或 2(预览 + 录像) |
output_buffers |
const camera3_stream_buffer_t* | 输出 buffer 数组,每个元素描述一个 output stream 的 buffer | 指向预览 stream 的 buffer |
num_physcam_settings |
uint32_t | 物理 camera settings 数量,用于多 camera 场景 | 0(单 camera) |
physcam_settings |
const camera3_physical_camera_settings_t* | 物理 camera settings 数组,每个物理 camera 独立设置 | NULL |
4.4 camera3_stream_buffer_t 结构解析
camera3_stream_buffer_t 是 camera3_capture_request_t 中描述 buffer 的核心子结构:
| 字段名 | 类型 | 描述 |
|---|---|---|
stream |
camera3_stream_t* | 指向 stream 的指针,标识该 buffer 属于哪个 stream |
buffer |
buffer_handle_t* | 实际 buffer 的 handle,指向 GraphicBuffer |
status |
int | buffer 状态,CAMERA3_BUFFER_STATUS_OK 或 ERROR |
acquire_fence |
int | acquire fence fd,HAL 等待此 fence 后才能写入 buffer |
release_fence |
int | release fence fd,HAL 写入完成后 signal 此 fence |
性能提示:Preview 场景中,
acquire_fence 通常为 -1(无需等待),因为 SurfaceFlinger 已经准备好 buffer。但录像或高帧率场景中,fence 机制对同步至关重要。
4.5 Framework 到 HAL 的转换流程
以下代码展示了 Camera3Device 如何将 Framework 的 CaptureRequest 转换为 HAL 的 camera3_capture_request_t:
// frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
status_t Camera3Device::convertRequestToHAL(
const CaptureRequest &frameworkRequest,
camera3_capture_request_t *halRequest) {
// 1. 填充 frame_number
halRequest->frame_number = frameworkRequest.mFrameNumber;
// 2. 转换 metadata
halRequest->settings = frameworkRequest.mSettings.get();
// 3. 处理 input buffer(Preview 通常为 NULL)
halRequest->input_buffer = nullptr;
// 4. 构建 output buffers 数组
Vector<camera3_stream_buffer_t> outputBuffers;
for (auto &surface : frameworkRequest.mSurfaceList) {
camera3_stream_buffer_t buf;
buf.stream = getStreamForSurface(surface);
buf.buffer = getBufferForSurface(surface);
buf.status = CAMERA3_BUFFER_STATUS_OK;
buf.acquire_fence = -1;
buf.release_fence = -1;
outputBuffers.add(buf);
}
halRequest->num_output_buffers = outputBuffers.size();
halRequest->output_buffers = outputBuffers.array();
// 5. 处理物理 camera settings
halRequest->num_physcam_settings = 0;
halRequest->physcam_settings = nullptr;
return OK;
}
4.6 Preview 场景下的字段填充示例
以一个典型的 1080p Preview 请求为例,各字段的实际填充值如下:
| 字段 | 示例值 | 说明 |
|---|---|---|
frame_number |
42 | 第 42 帧请求 |
settings |
包含 AE_MODE=ON, AE_TARGET_FPS_RANGE=[30,30], ANDROID_CONTROL_AE_LOCK=false 等 | 预览模式的标准 metadata |
num_output_buffers |
1 | 仅预览 Surface |
output_buffers[0].stream |
指向 preview stream,格式 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED | 分辨率 1920x1080 |
output_buffers[0].acquire_fence |
-1 | 无需等待 |
output_buffers[0].release_fence |
-1 | HAL 完成后 signal |
4.7 性能关键点与优化建议
性能关键点:
- metadata 序列化开销:每次请求都需序列化 metadata,大量重复 key 会增加 Binder 传输负担。建议使用
CameraMetadata的缓存机制减少重复设置。 - buffer 分配策略:Preview 场景建议使用
dequeueBuffer预分配 buffer 池,避免每帧动态分配。 - fence 管理:合理使用 acquire/release fence 可以减少 CPU 等待,提升 pipeline 吞吐量。
- frame_number 连续性:HAL 应保证 frame_number 连续,避免 Framework 侧超时或丢帧检测误判。
常见陷阱:
- HAL 实现中修改
settings指向的 metadata 内容会导致未定义行为,应视为只读。 output_buffers数组的生命周期仅持续到process_capture_request返回,HAL 需要深拷贝 buffer handles 用于异步处理。- 多 camera 场景下,
physcam_settings中的物理 camera ID 必须与 stream 配置一致,否则会导致 HAL 崩溃。
4.8 路径总结
Preview Request 从 Framework 到 HAL 的完整路径可概括为:
- 应用层:构建
CaptureRequest.Builder,设置 metadata 和 target surfaces。 - Framework 层:
CameraDeviceImpl封装为CaptureRequest,通过 Binder 发送到 Camera Service。 - Service 层:
Camera3Device的RequestThread调度请求,调用convertRequestToHAL()转换。 - Provider 层:通过 HAL Binder 接口将
camera3_capture_request_t传递给 HAL。 - HAL 层:
process_capture_request()接收请求,解析settings和output_buffers,开始 ISP 处理。