• CameraMetadata 知识学习整理


    一、涉及的相关代码路径

    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开头的一幅图再回来看一下

    三、 添加、更新、查找 metadata方法学习

    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

  • 相关阅读:
    python基础语言:tuple(元组)
    Mysql 入门篇之二进制安装
    【面试题精讲】Java 和 C++ 的区别?
    Linux基本指令(二)
    手搓哈希表、列表、队列,只为了用C语言快速求解华容道游戏,我不是大佬,只是一个游戏算法爱好者
    【RocketMQ 系列三】RocketMQ集群搭建(2m-2s-sync)
    『MySQL快速上手』-④-表的操作
    【JVM】G1垃圾收集器知多少
    软件架构风格总结以及场景应用
    【矩阵论】3. 矩阵函数——矩阵函数求导
  • 原文地址:https://blog.csdn.net/cfc1243570631/article/details/128033812