2. Stream基础概念:Stream的定义、Stream类型(Input/Output)、Stream配置参数(分辨率/格式/Usage)
2.1 Stream的定义
在Camera HAL(硬件抽象层)中,Stream 是连接图像数据生产者(Camera Sensor / ISP)与消费者(应用层 / 编码器 / 显示)的逻辑数据通道。每个Stream代表一条独立的、具有特定配置的图像数据流路径。
从实现角度看,Stream是HAL层与Framework层之间协商并建立的缓冲区队列(BufferQueue)的抽象。Framework通过配置Stream的参数,决定Camera设备如何输出图像数据,以及输出数据的格式、尺寸和用途。
2.2 Stream类型:Input / Output
根据数据流向,Camera HAL中的Stream分为两大类:Output Stream 和 Input Stream。绝大多数应用场景使用Output Stream,Input Stream用于特殊场景(如视频重处理、Camera2 API的ZSL等)。
| Stream类型 | 方向 | 数据流向 | 典型用途 | HAL接口 |
|---|---|---|---|---|
| Output Stream | HAL → Framework | Camera设备输出图像数据给应用 | 预览、拍照、视频录制、图像分析 | processCaptureRequest() 输出缓冲区 |
| Input Stream | Framework → HAL | 应用输入图像数据给Camera设备处理 | 视频重处理(Reprocessing)、ZSL、HDR合成 | processCaptureRequest() 输入缓冲区 |
REQUEST_AVAILABLE_CAPABILITIES_REPROCESS 能力才能使用Input Stream。大多数中低端设备不支持此功能。
2.2.1 Output Stream详解
Output Stream是Camera设备向Framework输出图像数据的通道。一个Camera设备可以同时拥有多个Output Stream,每个Stream独立配置。常见的Output Stream组合:
- 预览Stream:通常配置为
YUV_420_888或NV21,分辨率匹配屏幕尺寸,用于实时显示。 - 拍照Stream:通常配置为
JPEG或RAW10,分辨率使用Sensor最大或接近最大尺寸。 - 视频Stream:通常配置为
YUV_420_888,分辨率匹配视频录制规格(如1080p、4K)。 - 分析Stream:通常配置为
YUV_420_888,分辨率较低(如640x480),用于人脸检测、二维码扫描等。
2.2.2 Input Stream详解
Input Stream允许应用将图像数据输入到Camera HAL进行二次处理。典型流程:
- 应用通过Output Stream获取一张高分辨率RAW或YUV图像。
- 应用将这张图像通过Input Stream重新提交给HAL。
- HAL对图像进行重处理(如多帧降噪、HDR合成、数字变焦),输出最终结果。
configureStreams() 中会校验Input/Output Stream的配置一致性。
2.3 Stream配置参数:分辨率 / 格式 / Usage
每个Stream在创建时必须指定一组配置参数,这些参数决定了Stream的行为和性能。核心参数包括:分辨率(Width/Height)、图像格式(Format)和 Usage标志(用途)。
2.3.1 分辨率(Width / Height)
分辨率定义了Stream输出图像的像素尺寸。HAL必须支持Framework请求的分辨率,否则 configureStreams() 会返回错误。
- 约束:分辨率必须在Camera设备支持的
SCALER_AVAILABLE_STREAM_CONFIGURATIONS列表中。 - 对齐:某些HAL实现要求宽高为16或32的倍数(特别是YUV格式)。
- 性能影响:分辨率越大,带宽和内存占用越高。预览Stream通常使用屏幕分辨率,拍照Stream使用Sensor最大分辨率。
2.3.2 图像格式(Format)
格式定义了Stream输出图像的像素编码方式。Android Camera HAL支持多种格式,常见的有:
| 格式常量 | 描述 | 位深 | 典型用途 | 备注 |
|---|---|---|---|---|
HAL_PIXEL_FORMAT_YCbCr_420_888 |
灵活YUV 4:2:0 | 8-bit | 预览、视频、分析 | 最通用格式,支持多平面 |
HAL_PIXEL_FORMAT_NV21 |
YUV 4:2:0 NV21 | 8-bit | 预览、编码 | 传统格式,单平面交错 |
HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED |
实现定义格式 | 可变 | 显示、GPU处理 | 由Gralloc决定实际格式 |
HAL_PIXEL_FORMAT_BLOB |
二进制大对象 | 可变 | JPEG编码输出 | 包含JPEG头部和数据 |
HAL_PIXEL_FORMAT_RAW10 |
10-bit RAW Bayer | 10-bit | 专业拍照、DNG输出 | 需要Sensor RAW支持 |
HAL_PIXEL_FORMAT_RAW16 |
16-bit RAW Bayer | 16-bit | 专业拍照、DNG输出 | 精度更高,带宽更大 |
HAL_PIXEL_FORMAT_YCbCr_420_888,它兼容性最好且支持灵活的内存布局。对于显示场景,使用 HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED 可以让Gralloc选择最高效的格式(如RGBA_8888或NV12)。
2.3.3 Usage标志(用途)
Usage标志是Android Gralloc分配缓冲区时使用的消费者/生产者用途标记。它告诉HAL和Gralloc:这个Stream的缓冲区将被如何使用,从而影响内存分配策略(如CPU访问、GPU纹理、显示合成等)。
常见的Usage标志(定义在 gralloc.h 或 hardware/gralloc.h):
| Usage标志 | 值(示例) | 含义 | 典型场景 |
|---|---|---|---|
GRALLOC_USAGE_SW_READ_OFTEN |
0x00000003 | CPU频繁读取 | 图像分析、人脸检测 |
GRALLOC_USAGE_SW_WRITE_OFTEN |
0x00000005 | CPU频繁写入 | 应用层图像处理 |
GRALLOC_USAGE_HW_TEXTURE |
0x00000100 | GPU纹理采样 | OpenGL渲染、滤镜 |
GRALLOC_USAGE_HW_RENDER |
0x00000200 | GPU渲染目标 | 离屏渲染、特效 |
GRALLOC_USAGE_HW_VIDEO_ENCODER |
0x00010000 | 视频编码器输入 | 视频录制 |
GRALLOC_USAGE_HW_CAMERA_WRITE |
0x00020000 | Camera HAL写入 | 所有Camera输出Stream |
GRALLOC_USAGE_HW_COMPOSER |
0x00000800 | 显示合成器使用 | 预览显示 |
| 组合。但组合不当会导致内存分配失败或性能下降。例如:同时设置 SW_READ_OFTEN 和 HW_VIDEO_ENCODER 可能导致缓冲区无法被硬件高效访问。HAL开发者在配置Stream时,必须根据实际消费者合理设置Usage。
2.3.4 配置参数组合示例
以下是一个典型的Stream配置代码片段(HAL层伪代码):
// 配置预览Stream
camera3_stream_t preview_stream;
preview_stream.stream_type = CAMERA3_STREAM_OUTPUT; // Output类型
preview_stream.width = 1920; // 分辨率宽
preview_stream.height = 1080; // 分辨率高
preview_stream.format = HAL_PIXEL_FORMAT_YCbCr_420_888; // YUV格式
preview_stream.usage = GRALLOC_USAGE_HW_CAMERA_WRITE // Camera写入
| GRALLOC_USAGE_HW_COMPOSER // 显示合成
| GRALLOC_USAGE_HW_VIDEO_ENCODER; // 视频编码
preview_stream.max_buffers = 4; // 缓冲区数量
// 配置拍照Stream
camera3_stream_t jpeg_stream;
jpeg_stream.stream_type = CAMERA3_STREAM_OUTPUT;
jpeg_stream.width = 4000;
jpeg_stream.height = 3000;
jpeg_stream.format = HAL_PIXEL_FORMAT_BLOB; // JPEG格式
jpeg_stream.usage = GRALLOC_USAGE_HW_CAMERA_WRITE
| GRALLOC_USAGE_SW_READ_OFTEN; // CPU读取JPEG数据
jpeg_stream.max_buffers = 2;
2.4 Stream配置的约束与校验
在HAL的 configureStreams() 函数中,Framework会传入一个Stream配置列表。HAL必须校验这些配置的合法性:
- 分辨率校验:检查每个Stream的分辨率是否在
SCALER_AVAILABLE_STREAM_CONFIGURATIONS中。 - 格式校验:检查格式是否被Sensor或ISP支持。
- 组合校验:检查多个Stream的组合是否可行(例如:同时输出4K视频和RAW拍照是否超过ISP带宽)。
- Usage兼容性:检查Usage标志是否与格式、分辨率兼容(例如:BLOB格式通常不支持GPU纹理)。
本章节介绍了Stream的基础概念,包括定义、Input/Output类型以及分辨率、格式、Usage三大配置参数。这些知识是理解Camera HAL数据流和后续Stream复用优化的基石。