Android Camera HAL3 -SessionParameter

本文参考:

  1. https://source.android.google.cn/devices/camera/session-parameters
  2. https://source.android.google.cn/devices/camera/bokeh

Session Parameter 是用于在 configure_streams 阶段就进行初始化配置的选项,类似于之前的 setParameters 的作用,自 camera 的架构改成全部参数使用 metadata 来传递之后,在 configure_streams 阶段可以传递的参数就是有限的,原本的 configure_streams 的传递参数如下:

typedef struct camera3_stream {
    int stream_type;
    uint32_t width;
    uint32_t height;
    int format;
    uint32_t usage;
    uint32_t max_buffers;
    void *priv;
    android_dataspace_t data_space;
    int rotation;
    /**
     * The physical camera id this stream belongs to.
     *
     *    Always set by camera service. If the camera device is not a logical
     *    multi camera, or if the camera is a logical multi camera but the stream
     *    is not a physical output stream, this field will point to a 0-length
     *    string.
     *
     *    A logical multi camera is a camera device backed by multiple physical
     *    cameras that are also exposed to the application. And for a logical
     *    multi camera, a physical output stream is an output stream specifically
     *    requested on an underlying physical camera.
     *
     *    For an input stream, this field is guaranteed to be a 0-length string.
     */
    const char* physical_camera_id;
    void *reserved[6];
} camera3_stream_t;

typedef struct camera3_stream_configuration {
    uint32_t num_streams;
    camera3_stream_t **streams;
    uint32_t operation_mode;
    /**
     * >= CAMERA_DEVICE_API_VERSION_3_5:
     *
     * The session metadata buffer contains the initial values of
     * ANDROID_REQUEST_AVAILABLE_SESSION_KEYS. This field is optional
     * and camera clients can choose to ignore it, in which case it will
     * be set to NULL. If parameters are present, then Hal should examine
     * the parameter values and configure its internal camera pipeline
     * accordingly.
     */
    const camera_metadata_t *session_parameters;
} camera3_stream_configuration_t;

大于 HAL 3.5 版本才加进去的参数上面都保留了注释,可以看到在 configure_streams 的时候可以表示的参数还是有限的,除了规定的那几种,显得不是那么的灵活,有些客户自定义的属性可能就得等到第一个 request 下发的时候随着 request 的 settings 发下去给到 Vendor HAL 了,这样可能会加长第一帧显示的时间,因为有些实在是无法在 configure_streams 阶段就确定的参数只能等到 request 的时候才能够确定,这个时候 Vendor HAL 那边才开始去配置。以往没有这个的话就只能尽可能详细的先划分好 Usecase 之类的场景,尽可能在 configure_streams 阶段确认好参数,有可能是双方先约定好怎样怎样,总归大部分参数是有办法尽早确定的,但是总归是不够灵活,并且可能有的参数实在是只能等到第一个 request 的时候才能够下发到 Vendor HAL 那边。

Session Parameter 的加入就是为了提前这个过程以及让参数配置更加灵活化一点,Session Parameter 可用的 Key 在 Get camera 之后存放在 camera 设备的 characteristics 里面作为一个 meta 项存在,Session Key 是 request Key 的一个子集,也就是说后者 Key 包含且数量大于等于前者的 Key:

  • Session Parameter meta:ANDROID_REQUEST_AVAILABLE_SESSION_KEYS
  • Request meta:ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS

这些可用的 Session Parameter Key 由 Vendor HAL post 给 Android framework 以供 APP 使用。关于这个参数的使用在 Qcom 的 Android 源代码例程里面有一个实例,可以参见该文件 - QCamera3HWI.cpp

int32_t session_keys[] = {ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
    ANDROID_CONTROL_AE_TARGET_FPS_RANGE, QCAMERA3_INSTANT_AEC_MODE, QCAMERA3_USE_AV_TIMER,
    QCAMERA3_VIDEO_HDR_MODE, TANGO_MODE_DATA_SENSOR_FULLFOV};
staticInfo.update(ANDROID_REQUEST_AVAILABLE_SESSION_KEYS, session_keys,
        sizeof(session_keys) / sizeof(session_keys[0]));

对于 Camera Client 端来讲,可以使用:getAvailableSessionKeys() 接口来获取可以设置的 Session Parameter key,也就是上面 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS 这个 meta 里面的数组项,获取到可以设置的 Key 之后就可以通过 setSessionParameters() 来更换 APP 想要的参数,这部分参数在 configure_streams 函数调用的时候会被传递到 Vendor HAL 那边去,传递的载体就是上面的 camera3_stream_configuration_t 的最后一个成员。

Google 给的建议是,会导致耗时的硬件 reconfiguration 或者 Vendor HAL 内部 pipeline 变化的参数最好能放就放这里面去,当然因为 Session Parameter 是 Request Key 的一个子集,所以发 request 的时候也可以改变这些值,只不过可能会造成一定的时间延迟。Framework 端会监控 request 里面的所有 Key 的值,如果发现有和 configure_streams 的时候设置的 Session Parameter 不一样的项目,就会重新配置流,新的 stream configuration 带着更新的参数传递给 Vendor HAL 这边,从而触发重新配置,如果不需要这个功能的话就可以把 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS 置为空。需要注意的是,作为 SessionParameter 的 Key 最好保证不要过于频繁的去更改,因为这样会造成频繁的 re-configuration,这样会导致 CTS 测试有一定的失败可能。

在 Android 10 以及往后的版本,HAL 提供了一个用于查询当 SessionParameter 改变之后是否需要重新配置的接口,HIDL 定义可以在 ICameraDeviceSession 里面找到,具体的函数接口名是:isReconfigurationRequired。有了这个接口之后,每次检测到参数变更之后,先检查下是否真的需要进行重新配置,需要的话才会真正的去调用,这样可以提高整个系统的效率,不至于出现很多没必要的重配。至于该函数的参数,那就是需要改变的 SessionParameter Keys 列表了,一个是旧的参数,一个是新的参数,由 HAL 这边获取并判断是否需要进行重新配置操作。

返回参数为 FALSE 的时候,framework 这边就会跳过内部的重新配置操作,如果返回结果为 TRUE 的话,framework 就会执行重新配置操作,并且把新的参数传递下去,如果不实现的话,默认 framework 那边会返回一个 FALSE,所以每次改变的时候都不会重新 configure,但是会把新的参数传递下去。由于该方法会在新的 request 参数传递下去之前调用,并且还有可能在正式 submit 下去的时候取消,所以 HAL 这边最好不要在里面加入一些改变状态之类的操作,不然可能会把 Vendor HAL 这边的状态搞乱了。Vendor HAL 这边的实现要能够保证下面几个点:

  • Framework 可以在 session 创建之后的任何时间调用该方法,也就是不依赖于一些运行时的特定资源。
  • 该方法的调用不能导致任何延迟,要保证非阻塞并且能够很快地返回。
  • 硬件和软件的 camera settings 不能够有所更改,这样会导致一些延迟或者期望结果的变化,这是不允许的。
  • 不能有任何人眼可见的延迟副作用。

使用 SessionParameter 实现的一个功能配置例子就是 Camera Bokeh 的用例选择,就是俗称的人像模式,最大的特点就是背景虚化,在 Android 11 上面这个用例成为了标准化的功能以供三方软件使用。要想在设备上面实现这点,就需要关于以下几个方面:

  • Publish ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES 这个 tag,该 tag 对应的内容是一个三个为一组的参数列表,基本形式:{mode, maxWidth, maxHeight}。该列表描述了各种 Bokeh 模式下面可以支持的最大分辨率。
  • Publish ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_ZOOM_RATIO_RANGES,该 tag 是一个两个浮点数为一组的参数列表,形式为:{minZoomRatio, maxZoomRatio}。分别和上面的 tag 的内容列表按照先后顺序一一对应,如果某一项不支持 zoom,那么它的 min 和 max 应为 1.0, 1.0,表示不支持缩放。
  • 添加 ANDROID_CONTROL_USE_EXTENDED_SCENE_MODE 项到 ANDROID_CONTROL_AVAILABLE_MODES tag 里面去。

APP 想要触发 Bokeh 模式的话,就需要设置 ANDROID_CONTROL_MODEANDROID_CONTROL_USE_EXTENDED_SCENE_MODE,并且设置 ANDROID_CONTROL_EXTENDED_SCENE_MODE 为支持的模式之一:DISABLE,BOKEH_STILL_CAPTURE, BOKEH_CONTINUOUS。实现 Bokeh 会带来额外的内存使用,因为算法计算部分会增加内存用量。如果该模式并不支持每一帧都可以随意更换的话,那就需要把 ANDROID_CONTROL_EXTENDED_SCENE_MODE 添加到 ANDROID_REQUEST_AVAILABLE_SESSION_KEYS 里面去,并且 Vendor HAL 端实现 isReconfigurationRequired 在 Bokeh mode 有变化的时候返回 TRUE 来触发 framework 重新配置 stream,这就是一个比较典型的用法了。


在这里插入图片描述

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页