system/media/camera/src/camera_metadata.c // metadata的核心内容,包含metadata内存分配,扩容规则,update, find等
system/media/camera/src/camera_metadata_tag_info.c // 所有android原生tag的在内存里面section的定义
frameworks/av/camera/CameraMetadata.cpp // camera_metadata.c 的封装
hardware/interface/camera/...... 目录下也有一个CameraMetadata.cpp,看不出来干什么用的
整个camera_metadata的结构体
size: 整个metadata内存大小,计算方式如下
结构体头的大小 + camera_metadata_buffer_entry_t总大小(每个metadata的内存结构)+ 大于4字节的metadata数据部分(后面介绍) ;ALGIN_TO字节对齐,不用深究。
version:版本号,不重要
flags:不重要
entry_count:已经添加的metadata个数
entry_capacity:整个metadata空间可容纳最多metadata个数
entries_start:metadata结构体存储开始的地方
可以看到entries_start就是紧接着camera_metada_t结构体之后
data_count:数据部分大于4字节的metadata的数据部分总大小
data_capacity:数据部分大于4字节的metadata的数据部分最大容量
data_start:数据部分大于4字节的metadata的数据部分开始地址
可以看到data_start紧接着一堆 camera_metadata_buffer_entry_t 类型数据之后
padding:不重要
vendor_id:不重要
单个具体metadata结构体
从注释可以看到,如果该metadata的数据部分大于4个字节,就存储到父数组里面,就是所有camera_metadata_buffer_entry_t 之后;如果小于等于4字节,直接存储到value[4]里面。
tag:就是下面的枚举值,基于各个section的偏移,标识唯一的tag
count:个人理解count=1是基本数据,count > 1就是数组了;未深入最终过
data.offset:如果数据部分超过4字节,offset就表示该tag的数据存放在 data_start + offset开始处
data.value:如果数据部分不超过4字节, 表示该tag的数据存放在value数组里面。
type:metadata的数据类型,如下是数据类型和数据类型大小
reserved:不重要
以上就是metadata两个最重要数据结构的介绍,理解数据怎么存储的,才能继续去理解代码逻辑
camera_metadata.c开头的一幅图再回来看一下
CameraMetadata.cpp里面定义了各个类型的metadata的update方法,通过注释看到,如果这个tag有了就做更新操作,没有就创建。
主要方法是updateImpl,先获取tag的类型,然后根据类型和data_count计算data_size,计算data_size的目的就是为了扩容做准备,resizeIfNeeded 就是扩容的具体做法。接着会根据tag到metadata里面找对应的camera_metadata_entry_t项,找到了就更新,找不到就创建
【扩容】:
resizeIfNeeded 是非常重要的扩容方法,如果之前没有创建过metadata,是第一个metadata,那么mBuffer一定是空的,就先创建;如果metadata创建过了,会分别计算新的entryCount和dataCount,如果有一个超过了capacity就需要重新分配camera_metadata的空间了,append_camera_metadata会将旧的数据拷到新的空间中, free_camera_metadata将旧的控件释放掉。
另外扩容的大小都是在现有的基础上乘以2,指数级的增加,所以扩容操作其实不频繁。
【添加】:
接下来在看一下add_camera_metadata_entry_raw方法,内存在上面分配好了之后就可以往里面填写数据了,data_bytes就是计算该tag数据部分占用多少个字节,如果不超过4字节,就返回0,走第一个memcpy;如果超过4字节就做了8字节对齐,走下面一个memcpy。data_payload_bytes是真正要拷贝的数据大小,就是简单的 个数 x 类型大小, 而dst buffer的大小肯定大于等于这个数值。
【更新】:
个人人为最精彩的就是 update_camera_metadata_entry的逻辑了,该方法里面的每一行都很精彩,所以在几乎每一行后面加了个人理解。
最后用一幅图简单说明update的时候内存怎么挪动的
【查询】:
最后的最后看看 find_camera_metadata_entry方法就很简单了,根据metadata是否被排过序进行查找,排过序就用二分查找(根据tag), 没有排过序就遍历entries找到目标tag