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设备如何输出图像数据,以及输出数据的格式、尺寸和用途。

核心要点:Stream ≠ 物理通道。一个物理Camera设备可以同时输出多个Stream(例如:预览流、拍照流、视频流),每个Stream独立配置、独立传输。
类比理解:Stream就像自来水管道系统中的独立水管。水源(Sensor)相同,但不同的水管可以通向不同的水龙头(预览、拍照、录像),每个水龙头可以调节出水量(分辨率)和水质(格式)。
Stream在Camera HAL中的位置与作用 应用层(Camera App / Framework) Stream抽象层(BufferQueue / HAL Stream配置) 预览Stream | 拍照Stream | 视频Stream | 分析Stream Camera HAL & 硬件(ISP / Sensor) 图像数据生产 & 格式转换 & 输出 Stream是连接应用层与硬件层的桥梁,每个Stream独立配置分辨率、格式和Usage

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() 输入缓冲区
注意:Input Stream在Android Camera2 API中主要用于重处理请求(Reprocess Request)。设备必须声明支持 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进行二次处理。典型流程:

  1. 应用通过Output Stream获取一张高分辨率RAW或YUV图像。
  2. 应用将这张图像通过Input Stream重新提交给HAL。
  3. HAL对图像进行重处理(如多帧降噪、HDR合成、数字变焦),输出最终结果。
Input Stream的限制:Input Stream必须与某个Output Stream配对使用,且两者的分辨率、格式必须兼容。HAL在 configureStreams() 中会校验Input/Output Stream的配置一致性。
Input / Output Stream 数据流向对比 Output Stream(输出流) Camera HAL Framework 数据方向:HAL → Framework 用途:预览、拍照、录像、分析 数量:可同时配置多个 Input Stream(输入流) Framework Camera HAL 数据方向:Framework → HAL 用途:重处理、ZSL、HDR合成 数量:通常1个,需与Output配对

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 显示合成器使用 预览显示
Usage标志的坑:多个Usage标志可以通过 | 组合。但组合不当会导致内存分配失败或性能下降。例如:同时设置 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;
Stream配置参数关系图 Stream实例 分辨率 Width × Height 图像格式 YUV / JPEG / RAW Usage标志 CPU / GPU / 编码 / 显示 三者共同决定Stream的行为和性能 分辨率影响带宽 → 格式决定内存布局 → Usage影响分配策略

2.4 Stream配置的约束与校验

在HAL的 configureStreams() 函数中,Framework会传入一个Stream配置列表。HAL必须校验这些配置的合法性:

  • 分辨率校验:检查每个Stream的分辨率是否在 SCALER_AVAILABLE_STREAM_CONFIGURATIONS 中。
  • 格式校验:检查格式是否被Sensor或ISP支持。
  • 组合校验:检查多个Stream的组合是否可行(例如:同时输出4K视频和RAW拍照是否超过ISP带宽)。
  • Usage兼容性:检查Usage标志是否与格式、分辨率兼容(例如:BLOB格式通常不支持GPU纹理)。
Stream复用优化基础:理解Stream的配置参数是后续学习Stream复用的前提。复用策略的核心就是:在满足应用需求的前提下,通过共享缓冲区、合并Stream配置、减少不必要的Stream数量,来降低内存和带宽消耗。

本章节介绍了Stream的基础概念,包括定义、Input/Output类型以及分辨率、格式、Usage三大配置参数。这些知识是理解Camera HAL数据流和后续Stream复用优化的基石。