一、实现
先看一下metadata内部是什么样子:
可以看出,metadata 内部是一块连续的内存空间。
其内存分布大致可概括为:
区域一 :存 camera_metadata_t 结构体定义,占用内存 96 Byte
区域二 :保留区,供未来使用
区域三 :序号为 0 ~ entry_count-1 的 camera_metadata_buffer_entry_t 结构体对象,简
称 metadata_entry 结构体对象,每个对象有自己的 tag。
区域四 :剩余未使用的 Tag 结构体的内存保留,该区域大小为(entry_capacity – entry_count)
个 TAG,也就是(entry_capacity – entry_count)个 camera_metadata_buffer_entry_t 的空间
区域五 :所有 Tag 对应的具体 metadata 数据
区域六 :剩余未使用的 Tag 占用的内存
可以简单记成:Head 区、Entry 区、Data 区。
在这其中,TAG 又是个什么玩意儿?
其实我们既然了解了 metadata 是用来描述图像特征的参数,比如常见的曝光、ISO 等等,
就不难理解它的数据结构应该是由 N 个 key 和 value 组成的。
二、TAG
camera_metadata_buffer_entry_t 和 camera_metadata_data_t
所谓TAG,就是camera_metadata_buffer_entry
按行依次注释来看,其中,
tag 就是 TAG 的 key 值
count 就是 TAG 的 value 对应的 data 的数量
offset 标记当前的 key 值对应的 value 在 data_start 中的位置
当 value 占用的字节数小于等于 4 的时候,直接存储到 value[4]中(省空间)
tag
我们既然知道了 key 就是 camera_metadata_buffer_entry 里的 tag,那么这个 tag(key)到底
有哪些呢?
tag 很多,会按功能分组,每组叫做一个 section:
为了更方便快捷,常使用宏定义,一般目录系统默认定义 26 个 TAG:
注意这里最后一个 VENDOR_SECTION,它在枚举中的值为 0x8000,这是因为 vendor 可能还会
自己定义一些别 tag,这些 vendor 在 0x8000 后面 enum 值就不会冲突了。
定义各个 TAG 对应详细的参数,每个 TAG 用 START 开头、END 结尾。所有的 tag,都是以 section 中的名称为前缀,从 START 开始,以 END 结束
data
说完了 key,再来看一下 value,也就是每个 tag 对应的 data。
为了设计出 API,定义了这样的结构体,在这其中,tag 为 key,data 就是 union 中的指针指
向的 data(metadata_data_t),也就是 kv 模型中的 value。
再看 system/media/camera/src/camera_metadata.c 中的这个结构体:
这个结构体定义了每个 tag 的名字以及它的类型
(注意这里的类型不是说 Value 的类型,tag_info_t 的数组会分别定义这个 section 每个 tag 的实际 Value 类型)
每个 tag 不仅可以通过唯一的 key 找到,也可通过唯一的名字找到,进而获取 Value。