camera metadata内存模型
3600 Words|Read in about 17 Min|本文总阅读量次
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过程是:
-
Static(characteristic)
描述device的规格与具备的能力,可以称为静态能力。
-
Control(request)
当APK获取到static metadata后,可以做出想要的控制,即下发请求。
-
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 头文件定义在如下几个文件中:
-
MetaData 层次结构定义及 基本宏定义
/system/media/camera/include/system/camera_metadata_tags.h
-
MetaData 枚举定义及常用API 定义
/system/media/camera/include/system/camera_metadata.h
-
MetaData 基本函数操作结构体定义
/system/media/camera/include/system/camera_vendor_tags.h
-
MetaData 宏定义与字符串绑定
/system/media/camera/src/camera_metadata_tag_info.c
-
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各区域
- 区域一 : 何存camera_metadata_t 结构体定义,占用内存 96 Byte
- 区域二 : 保留区,供未来使用
- 区域三 : 何存所有 Tag 结构体定义,TAG[0]、TAG[1]、…、TAG[entry_count-1]
- 区域四 : 剩余未使用的 Tag 结构体的内存保留,该区域大小为 (entry_capacity - entry_count) 个TAG
- 区域五 : 所有 Tag对应的具体 metadata 数据
- 区域六 : 剩余未使用的 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}
- 首先对默认结构体数据进行四字节对齐
- 其次对传进来的entry数组数据进行4字节对齐
- 然后对传进来的data数组数据进行8字节对齐
- 最后将所有数据进行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}
-
根据tag拿到其存储的value的type
能够根据tag拿到type,说明一开始有些东西是初始化好的,或者说有地方去定义好的,到这里我们有必要再多了解一下这里的tag了。tag分为系统原生的tag和厂商自己定义的tag(vendor tag),tag是分组的,每一组tag表示同一功能的不同属性,每一个分组我们又叫一个section。
-
拿到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}
- meta不为NULL,所以id为meta->vendor_id的值
- 然后先获取tag的section值(前16位)
- 获取tag的偏移index(后16位)
- 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}
-
拿到要更新的entry的地址
-
计算出要更新的data的大小,小于等于4返回0,否则内存对齐后返回
-
计算出需要替换的大小和当前需要更新entry的原数据大小
-
分类讨论
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直接更新即可
-
获取对应的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.