camera metadata内存模型学习。

1简介

简单来说,Camera 设置参数,以前都是调用 SetParameter()/Paramters() 来实现下发或获取参数。 而现在新的 Camera API2 / HAL3 架构,则修改为使用 Camera MetaData 的形式来下发或获取参数。

Camera MetaData 就是将参数以共享内存的形式,将所有的Camera 参数以有序的结构体的形式 保存在一块连接的内存中。

在API2 中,Java层中直接对参数进行设置并将其封装到Capture_Request即可,而兼容 API1 ,则在 API1中的 SetParameter()/Paramters() 方法中进行转换,最终以 MetaData 的形式传递下去。本文基于android14代码来说明。

1.1metadata机制

Camera API2/HAL3的核心为per-frame control,为了达成这个目标产生了metadata的机制,metadata一共分成了三类:static,control,dynamic。

对应的camera过程是:

  1. Static(characteristic)

    描述device的规格与具备的能力,可以称为静态能力。

  2. Control(request)

    当APK获取到static metadata后,可以做出想要的控制,即下发请求。

  3. Dynamic(result)

    当HAL收到control metadata后,设定给ISP,然后产生对应的结果。

Metadata 贯穿了 Camera 的Application、Framework 和 vendor HAL,实现了去耦合的参数传递方式,是所有的APP层下发、hal层更新参数(如ISO、EV等)的接口实现。

简单来说,camera metadata就是一块用来存储camera相关参数的内存。比如拍照时的闪光灯,是打开还是关闭还是自动,这个参数就是存储在这块内存当中的。当然,camera的参数有很多,其类型有很多。camera metadata以一定的规则将这些信息全部存储起来,然后再用相同的规则取出。

2Metadata定义

  • 编译产物:libcamera_metadata.so
  • 系统位置:/system/lib64/,/system/lib/
  • 源代码位置:/system/media/camera/

Camera MetaData 的定义,其主要集中在 /system/media/camera/ 目录, 从 Android.bp 中可以看出,最终是编译成 libcamera_metadata.so库。

 1// system/media/camera/Android.bp
 2subdirs = ["tests"]
 3
 4cc_library_shared {
 5    name: "libcamera_metadata",
 6    vendor_available: true,
 7    vndk: {
 8        enabled: true,
 9    },
10    srcs: ["src/camera_metadata.c"],
11
12    include_dirs: ["system/media/private/camera/include"],
13    local_include_dirs: ["include"],
14    export_include_dirs: ["include"],
15
16    shared_libs: [
17        "libcutils",
18        "liblog",
19    ],
20}

Camera MetaData 头文件定义在如下几个文件中:

  1. MetaData 层次结构定义及 基本宏定义

    /system/media/camera/include/system/camera_metadata_tags.h

  2. MetaData 枚举定义及常用API 定义

    /system/media/camera/include/system/camera_metadata.h

  3. MetaData 基本函数操作结构体定义

    /system/media/camera/include/system/camera_vendor_tags.h

  4. MetaData 宏定义与字符串绑定

    /system/media/camera/src/camera_metadata_tag_info.c

  5. MetaData 核心代码实现

    /system/media/camera/src/camera_metadata.c

3代码跟读

2.1Metadata内存分布

 1//system/media/camera/src/camera_metadata.c
 2#define METADATA_ALIGNMENT ((size_t) 4)
 3struct camera_metadata {
 4    metadata_size_t          size;
 5    uint32_t                 version;
 6    uint32_t                 flags;
 7    metadata_size_t          entry_count;
 8    metadata_size_t          entry_capacity;
 9    metadata_uptrdiff_t      entries_start; // Offset from camera_metadata
10    metadata_size_t          data_count;
11    metadata_size_t          data_capacity;
12    metadata_uptrdiff_t      data_start; // Offset from camera_metadata
13    uint32_t                 padding;    // padding to 8 bytes boundary
14    metadata_vendor_id_t     vendor_id;
15};
结构体成员名 含义
size 该包metadata所占的总的字节数
version 版本号
flags 标记当前是否有对entry进行排序
entry_count entry数量,初始值为0
entry_capacity 该包metadata能存储的最大的entry数量
entries_start entry相对于camera_metadata_t起始地址的偏移量,即从camera_metadata_t的起始地址再偏移entries_start就到了开始存储entry的位置了
data_count data数量,初始值为0
data_capacity 该包metadata能存储的最大的data数量
data_start data相对于camera_metadata_t起始地址的偏移量,即从camera_metadata_t的起始地址再偏移data_start就到了开始存储data的位置了
vendor_id 跟当前这个手机上的CameraDeviceProvider相关,每个CameraDeviceProvider都有自己对应的vendor_id

具体对整个结构体划分,可以划分成6各区域

  1. 区域一 : 何存camera_metadata_t 结构体定义,占用内存 96 Byte
  2. 区域二 : 保留区,供未来使用
  3. 区域三 : 何存所有 Tag 结构体定义,TAG[0]、TAG[1]、…、TAG[entry_count-1]
  4. 区域四 : 剩余未使用的 Tag 结构体的内存保留,该区域大小为 (entry_capacity - entry_count) 个TAG
  5. 区域五 : 所有 Tag对应的具体 metadata 数据
  6. 区域六 : 剩余未使用的 Tag 占用的内存

可以简化记作三个分区:Header区、Entry区、Data区。

2.1.1联合体camera_metadata_data

 1//system/media/camera/src/camera_metadata.c
 2#define DATA_ALIGNMENT ((size_t) 8)
 3typedef union camera_metadata_data {
 4    uint8_t u8;
 5    int32_t i32;
 6    float   f;
 7    int64_t i64;
 8    double  d;
 9    camera_metadata_rational_t r;
10} camera_metadata_data_t;

2.1.2结构体camera_metadata_buffer_entry

 1//system/media/camera/src/camera_metadata.c
 2#define ENTRY_ALIGNMENT ((size_t) 4)
 3typedef struct camera_metadata_buffer_entry {
 4    uint32_t tag;
 5    uint32_t count;
 6    union {
 7        uint32_t offset;
 8        uint8_t  value[4];
 9    } data;
10    uint8_t  type;
11    uint8_t  reserved[3];
12} camera_metadata_buffer_entry_t;

这里在详细说明下:

结构体metadata内存中的entry指的是camera_metadata_buffer_entry里面的tag,就是区分每个metadata的条目。

另外这里的data用于存储少量的数据,不大于4字节,超过4字节的数据会存储在data区域。(详见2.1Metadata内存分布)

2.1.3枚举类camera_metadata_section

关于camera_metadata_buffer_entry里面的tag有可以拆分成section区域,类似section为猫科动物,但是猫科动物又有很多种,其中包括猎豹属,猫属,兔狲属,豹猫属等等.

为了保证每一个section能容纳足够的tag,系统给每个section预留了64K的空间,从前面我们可以知道tag的类型是uint32_t,也就是32位4字节。

 1//system/media/camera/include/system/camera_metadata_tags.h
 2typedef enum camera_metadata_section {
 3    ANDROID_COLOR_CORRECTION,
 4    ANDROID_CONTROL,
 5    ANDROID_DEMOSAIC,
 6    ANDROID_EDGE,
 7    ANDROID_FLASH,
 8    ANDROID_FLASH_INFO,
 9    ANDROID_HOT_PIXEL,
10    ANDROID_JPEG,
11    ANDROID_LENS,
12    ANDROID_LENS_INFO,
13    ANDROID_NOISE_REDUCTION,
14    ANDROID_QUIRKS,
15    ANDROID_REQUEST,
16    ANDROID_SCALER,
17    ANDROID_SENSOR,
18    ANDROID_SENSOR_INFO,
19    ANDROID_SHADING,
20    ANDROID_STATISTICS,
21    ANDROID_STATISTICS_INFO,
22    ANDROID_TONEMAP,
23    ANDROID_LED,
24    ANDROID_INFO,
25    ANDROID_BLACK_LEVEL,
26    ANDROID_SYNC,
27    ANDROID_REPROCESS,
28    ANDROID_DEPTH,
29    ANDROID_LOGICAL_MULTI_CAMERA,
30    ANDROID_DISTORTION_CORRECTION,
31    ANDROID_HEIC,
32    ANDROID_HEIC_INFO,
33    ANDROID_AUTOMOTIVE,
34    ANDROID_AUTOMOTIVE_LENS,
35    ANDROID_EXTENSION,
36    ANDROID_JPEGR,
37    ANDROID_SECTION_COUNT,
38
39    VENDOR_SECTION = 0x8000
40} camera_metadata_section_t;

2.1.4层次结构位置camera_metadata_section_start

 1//system/media/camera/include/system/camera_metadata_tags.h
 2typedef enum camera_metadata_section_start {
 3    ANDROID_COLOR_CORRECTION_START = ANDROID_COLOR_CORRECTION  << 16,
 4    ANDROID_CONTROL_START          = ANDROID_CONTROL           << 16,
 5    ANDROID_DEMOSAIC_START         = ANDROID_DEMOSAIC          << 16,
 6    ANDROID_EDGE_START             = ANDROID_EDGE              << 16,
 7    ANDROID_FLASH_START            = ANDROID_FLASH             << 16,
 8    ANDROID_FLASH_INFO_START       = ANDROID_FLASH_INFO        << 16,
 9    ANDROID_HOT_PIXEL_START        = ANDROID_HOT_PIXEL         << 16,
10    ANDROID_JPEG_START             = ANDROID_JPEG              << 16,
11    ANDROID_LENS_START             = ANDROID_LENS              << 16,
12    ANDROID_LENS_INFO_START        = ANDROID_LENS_INFO         << 16,
13    ANDROID_NOISE_REDUCTION_START  = ANDROID_NOISE_REDUCTION   << 16,
14    ANDROID_QUIRKS_START           = ANDROID_QUIRKS            << 16,
15    ANDROID_REQUEST_START          = ANDROID_REQUEST           << 16,
16    ANDROID_SCALER_START           = ANDROID_SCALER            << 16,
17    ANDROID_SENSOR_START           = ANDROID_SENSOR            << 16,
18    ANDROID_SENSOR_INFO_START      = ANDROID_SENSOR_INFO       << 16,
19    ANDROID_SHADING_START          = ANDROID_SHADING           << 16,
20    ANDROID_STATISTICS_START       = ANDROID_STATISTICS        << 16,
21    ANDROID_STATISTICS_INFO_START  = ANDROID_STATISTICS_INFO   << 16,
22    ANDROID_TONEMAP_START          = ANDROID_TONEMAP           << 16,
23    ANDROID_LED_START              = ANDROID_LED               << 16,
24    ANDROID_INFO_START             = ANDROID_INFO              << 16,
25    ANDROID_BLACK_LEVEL_START      = ANDROID_BLACK_LEVEL       << 16,
26    ANDROID_SYNC_START             = ANDROID_SYNC              << 16,
27    ANDROID_REPROCESS_START        = ANDROID_REPROCESS         << 16,
28    ANDROID_DEPTH_START            = ANDROID_DEPTH             << 16,
29    VENDOR_SECTION_START           = VENDOR_SECTION            << 16
30} camera_metadata_section_start_t;

2.1.5TAG详细的参数camera_metadata_tag

每个 TAG 以 ##TAG##_START##TAG##_END 结束

 1//system/media/camera/include/system/camera_metadata_tags.h
 2typedef enum camera_metadata_tag {
 3    ANDROID_COLOR_CORRECTION_MODE =                   // enum         | public
 4           ANDROID_COLOR_CORRECTION_START,
 5    ANDROID_COLOR_CORRECTION_TRANSFORM,               // rational[]   | public
 6    ANDROID_COLOR_CORRECTION_GAINS,                   // float[]      | public
 7    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,         // enum         | public
 8    ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
 9                                                      // byte[]       | public
10    ANDROID_COLOR_CORRECTION_END,
11
12    ANDROID_CONTROL_AE_ANTIBANDING_MODE =             // enum         | public
13            ANDROID_CONTROL_START,
14    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,         // int32        | public
15    ANDROID_CONTROL_AE_LOCK,                          // enum         | public
16    ANDROID_CONTROL_AE_MODE,                          // enum         | public
17	......
18	ANDROID_CONTROL_END,
19	......
20    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS = 
21                                                      // enum[]       | ndk_public   | HIDL v3.9
22            ANDROID_JPEGR_START,
23    ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS,
24                                                      // int64[]      | ndk_public   | HIDL v3.9
25    ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS,   // int64[]      | ndk_public   | HIDL v3.9
26    ANDROID_JPEGR_AVAILABLE_JPEG_R_STREAM_CONFIGURATIONS_MAXIMUM_RESOLUTION,
27                                                      // enum[]       | ndk_public   | HIDL v3.9
28    ANDROID_JPEGR_AVAILABLE_JPEG_R_MIN_FRAME_DURATIONS_MAXIMUM_RESOLUTION,
29                                                      // int64[]      | ndk_public   | HIDL v3.9
30    ANDROID_JPEGR_AVAILABLE_JPEG_R_STALL_DURATIONS_MAXIMUM_RESOLUTION,
31                                                      // int64[]      | ndk_public   | HIDL v3.9
32    ANDROID_JPEGR_END,
33}

2.1.6 结构体camera_metadata_entry

每个 Tag 的数据结构体定义

 1//system/media/camera/include/system/camera_metadata.h
 2typedef struct camera_metadata_entry {
 3    size_t   index;
 4    uint32_t tag;
 5    uint8_t  type;
 6    size_t   count;
 7    union {
 8        uint8_t *u8;
 9        int32_t *i32;
10        float   *f;
11        int64_t *i64;
12        double  *d;
13        camera_metadata_rational_t *r;
14    } data;
15} camera_metadata_entry_t;

camera_metadata_entry 需要和上面的camera_metadata_buffer_entry 区别开

2.1.7数组camera_metadata_section_bounds

定义了metadata数组每个tag的范围,可以找到对应tag的起点和终点

 1//system/media/camera/src/camera_metadata_tag_info.c
 2ANDROID_API
 3extern unsigned int camera_metadata_section_bounds[ANDROID_SECTION_COUNT][2];
 4unsigned int camera_metadata_section_bounds[ANDROID_SECTION_COUNT][2] = {
 5    [ANDROID_COLOR_CORRECTION]     = { ANDROID_COLOR_CORRECTION_START,
 6                                       ANDROID_COLOR_CORRECTION_END },
 7    [ANDROID_CONTROL]              = { ANDROID_CONTROL_START,
 8                                       ANDROID_CONTROL_END },
 9    [ANDROID_DEMOSAIC]             = { ANDROID_DEMOSAIC_START,
10                                       ANDROID_DEMOSAIC_END },
11    [ANDROID_EDGE]                 = { ANDROID_EDGE_START,
12                                       ANDROID_EDGE_END },
13    [ANDROID_FLASH]                = { ANDROID_FLASH_START,
14                                       ANDROID_FLASH_END },
15    [ANDROID_FLASH_INFO]           = { ANDROID_FLASH_INFO_START,
16                                       ANDROID_FLASH_INFO_END },
17    [ANDROID_HOT_PIXEL]            = { ANDROID_HOT_PIXEL_START,
18                                       ANDROID_HOT_PIXEL_END },
19    [ANDROID_JPEG]                 = { ANDROID_JPEG_START,
20                                       ANDROID_JPEG_END },
21    [ANDROID_LENS]                 = { ANDROID_LENS_START,
22                                       ANDROID_LENS_END },
23    [ANDROID_LENS_INFO]            = { ANDROID_LENS_INFO_START,
24                                       ANDROID_LENS_INFO_END },
25    [ANDROID_NOISE_REDUCTION]      = { ANDROID_NOISE_REDUCTION_START,
26                                       ANDROID_NOISE_REDUCTION_END },
27    [ANDROID_QUIRKS]               = { ANDROID_QUIRKS_START,
28                                       ANDROID_QUIRKS_END },
29    [ANDROID_REQUEST]              = { ANDROID_REQUEST_START,
30                                       ANDROID_REQUEST_END },
31    [ANDROID_SCALER]               = { ANDROID_SCALER_START,
32                                       ANDROID_SCALER_END },
33    [ANDROID_SENSOR]               = { ANDROID_SENSOR_START,
34                                       ANDROID_SENSOR_END },
35    [ANDROID_SENSOR_INFO]          = { ANDROID_SENSOR_INFO_START,
36                                       ANDROID_SENSOR_INFO_END },
37    [ANDROID_SHADING]              = { ANDROID_SHADING_START,
38                                       ANDROID_SHADING_END },
39    [ANDROID_STATISTICS]           = { ANDROID_STATISTICS_START,
40                                       ANDROID_STATISTICS_END },
41    [ANDROID_STATISTICS_INFO]      = { ANDROID_STATISTICS_INFO_START,
42                                       ANDROID_STATISTICS_INFO_END },
43    [ANDROID_TONEMAP]              = { ANDROID_TONEMAP_START,
44                                       ANDROID_TONEMAP_END },
45    [ANDROID_LED]                  = { ANDROID_LED_START,
46                                       ANDROID_LED_END },
47    [ANDROID_INFO]                 = { ANDROID_INFO_START,
48                                       ANDROID_INFO_END },
49    [ANDROID_BLACK_LEVEL]          = { ANDROID_BLACK_LEVEL_START,
50                                       ANDROID_BLACK_LEVEL_END },
51    [ANDROID_SYNC]                 = { ANDROID_SYNC_START,
52                                       ANDROID_SYNC_END },
53    [ANDROID_REPROCESS]            = { ANDROID_REPROCESS_START,
54                                       ANDROID_REPROCESS_END },
55    [ANDROID_DEPTH]                = { ANDROID_DEPTH_START,
56                                       ANDROID_DEPTH_END },
57    [ANDROID_LOGICAL_MULTI_CAMERA] = { ANDROID_LOGICAL_MULTI_CAMERA_START,
58                                       ANDROID_LOGICAL_MULTI_CAMERA_END },
59    [ANDROID_DISTORTION_CORRECTION]
60                                    = { ANDROID_DISTORTION_CORRECTION_START,
61                                       ANDROID_DISTORTION_CORRECTION_END },
62    [ANDROID_HEIC]                 = { ANDROID_HEIC_START,
63                                       ANDROID_HEIC_END },
64    [ANDROID_HEIC_INFO]            = { ANDROID_HEIC_INFO_START,
65                                       ANDROID_HEIC_INFO_END },
66    [ANDROID_AUTOMOTIVE]           = { ANDROID_AUTOMOTIVE_START,
67                                       ANDROID_AUTOMOTIVE_END },
68    [ANDROID_AUTOMOTIVE_LENS]      = { ANDROID_AUTOMOTIVE_LENS_START,
69                                       ANDROID_AUTOMOTIVE_LENS_END },
70    [ANDROID_EXTENSION]            = { ANDROID_EXTENSION_START,
71                                       ANDROID_EXTENSION_END },
72    [ANDROID_JPEGR]                = { ANDROID_JPEGR_START,
73                                       ANDROID_JPEGR_END },
74};

2.1.8数组camera_metadata_section_names

 1//system/media/camera/src/camera_metadata_tag_info.c
 2ANDROID_API
 3extern const char *camera_metadata_section_names[ANDROID_SECTION_COUNT];
 4const char *camera_metadata_section_names[ANDROID_SECTION_COUNT] = {
 5    [ANDROID_COLOR_CORRECTION]     = "android.colorCorrection",
 6    [ANDROID_CONTROL]              = "android.control",
 7    [ANDROID_DEMOSAIC]             = "android.demosaic",
 8    [ANDROID_EDGE]                 = "android.edge",
 9    [ANDROID_FLASH]                = "android.flash",
10    [ANDROID_FLASH_INFO]           = "android.flash.info",
11    [ANDROID_HOT_PIXEL]            = "android.hotPixel",
12    [ANDROID_JPEG]                 = "android.jpeg",
13    [ANDROID_LENS]                 = "android.lens",
14    [ANDROID_LENS_INFO]            = "android.lens.info",
15    [ANDROID_NOISE_REDUCTION]      = "android.noiseReduction",
16    [ANDROID_QUIRKS]               = "android.quirks",
17    [ANDROID_REQUEST]              = "android.request",
18    [ANDROID_SCALER]               = "android.scaler",
19    [ANDROID_SENSOR]               = "android.sensor",
20    [ANDROID_SENSOR_INFO]          = "android.sensor.info",
21    [ANDROID_SHADING]              = "android.shading",
22    [ANDROID_STATISTICS]           = "android.statistics",
23    [ANDROID_STATISTICS_INFO]      = "android.statistics.info",
24    [ANDROID_TONEMAP]              = "android.tonemap",
25    [ANDROID_LED]                  = "android.led",
26    [ANDROID_INFO]                 = "android.info",
27    [ANDROID_BLACK_LEVEL]          = "android.blackLevel",
28    [ANDROID_SYNC]                 = "android.sync",
29    [ANDROID_REPROCESS]            = "android.reprocess",
30    [ANDROID_DEPTH]                = "android.depth",
31    [ANDROID_LOGICAL_MULTI_CAMERA] = "android.logicalMultiCamera",
32    [ANDROID_DISTORTION_CORRECTION]
33                                    = "android.distortionCorrection",
34    [ANDROID_HEIC]                 = "android.heic",
35    [ANDROID_HEIC_INFO]            = "android.heic.info",
36    [ANDROID_AUTOMOTIVE]           = "android.automotive",
37    [ANDROID_AUTOMOTIVE_LENS]      = "android.automotive.lens",
38    [ANDROID_EXTENSION]            = "android.extension",
39    [ANDROID_JPEGR]                = "android.jpegr",
40};

以颜色校正为例,颜色校正数组大小为5,对应info分别有mode、transform、gains、aberrationMode和availableAberrationModes

 1//system/media/camera/src/camera_metadata_tag_info.c
 2static tag_info_t android_color_correction[ANDROID_COLOR_CORRECTION_END -
 3        ANDROID_COLOR_CORRECTION_START] = {
 4    [ ANDROID_COLOR_CORRECTION_MODE - ANDROID_COLOR_CORRECTION_START ] =
 5    { "mode",                          TYPE_BYTE   },
 6    [ ANDROID_COLOR_CORRECTION_TRANSFORM - ANDROID_COLOR_CORRECTION_START ] =
 7    { "transform",                     TYPE_RATIONAL
 8                },
 9    [ ANDROID_COLOR_CORRECTION_GAINS - ANDROID_COLOR_CORRECTION_START ] =
10    { "gains",                         TYPE_FLOAT  },
11    [ ANDROID_COLOR_CORRECTION_ABERRATION_MODE - ANDROID_COLOR_CORRECTION_START ] =
12    { "aberrationMode",                TYPE_BYTE   },
13    [ ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES - ANDROID_COLOR_CORRECTION_START ] =
14    { "availableAberrationModes",      TYPE_BYTE   },
15};
16//每个section中有很多tag,而每个tag所存储的数据类型却不一定是相同的,所以我们必须指定,同时,每个tag都有自己的name
17typedef struct tag_info {
18    const char *tag_name;
19    uint8_t     tag_type;
20} tag_info_t;

2.1.9供产商自定义 metadata 及查询的方法

主要定义了一些函数指针和缺省数组,缺省数组用来后续产商自定义一些数据结构

 1//system/media/camera/include/system/camera_vendor_tags.h
 2typedef struct vendor_tag_ops vendor_tag_ops_t;
 3struct vendor_tag_ops {
 4    int (*get_tag_count)(const vendor_tag_ops_t *v);
 5    void (*get_all_tags)(const vendor_tag_ops_t *v, uint32_t *tag_array);
 6    const char *(*get_section_name)(const vendor_tag_ops_t *v, uint32_t tag);
 7    const char *(*get_tag_name)(const vendor_tag_ops_t *v, uint32_t tag);
 8    int (*get_tag_type)(const vendor_tag_ops_t *v, uint32_t tag);
 9    void* reserved[8];
10};
11
12struct vendor_tag_cache_ops {
13    int (*get_tag_count)(metadata_vendor_id_t id);
14    void (*get_all_tags)(uint32_t *tag_array, metadata_vendor_id_t id);
15    const char *(*get_section_name)(uint32_t tag, metadata_vendor_id_t id);
16    const char *(*get_tag_name)(uint32_t tag, metadata_vendor_id_t id);
17    int (*get_tag_type)(uint32_t tag, metadata_vendor_id_t id);
18    void* reserved[8];
19};

2.2分配内存allocate_camera_metadata

这里会在堆区里面开辟一个内存区域,这片内存用于存放camera_metadata结构体数据

 1// system/media/camera/include/system/camera_metadata.h
 2ANDROID_API
 3camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
 4        size_t data_capacity);
 5// system/media/camera/src/camera_metadata.c
 6camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
 7                                            size_t data_capacity) {
 8	//应该是通过这个调用计算出了需要分配内存的大小
 9    size_t memory_needed = calculate_camera_metadata_size(entry_capacity,data_capacity);
10    // 调用calloc函数进行内存分配,分配1块大小为memory_needed的连续内存并且初始化为0 
11    void *buffer = calloc(1, memory_needed);
12    // 这里是将分配的内存地址赋值给一个camera_metadata_t的指针,然后对其中的一些参数进行初始化
13    camera_metadata_t *metadata = place_camera_metadata(
14        buffer, memory_needed, entry_capacity, data_capacity);
15    return metadata;
16}

这里有两个方法,一个计算分配内存大小,另一个是将分配的内存地址进行初始化操作。

2.2.1calculate_camera_metadata_size

 1// system/media/camera/src/camera_metadata.c
 2#define ALIGN_TO(val, alignment) \
 3    (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))//这个用于结构体内存对齐的
 4#define ENTRY_ALIGNMENT ((size_t) 4)
 5#define METADATA_ALIGNMENT ((size_t) 4)
 6#define DATA_ALIGNMENT ((size_t) 8)
 7#define MAX_ALIGNMENT(A, B) (((A) > (B)) ? (A) : (B))
 8#define METADATA_PACKET_ALIGNMENT \
 9    MAX_ALIGNMENT(MAX_ALIGNMENT(DATA_ALIGNMENT, METADATA_ALIGNMENT), ENTRY_ALIGNMENT)
10
11size_t calculate_camera_metadata_size(size_t entry_count,
12                                      size_t data_count) {
13    // 先拿到camera_metadata_t的大小,大小为44个字节
14    size_t memory_needed = sizeof(camera_metadata_t);
15    // 作4字节对齐
16    memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
17    // 再加上entry * entry_count的大小,注意这里entry_count实际是entry_capacity
18    memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
19    // 作8字节对齐
20    memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
21    // 加上data_count, 因为data就是以字节为单位的,所以直接加data_count
22    // 同样,这里data_count是data_capacity
23    memory_needed += sizeof(uint8_t[data_count]);
24    // 8字节对齐
25    memory_needed = ALIGN_TO(memory_needed, METADATA_PACKET_ALIGNMENT);
26    return memory_needed;
27}
  1. 首先对默认结构体数据进行四字节对齐
  2. 其次对传进来的entry数组数据进行4字节对齐
  3. 然后对传进来的data数组数据进行8字节对齐
  4. 最后将所有数据进行8字节对齐

2.2.2place_camera_metadata

 1// system/media/camera/src/camera_metadata.c
 2// dst: 使用calloc分配的内存地址
 3// dst_size: 上面计算出的memory_needed
 4camera_metadata_t *place_camera_metadata(void *dst,
 5                                         size_t dst_size,
 6                                         size_t entry_capacity,
 7                                         size_t data_capacity) {
 8    if (dst == NULL) return NULL;
 9
10    // 又计算了一次内存大小,原因是拷贝函数copy_camera_metadata中也调用了place_camera_metadata
11    // 拷贝时,src size是不能大于dst size的,所以下面我们会看到有个比较
12    size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
13                                                          data_capacity);
14
15    // 对camera_metadata_t进行初始化,将dst地址赋值给metadata地址,
16    camera_metadata_t *metadata = (camera_metadata_t*)dst;
17    metadata->version = CURRENT_METADATA_VERSION; // 版本号为1
18    metadata->flags = 0; // 0表示不对entry进行排序
19    metadata->entry_count = 0; // 初始大小都为0,data也一样,后面有插入时递增
20    metadata->entry_capacity = entry_capacity; // 最大容量entry
21    metadata->entries_start = // entry的起始地址,在camera_metadata_t后面做字节对齐后就是entry_start
22            ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
23    metadata->data_count = 0; // 初始value为0
24    metadata->data_capacity = data_capacity; // 最大value字节数
25    metadata->size = memory_needed; // 申请的内存大小
26    // entry_start + entry_capacity的大小
27    size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
28            metadata->entry_capacity) - (uint8_t*)metadata;
29    // entry_start + entry_capacity作8字节对齐后,就是data_start在metadata中的相对地址
30    metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
31    // vendor_id有api可以设置,我们放到下个章节详细讲解vendor metadata
32    metadata->vendor_id = CAMERA_METADATA_INVALID_VENDOR_ID;
33    return metadata;
34}

这个函数其实就是初始化了分配的内存中的头部部分,也就是camera_metadata_t所占用的内存,剩余未分配的内存里面现在全是0

data_unaligned就是entry_start + entry_capacity的大小

这里的(uint8_t*)metadata为内存camera_metadata_t的首地址,那么get_entries就是获取到entry_start + entry_capacity的地址

1// system/media/camera/src/camera_metadata.c
2static camera_metadata_buffer_entry_t *get_entries(
3        const camera_metadata_t *metadata) {
4    return (camera_metadata_buffer_entry_t*)
5            ((uint8_t*)metadata + metadata->entries_start);
6}

2.3增加add_camera_metadata_entry

 1// system/media/camera/include/system/camera_metadata.h
 2ANDROID_API
 3int add_camera_metadata_entry(camera_metadata_t *dst,
 4        uint32_t tag,
 5        const void *data,
 6        size_t data_count);
 7
 8// system/media/camera/src/camera_metadata.c
 9int add_camera_metadata_entry(camera_metadata_t *dst,
10        uint32_t tag,
11        const void *data,
12        size_t data_count) {
13    // 很简单,根据tag拿到其存储的value的type,也就是这个type其实是一开始就定义好的
14    int type = get_local_camera_metadata_tag_type(tag, dst);
15    // 拿到type之后再继续调用这个函数,其中多了一个type参数
16    return add_camera_metadata_entry_raw(dst,
17            tag,
18            type,
19            data,
20            data_count);
21}
  1. 根据tag拿到其存储的value的type

    能够根据tag拿到type,说明一开始有些东西是初始化好的,或者说有地方去定义好的,到这里我们有必要再多了解一下这里的tag了。tag分为系统原生的tag厂商自己定义的tag(vendor tag),tag是分组的,每一组tag表示同一功能的不同属性,每一个分组我们又叫一个section。

  2. 拿到type之后再继续调用add_camera_metadata_entry_raw这个函数

2.3.1get_local_camera_metadata_tag_type

 1// system/media/camera/src/camera_metadata.c
 2int get_local_camera_metadata_tag_type(uint32_t tag,
 3        const camera_metadata_t *meta) {
 4    // meta不为NULL,所以id为meta->vendor_id的值
 5    metadata_vendor_id_t id = (NULL == meta) ? CAMERA_METADATA_INVALID_VENDOR_ID :
 6            meta->vendor_id;
 7
 8    return get_local_camera_metadata_tag_type_vendor_id(tag, id);
 9}
10
11// system/media/camera/src/camera_metadata.c
12// 这里假设我们添加的是系统section,非vendor_section
13int get_local_camera_metadata_tag_type_vendor_id(uint32_t tag,
14        metadata_vendor_id_t id) {
15    // tag右移16位得到的是tag所在的section
16    uint32_t tag_section = tag >> 16;
17    ...
18    // 这里注意,0xFFFF的高16位全为0,低16位全为1,进行按位与运算后,
19    // 就得到了低16位的值,也就是每个tag相对于其section_start的偏移
20    uint32_t tag_index = tag & 0xFFFF;
21    // tag_section的第tag_index个tag
22    return tag_info[tag_section][tag_index].tag_type;
23}
  1. meta不为NULL,所以id为meta->vendor_id的值
  2. 然后先获取tag的section值(前16位)
  3. 获取tag的偏移index(后16位)
  4. tag_section和tag_index获取到真实的tag_info中的tag_info_t结构体,最后返回对应tag_info_t结构体的tag_type

2.3.2add_camera_metadata_entry_raw

 1// system/media/camera/src/camera_metadata.c
 2static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
 3        uint32_t tag,
 4        uint8_t  type,
 5        const void *data,
 6        size_t data_count) {
 7    // 拿到需要存储的value所占用的字节数
 8    //这里也存在为0,0存在到时候存储在data.value里面,否则存在data区中
 9    size_t data_bytes =
10            calculate_camera_metadata_entry_data_size(type, data_count);
11
12    // calculate_camera_metadata_entry_data_size end
13    // data占用的空间超出了分配的最大空间,返回错误
14    if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
15
16    // value真正占用的字节数
17    size_t data_payload_bytes =
18            data_count * camera_metadata_type_size[type];
19    // 新的entry的地址
20    camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
21    // 初始化为0
22    memset(entry, 0, sizeof(camera_metadata_buffer_entry_t));
23    // 赋值
24    entry->tag = tag;
25    entry->type = type;
26    entry->count = data_count;
27
28    if (data_bytes == 0) {
29        // value小于等于4字节,存储到data.value
30        memcpy(entry->data.value, data,
31                data_payload_bytes);
32    } else {
33        // value大于4字节,在data区末尾添加value
34        entry->data.offset = dst->data_count;
35        memcpy(get_data(dst) + entry->data.offset, data,
36                data_payload_bytes);
37        // 更新data_count,这里的data_bytes大于等于data_payload_bytes,
38        // 因为做了8字节对齐
39        dst->data_count += data_bytes;
40    }
41    // entry_count递增
42    dst->entry_count++;
43    // 不排序
44    dst->flags &= ~FLAG_SORTED;
45    // 对齐检查,整个内存必须保证METADATA_ALIGNMENT,ENTRY_ALIGNMENT,
46    // DATA_ALIGNMENT都能对齐,否则抛出异常。
47    assert(validate_camera_metadata_structure(dst, NULL) == OK);
48    return OK;
49}

2.3.3calculate_camera_metadata_entry_data_size

拿到需要存储的value所占用的字节数

 1// calculate_camera_metadata_entry_data_size start
 2size_t calculate_camera_metadata_entry_data_size(uint8_t type,
 3                                                 size_t data_count) {
 4    // 不再定义的类型范围内,也就是不支持此类型
 5    if (type >= NUM_TYPES) return 0;
 6    // data_count乘以type占用的字节数就是整个value占用的字节数
 7    size_t data_bytes = data_count *
 8        camera_metadata_type_size[type];
 9    // value所需字节数小于4返回0,到时候存储在data.value里面,否则按8字节对齐返回,
10    // 保存在偏移量为offset的data区,
11    return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
12}
13// system/media/camera/include/system/camera_metadata.h
14enum {
15    // Unsigned 8-bit integer (uint8_t)
16    TYPE_BYTE = 0,
17    // Signed 32-bit integer (int32_t)
18    TYPE_INT32 = 1,
19    // 32-bit float (float)
20    TYPE_FLOAT = 2,
21    // Signed 64-bit integer (int64_t)
22    TYPE_INT64 = 3,
23    // 64-bit float (double)
24    TYPE_DOUBLE = 4,
25    // A 64-bit fraction (camera_metadata_rational_t)
26    TYPE_RATIONAL = 5,
27    // Number of type fields
28    NUM_TYPES
29};
30// system/media/camera/src/camera_metadata.c
31const size_t camera_metadata_type_size[NUM_TYPES] = {
32    [TYPE_BYTE]     = sizeof(uint8_t),
33    [TYPE_INT32]    = sizeof(int32_t),
34    [TYPE_FLOAT]    = sizeof(float),
35    [TYPE_INT64]    = sizeof(int64_t),
36    [TYPE_DOUBLE]   = sizeof(double),
37    [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
38};
  • 根据传入的type数据类型,来得到对应的真实数据量data_bytes
  • value所需字节数小于4返回0,到时候存储在data.value里面,否则按8字节对齐返回

2.4删除delete_camera_metadata_entry

 1// system/media/camera/include/system/camera_metadata.h
 2ANDROID_API
 3int delete_camera_metadata_entry(camera_metadata_t *dst,
 4        size_t index);
 5
 6// system/media/camera/src/camera_metadata.c
 7// 参数index表示要查询的entry是第几个,也就是从entry_start开始的第几个entry
 8int delete_camera_metadata_entry(camera_metadata_t *dst,
 9        size_t index) {
10    // 得到要删除的entry地址
11    camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
12    // 拿到该entry中的value占用的字节数,这个函数我们前面已经分析过
13    size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
14            entry->count);
15    // 大于0,说明字节数是大于4的,存储在data区段
16    if (data_bytes > 0) {
17        // Shift data buffer to overwrite deleted data
18        // 拿到data的地址
19        uint8_t *start = get_data(dst) + entry->data.offset;
20        // data结束的地址
21        uint8_t *end = start + data_bytes;
22        // length为data区段中去除要删除的entry data后剩余的data value占用的字节数
23        size_t length = dst->data_count - entry->data.offset - data_bytes;
24        // 剩余的data区段向上移动到要删除的entry的offset处,也就是将要删除的entry data
25        // 进行了覆盖
26        memmove(start, end, length);
27
28        // Update all entry indices to account for shift
29        // 很显然的是,data进行了移动,那么对应的entry中的offset字段也得更新。
30        // 将每一个在要删除的entry后面的entry的data.offset前移data_bytes
31        // 个字节(其data.value大于4字节的,小于4字节的不用处理的,因为不在
32        // data区段存储value)
33        camera_metadata_buffer_entry_t *e = get_entries(dst);
34        size_t i;
35        for (i = 0; i < dst->entry_count; i++) {
36            if (calculate_camera_metadata_entry_data_size(
37                    e->type, e->count) > 0 &&
38                    e->data.offset > entry->data.offset) {
39                e->data.offset -= data_bytes;
40            }
41            ++e;
42        }
43        // 整个的data_count减去data_bytes
44        dst->data_count -= data_bytes;
45    }
46    // Shift entry array
47    // 将存储entry的区域,把要删除的entry的后面的entry前移。
48    // 如果存储的数据小于等于4字节的话直接执行这里一段就OK了,
49    // 那就是只移动entry,因为data区没有存储数据
50    memmove(entry, entry + 1,
51            sizeof(camera_metadata_buffer_entry_t) *
52            (dst->entry_count - index - 1) );
53    // entry_cunt减1
54    dst->entry_count -= 1;
55
56    assert(validate_camera_metadata_structure(dst, NULL) == OK);
57    return OK;
58}
  • 得到要删除的entry地址

  • 拿到该entry中的value占用的字节数

    1)如果为0,用memmove后面的entry来覆盖要删除的entry

    2)如果不为0,那么value数据在data区中,找到这段数据并用memove后面的数据来覆盖要删除的数据,并更新data区的offset字段

删除的代码理解起来比较简单,就是memove其中的内存数据的移动比较消耗性能。

2.5修改update_camera_metadata_entry

如果data的大小不变,其算法复杂度为O(1),否则为O(N)

 1// system/media/camera/include/system/camera_metadata.h
 2ANDROID_API
 3int update_camera_metadata_entry(camera_metadata_t *dst,
 4        size_t index,
 5        const void *data,
 6        size_t data_count,
 7        camera_metadata_entry_t *updated_entry);
 8// system/media/camera/src/camera_metadata.c
 9int update_camera_metadata_entry(camera_metadata_t *dst,
10        size_t index,
11        const void *data,
12        size_t data_count,
13        camera_metadata_entry_t *updated_entry) {
14    // 拿到要更新的entry的地址
15    camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
16
17    // 计算出要更新的data的大小,小于等于4返回0,否则内存对齐后返回
18    size_t data_bytes =
19            calculate_camera_metadata_entry_data_size(entry->type,
20                    data_count);
21    // 要更新的data的大小的实际大小
22    size_t data_payload_bytes =
23            data_count * camera_metadata_type_size[entry->type];
24
25    // 目前entry的data占用的大小
26    size_t entry_bytes =
27            calculate_camera_metadata_entry_data_size(entry->type,
28                    entry->count);
29    // 更新前后大小不一致
30    if (data_bytes != entry_bytes) {
31        // May need to shift/add to data array
32        // 大了,超出了capacity,返回错误
33        if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
34            // No room
35            return ERROR;
36        }
37        // 大于4字节的情况【情况3,情况4-1】
38        if (entry_bytes != 0) {
39            // Remove old data
40            // 这个代码熟悉吗,跟删除操作了删除data的地方一样的
41            uint8_t *start = get_data(dst) + entry->data.offset;
42            uint8_t *end = start + entry_bytes;
43            size_t length = dst->data_count - entry->data.offset - entry_bytes;
44            memmove(start, end, length);
45            dst->data_count -= entry_bytes;
46
47            // Update all entry indices to account for shift
48            // offset更新
49            camera_metadata_buffer_entry_t *e = get_entries(dst);
50            size_t i;
51            for (i = 0; i < dst->entry_count; i++) {
52                if (calculate_camera_metadata_entry_data_size(
53                        e->type, e->count) > 0 &&
54                        e->data.offset > entry->data.offset) {
55                    e->data.offset -= entry_bytes;
56                }
57                ++e;
58            }
59        }
60		//[情况4-1和情况2]
61        if (data_bytes != 0) {
62            // Append new data
63            // 更add entry里的代码又一样了
64            // 所以就是进行了一次先删除,后插入的操作
65            entry->data.offset = dst->data_count;
66
67            memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
68            dst->data_count += data_bytes;
69        }
70    //[情况4-2]
71    } else if (data_bytes != 0) {
72        // data size unchanged, reuse same data location
73        // 如果data大小不变,只更新内存的数据既可以了
74        memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
75    }
76    //[情况1-1,情况1-2,情况3]
77    if (data_bytes == 0) {
78        // Data fits into entry
79        // 如果小于等于4字节,则更新data.value字段即可
80        memcpy(entry->data.value, data,
81                data_payload_bytes);
82    }
83
84    // 更新count
85    entry->count = data_count;
86
87    // 这里的updated_entry是一个出参
88    // 不为空的话返回更新后的entry信息
89    if (updated_entry != NULL) {
90        get_camera_metadata_entry(dst,
91                index,
92                updated_entry);
93    }
94
95    assert(validate_camera_metadata_structure(dst, NULL) == OK);
96    return OK;
97}
  1. 拿到要更新的entry的地址

  2. 计算出要更新的data的大小,小于等于4返回0,否则内存对齐后返回

  3. 计算出需要替换的大小和当前需要更新entry的原数据大小

  4. 分类讨论

    data_bytes(可能为0,需要更新的数据) entry_bytes(可能为0,原先的数据) 场景 操作
    0 0 情况1-1(不相等)情况1-2(相等) 情况1-1/情况1-2用4方式更新
    大于4 0 情况2 用2方式更新
    0 大于4 情况3 先1方式后4方式
    大于4 大于4 情况4-1(不相等)情况4-2(相等) 情况4-1:先1方式后2方式情况4-2:用3方式

    方式1:如果原先数据大于4字节,那么会删除原先数据,具体删除可以查看2.4中的第二种删除情况,都是一致的

    方式2:如果需要更新的数据大于4字节,那么直接更新到data区中当前data数据的后面

    方式3:如果原先数据和需要更新数据一致,那么直接覆盖更新即可

    方式4:如果需要更新的数据小于4,直接在entry的data.value直接更新即可

  5. 获取对应的entry,这个entry是camera_metadata_entry

2.5.1get_camera_metadata_entry

获取对应的entry,这里的entry不是camera_metadata_buffer_entry,而是camera_metadata_entry

 1// system/media/camera/src/camera_metadata.c
 2int get_camera_metadata_entry(camera_metadata_t *src,
 3        size_t index,
 4        camera_metadata_entry_t *entry) {
 5    if (src == NULL || entry == NULL) return ERROR;
 6    if (index >= src->entry_count) return ERROR;
 7
 8    camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
 9
10    entry->index = index;
11    entry->tag = buffer_entry->tag;
12    entry->type = buffer_entry->type;
13    entry->count = buffer_entry->count;
14    if (buffer_entry->count *
15            camera_metadata_type_size[buffer_entry->type] > 4) {
16        entry->data.u8 = get_data(src) + buffer_entry->data.offset;
17    } else {
18        entry->data.u8 = buffer_entry->data.value;
19    }
20    return OK;
21}

这个数据地址如果小于4,那么指向buffer_entry->data.value,如果大于4,那么指向data区,get_data(src) + buffer_entry->data.offset

2.6查找find_camera_metadata_entry

这里跟2.5.1一样,entry是camera_metadata_entry

 1// system/media/camera/include/system/camera_metadata.h
 2ANDROID_API
 3int find_camera_metadata_entry(camera_metadata_t *src,
 4        uint32_t tag,
 5        camera_metadata_entry_t *entry);
 6
 7// system/media/camera/src/camera_metadata.c
 8int find_camera_metadata_entry(camera_metadata_t *src,
 9        uint32_t tag,
10        camera_metadata_entry_t *entry) {
11    if (src == NULL) return ERROR;
12
13    uint32_t index;
14    // 如果已经排序了,则做二分查找,
15    // 有多个相同tag存在的话,返回哪一个就不确定了
16    if (src->flags & FLAG_SORTED) {
17        // Sorted entries, do a binary search
18        camera_metadata_buffer_entry_t *search_entry = NULL;
19        camera_metadata_buffer_entry_t key;
20        key.tag = tag;
21        search_entry = bsearch(&key,
22                get_entries(src),
23                src->entry_count,
24                sizeof(camera_metadata_buffer_entry_t),
25                compare_entry_tags);
26        if (search_entry == NULL) return NOT_FOUND;
27        index = search_entry - get_entries(src);
28    } else {
29        // Not sorted, linear search
30        // 没有排序,线性查找,这样返回的就是找到的第一个
31        camera_metadata_buffer_entry_t *search_entry = get_entries(src);
32        for (index = 0; index < src->entry_count; index++, search_entry++) {
33            if (search_entry->tag == tag) {
34                break;
35            }
36        }
37        if (index == src->entry_count) return NOT_FOUND;
38    }
39    //这里的get_camera_metadata_entry,又回到2.5.1了
40    return get_camera_metadata_entry(src, index,
41            entry);
42}

这里的查找比较简单,用metadata的flag字段来判断是否排序

  • 如果存在排序,那么二分法查找,时间复杂度o(logn)
  • 如果不存在排序,线性查找,时间复杂度为o(n)

3实例

其实很多情况下,不会直接调用上述的分配内存或者是增删改查,外部通常会有一个外观者模式,把这些功能包裹起来。

真实调用会调用到对应的CameraMetadata的api

 1//frameworks/av/include/camera/CameraMetadata.h
 2class CameraMetadata: public Parcelable {
 3  public:
 4    /** Creates an empty object; best used when expecting to acquire contents from elsewhere */
 5    CameraMetadata();
 6    /** Creates an object with space for entryCapacity entries, with dataCapacity extra storage */
 7    CameraMetadata(size_t entryCapacity, size_t dataCapacity = 10);
 8    /** Takes ownership of passed-in buffer */
 9    CameraMetadata(camera_metadata_t *buffer);
10    /** Clones the metadata */
11    CameraMetadata(const CameraMetadata &other);
12	
13	/* Update metadata entry. Will create entry if it doesn't exist already, and
14     * will reallocate the buffer if insufficient space exists. Overloaded for
15     * the various types of valid data. */
16  	status_t update(uint32_t tag, const uint8_t *data, size_t data_count);
17    status_t update(uint32_t tag, const int32_t *data, size_t data_count);
18    status_t update(uint32_t tag, const float *data, size_t data_count);
19    status_t update(uint32_t tag, const int64_t *data, size_t data_count);
20    status_t update(uint32_t tag, const double *data, size_t data_count);
21    status_t update(uint32_t tag, const camera_metadata_rational_t *data, size_t data_count);
22    status_t update(uint32_t tag, const String8 &string);
23    status_t update(const camera_metadata_ro_entry &entry);
24    template<typename T>
25    status_t update(uint32_t tag, Vector<T> data) {
26        return update(tag, data.array(), data.size());
27    }
28    
29	// Metadata object is unchanged when reading from parcel fails.
30    virtual status_t readFromParcel(const Parcel *parcel) override;
31    virtual status_t writeToParcel(Parcel *parcel) const override;
32
33    /* Caller becomes the owner of the new metadata
34      * 'const Parcel' doesnt prevent us from calling the read functions.
35      *  which is interesting since it changes the internal state
36      *
37      * NULL can be returned when no metadata was sent, OR if there was an issue
38      * unpacking the serialized data (i.e. bad parcel or invalid structure).*/
39    static status_t readFromParcel(const Parcel &parcel, camera_metadata_t** out);
40    /* Caller retains ownership of metadata
41      * - Write 2 (int32 + blob) args in the current position */
42    static status_t writeToParcel(Parcel &parcel, const camera_metadata_t* metadata);
43private:
44    camera_metadata_t *mBuffer;
45};

比如构造完成CameraMetadata之后,直接调用updateImpl方法

1uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
2metadata.update(ANDROID_LED_TRANSMIT,&transmitDefault, 1);

update会调用到CameraMetadata::updateImpl方法

 1# frameworks/av/camera/CameraMetadata.cpp
 2status_t CameraMetadata::updateImpl(uint32_t tag, const void *data, size_t data_count) {
 3
 4    int type = get_camera_metadata_tag_type(tag);//获取tag的Type,为后面计算内存做准备
 5    
 6    // Safety check - ensure that data isn't pointing to this metadata, since
 7    // that would get invalidated if a resize is needed
 8    size_t bufferSize = get_camera_metadata_size(mBuffer);
 9    uintptr_t bufAddr = reinterpret_cast<uintptr_t>(mBuffer);
10    uintptr_t dataAddr = reinterpret_cast<uintptr_t>(data);
11
12    size_t data_size = calculate_camera_metadata_entry_data_size(type, data_count);
13    //如果第一次进来会分配camera_metadata空间
14    res = resizeIfNeeded(1, data_size);
15
16    if (res == OK) {
17        camera_metadata_entry_t entry;
18        //尝试寻找对应的entry
19        res = find_camera_metadata_entry(mBuffer, tag, &entry);
20        if (res == NAME_NOT_FOUND) {
21            //第一次调用的话,会增加一个新的entry
22            res = add_camera_metadata_entry(mBuffer,tag, data, data_count);
23        } else if (res == OK) {
24            //存在entry的话,直接更新entry对应的数据内容
25            res = update_camera_metadata_entry(mBuffer, entry.index, data, data_count, NULL);
26        }
27    }
28    return res;
29}

参考

[1] 无限无羡. Android 13 CameraMetadata详解1 (内存分布以及增删改查), 2023.

[2] Android开发手册. CameraMetadata, 2023.

[3] c枫_撸码的日子. [Camera专题]Qcom- 获取metadata数据, 2021.

[4] “小夜猫&小懒虫&小财迷"的男人. 【高通SDM660平台】(8) — Camera MetaData介绍, 2023.

[5] alibli. Camera MetaData介绍_独家原创, 2023.