目录
1. Camera MetaData 作用
2. Camera MetaData 定义
2.1 内存分布
2.2 常用 API
2.3 vendor tag 操作集
3. Camera Metadata 参数下发流程分析
新的 Camera API2 / HAL3 架构将 SetParameter()/GetParameter() 改为 Camera MetaData 的方式设置或获取参数。
Camera MetaData 将参数以有序结构体的形式保存在一块连续内存中。
编译产物:libcamera_metadata.so
系统位置:/system/lib64/,/system/lib/
源代码位置:/system/media/camera/
看下编译配置文件 Android.bp:
package {
// http://go/android-license-faq
// A large-scale-change added 'default_applicable_licenses' to import
// the below license kinds from "system_media_license":
// SPDX-license-identifier-Apache-2.0
default_applicable_licenses: ["system_media_license"],
}
subdirs = ["tests"]
cc_library_shared {
name: "libcamera_metadata",
vendor_available: true,
product_available: true,
// remove when no longer needed.
native_bridge_supported: true,
host_supported: true,
vndk: {
enabled: true,
},
double_loadable: true,
srcs: ["src/camera_metadata.c"],
include_dirs: ["system/media/private/camera/include"],
local_include_dirs: ["include"],
export_include_dirs: ["include"],
header_libs: [
"libcutils_headers",
],
export_header_lib_headers: [
"libcutils_headers",
],
shared_libs: [
"liblog",
],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-fvisibility=hidden",
"-std=c11",
],
product_variables: {
eng: {
// Enable assert()
cflags: [
"-UNDEBUG",
"-DLOG_NDEBUG=1",
],
},
},
}
filegroup {
name: "libcamera_metadata_tags_file",
srcs: ["include/system/camera_metadata_tags.h"],
}
一块儿连续的内存空间,数据分布情况代码注释说明:
# 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 |
* | |
* |-----------------------------------------------|
* | reserved for future expansion |
* |-----------------------------------------------|
* | camera_metadata_buffer_entry_t #0 |
* |-----------------------------------------------|
* | .... |
* |-----------------------------------------------|
* | camera_metadata_buffer_entry_t #entry_count-1 |
* |-----------------------------------------------|
* | free space for |
* | (entry_capacity-entry_count) entries |
* |-----------------------------------------------|
* | start of camera_metadata.data |
* | |
* |-----------------------------------------------|
* | free space for |
* | (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;
uint32_t version;
uint32_t flags;
metadata_size_t entry_count;
metadata_size_t entry_capacity;
metadata_uptrdiff_t entries_start; // 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;
};
上面涉及的结构体 camera_metadata_buffer_entry_t 和 camera_metadata_data_t 都是什么呢?直接看注释:
metadata_entry:
/**
* A single metadata entry, storing an array of values of a given type. If the
* array is no larger than 4 bytes in size, it is stored in the data.value[]
* array; otherwise, it can found in the parent's data array at index
* data.offset.
*/
#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;
typedef uint32_t metadata_uptrdiff_t;
typedef uint32_t metadata_size_t;
metadata_data:
/**
* 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;
那问题来了,tag 究竟有哪些?
是这样,tag很多,会分组,每组叫做一个section,先看section。在 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_LOGICAL_MULTI_CAMERA,
ANDROID_DISTORTION_CORRECTION,
ANDROID_HEIC,
ANDROID_HEIC_INFO,
ANDROID_SECTION_COUNT,
VENDOR_SECTION = 0x8000
} camera_metadata_section_t;
再看详细的所有 tag,我想你应该懂了,没错,每个 tag 都是 section 为前缀的,并且都是以 [section]_START 开始以 [section]_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 | HIDL v3.2
ANDROID_COLOR_CORRECTION_START,
ANDROID_COLOR_CORRECTION_TRANSFORM, // rational[] | public | HIDL v3.2
ANDROID_COLOR_CORRECTION_GAINS, // float[] | public | HIDL v3.2
ANDROID_COLOR_CORRECTION_ABERRATION_MODE, // enum | public | HIDL v3.2
ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
// byte[] | public | HIDL v3.2
ANDROID_COLOR_CORRECTION_END,
ANDROID_CONTROL_AE_ANTIBANDING_MODE = // enum | public | HIDL v3.2
ANDROID_CONTROL_START,
ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, // int32 | public | HIDL v3.2
ANDROID_CONTROL_AE_LOCK, // enum | public | HIDL v3.2
ANDROID_CONTROL_AE_MODE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AE_REGIONS, // int32[] | public | HIDL v3.2
ANDROID_CONTROL_AE_TARGET_FPS_RANGE, // int32[] | public | HIDL v3.2
ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, // enum | public | HIDL v3.2
ANDROID_CONTROL_AF_MODE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AF_REGIONS, // int32[] | public | HIDL v3.2
ANDROID_CONTROL_AF_TRIGGER, // enum | public | HIDL v3.2
ANDROID_CONTROL_AWB_LOCK, // enum | public | HIDL v3.2
ANDROID_CONTROL_AWB_MODE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AWB_REGIONS, // int32[] | public | HIDL v3.2
ANDROID_CONTROL_CAPTURE_INTENT, // enum | public | HIDL v3.2
ANDROID_CONTROL_EFFECT_MODE, // enum | public | HIDL v3.2
ANDROID_CONTROL_MODE, // enum | public | HIDL v3.2
ANDROID_CONTROL_SCENE_MODE, // enum | public | HIDL v3.2
ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, // byte[] | public | HIDL v3.2
ANDROID_CONTROL_AE_AVAILABLE_MODES, // byte[] | public | HIDL v3.2
ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, // int32[] | public | HIDL v3.2
ANDROID_CONTROL_AE_COMPENSATION_RANGE, // int32[] | public | HIDL v3.2
ANDROID_CONTROL_AE_COMPENSATION_STEP, // rational | public | HIDL v3.2
ANDROID_CONTROL_AF_AVAILABLE_MODES, // byte[] | public | HIDL v3.2
ANDROID_CONTROL_AVAILABLE_EFFECTS, // byte[] | public | HIDL v3.2
ANDROID_CONTROL_AVAILABLE_SCENE_MODES, // byte[] | public | HIDL v3.2
ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
// byte[] | public | HIDL v3.2
ANDROID_CONTROL_AWB_AVAILABLE_MODES, // byte[] | public | HIDL v3.2
ANDROID_CONTROL_MAX_REGIONS, // int32[] | ndk_public | HIDL v3.2
ANDROID_CONTROL_SCENE_MODE_OVERRIDES, // byte[] | system | HIDL v3.2
ANDROID_CONTROL_AE_PRECAPTURE_ID, // int32 | system | HIDL v3.2
ANDROID_CONTROL_AE_STATE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AF_STATE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AF_TRIGGER_ID, // int32 | system | HIDL v3.2
ANDROID_CONTROL_AWB_STATE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS,
// int32[] | hidden | HIDL v3.2
ANDROID_CONTROL_AE_LOCK_AVAILABLE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AWB_LOCK_AVAILABLE, // enum | public | HIDL v3.2
ANDROID_CONTROL_AVAILABLE_MODES, // byte[] | public | HIDL v3.2
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE, // int32[] | public | HIDL v3.2
ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, // int32 | public | HIDL v3.2
ANDROID_CONTROL_ENABLE_ZSL, // enum | public | HIDL v3.2
ANDROID_CONTROL_AF_SCENE_CHANGE, // enum | public | HIDL v3.3
ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_MAX_SIZES,
// int32[] | ndk_public | HIDL v3.5
ANDROID_CONTROL_AVAILABLE_EXTENDED_SCENE_MODE_ZOOM_RATIO_RANGES,
// float[] | ndk_public | HIDL v3.5
ANDROID_CONTROL_EXTENDED_SCENE_MODE, // enum | public | HIDL v3.5
ANDROID_CONTROL_ZOOM_RATIO_RANGE, // float[] | public | HIDL v3.5
ANDROID_CONTROL_ZOOM_RATIO, // float | public | HIDL v3.5
ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION,
// int32[] | hidden | HIDL v3.6
ANDROID_CONTROL_AF_REGIONS_SET, // enum | fwk_only
ANDROID_CONTROL_AE_REGIONS_SET, // enum | fwk_only
ANDROID_CONTROL_AWB_REGIONS_SET, // enum | fwk_only
ANDROID_CONTROL_END,
ANDROID_DEMOSAIC_MODE = // enum | system | HIDL v3.2
ANDROID_DEMOSAIC_START,
ANDROID_DEMOSAIC_END,
ANDROID_EDGE_MODE = // enum | public | HIDL v3.2
ANDROID_EDGE_START,
ANDROID_EDGE_STRENGTH, // byte | system | HIDL v3.2
ANDROID_EDGE_AVAILABLE_EDGE_MODES, // byte[] | public | HIDL v3.2
ANDROID_EDGE_END,
ANDROID_FLASH_FIRING_POWER = // byte | system | HIDL v3.2
ANDROID_FLASH_START,
ANDROID_FLASH_FIRING_TIME, // int64 | system | HIDL v3.2
ANDROID_FLASH_MODE, // enum | public | HIDL v3.2
ANDROID_FLASH_COLOR_TEMPERATURE, // byte | system | HIDL v3.2
ANDROID_FLASH_MAX_ENERGY, // byte | system | HIDL v3.2
ANDROID_FLASH_STATE, // enum | public | HIDL v3.2
ANDROID_FLASH_END,
ANDROID_FLASH_INFO_AVAILABLE = // enum | public | HIDL v3.2
ANDROID_FLASH_INFO_START,
ANDROID_FLASH_INFO_CHARGE_DURATION, // int64 | system | HIDL v3.2
ANDROID_FLASH_INFO_END,
// 省略一堆代码
} camera_metadata_tag_t;
每个 tag 的数据结构体定义呢?
由 union 指针指向真实数据。
/**
* A reference to a metadata entry in a buffer.
*
* The data union pointers point to the real data in the buffer, and can be
* modified in-place if the count does not need to change. The count is the
* number of entries in data of the entry's type, not a count of bytes.
*/
typedef struct camera_metadata_entry {
size_t index;
uint32_t tag;
uint8_t type;
size_t count;
union {
uint8_t *u8;
int32_t *i32;
float *f;
int64_t *i64;
double *d;
camera_metadata_rational_t *r;
} data;
} camera_metadata_entry_t;
在 system/media/camera/include/system/camera_metadata.h 里,用来操作 metadata,太多就不展示了。接口实现在 camera_metadata.c 里,举几个例子:
static camera_metadata_buffer_entry_t *get_entries(
const camera_metadata_t *metadata) {
return (camera_metadata_buffer_entry_t*)
((uint8_t*)metadata + metadata->entries_start);
}
static uint8_t *get_data(const camera_metadata_t *metadata) {
return (uint8_t*)metadata + metadata->data_start;
}
size_t get_camera_metadata_alignment() {
return METADATA_PACKET_ALIGNMENT;
}
camera_metadata_t *allocate_copy_camera_metadata_checked(
const camera_metadata_t *src,
size_t src_size) {
if (src == NULL) {
return NULL;
}
if (src_size < sizeof(camera_metadata_t)) {
ALOGE("%s: Source size too small!", __FUNCTION__);
android_errorWriteLog(0x534e4554, "67782345");
return NULL;
}
void *buffer = calloc(1, src_size);
memcpy(buffer, src, src_size);
camera_metadata_t *metadata = (camera_metadata_t*) buffer;
if (validate_camera_metadata_structure(metadata, &src_size) != OK) {
free(buffer);
return NULL;
}
return metadata;
}
camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
size_t data_capacity) {
size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
data_capacity);
void *buffer = calloc(1, memory_needed);
camera_metadata_t *metadata = place_camera_metadata(
buffer, memory_needed, entry_capacity, data_capacity);
if (!metadata) {
/* This should not happen when memory_needed is the same
* calculated in this function and in place_camera_metadata.
*/
free(buffer);
}
return metadata;
}
camera_metadata_t *place_camera_metadata(void *dst,
size_t dst_size,
size_t entry_capacity,
size_t data_capacity) {
if (dst == NULL) return NULL;
size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
data_capacity);
if (memory_needed > dst_size) {
ALOGE("%s: Memory needed to place camera metadata (%zu) > dst size (%zu)", __FUNCTION__,
memory_needed, dst_size);
return NULL;
}
camera_metadata_t *metadata = (camera_metadata_t*)dst;
metadata->version = CURRENT_METADATA_VERSION;
metadata->flags = 0;
metadata->entry_count = 0;
metadata->entry_capacity = entry_capacity;
metadata->entries_start =
ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
metadata->data_count = 0;
metadata->data_capacity = data_capacity;
metadata->size = memory_needed;
size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
metadata->entry_capacity) - (uint8_t*)metadata;
metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
metadata->vendor_id = CAMERA_METADATA_INVALID_VENDOR_ID;
assert(validate_camera_metadata_structure(metadata, NULL) == OK);
return metadata;
}
void free_camera_metadata(camera_metadata_t *metadata) {
free(metadata);
}
size_t calculate_camera_metadata_size(size_t entry_count,
size_t data_count) {
size_t memory_needed = sizeof(camera_metadata_t);
// Start entry list at aligned boundary
memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
// Start buffer list at aligned boundary
memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
memory_needed += sizeof(uint8_t[data_count]);
// Make sure camera metadata can be stacked in continuous memory
memory_needed = ALIGN_TO(memory_needed, METADATA_PACKET_ALIGNMENT);
return memory_needed;
}
size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
if (metadata == NULL) return ERROR;
return metadata->size;
}
size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
if (metadata == NULL) return ERROR;
return calculate_camera_metadata_size(metadata->entry_count,
metadata->data_count);
}
size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
return metadata->entry_count;
}
size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
return metadata->entry_capacity;
}
size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
return metadata->data_count;
}
size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
return metadata->data_capacity;
}
camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
const camera_metadata_t *src) {
size_t memory_needed = get_camera_metadata_compact_size(src);
if (dst == NULL) return NULL;
if (dst_size < memory_needed) {
ALOGE("%s: Memory needed to place camera metadata (%zu) > dst size (%zu)", __FUNCTION__,
memory_needed, dst_size);
return NULL;
}
camera_metadata_t *metadata =
place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
metadata->flags = src->flags;
metadata->entry_count = src->entry_count;
metadata->data_count = src->data_count;
metadata->vendor_id = src->vendor_id;
memcpy(get_entries(metadata), get_entries(src),
sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
memcpy(get_data(metadata), get_data(src),
sizeof(uint8_t[metadata->data_count]));
assert(validate_camera_metadata_structure(metadata, NULL) == OK);
return metadata;
}
如果对上面几个小节理解了,比如内存分布,结构体定义等,那么这些 API 代码实现也就好理解了。
对于OEM厂商可能想对自己定义的 metadata 进行操作。查询其静态信息,验证HAL返回的 metadata 数据结构,并允许供应商定义的元数据标签在面向相机API的应用程序中可见。
/**
* Vendor tags:
*
* This structure contains basic functions for enumerating an immutable set of
* vendor-defined camera metadata tags, and querying static information about
* their structure/type. The intended use of this information is to validate
* the structure of metadata returned by the camera HAL, and to allow vendor-
* defined metadata tags to be visible in application facing camera API.
*/
typedef struct vendor_tag_ops vendor_tag_ops_t;
struct vendor_tag_ops {
/**
* Get the number of vendor tags supported on this platform. Used to
* calculate the size of buffer needed for holding the array of all tags
* returned by get_all_tags(). This must return -1 on error.
*/
int (*get_tag_count)(const vendor_tag_ops_t *v);
/**
* Fill an array with all of the supported vendor tags on this platform.
* get_tag_count() must return the number of tags supported, and
* tag_array will be allocated with enough space to hold the number of tags
* returned by get_tag_count().
*/
void (*get_all_tags)(const vendor_tag_ops_t *v, uint32_t *tag_array);
/**
* Get the vendor section name for a vendor-specified entry tag. This will
* only be called for vendor-defined tags.
*
* The naming convention for the vendor-specific section names should
* follow a style similar to the Java package style. For example,
* CameraZoom Inc. must prefix their sections with "com.camerazoom."
* This must return NULL if the tag is outside the bounds of
* vendor-defined sections.
*
* There may be different vendor-defined tag sections, for example the
* phone maker, the chipset maker, and the camera module maker may each
* have their own "com.vendor."-prefixed section.
*
* The memory pointed to by the return value must remain valid for the
* lifetime of the module, and is owned by the module.
*/
const char *(*get_section_name)(const vendor_tag_ops_t *v, uint32_t tag);
/**
* Get the tag name for a vendor-specified entry tag. This is only called
* for vendor-defined tags, and must return NULL if it is not a
* vendor-defined tag.
*
* The memory pointed to by the return value must remain valid for the
* lifetime of the module, and is owned by the module.
*/
const char *(*get_tag_name)(const vendor_tag_ops_t *v, uint32_t tag);
/**
* Get tag type for a vendor-specified entry tag. The type returned must be
* a valid type defined in camera_metadata.h. This method is only called
* for tags >= CAMERA_METADATA_VENDOR_TAG_BOUNDARY, and must return
* -1 if the tag is outside the bounds of the vendor-defined sections.
*/
int (*get_tag_type)(const vendor_tag_ops_t *v, uint32_t tag);
/* Reserved for future use. These must be initialized to NULL. */
void* reserved[8];
};
struct vendor_tag_cache_ops {
/**
* Get the number of vendor tags supported on this platform. Used to
* calculate the size of buffer needed for holding the array of all tags
* returned by get_all_tags(). This must return -1 on error.
*/
int (*get_tag_count)(metadata_vendor_id_t id);
/**
* Fill an array with all of the supported vendor tags on this platform.
* get_tag_count() must return the number of tags supported, and
* tag_array will be allocated with enough space to hold the number of tags
* returned by get_tag_count().
*/
void (*get_all_tags)(uint32_t *tag_array, metadata_vendor_id_t id);
/**
* Get the vendor section name for a vendor-specified entry tag. This will
* only be called for vendor-defined tags.
*
* The naming convention for the vendor-specific section names should
* follow a style similar to the Java package style. For example,
* CameraZoom Inc. must prefix their sections with "com.camerazoom."
* This must return NULL if the tag is outside the bounds of
* vendor-defined sections.
*
* There may be different vendor-defined tag sections, for example the
* phone maker, the chipset maker, and the camera module maker may each
* have their own "com.vendor."-prefixed section.
*
* The memory pointed to by the return value must remain valid for the
* lifetime of the module, and is owned by the module.
*/
const char *(*get_section_name)(uint32_t tag, metadata_vendor_id_t id);
/**
* Get the tag name for a vendor-specified entry tag. This is only called
* for vendor-defined tags, and must return NULL if it is not a
* vendor-defined tag.
*
* The memory pointed to by the return value must remain valid for the
* lifetime of the module, and is owned by the module.
*/
const char *(*get_tag_name)(uint32_t tag, metadata_vendor_id_t id);
/**
* Get tag type for a vendor-specified entry tag. The type returned must be
* a valid type defined in camera_metadata.h. This method is only called
* for tags >= CAMERA_METADATA_VENDOR_TAG_BOUNDARY, and must return
* -1 if the tag is outside the bounds of the vendor-defined sections.
*/
int (*get_tag_type)(uint32_t tag, metadata_vendor_id_t id);
/* Reserved for future use. These must be initialized to NULL. */
void* reserved[8];
};
用户可以自定义 vendor tag 的操作方法:
// Declared in system/media/private/camera/include/camera_metadata_hidden.h
int set_camera_metadata_vendor_ops(const vendor_tag_ops_t* ops) {
vendor_tag_ops = ops;
return OK;
}
// Declared in system/media/private/camera/include/camera_metadata_hidden.h
int set_camera_metadata_vendor_cache_ops(
const struct vendor_tag_cache_ops *query_cache_ops) {
vendor_cache_ops = query_cache_ops;
return OK;
}
具体代码不讲,代码在更新,写法可能有区别,但流程一样。直接说流程:
在 Camera3Device.cpp 中,最终将 request 放入mRequestQueue 中。
在 Camera3Device::RequestThread::threadLoop() 来对 mRequestQueue 消息进行处理。
调用 HAL 层的 process_capture_request() 方法,处理 request 请求
最终通过ioctl(fd, VIDIOC_S_CTRL, &control); 往 V4L2 driver 下发参数。
在 driver 中,根据具体设备注册 V4L2_ctrl 时的 ops ,调用不同的操作函数,来更新具体的硬件寄存器。