和你一起终身学习,这里是程序员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