Camera MetaData 介绍

本文深入解析Android相机框架中CameraMetadata的使用,包括其内存布局、宏定义、API方法以及核心代码实现。文章通过跟踪代码展示了如何设置和更新CameraMetadata参数,并最终通过硬件接口下发到底层。此外,还探讨了CameraMetadata在硬件层面如何影响参数设置的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

929cf4e81cf99cb0fe5c4c1c46f22ed4.gif

和你一起终身学习,这里是程序员Android

经典好文推荐,通过阅读本文,您将收获以下知识点:

一、Camera MetaData 作用简介
二、MetaData 定义介绍
三、Camera MetaData 代码流程分析
四、CameraMetadata.cpp 代码分析

一、Camera MetaData 作用简介

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

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

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

接下来,我们分别来学习下 Camera MetaData 的定义 及 使用方法。

二、MetaData 定义介绍

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

# system/media/camera/Android.bp
subdirs = ["tests"]

cc_library_shared {
    name: "libcamera_metadata",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
    srcs: ["src/camera_metadata.c"],

    include_dirs: ["system/media/private/camera/include"],
    local_include_dirs: ["include"],
    export_include_dirs: ["include"],

    shared_libs: [
        "libcutils",
        "liblog",
    ],
}

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

2.1 Camera MetaData 内存分布

在 camera_metadata.c 中,有一幅 内存分存图,可以看出 Camera MetaData 数据结构是一块连续的内存空间。

其内存区分布如下:

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

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

/**
 * A packet of metadata. This is a list of entries, each of which may point to
 * its values stored at an offset in data.
 *
 * It is assumed by the utility functions that the memory layout of the packet
 * is as follows:
 *   |-----------------------------------------------|
 *   | camera_metadata_t                             |  区域一 :何存camera_metadata_t  结构体定义
 *   |                                               |
 *   |-----------------------------------------------|
 *   | reserved for future expansion                 |  区域二 :保留区,供未来使用
 *   |-----------------------------------------------|
 *   | camera_metadata_buffer_entry_t #0             |  区域三 :何存所有 Tag 结构体定义
 *   |-----------------------------------------------|          TAG[0]、TAG[1]、.....、TAG[entry_count-1]
 *   | ....                                          |
 *   |-----------------------------------------------|
 *   | camera_metadata_buffer_entry_t #entry_count-1 |
 *   |-----------------------------------------------|
 *   | free space for                                |  区域四 :剩余未使用的 Tag 结构体的内存保留,
 *   | (entry_capacity-entry_count) entries          |          该区域大小为 (entry_capacity - entry_count) 个TAG  
 *   |-----------------------------------------------|
 *   | start of camera_metadata.data                 |  区域五 :所有 Tag对应的具体 metadata 数据
 *   |                                               |
 *   |-----------------------------------------------|
 *   | free space for                                |  区域六 :剩余未使用的 Tag 占用的内存 
 *   | (data_capacity-data_count) bytes              |
 *   |-----------------------------------------------|
 *
 * With the total length of the whole packet being camera_metadata.size bytes.
 *
 * In short, the entries and data are contiguous in memory after the metadata
 * header.
 */
#define METADATA_ALIGNMENT ((size_t) 4)
struct camera_metadata {
    metadata_size_t          size;              //整个metadata数据大小
    uint32_t                 version;           //version
    uint32_t                 flags;
    metadata_size_t          entry_count;       //已经添加TAG的入口数量,(即内存块中已经包含多少TAG了)
    metadata_size_t          entry_capacity;    //最大能容纳TAG的入口数量(即最大能放多少tag)
    metadata_uptrdiff_t      entries_start;     //TAG区域相对开始处的偏移  Offset from camera_metadata
    metadata_size_t          data_count;        //记录数据段当前已用的内存空间
    metadata_size_t          data_capacity;     //总的数据段内存空间
    metadata_uptrdiff_t      data_start;        //数据区相对开始处的偏移 Offset from camera_metadata
    uint32_t                 padding;           // padding to 8 bytes boundary
    metadata_vendor_id_t     vendor_id;         // vendor id
};
typedef struct camera_metadata camera_metadata_t;

每个TAG 对应的数据结构体如下,占用内存 33 Byte,由于是以 8字节对齐,所以该结构体占用 40 个Byte。

/**
 * A datum of metadata. This corresponds to camera_metadata_entry_t::data
 * with the difference that each element is not a pointer. We need to have a
 * non-pointer type description in order to figure out the largest alignment
 * requirement for data (DATA_ALIGNMENT).
 */
#define DATA_ALIGNMENT ((size_t) 8)
typedef union camera_metadata_data {
    uint8_t u8;
    int32_t i32;
    float   f;
    int64_t i64;
    double  d;
    camera_metadata_rational_t r;
} camera_metadata_data_t;

#define ENTRY_ALIGNMENT ((size_t) 4)
typedef struct camera_metadata_buffer_entry {
    uint32_t tag;
    uint32_t count;
    union {
        uint32_t offset;
        uint8_t  value[4];
    } data;
    uint8_t  type;
    uint8_t  reserved[3];
} camera_metadata_buffer_entry_t;
2.2 基本宏定义 camera_metadata_tags.h

Camera MetaData 中所有的TAG 定义在 camera_metadata_tags.h 中。
可以看出,目录系统默认定义了 26 个Tag,分别如下:

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

/* Top level hierarchy definitions for camera metadata. *_INFO sections are for
 * the static metadata that can be retrived without opening the camera device.
 * New sections must be added right before ANDROID_SECTION_COUNT to maintain
 * existing enumerations. */
typedef enum camera_metadata_section {
    ANDROID_COLOR_CORRECTION,
    ANDROID_CONTROL,            // 控制数据
    ANDROID_DEMOSAIC,
    ANDROID_EDGE,
    ANDROID_FLASH,              // 
    ANDROID_FLASH_INFO,
    ANDROID_HOT_PIXEL,
    ANDROID_JPEG,
    ANDROID_LENS,
    ANDROID_LENS_INFO,
    ANDROID_NOISE_REDUCTION,
    ANDROID_QUIRKS,
    ANDROID_REQUEST,
    ANDROID_SCALER,
    ANDROID_SENSOR,
    ANDROID_SENSOR_INFO,
    ANDROID_SHADING,
    ANDROID_STATISTICS,
    ANDROID_STATISTICS_INFO,
    ANDROID_TONEMAP,
    ANDROID_LED,
    ANDROID_INFO,
    ANDROID_BLACK_LEVEL,
    ANDROID_SYNC,
    ANDROID_REPROCESS,
    ANDROID_DEPTH,
    ANDROID_SECTION_COUNT,

    VENDOR_SECTION = 0x8000
} camera_metadata_section_t;

由于在内存中,各个tag 数据都是以有序的结构体形式保存起来,各个tag 对应的偏移地址如下:

/**
 * Hierarchy positions in enum space. All vendor extension tags must be
 * defined with tag >= VENDOR_SECTION_START
 */
typedef enum camera_metadata_section_start {
    ANDROID_COLOR_CORRECTION_START = ANDROID_COLOR_CORRECTION  << 16,
    ANDROID_CONTROL_START          = ANDROID_CONTROL           << 16,
    ANDROID_DEMOSAIC_START         = ANDROID_DEMOSAIC          << 16,
    ANDROID_EDGE_START             = ANDROID_EDGE              << 16,
    ANDROID_FLASH_START            = ANDROID_FLASH             << 16,
    ANDROID_FLASH_INFO_START       = ANDROID_FLASH_INFO        << 16,
    ANDROID_HOT_PIXEL_START        = ANDROID_HOT_PIXEL         << 16,
    ANDROID_JPEG_START             = ANDROID_JPEG              << 16,
    ANDROID_LENS_START             = ANDROID_LENS              << 16,
    ANDROID_LENS_INFO_START        = ANDROID_LENS_INFO         << 16,
    ANDROID_NOISE_REDUCTION_START  = ANDROID_NOISE_REDUCTION   << 16,
    ANDROID_QUIRKS_START           = ANDROID_QUIRKS            << 16,
    ANDROID_REQUEST_START          = ANDROID_REQUEST           << 16,
    ANDROID_SCALER_START           = ANDROID_SCALER            << 16,
    ANDROID_SENSOR_START           = ANDROID_SENSOR            << 16,
    ANDROID_SENSOR_INFO_START      = ANDROID_SENSOR_INFO       << 16,
    ANDROID_SHADING_START          = ANDROID_SHADING           << 16,
    ANDROID_STATISTICS_START       = ANDROID_STATISTICS        << 16,
    ANDROID_STATISTICS_INFO_START  = ANDROID_STATISTICS_INFO   << 16,
    ANDROID_TONEMAP_START          = ANDROID_TONEMAP           << 16,
    ANDROID_LED_START              = ANDROID_LED               << 16,
    ANDROID_INFO_START             = ANDROID_INFO              << 16,
    ANDROID_BLACK_LEVEL_START      = ANDROID_BLACK_LEVEL       << 16,
    ANDROID_SYNC_START             = ANDROID_SYNC              << 16,
    ANDROID_REPROCESS_START        = ANDROID_REPROCESS         << 16,
    ANDROID_DEPTH_START            = ANDROID_DEPTH             << 16,
    VENDOR_SECTION_START           = VENDOR_SECTION            << 16
} camera_metadata_section_start_t;

接下来,定义了,各个TAG 对应换详细的参数,每个 TAG 以 ##TAG##_START 和 ##TAG##_END 结束。

/**
 * Main enum for defining camera metadata tags.  New entries must always go
 * before the section _END tag to preserve existing enumeration values.  In
 * addition, the name and type of the tag needs to be added to
 * system/media/camera/src/camera_metadata_tag_info.c
 */
typedef enum camera_metadata_tag {
    ANDROID_COLOR_CORRECTION_MODE =                   // enum         | public
           ANDROID_COLOR_CORRECTION_START,
    ANDROID_COLOR_CORRECTION_TRANSFORM,               // rational[]   | public
    ANDROID_COLOR_CORRECTION_GAINS,                   // float[]      | public
    ANDROID_COLOR_CORRECTION_ABERRATION_MODE,         // enum         | public
    ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
                                                      // byte[]       | public
    ANDROID_COLOR_CORRECTION_END,

    ANDROID_CONTROL_AE_ANTIBANDING_MODE =             // enum         | public
            ANDROID_CONTROL_START,
    ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,         // int32        | public
    ANDROID_CONTROL_AE_LOCK,                          // enum         | public
    ANDROID_CONTROL_AE_MODE,                          // enum         | public
    ......
    ANDROID_CONTROL_END,
    
    ANDROID
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员Android

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值