StreamConfigurationMap实现逻辑与解析过程详解:相机流能力的声明、匹配与验证机制全景

关键词:
StreamConfigurationMap、CameraCharacteristics、OutputFormat、InputFormat、Size 配置、帧率范围、流兼容性、配置失败调试

摘要:
StreamConfigurationMap 是 Android 相机框架中的关键数据结构之一,承载了 HAL 层报告的所有可支持流组合,包括输出格式、输入重处理格式、尺寸列表、最低帧率等信息。在开发中,无论是构建 ImageReader、配置 CaptureSession,还是校验目标尺寸是否支持,均离不开对其的正确解析与使用。本文将基于 AOSP 最新版本源码与平台实践,系统拆解 StreamConfigurationMap 的构建路径、接口实现、内部数据组织与典型问题处理策略,帮助开发者深入理解背后的匹配逻辑与流能力限制。


目录

一、系统定位:StreamConfigurationMap 的作用与关联模块概览
二、能力声明入口:HAL 如何填充 stream 配置能力并传递给 framework
三、构建路径追踪:从 HAL Metadata 到 Java 层 Map 对象的封装过程
四、关键接口详解:getOutputSizes / getInputFormats / getValidOutputFormatsForInput 行为分析
五、内部数据结构解析:Size 配置 × Format 映射 × Dynamic Range 支持方式
六、典型问题场景分析:尺寸不支持、流类型冲突、format 配置失败案例
七、性能与兼容性建议:构建 Session 前的能力预判与流选型策略
八、工程调试技巧:如何通过 dumpsys + HAL log + camera-profile.xml 还原 stream 匹配流程


一、系统定位:StreamConfigurationMap 的作用与关联模块概览

在 Android Camera 框架中,StreamConfigurationMapCameraCharacteristics 返回结构的一部分,主要承载与流配置能力相关的声明信息,其本质是 HAL 层通过 metadata 报告的一组支持的输入/输出格式、尺寸、帧率范围与重处理能力的集合,它是 Camera 流设计与 Session 创建过程的核心决策依据。

整个框架中与 StreamConfigurationMap 直接关联的关键组件包括:

  1. CameraMetadata(native 层)
    • 定义并填充 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONSANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS 等字段。
  2. CameraCharacteristics(Java 层)
    • 从 HAL metadata 映射到 Java 对象,由 CameraManager#getCameraCharacteristics() 返回。
  3. CameraDevice / CaptureSession 配置流程
    • 应用层通过 getOutputSizes() 等接口判断目标流是否受支持,并据此创建 ImageReaderSurfaceTexture 等输出对象,作为 Session 配置输入。
  4. StreamConfigurationMap(Java 封装类)
    • 封装各类接口能力,包括:
      • getOutputSizes(int format)
      • getOutputMinFrameDuration()
      • isOutputSupportedFor(Class<?> klass)
      • getValidOutputFormatsForInput()
  5. CameraCaptureSession 设备协商路径
    • session 构建前,CameraFramework 会根据 StreamConfigurationMap 中的内容对输入流和输出流组合进行合法性校验,非法配置会直接抛出 IllegalArgumentException

总结来说,StreamConfigurationMap 处于 framework 与 HAL 能力协商的关键中间层,是连接App × Framework × HAL的标准能力桥梁,其合理性直接决定了拍照、录像、预览、AI流等功能是否能够顺利启用。


二、能力声明入口:HAL 如何填充 stream 配置能力并传递给 framework

HAL 通过向系统上报静态 metadata 的方式,向上层暴露 Camera 的流配置能力。其核心字段包括:

  1. ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS

该字段是最关键的配置列表,格式如下:

typedef struct camera3_stream_configuration {
    int32_t format;         // 输出或输入格式,如 YUV_420_888、JPEG、RAW_SENSOR
    uint32_t width;         // 分辨率宽度
    uint32_t height;        // 分辨率高度
    uint32_t isInput;       // 0 表示输出,1 表示输入(如 reprocessing)
} camera3_stream_configuration_t;

HAL 层会在 get_camera_metadata() 时,将上述配置封装成一组 CameraMetadataEntry 条目,以静态 metadata 形式报告。

举例:

const int32_t available_stream_config[] = {
    HAL_PIXEL_FORMAT_YCbCr_420_888, 1920, 1080, 0,
    HAL_PIXEL_FORMAT_YCbCr_420_888, 1280, 720, 0,
    HAL_PIXEL_FORMAT_BLOB,          4032, 3024, 0,
    HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, 1920, 1080, 0,
};
  1. 其他辅助字段包括:
  • ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS:每个 format + size 对应的最小帧时间(影响帧率上限)
  • ANDROID_SCALER_AVAILABLE_STALL_DURATIONS:JPEG 或 YUV reprocess 流的处理延迟
  • ANDROID_REQUEST_AVAILABLE_CAPABILITIES:决定是否支持 YUV reprocessing、RAW 等能力
  • ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP(AIDL)或 reprocess_input_output_map(HIDL):用于构建输入流与可支持输出格式的关系
  1. 上报流程:

以 HIDL 模式为例,HAL 中定义的 ICameraProvider::getCameraDeviceInterface_V3_x() 实现最终通过 constructDefaultRequestSettings()getCameraCharacteristics() 两条路径,将支持的 stream 配置能力写入 metadata 中传递到 framework。

framework 端接收到 metadata 后,会在 CameraMetadata::buildStreamConfigurationMap() 中逐项解析 stream 配置字段,最终封装为 StreamConfigurationMap 并挂载到 CameraCharacteristics 中供上层使用。


五、内部数据结构解析:Size 配置 × Format 映射 × Dynamic Range 支持方式

StreamConfigurationMap 的底层核心是一组高效封装的映射结构,支撑其各类能力查询函数。理解这些内部结构的组织方式,对于调试 camera 流配置问题、扩展新能力(如 HDR、10-bit)具有重要意义。


  1. Output Size × Format 映射结构

最基本的结构是基于 format 的 输出尺寸列表

Map<Integer /*format*/, Size[] /*available sizes*/> mOutputFormats;

其中每个 format(如 ImageFormat.YUV_420_888ImageFormat.JPEG)对应一组可支持的尺寸(Size 为 width × height 封装对象)。

数据来源是 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS 中的 isInput == 0 条目。解析时按照 format 分类聚合。

例如:

HAL 上报:
YUV_420_888, 1920×1080, output
YUV_420_888, 1280×720, output
JPEG,        4032×3024, output

构造成:
{
  YUV_420_888 → [1920x1080, 1280x720],
  JPEG        → [4032x3024]
}

  1. Input Format 支持结构

对于支持输入流的 HAL,还需解析 isInput == 1 条目:

Set<Integer /*input formats*/> mInputFormats;

该结构用于支持 reprocessing 功能判断,决定是否可以使用 ImageWriter/ReprocessableCaptureSession


  1. Input → Output format 映射表(Reprocess)

存在 ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP 字段时,将其构造成:

Map<Integer /*input format*/, int[] /*valid output formats*/> mInputOutputMap;

该映射用于快速判断:给定一个输入格式(如 YUV),能否构建出特定输出(如 JPEG)流。


  1. Min Frame Duration、Stall Duration 数据结构
  • Map<Format+Size, Long> 类型,用于判断不同流的帧率上限与处理延迟:
mMinFrameDurations: Map<format+size, duration>
mStallDurations:    Map<format+size, duration>

例如 JPEG 输出通常会有长时间 Stall,用于影响 Session 配置顺序、App 节奏控制。


  1. Dynamic Range 与色彩能力扩展(Android 13+)

自 Android 13 开始,Google 引入了对 HDR 类型(如 HLG、PQ)与 10-bit color format 的扩展支持。

对应字段包括:

  • ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES
  • ANDROID_REQUEST_AVAILABLE_COLOR_SPACES

framework 中添加了对 StreamConfigurationMap#getHighResolutionOutputSizes()getSupportedDynamicRanges() 的封装,用于 App 选择支持的高 bit-depth 输出格式。

结构上一般构建为:

Map<format, DynamicRange[]>

App 可通过 OutputConfiguration#setDynamicRangeProfile() 来定制输出要求,HAL 若支持将匹配所需格式并返回对应流配置。


六、典型问题场景分析:尺寸不支持、流类型冲突、format 配置失败案例

在 Camera 开发或调试过程中,StreamConfigurationMap 显式与隐式定义的能力限制常常成为出错源头,以下是典型的三类问题及定位方法:


场景一:输出尺寸不被支持

现象:
调用 ImageReader.newInstance(w, h, format) 后,CameraCaptureSession 创建失败,日志中报:

E CameraDevice: Stream configuration failed: unsupported size

根因排查:

  1. 使用 cameraCharacteristics.get(StreamConfigurationMap.class).getOutputSizes(format) 获取支持列表。
  2. 核对分辨率是否在其中,特别注意是否使用了非常规尺寸(如非 16:9)。

解决建议:

  • 替换为标准尺寸,如 1280x720、1920x1080。
  • 若需求特殊,需在 HAL 层声明更多尺寸。

场景二:输入流与输出流类型冲突(如 Reprocess 配置错误)

现象:
创建 ReprocessableCaptureSession 时崩溃:

IllegalArgumentException: Input configuration not supported

根因排查:

  • 调用 StreamConfigurationMap.getInputFormats() 确认输入流支持。
  • 检查输入与输出是否匹配 getValidOutputFormatsForInput()

解决建议:

  • 确保 input 格式为 YUV_420_888。
  • 避免使用未声明支持 reprocess 的设备。

场景三:Format 配置失败(App 未做能力判断)

现象:
App 固定使用某 format(如 RAW_SENSOR),在部分平台上报错:

CameraAccessException: Stream configuration map does not support RAW_SENSOR

根因排查:

  • 多数平台仅主摄或某些特定模块支持 RAW。
  • HAL 没有上报 ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS 中的 RAW 条目。

解决建议:

  • 使用 getOutputFormats() 先行判断是否包含 ImageFormat.RAW_SENSOR
  • 避免盲目申请高 bit-depth 输出。

总结:

  • 所有流配置异常问题,最终都可追溯到 StreamConfigurationMap 所声明的能力与调用配置的匹配问题。
  • 推荐在 APP 层统一封装一套流能力判断逻辑,防止业务调用路径出现碎片化配置错误。

七、性能与兼容性建议:构建 Session 前的能力预判与流选型策略

在复杂场景下,尤其是涉及多摄、多格式、HDR/HDR10、Video + Preview + Capture 并存的业务配置中,合理设计流选型策略,提前预判设备能力,是保障稳定性的关键。以下是构建 CameraCaptureSession 之前进行能力评估与 stream 配置选型的建议:


  1. 避免“盲配”:所有输出流都应通过 StreamConfigurationMap 验证
  • 对每一个待创建的流(如 ImageReader / SurfaceTexture):
    • 使用 getOutputSizes(format) 确认尺寸支持;
    • 使用 getHighResolutionOutputSizes() 判断高分辨率模式是否存在;
    • 对于 YUV/RAW,判断是否存在特殊限制(某些平台仅主摄支持)。

  1. 视频流与拍照流组合时,优先采用平台推荐组合
  • 多数平台会预定义 camera_profile.xml 或硬编码推荐组合,如:
    • 1920x1080 视频 + 640x480 预览 + JPEG 4032x3024 拍照
  • 建议参考 dumpsys media.camera 中的 availableStreamConfigurations 区段,找出 HAL 报告的已测试组合

  1. 流格式选型与“组合压力”评估
  • JPEG vs YUV: 拍照建议使用 JPEG,若需高吞吐处理,则选择 YUV + 软件编码
  • 预览建议 SurfaceTexture/SurfaceView,避免 ImageReader 影响帧率
  • Reprocess 时需确保 inputFormat 与 outputFormat 配对支持

  1. 高分辨率与高帧率不可兼得

部分平台将 max resolutionmax frame rate 配置为互斥能力:

- 4032x3024 @ 30fps:支持
- 4032x3024 @ 60fps:不支持
- 1920x1080 @ 60fps:支持

在 session 构建前判断:

long duration = getOutputMinFrameDuration(format, size);
if (duration > 0) {
    long maxFps = 1e9 / duration;
}

  1. 尽量避免冷启动时就构建所有流
  • 某些平台在 session 初始化时会根据 stream 类型一次性分配 buffer 和 pipeline
  • 可拆分 session 创建节奏(先预览,后添加拍照)以减少 OOM 或构建失败风险

八、工程调试技巧:如何通过 dumpsys + HAL log + camera-profile.xml 还原 stream 匹配流程

当遇到 stream 创建失败、configureStreams 报错、或实际运行中流错配等问题时,建议采用如下组合工具还原设备配置与系统匹配链路:


  1. dumpsys media.camera

执行命令:

adb shell dumpsys media.camera -v

重点关注:

  • Camera ID 对应条目下的:
    • Stream Configuration Map
    • Min Frame Duration
    • Stall Duration
    • Dynamic Range Profiles
  • Available Capabilities 是否包含所需功能(如 RAW、REPROCESSING)

  1. HAL log / vendor log
  • MTK 平台:vendor.debug.camera.* 日志中有 StreamConfigParserStreamFeatureMapping 输出
  • 高通平台:使用 adb shell logcat | grep QCamera3HardwareInterface

查看是否存在配置失败的日志,如:

[ERROR] configure_streams: unsupported resolution 3264x2448 for format 35

  1. camera-profile.xml 分析

部分平台在 /vendor/etc/camera//vendor/etc/camera_profiles.xml 中定义 stream 默认组合。

查看内容:

<camera>
  <streamComb>
    <stream id="0" type="preview" format="YUV" size="1280x720" />
    <stream id="1" type="video" format="YUV" size="1920x1080" />
    <stream id="2" type="still" format="JPEG" size="4032x3024" />
  </streamComb>
</camera>

这些组合直接影响 HAL 对 configureStreams 的支持度。


  1. 验证组合路径:
  • 使用 CameraManager.getCameraCharacteristics() 对照 dumpsys 报告的内容确认是否一致
  • 若 app 层配置失败,优先考虑缩减流数量或尺寸进行回退测试

  1. 补充调试工具:
  • atrace --async_start camera:用于记录从 configure → request → result 的时序链
  • perfetto:可视化 session 构建的线程瓶颈与内核中断响应延迟
  • simplecamera / CTS Camera ITS:用于构造标准配置验证路径

总结建议:

在复杂 stream 配置场景下,必须构建一套稳定的“配置验证流程”,结合 framework 层能力查询、vendor HAL log 验证与 camera profile 预判策略,形成一套工程闭环,避免上线版本因设备差异出现 stream 配置崩溃。

原文:https://zhxin.blog.csdn.net/article/details/149725582