【高通SDM660平台】Camera MetaData介绍
《【高通SDM660平台】(1) — Camera 驱动 Bringup Guide》
《【高通SDM660平台】(2) — Camera Kernel 驱动层代码逻辑分析》
《【高通SDM660平台】(3) — Camera V4L2 驱动层分析 》
《【高通SDM660平台】(4) — Camera Init 初始化流程 》
《【高通SDM660平台】(5) — Camera Open 流程》
《【高通SDM660平台】(6) — Camera getParameters 及 setParameters 流程》
《【高通SDM660平台】(7) — Camera onPreview 代码流程》
《【高通SDM660平台】(8) — Camera MetaData介绍》
《【高通SDM660平台 Android 10.0】(9) — Qcom Camera Daemon 代码分析》
《【高通SDM660平台 Android 10.0】(10) — Camera Sensor lib 与 Kernel Camera Probe 代码分析》
《【高通SDM660平台】Camera Capture 流程》
《【高通SDM660平台】Camera mm-qcamera-app 代码分析》
一、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<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"system/media/private/camera/include"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
local_include_dirs<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"include"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
export_include_dirs<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"include"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
shared_libs<span class="token operator">:</span> <span class="token punctuation">[</span>
<span class="token string">"libcutils"</span><span class="token punctuation">,</span>
<span class="token string">"liblog"</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">,</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
每个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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
由于在内存中,各个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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
接下来,定义了,各个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 <span class="token operator">=</span> <span class="token comment">// enum | public</span> ANDROID_CONTROL_START<span class="token punctuation">,</span> ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION<span class="token punctuation">,</span> <span class="token comment">// int32 | public</span> ANDROID_CONTROL_AE_LOCK<span class="token punctuation">,</span> <span class="token comment">// enum | public</span> ANDROID_CONTROL_AE_MODE<span class="token punctuation">,</span> <span class="token comment">// enum | public</span> <span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span><span class="token punctuation">.</span> ANDROID_CONTROL_END<span class="token punctuation">,</span> ANDROID_FLASH_FIRING_POWER <span class="token operator">=</span> <span class="token comment">// byte | system</span> ANDROID_FLASH_START<span class="token punctuation">,</span> ANDROID_FLASH_FIRING_TIME<span class="token punctuation">,</span> <span class="token comment">// int64 | system</span> ANDROID_FLASH_MODE<span class="token punctuation">,</span> <span class="token comment">// enum | public</span> ANDROID_FLASH_COLOR_TEMPERATURE<span class="token punctuation">,</span> <span class="token comment">// byte | system</span> ANDROID_FLASH_MAX_ENERGY<span class="token punctuation">,</span> <span class="token comment">// byte | system</span> ANDROID_FLASH_STATE<span class="token punctuation">,</span> <span class="token comment">// enum | public</span> ANDROID_FLASH_END<span class="token punctuation">,</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
2.3 基本API定义 camera_metadata.h
# system/media/camera/include/system/camera_metadata.h
// 根据 TAG 数量定义两个数组。
#include “camera_metadata_tags.h”
ANDROID_API
extern unsigned int camera_metadata_section_bounds[ANDROID_SECTION_COUNT][2];
ANDROID_API
extern const char *camera_metadata_section_names[ANDROID_SECTION_COUNT];
/**
- 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.
/
// 每个 Tag 的数据结构体定义
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
接着在该头文件中定义了一些常用的 API 方法:
ANDROID_API
camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,size_t data_capacity);
ANDROID_API
camera_metadata_t place_camera_metadata(void dst, size_t dst_size,size_t data_capacity);
ANDROID_API
void free_camera_metadata(camera_metadata_t *metadata);
ANDROID_API
size_t calculate_camera_metadata_size(size_t entry_count,size_t data_count);
ANDROID_API
camera_metadata_t copy_camera_metadata(void dst, size_t dst_size, const camera_metadata_t *src);
ANDROID_API
int add_camera_metadata_entry(camera_metadata_t dst, uint32_t tag, const void data, size_t data_count);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
2.4 产商API自定义 camera_vendor_tags.h
在该头文件中,定义了供产商自定义 metadata 及查询的方法。
# system/media/camera/include/system/camera_vendor_tags.h
typedef struct vendor_tag_ops vendor_tag_ops_t;
struct vendor_tag_ops {
int (get_tag_count)(const vendor_tag_ops_t v);
void (get_all_tags)(const vendor_tag_ops_t v, uint32_t tag_array);
const char (get_section_name)(const vendor_tag_ops_t v, uint32_t tag);
const char (get_tag_name)(const vendor_tag_ops_t v, uint32_t tag);
int (get_tag_type)(const vendor_tag_ops_t v, uint32_t tag);
void reserved[8];
};
struct vendor_tag_cache_ops {
int (get_tag_count)(metadata_vendor_id_t id);
void (get_all_tags)(uint32_t tag_array, metadata_vendor_id_t id);
const char (get_section_name)(uint32_t tag, metadata_vendor_id_t id);
const char (get_tag_name)(uint32_t tag, metadata_vendor_id_t id);
int (get_tag_type)(uint32_t tag, metadata_vendor_id_t id);
void* reserved[8];
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
2.5 将宏与字符串绑定 camera_metadata_tag_info.c
# system/media/camera/src/camera_metadata_tag_info.c
const char *camera_metadata_section_names[ANDROID_SECTION_COUNT] = {
[ANDROID_COLOR_CORRECTION] = “android.colorCorrection”,
[ANDROID_CONTROL] = “android.control”,
[ANDROID_DEMOSAIC] = “android.demosaic”,
[ANDROID_EDGE] = “android.edge”,
[ANDROID_FLASH] = “android.flash”,
[ANDROID_FLASH_INFO] = “android.flash.info”,
[ANDROID_HOT_PIXEL] = “android.hotPixel”,
[ANDROID_JPEG] = “android.jpeg”,
[ANDROID_LENS] = “android.lens”,
[ANDROID_LENS_INFO] = “android.lens.info”,
[ANDROID_NOISE_REDUCTION] = “android.noiseReduction”,
[ANDROID_QUIRKS] = “android.quirks”,
[ANDROID_REQUEST] = “android.request”,
[ANDROID_SCALER] = “android.scaler”,
[ANDROID_SENSOR] = “android.sensor”,
[ANDROID_SENSOR_INFO] = “android.sensor.info”,
[ANDROID_SHADING] = “android.shading”,
[ANDROID_STATISTICS] = “android.statistics”,
[ANDROID_STATISTICS_INFO] = “android.statistics.info”,
[ANDROID_TONEMAP] = “android.tonemap”,
[ANDROID_LED] = “android.led”,
[ANDROID_INFO] = “android.info”,
[ANDROID_BLACK_LEVEL] = “android.blackLevel”,
[ANDROID_SYNC] = “android.sync”,
[ANDROID_REPROCESS] = “android.reprocess”,
[ANDROID_DEPTH] = “android.depth”,
};
static tag_info_t android_flash[ANDROID_FLASH_END -
ANDROID_FLASH_START] = {
[ ANDROID_FLASH_FIRING_POWER - ANDROID_FLASH_START ] =
{ “firingPower”, TYPE_BYTE },
[ ANDROID_FLASH_FIRING_TIME - ANDROID_FLASH_START ] =
{ “firingTime”, TYPE_INT64 },
[ ANDROID_FLASH_MODE - ANDROID_FLASH_START ] =
{ “mode”, TYPE_BYTE },
[ ANDROID_FLASH_COLOR_TEMPERATURE - ANDROID_FLASH_START ] =
{ “colorTemperature”, TYPE_BYTE },
[ ANDROID_FLASH_MAX_ENERGY - ANDROID_FLASH_START ] =
{ “maxEnergy”, TYPE_BYTE },
[ ANDROID_FLASH_STATE - ANDROID_FLASH_START ] =
{ “state”, TYPE_BYTE },
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
2.6 核心代码实现
前面了解清楚它的内存分布,宏定义,及操作方法后,我们开始进入c代码看下它的核心实现。
# system/media/camera/src/camera_metadata.c
#define LOG_TAG “camera_metadata”
#include <system/camera_metadata.h>
#include <camera_metadata_hidden.h>
// 获取 entries
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;
}
// 分配一个 camera_metadata 结构体对象
camera_metadata_t allocate_camera_metadata(size_t entry_capacity,size_t data_capacity) {
size_t memory_needed <span class="token operator">=</span> <span class="token function">calculate_camera_metadata_size</span><span class="token punctuation">(</span>entry_capacity<span class="token punctuation">,</span>data_capacity<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">void</span> <span class="token operator">*</span>buffer <span class="token operator">=</span> <span class="token function">calloc</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> memory_needed<span class="token punctuation">)</span><span class="token punctuation">;</span>
camera_metadata_t <span class="token operator">*</span>metadata <span class="token operator">=</span> <span class="token function">place_camera_metadata</span><span class="token punctuation">(</span> buffer<span class="token punctuation">,</span> memory_needed<span class="token punctuation">,</span> entry_capacity<span class="token punctuation">,</span> data_capacity<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> metadata<span class="token punctuation">;</span>
}
// 获取 metadata 结构体
camera_metadata_t place_camera_metadata(void dst, size_t dst_size, size_t entry_capacity, size_t data_capacity) {
size_t memory_needed <span class="token operator">=</span> <span class="token function">calculate_camera_metadata_size</span><span class="token punctuation">(</span>entry_capacity<span class="token punctuation">,</span> data_capacity<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>memory_needed <span class="token operator">></span> dst_size<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
camera_metadata_t <span class="token operator">*</span>metadata <span class="token operator">=</span> <span class="token punctuation">(</span>camera_metadata_t<span class="token operator">*</span><span class="token punctuation">)</span>dst<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>version <span class="token operator">=</span> CURRENT_METADATA_VERSION<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>flags <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>entry_count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>entry_capacity <span class="token operator">=</span> entry_capacity<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>entries_start <span class="token operator">=</span> <span class="token function">ALIGN_TO</span><span class="token punctuation">(</span><span class="token keyword">sizeof</span><span class="token punctuation">(</span>camera_metadata_t<span class="token punctuation">)</span><span class="token punctuation">,</span> ENTRY_ALIGNMENT<span class="token punctuation">)</span><span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>data_capacity <span class="token operator">=</span> data_capacity<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>size <span class="token operator">=</span> memory_needed<span class="token punctuation">;</span>
size_t data_unaligned <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">uint8_t</span><span class="token operator">*</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token function">get_entries</span><span class="token punctuation">(</span>metadata<span class="token punctuation">)</span> <span class="token operator">+</span> metadata<span class="token operator">-</span><span class="token operator">></span>entry_capacity<span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token punctuation">(</span><span class="token keyword">uint8_t</span><span class="token operator">*</span><span class="token punctuation">)</span>metadata<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>data_start <span class="token operator">=</span> <span class="token function">ALIGN_TO</span><span class="token punctuation">(</span>data_unaligned<span class="token punctuation">,</span> DATA_ALIGNMENT<span class="token punctuation">)</span><span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>vendor_id <span class="token operator">=</span> CAMERA_METADATA_INVALID_VENDOR_ID<span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span><span class="token function">validate_camera_metadata_structure</span><span class="token punctuation">(</span>metadata<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token operator">==</span> OK<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> metadata<span class="token punctuation">;</span>
}
void free_camera_metadata(camera_metadata_t *metadata) {
free(metadata);
}
// 拷贝 metadata 结构体
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);
camera_metadata_t <span class="token operator">*</span>metadata <span class="token operator">=</span> <span class="token function">place_camera_metadata</span><span class="token punctuation">(</span>dst<span class="token punctuation">,</span> dst_size<span class="token punctuation">,</span> src<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">,</span> src<span class="token operator">-</span><span class="token operator">></span>data_count<span class="token punctuation">)</span><span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>flags <span class="token operator">=</span> src<span class="token operator">-</span><span class="token operator">></span>flags<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>entry_count <span class="token operator">=</span> src<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">=</span> src<span class="token operator">-</span><span class="token operator">></span>data_count<span class="token punctuation">;</span>
metadata<span class="token operator">-</span><span class="token operator">></span>vendor_id <span class="token operator">=</span> src<span class="token operator">-</span><span class="token operator">></span>vendor_id<span class="token punctuation">;</span>
<span class="token function">memcpy</span><span class="token punctuation">(</span><span class="token function">get_entries</span><span class="token punctuation">(</span>metadata<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">get_entries</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>camera_metadata_buffer_entry_t<span class="token punctuation">[</span>metadata<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">memcpy</span><span class="token punctuation">(</span><span class="token function">get_data</span><span class="token punctuation">(</span>metadata<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">get_data</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span><span class="token keyword">uint8_t</span><span class="token punctuation">[</span>metadata<span class="token operator">-</span><span class="token operator">></span>data_count<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span><span class="token function">validate_camera_metadata_structure</span><span class="token punctuation">(</span>metadata<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token operator">==</span> OK<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> metadata<span class="token punctuation">;</span>
}
int add_camera_metadata_entry(camera_metadata_t dst, uint32_t tag, const void data, size_t data_count) {
int type = get_local_camera_metadata_tag_type(tag, dst);
return add_camera_metadata_entry_raw(dst, tag, type, data, data_count);
}
int find_camera_metadata_entry(camera_metadata_t src, uint32_t tag, camera_metadata_entry_t entry) {
if (src == NULL) return ERROR;
<span class="token keyword">uint32_t</span> index<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>src<span class="token operator">-</span><span class="token operator">></span>flags <span class="token operator">&</span> FLAG_SORTED<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Sorted entries, do a binary search</span>
camera_metadata_buffer_entry_t <span class="token operator">*</span>search_entry <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span>
camera_metadata_buffer_entry_t key<span class="token punctuation">;</span>
key<span class="token punctuation">.</span>tag <span class="token operator">=</span> tag<span class="token punctuation">;</span>
search_entry <span class="token operator">=</span> <span class="token function">bsearch</span><span class="token punctuation">(</span><span class="token operator">&</span>key<span class="token punctuation">,</span> <span class="token function">get_entries</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">,</span> src<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">,</span>
<span class="token keyword">sizeof</span><span class="token punctuation">(</span>camera_metadata_buffer_entry_t<span class="token punctuation">)</span><span class="token punctuation">,</span> compare_entry_tags<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>search_entry <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token keyword">return</span> NOT_FOUND<span class="token punctuation">;</span>
index <span class="token operator">=</span> search_entry <span class="token operator">-</span> <span class="token function">get_entries</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
<span class="token comment">// Not sorted, linear search</span>
camera_metadata_buffer_entry_t <span class="token operator">*</span>search_entry <span class="token operator">=</span> <span class="token function">get_entries</span><span class="token punctuation">(</span>src<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>index <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> index <span class="token operator"><</span> src<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">;</span> index<span class="token operator">++</span><span class="token punctuation">,</span> search_entry<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>search_entry<span class="token operator">-</span><span class="token operator">></span>tag <span class="token operator">==</span> tag<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">==</span> src<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">)</span> <span class="token keyword">return</span> NOT_FOUND<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> <span class="token function">get_camera_metadata_entry</span><span class="token punctuation">(</span>src<span class="token punctuation">,</span> index<span class="token punctuation">,</span> entry<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
int delete_camera_metadata_entry(camera_metadata_t dst, size_t index) {
camera_metadata_buffer_entry_t entry = get_entries(dst) + index;
size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type, entry->count);
<span class="token keyword">if</span> <span class="token punctuation">(</span>data_bytes <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Shift data buffer to overwrite deleted data</span>
<span class="token keyword">uint8_t</span> <span class="token operator">*</span>start <span class="token operator">=</span> <span class="token function">get_data</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> <span class="token operator">+</span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset<span class="token punctuation">;</span>
<span class="token keyword">uint8_t</span> <span class="token operator">*</span>end <span class="token operator">=</span> start <span class="token operator">+</span> data_bytes<span class="token punctuation">;</span>
size_t length <span class="token operator">=</span> dst<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">-</span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset <span class="token operator">-</span> data_bytes<span class="token punctuation">;</span>
<span class="token function">memmove</span><span class="token punctuation">(</span>start<span class="token punctuation">,</span> end<span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// Update all entry indices to account for shift</span>
camera_metadata_buffer_entry_t <span class="token operator">*</span>e <span class="token operator">=</span> <span class="token function">get_entries</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span><span class="token punctuation">;</span>
size_t i<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> dst<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">calculate_camera_metadata_entry_data_size</span><span class="token punctuation">(</span> e<span class="token operator">-</span><span class="token operator">></span>type<span class="token punctuation">,</span> e<span class="token operator">-</span><span class="token operator">></span>count<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&&</span>
e<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset <span class="token operator">></span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset<span class="token punctuation">)</span> <span class="token punctuation">{</span>
e<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset <span class="token operator">-</span><span class="token operator">=</span> data_bytes<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token operator">++</span>e<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
dst<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">-</span><span class="token operator">=</span> data_bytes<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Shift entry array</span>
<span class="token function">memmove</span><span class="token punctuation">(</span>entry<span class="token punctuation">,</span> entry <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>camera_metadata_buffer_entry_t<span class="token punctuation">)</span> <span class="token operator">*</span><span class="token punctuation">(</span>dst<span class="token operator">-</span><span class="token operator">></span>entry_count <span class="token operator">-</span> index <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">)</span><span class="token punctuation">;</span>
dst<span class="token operator">-</span><span class="token operator">></span>entry_count <span class="token operator">-</span><span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token function">assert</span><span class="token punctuation">(</span><span class="token function">validate_camera_metadata_structure</span><span class="token punctuation">(</span>dst<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token operator">==</span> OK<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> OK<span class="token punctuation">;</span>
}
int update_camera_metadata_entry(camera_metadata_t dst,size_t index, const void data,size_t data_count,
camera_metadata_entry_t *updated_entry) {
camera_metadata_buffer_entry_t <span class="token operator">*</span>entry <span class="token operator">=</span> <span class="token function">get_entries</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> <span class="token operator">+</span> index<span class="token punctuation">;</span>
size_t data_bytes <span class="token operator">=</span><span class="token function">calculate_camera_metadata_entry_data_size</span><span class="token punctuation">(</span>entry<span class="token operator">-</span><span class="token operator">></span>type<span class="token punctuation">,</span> data_count<span class="token punctuation">)</span><span class="token punctuation">;</span>
size_t data_payload_bytes <span class="token operator">=</span>data_count <span class="token operator">*</span> camera_metadata_type_size<span class="token punctuation">[</span>entry<span class="token operator">-</span><span class="token operator">></span>type<span class="token punctuation">]</span><span class="token punctuation">;</span>
size_t entry_bytes <span class="token operator">=</span> <span class="token function">calculate_camera_metadata_entry_data_size</span><span class="token punctuation">(</span>entry<span class="token operator">-</span><span class="token operator">></span>type<span class="token punctuation">,</span> entry<span class="token operator">-</span><span class="token operator">></span>count<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>data_bytes <span class="token operator">!=</span> entry_bytes<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// May need to shift/add to data array</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>dst<span class="token operator">-</span><span class="token operator">></span>data_capacity <span class="token operator"><</span> dst<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">+</span> data_bytes <span class="token operator">-</span> entry_bytes<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// No room</span>
<span class="token keyword">return</span> ERROR<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>entry_bytes <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Remove old data</span>
<span class="token keyword">uint8_t</span> <span class="token operator">*</span>start <span class="token operator">=</span> <span class="token function">get_data</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> <span class="token operator">+</span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset<span class="token punctuation">;</span>
<span class="token keyword">uint8_t</span> <span class="token operator">*</span>end <span class="token operator">=</span> start <span class="token operator">+</span> entry_bytes<span class="token punctuation">;</span>
size_t length <span class="token operator">=</span> dst<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">-</span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset <span class="token operator">-</span> entry_bytes<span class="token punctuation">;</span>
<span class="token function">memmove</span><span class="token punctuation">(</span>start<span class="token punctuation">,</span> end<span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">;</span>
dst<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">-</span><span class="token operator">=</span> entry_bytes<span class="token punctuation">;</span>
<span class="token comment">// Update all entry indices to account for shift</span>
camera_metadata_buffer_entry_t <span class="token operator">*</span>e <span class="token operator">=</span> <span class="token function">get_entries</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span><span class="token punctuation">;</span>
size_t i<span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> dst<span class="token operator">-</span><span class="token operator">></span>entry_count<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">calculate_camera_metadata_entry_data_size</span><span class="token punctuation">(</span> e<span class="token operator">-</span><span class="token operator">></span>type<span class="token punctuation">,</span> e<span class="token operator">-</span><span class="token operator">></span>count<span class="token punctuation">)</span> <span class="token operator">></span> <span class="token number">0</span> <span class="token operator">&&</span> e<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset <span class="token operator">></span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset<span class="token punctuation">)</span> <span class="token punctuation">{</span>
e<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset <span class="token operator">-</span><span class="token operator">=</span> entry_bytes<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token operator">++</span>e<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>data_bytes <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Append new data</span>
entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset <span class="token operator">=</span> dst<span class="token operator">-</span><span class="token operator">></span>data_count<span class="token punctuation">;</span>
<span class="token function">memcpy</span><span class="token punctuation">(</span><span class="token function">get_data</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> <span class="token operator">+</span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset<span class="token punctuation">,</span> data<span class="token punctuation">,</span> data_payload_bytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
dst<span class="token operator">-</span><span class="token operator">></span>data_count <span class="token operator">+</span><span class="token operator">=</span> data_bytes<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>data_bytes <span class="token operator">!=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// data size unchanged, reuse same data location</span>
<span class="token function">memcpy</span><span class="token punctuation">(</span><span class="token function">get_data</span><span class="token punctuation">(</span>dst<span class="token punctuation">)</span> <span class="token operator">+</span> entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>offset<span class="token punctuation">,</span> data<span class="token punctuation">,</span> data_payload_bytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>data_bytes <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// Data fits into entry</span>
<span class="token function">memcpy</span><span class="token punctuation">(</span>entry<span class="token operator">-</span><span class="token operator">></span>data<span class="token punctuation">.</span>value<span class="token punctuation">,</span> data<span class="token punctuation">,</span> data_payload_bytes<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
entry<span class="token operator">-</span><span class="token operator">></span>count <span class="token operator">=</span> data_count<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>updated_entry <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">get_camera_metadata_entry</span><span class="token punctuation">(</span>dst<span class="token punctuation">,</span> index<span class="token punctuation">,</span> updated_entry<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">assert</span><span class="token punctuation">(</span><span class="token function">validate_camera_metadata_structure</span><span class="token punctuation">(</span>dst<span class="token punctuation">,</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token operator">==</span> OK<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> OK<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
2.7 Vendor Ops 实现
通过 Vendor Ops ,用户可以自已定义 metadata 及 对应的操作方法 ops。
通过 set_camera_metadata_vendor_ops()
及 set_camera_metadata_vendor_cache_ops()
方法 自定义对应的 ops。
# system/media/camera/src/camera_metadata.c
static const vendor_tag_ops_t vendor_tag_ops = NULL;
static const struct vendor_tag_cache_ops vendor_cache_ops = NULL;
// 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;
}
static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type, int count, int indentation);
void dump_camera_metadata(const camera_metadata_t *metadata, int fd, int verbosity) {
dump_indented_camera_metadata(metadata, fd, verbosity, 0);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
三、Camera MetaData 代码流程分析
Camera MetaData
代码 主要在 frameworks/av/camera/CameraMetadata.cpp
中。
从Android.mk
中可以看出,CameraMetadata.cpp
和 camera client
一起编译到 libcamera_client.so
库中的。
# frameworks/av/camera/Android.mk
LOCAL_SRC_FILES +=
Camera.cpp
CameraMetadata.cpp
CameraParameters.cpp
CameraParameters2.cpp
ICamera.cpp
ICameraClient.cpp \
LOCAL_SHARED_LIBRARIES :=
libcamera_metadata \ // 使用 system 中的 libcamera_metadata.so 共享库
LOCAL_MODULE:= libcamera_client
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
3.1 CameraMetadata 参数设置流程
参考 frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp
中的代码。
可以看出,当要使用 CameraMetadata,主要步骤如下:
- 初始化
mMetadata
对像 - 获取 TAG 为
CAMERA3_TEMPLATE_PREVIEW
的 Metadata - 调用
mMetadata->update
更新 Metadata 参数 - 调用
setStreamingRequest
下发参数
# frameworks/av/services/camera/libcameraservice/CameraFlashlight.cpp
status_t CameraDeviceClientFlashControl::submitTorchEnabledRequest() {
status_t res;
<span class="token keyword">if</span> <span class="token punctuation">(</span>mMetadata <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 1. 初始化 mMetadata 对像</span>
mMetadata <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">CameraMetadata</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 2. 获取 TAG 为 CAMERA3_TEMPLATE_PREVIEW 的 Metadata。</span>
res <span class="token operator">=</span> mDevice<span class="token operator">-</span><span class="token operator">></span><span class="token function">createDefaultRequest</span><span class="token punctuation">(</span> CAMERA3_TEMPLATE_PREVIEW<span class="token punctuation">,</span> mMetadata<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// 3. 调用 mMetadata->update 更新 Metadata 参数</span>
<span class="token keyword">uint8_t</span> torchOn <span class="token operator">=</span> ANDROID_FLASH_MODE_TORCH<span class="token punctuation">;</span>
mMetadata<span class="token operator">-</span><span class="token operator">></span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_FLASH_MODE<span class="token punctuation">,</span> <span class="token operator">&</span>torchOn<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
mMetadata<span class="token operator">-</span><span class="token operator">></span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_REQUEST_OUTPUT_STREAMS<span class="token punctuation">,</span> <span class="token operator">&</span>mStreamId<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">uint8_t</span> aeMode <span class="token operator">=</span> ANDROID_CONTROL_AE_MODE_ON<span class="token punctuation">;</span>
mMetadata<span class="token operator">-</span><span class="token operator">></span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_CONTROL_AE_MODE<span class="token punctuation">,</span> <span class="token operator">&</span>aeMode<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">int32_t</span> requestId <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
mMetadata<span class="token operator">-</span><span class="token operator">></span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_REQUEST_ID<span class="token punctuation">,</span> <span class="token operator">&</span>requestId<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>mStreaming<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token comment">// 4. 调用setStreamingRequest 下发参数</span>
res <span class="token operator">=</span> mDevice<span class="token operator">-</span><span class="token operator">></span><span class="token function">setStreamingRequest</span><span class="token punctuation">(</span><span class="token operator">*</span>mMetadata<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span>
<span class="token operator">+</span> @ frameworks<span class="token operator">/</span>av<span class="token operator">/</span>services<span class="token operator">/</span>camera<span class="token operator">/</span>libcameraservice<span class="token operator">/</span>device3<span class="token operator">/</span>Camera3Device<span class="token punctuation">.</span>cpp
<span class="token operator">+</span> List<span class="token operator"><</span><span class="token keyword">const</span> CameraMetadata<span class="token operator">></span> requests<span class="token punctuation">;</span>
<span class="token operator">+</span> requests<span class="token punctuation">.</span><span class="token function">push_back</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">+</span> <span class="token keyword">return</span> setStreamin<span class="token operator">=</span><span class="token function">RequestList</span><span class="token punctuation">(</span>requests<span class="token punctuation">,</span> <span class="token comment">/*lastFrameNumber*/</span><span class="token constant">NULL</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">+</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span><span class="token operator">></span>
<span class="token operator">+</span> <span class="token keyword">return</span> <span class="token function">submitRequestsHelper</span><span class="token punctuation">(</span>requests<span class="token punctuation">,</span> <span class="token comment">/*repeating*/</span><span class="token boolean">true</span><span class="token punctuation">,</span> lastFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
res <span class="token operator">=</span> mDevice<span class="token operator">-</span><span class="token operator">></span><span class="token function">capture</span><span class="token punctuation">(</span><span class="token operator">*</span>mMetadata<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> res<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
可以看到 ,最终跑到了Camera3Device.cpp 中提交 request ,最终将 request 放入mRequestQueue 中,
由 Camera3Device::RequestThread 来对消息进行处理。
# frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp
status_t Camera3Device::submitRequestsHelper(
const List<const CameraMetadata> &requests, bool repeating, /out/ int64_t *lastFrameNumber) {
RequestList requestList<span class="token punctuation">;</span>
res <span class="token operator">=</span> <span class="token function">convertMetadataListToRequestListLocked</span><span class="token punctuation">(</span>requests<span class="token punctuation">,</span> <span class="token comment">/*out*/</span><span class="token operator">&</span>requestList<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>repeating<span class="token punctuation">)</span> <span class="token punctuation">{</span>
res <span class="token operator">=</span> mRequestThread<span class="token operator">-</span><span class="token operator">></span><span class="token function">setRepeatingRequests</span><span class="token punctuation">(</span>requestList<span class="token punctuation">,</span> lastFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
res <span class="token operator">=</span> mRequestThread<span class="token operator">-</span><span class="token operator">></span><span class="token function">queueRequestList</span><span class="token punctuation">(</span>requestList<span class="token punctuation">,</span> lastFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>res <span class="token operator">==</span> OK<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">waitUntilStateThenRelock</span><span class="token punctuation">(</span><span class="token comment">/*active*/</span><span class="token boolean">true</span><span class="token punctuation">,</span> kActiveTimeout<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>res <span class="token operator">!=</span> OK<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token function">SET_ERR_L</span><span class="token punctuation">(</span><span class="token string">"Can't transition to active in %f seconds!"</span><span class="token punctuation">,</span> kActiveTimeout<span class="token operator">/</span><span class="token number">1e9</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">ALOGV</span><span class="token punctuation">(</span><span class="token string">"Camera %d: Capture request %"</span> PRId32 <span class="token string">" enqueued"</span><span class="token punctuation">,</span> mId<span class="token punctuation">,</span>
<span class="token punctuation">(</span><span class="token operator">*</span><span class="token punctuation">(</span>requestList<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token operator">-</span><span class="token operator">></span>mResultExtras<span class="token punctuation">.</span>requestId<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">return</span> res<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
3.1.1 Camera3Device::RequestThread::threadLoop()
我们来看下 Camera3Device::RequestThread::threadLoop()
的具体实现:
- 等待下一个 request 请求,将请求保存在 mNextRequests 中。
- 获取 最新的request 的Entry, 这里为 CAMERA3_TEMPLATE_PREVIEW
- 调用hardware层的
process_capture_request()
方法,处理request 请求
# frameworks/av/services/camera/libcameraservice/device3/Camera3Device.cpp bool Camera3Device::RequestThread::threadLoop() { // 1. 等待下一个 request 请求,将请求保存在 mNextRequests 中。 // Wait for the next batch of requests. waitForNextRequestBatch(); ===========> + additionalRequest.captureRequest = waitForNextRequestLocked(); + mNextRequests.add(additionalRequest); <=========== if (mNextRequests.size() == 0) { return true; } // 2. 获取 最新的request 的Entry, 这里为 CAMERA3_TEMPLATE_PREVIEW // Get the latest request ID, if any int latestRequestId; camera_metadata_entry_t requestIdEntry = mNextRequests[mNextRequests.size() - 1]. captureRequest->mSettings.find(ANDROID_REQUEST_ID); if (requestIdEntry.count > 0) { latestRequestId = requestIdEntry.data.i32[0]; } // Prepare a batch of HAL requests and output buffers. res = prepareHalRequests(); =============> + status_t res = insertTriggers(captureRequest); + -------------> + mTriggerRemovedMap.add(tag, trigger); + res = metadata.update(tag, &entryValue, /*count*/1); + <------------- + mPrevRequest = captureRequest; <=============
mLatestRequestId <span class="token operator">=</span> latestRequestId<span class="token punctuation">;</span> mLatestRequestSignal<span class="token punctuation">.</span><span class="token function">signal</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 3. 调用hardware层的方法,处理request 请求</span> <span class="token function">ALOGVV</span><span class="token punctuation">(</span><span class="token string">"%s: %d: submitting %zu requests in a batch."</span><span class="token punctuation">,</span> __FUNCTION__<span class="token punctuation">,</span> <span class="token constant">__LINE__</span><span class="token punctuation">,</span> mNextRequests<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">auto</span><span class="token operator">&</span> nextRequest <span class="token operator">:</span> mNextRequests<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Submit request and block until ready for next one</span> <span class="token function">ATRACE_ASYNC_BEGIN</span><span class="token punctuation">(</span><span class="token string">"frame capture"</span><span class="token punctuation">,</span> nextRequest<span class="token punctuation">.</span>halRequest<span class="token punctuation">.</span>frame_number<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">ATRACE_BEGIN</span><span class="token punctuation">(</span><span class="token string">"camera3->process_capture_request"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> res <span class="token operator">=</span> mHal3Device<span class="token operator">-</span><span class="token operator">></span>ops<span class="token operator">-</span><span class="token operator">></span><span class="token function">process_capture_request</span><span class="token punctuation">(</span>mHal3Device<span class="token punctuation">,</span> <span class="token operator">&</span>nextRequest<span class="token punctuation">.</span>halRequest<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span> <span class="token operator">+</span> # hardware<span class="token operator">/</span>qcom<span class="token operator">/</span>camera<span class="token operator">/</span>QCamera2<span class="token operator">/</span>HAL3<span class="token operator">/</span>QCamera3HWI<span class="token punctuation">.</span>cpp <span class="token operator">+</span> QCamera3HardwareInterface <span class="token operator">*</span>hw <span class="token operator">=</span> <span class="token keyword">reinterpret_cast</span><span class="token operator"><</span>QCamera3HardwareInterface <span class="token operator">*</span><span class="token operator">></span><span class="token punctuation">(</span>device<span class="token operator">-</span><span class="token operator">></span>priv<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token keyword">int</span> rc <span class="token operator">=</span> hw<span class="token operator">-</span><span class="token operator">></span><span class="token function">orchestrateRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token comment">// Mark that the request has be submitted successfully.</span> nextRequest<span class="token punctuation">.</span>submitted <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token comment">// Update the latest request sent to HAL</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>nextRequest<span class="token punctuation">.</span>halRequest<span class="token punctuation">.</span>settings <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Don't update if they were unchanged</span> Mutex<span class="token operator">::</span>Autolock <span class="token function">al</span><span class="token punctuation">(</span>mLatestRequestMutex<span class="token punctuation">)</span><span class="token punctuation">;</span> camera_metadata_t<span class="token operator">*</span> cloned <span class="token operator">=</span> <span class="token function">clone_camera_metadata</span><span class="token punctuation">(</span>nextRequest<span class="token punctuation">.</span>halRequest<span class="token punctuation">.</span>settings<span class="token punctuation">)</span><span class="token punctuation">;</span> mLatestRequest<span class="token punctuation">.</span><span class="token function">acquire</span><span class="token punctuation">(</span>cloned<span class="token punctuation">)</span><span class="token punctuation">;</span> sp<span class="token operator"><</span>Camera3Device<span class="token operator">></span> parent <span class="token operator">=</span> mParent<span class="token punctuation">.</span><span class="token function">promote</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>parent <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> parent<span class="token operator">-</span><span class="token operator">></span><span class="token function">monitorMetadata</span><span class="token punctuation">(</span>TagMonitor<span class="token operator">::</span>REQUEST<span class="token punctuation">,</span> nextRequest<span class="token punctuation">.</span>halRequest<span class="token punctuation">.</span>frame_number<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> mLatestRequest<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token comment">// 移除当前请求</span> <span class="token comment">// Remove any previously queued triggers (after unlock)</span> res <span class="token operator">=</span> <span class="token function">removeTriggers</span><span class="token punctuation">(</span>mPrevRequest<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> mNextRequests<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
3.1.1.1 处理上层request 请求
# hardware/qcom/camera/QCamera2/HAL3/QCamera3HWI.cpp /*=========================================================================== * FUNCTION : orchestrateRequest * DESCRIPTION: Orchestrates a capture request from camera service * * PARAMETERS : * @request : request from framework to process * RETURN : Error status codes *==========================================================================*/ int32_t QCamera3HardwareInterface::orchestrateRequest( camera3_capture_request_t *request) {
<span class="token keyword">uint32_t</span> originalFrameNumber <span class="token operator">=</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number<span class="token punctuation">;</span> <span class="token keyword">uint32_t</span> originalOutputCount <span class="token operator">=</span> request<span class="token operator">-</span><span class="token operator">></span>num_output_buffers<span class="token punctuation">;</span> <span class="token keyword">const</span> camera_metadata_t <span class="token operator">*</span>original_settings <span class="token operator">=</span> request<span class="token operator">-</span><span class="token operator">></span>settings<span class="token punctuation">;</span> List<span class="token operator"><</span>InternalRequest<span class="token operator">></span> internallyRequestedStreams<span class="token punctuation">;</span> List<span class="token operator"><</span>InternalRequest<span class="token operator">></span> emptyInternalList<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isHdrSnapshotRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">)</span> <span class="token operator">&&</span> request<span class="token operator">-</span><span class="token operator">></span>input_buffer <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">LOGD</span><span class="token punctuation">(</span><span class="token string">"Framework requested:%d buffers in HDR snapshot"</span><span class="token punctuation">,</span> request<span class="token operator">-</span><span class="token operator">></span>num_output_buffers<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">uint32_t</span> internalFrameNumber<span class="token punctuation">;</span> CameraMetadata modified_meta<span class="token punctuation">;</span> <span class="token keyword">int8_t</span> hdr_exp_values<span class="token punctuation">;</span> cam_hdr_bracketing_info_t<span class="token operator">&</span> hdrBracketingSetting <span class="token operator">=</span> gCamCapability<span class="token punctuation">[</span>mCameraId<span class="token punctuation">]</span><span class="token operator">-</span><span class="token operator">></span>hdr_bracketing_setting<span class="token punctuation">;</span> <span class="token keyword">uint32_t</span> hdrFrameCount <span class="token operator">=</span> hdrBracketingSetting<span class="token punctuation">.</span>num_frames<span class="token punctuation">;</span> <span class="token function">LOGD</span><span class="token punctuation">(</span><span class="token string">"HDR values %d, %d frame count: %u"</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">int8_t</span><span class="token punctuation">)</span> hdrBracketingSetting<span class="token punctuation">.</span>exp_val<span class="token punctuation">.</span>values<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">int8_t</span><span class="token punctuation">)</span> hdrBracketingSetting<span class="token punctuation">.</span>exp_val<span class="token punctuation">.</span>values<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> hdrFrameCount<span class="token punctuation">)</span><span class="token punctuation">;</span> cam_exp_bracketing_t aeBracket<span class="token punctuation">;</span> <span class="token function">memset</span><span class="token punctuation">(</span><span class="token operator">&</span>aeBracket<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token keyword">sizeof</span><span class="token punctuation">(</span>cam_exp_bracketing_t<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> aeBracket<span class="token punctuation">.</span>mode <span class="token operator">=</span> hdrBracketingSetting<span class="token punctuation">.</span>exp_val<span class="token punctuation">.</span>mode<span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>aeBracket<span class="token punctuation">.</span>mode <span class="token operator">==</span> CAM_EXP_BRACKETING_OFF<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">LOGD</span><span class="token punctuation">(</span><span class="token string">" Bracketing is Off"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/* Add Blob channel to list of internally requested streams */</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">uint32_t</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> request<span class="token operator">-</span><span class="token operator">></span>num_output_buffers<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>request<span class="token operator">-</span><span class="token operator">></span>output_buffers<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>stream<span class="token operator">-</span><span class="token operator">></span>format <span class="token operator">==</span> HAL_PIXEL_FORMAT_BLOB<span class="token punctuation">)</span> <span class="token punctuation">{</span> InternalRequest streamRequested<span class="token punctuation">;</span> streamRequested<span class="token punctuation">.</span>meteringOnly <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> streamRequested<span class="token punctuation">.</span>need_metadata <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> streamRequested<span class="token punctuation">.</span>stream <span class="token operator">=</span> request<span class="token operator">-</span><span class="token operator">></span>output_buffers<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">.</span>stream<span class="token punctuation">;</span> internallyRequestedStreams<span class="token punctuation">.</span><span class="token function">push_back</span><span class="token punctuation">(</span>streamRequested<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> request<span class="token operator">-</span><span class="token operator">></span>num_output_buffers <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token keyword">auto</span> itr <span class="token operator">=</span> internallyRequestedStreams<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 获取metadata修改的地方</span> <span class="token comment">/* Modify setting to set compensation */</span> modified_meta <span class="token operator">=</span> request<span class="token operator">-</span><span class="token operator">></span>settings<span class="token punctuation">;</span> hdr_exp_values <span class="token operator">=</span> hdrBracketingSetting<span class="token punctuation">.</span>exp_val<span class="token punctuation">.</span>values<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token keyword">int32_t</span> expCompensation <span class="token operator">=</span> hdr_exp_values<span class="token punctuation">;</span> <span class="token keyword">uint8_t</span> aeLock <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> modified_meta<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION<span class="token punctuation">,</span> <span class="token operator">&</span>expCompensation<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> modified_meta<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_CONTROL_AE_LOCK<span class="token punctuation">,</span> <span class="token operator">&</span>aeLock<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> camera_metadata_t <span class="token operator">*</span>modified_settings <span class="token operator">=</span> modified_meta<span class="token punctuation">.</span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>settings <span class="token operator">=</span> modified_settings<span class="token punctuation">;</span> <span class="token comment">/* Capture Settling & -2x frame */</span> _orchestrationDb<span class="token punctuation">.</span><span class="token function">generateStoreInternalFrameNumber</span><span class="token punctuation">(</span>internalFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> <span class="token function">processCaptureRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> internallyRequestedStreams<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>num_output_buffers <span class="token operator">=</span> originalOutputCount<span class="token punctuation">;</span> _orchestrationDb<span class="token punctuation">.</span><span class="token function">allocStoreInternalFrameNumber</span><span class="token punctuation">(</span>originalFrameNumber<span class="token punctuation">,</span> internalFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> mHdrFrameNum <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> <span class="token function">processCaptureRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> emptyInternalList<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>num_output_buffers <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> modified_meta <span class="token operator">=</span> modified_settings<span class="token punctuation">;</span> hdr_exp_values <span class="token operator">=</span> hdrBracketingSetting<span class="token punctuation">.</span>exp_val<span class="token punctuation">.</span>values<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span> expCompensation <span class="token operator">=</span> hdr_exp_values<span class="token punctuation">;</span> aeLock <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> modified_meta<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION<span class="token punctuation">,</span> <span class="token operator">&</span>expCompensation<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> modified_meta<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_CONTROL_AE_LOCK<span class="token punctuation">,</span> <span class="token operator">&</span>aeLock<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> modified_settings <span class="token operator">=</span> modified_meta<span class="token punctuation">.</span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>settings <span class="token operator">=</span> modified_settings<span class="token punctuation">;</span> <span class="token comment">/* Capture Settling & 0X frame */</span> itr <span class="token operator">=</span> internallyRequestedStreams<span class="token punctuation">.</span><span class="token function">begin</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>itr <span class="token operator">==</span> internallyRequestedStreams<span class="token punctuation">.</span><span class="token function">end</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">LOGE</span><span class="token punctuation">(</span><span class="token string">"Error Internally Requested Stream list is empty"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">assert</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> itr<span class="token operator">-</span><span class="token operator">></span>need_metadata <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> itr<span class="token operator">-</span><span class="token operator">></span>meteringOnly <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> _orchestrationDb<span class="token punctuation">.</span><span class="token function">generateStoreInternalFrameNumber</span><span class="token punctuation">(</span>internalFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> <span class="token function">processCaptureRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> internallyRequestedStreams<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span> <span class="token operator">+</span> rc <span class="token operator">=</span> mCameraHandle<span class="token operator">-</span><span class="token operator">></span>ops<span class="token operator">-</span><span class="token operator">></span><span class="token function">set_parms</span><span class="token punctuation">(</span>mCameraHandle<span class="token operator">-</span><span class="token operator">></span>camera_handle<span class="token punctuation">,</span> mParameters<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span> <span class="token operator">+</span> <span class="token operator">-</span> # hardware<span class="token operator">/</span>qcom<span class="token operator">/</span>camera<span class="token operator">/</span>QCamera2<span class="token operator">/</span>stack<span class="token operator">/</span>mm<span class="token operator">-</span>camera<span class="token operator">-</span>interface<span class="token operator">/</span>src<span class="token operator">/</span>mm_camera_interface<span class="token punctuation">.</span>c <span class="token operator">+</span> <span class="token operator">-</span> <span class="token comment">/* camera ops v-table */</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token keyword">static</span> mm_camera_ops_t mm_camera_ops <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token punctuation">.</span>set_parms <span class="token operator">=</span> mm_camera_intf_set_parms<span class="token punctuation">,</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token punctuation">.</span>get_parms <span class="token operator">=</span> mm_camera_intf_get_parms<span class="token punctuation">,</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token punctuation">}</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token function">mm_camera_set_parms</span><span class="token punctuation">(</span>my_obj<span class="token punctuation">,</span> parms<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">+</span> # hardware<span class="token operator">/</span>qcom<span class="token operator">/</span>camera<span class="token operator">/</span>QCamera2<span class="token operator">/</span>stack<span class="token operator">/</span>mm<span class="token operator">-</span>camera<span class="token operator">-</span>interface<span class="token operator">/</span>src<span class="token operator">/</span>mm_camera<span class="token punctuation">.</span>c <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">+</span> c <span class="token operator">=</span> <span class="token function">mm_camera_util_s_ctrl</span><span class="token punctuation">(</span>my_obj<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> my_obj<span class="token operator">-</span><span class="token operator">></span>ctrl_fd<span class="token punctuation">,</span> CAM_PRIV_PARM<span class="token punctuation">,</span> <span class="token operator">&</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">+</span> <span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span><span class="token operator">></span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">+</span> # hardware<span class="token operator">/</span>qcom<span class="token operator">/</span>camera<span class="token operator">/</span>QCamera2<span class="token operator">/</span>stack<span class="token operator">/</span>mm<span class="token operator">-</span>camera<span class="token operator">-</span>interface<span class="token operator">/</span>src<span class="token operator">/</span>mm_camera<span class="token punctuation">.</span>c <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">+</span> control<span class="token punctuation">.</span>id <span class="token operator">=</span> id<span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">+</span> control<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token operator">*</span>value<span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator">+</span> rc <span class="token operator">=</span> <span class="token function">ioctl</span><span class="token punctuation">(</span>fd<span class="token punctuation">,</span> VIDIOC_S_CTRL<span class="token punctuation">,</span> <span class="token operator">&</span>control<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator">|</span> <span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token operator">+</span> <span class="token operator">-</span> <span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token operator">+</span> <span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> <span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span> _orchestrationDb<span class="token punctuation">.</span><span class="token function">generateStoreInternalFrameNumber</span><span class="token punctuation">(</span>internalFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> <span class="token function">processCaptureRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> internallyRequestedStreams<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Capture 2X frame*/</span> modified_meta <span class="token operator">=</span> modified_settings<span class="token punctuation">;</span> hdr_exp_values <span class="token operator">=</span> hdrBracketingSetting<span class="token punctuation">.</span>exp_val<span class="token punctuation">.</span>values<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span> expCompensation <span class="token operator">=</span> hdr_exp_values<span class="token punctuation">;</span> aeLock <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> modified_meta<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION<span class="token punctuation">,</span> <span class="token operator">&</span>expCompensation<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> modified_meta<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span>ANDROID_CONTROL_AE_LOCK<span class="token punctuation">,</span> <span class="token operator">&</span>aeLock<span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> modified_settings <span class="token operator">=</span> modified_meta<span class="token punctuation">.</span><span class="token function">release</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>settings <span class="token operator">=</span> modified_settings<span class="token punctuation">;</span> _orchestrationDb<span class="token punctuation">.</span><span class="token function">generateStoreInternalFrameNumber</span><span class="token punctuation">(</span>internalFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> <span class="token function">processCaptureRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> internallyRequestedStreams<span class="token punctuation">)</span><span class="token punctuation">;</span> _orchestrationDb<span class="token punctuation">.</span><span class="token function">generateStoreInternalFrameNumber</span><span class="token punctuation">(</span>internalFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> mHdrSnapshotRunning <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token function">processCaptureRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> internallyRequestedStreams<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Capture 2X on original streaming config*/</span> internallyRequestedStreams<span class="token punctuation">.</span><span class="token function">clear</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Restore original settings pointer */</span> request<span class="token operator">-</span><span class="token operator">></span>settings <span class="token operator">=</span> original_settings<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">uint32_t</span> internalFrameNumber<span class="token punctuation">;</span> _orchestrationDb<span class="token punctuation">.</span><span class="token function">allocStoreInternalFrameNumber</span><span class="token punctuation">(</span>request<span class="token operator">-</span><span class="token operator">></span>frame_number<span class="token punctuation">,</span> internalFrameNumber<span class="token punctuation">)</span><span class="token punctuation">;</span> request<span class="token operator">-</span><span class="token operator">></span>frame_number <span class="token operator">=</span> internalFrameNumber<span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">processCaptureRequest</span><span class="token punctuation">(</span>request<span class="token punctuation">,</span> internallyRequestedStreams<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> NO_ERROR<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
3.1.1.2 通过IOCTL 往V4L2 层下发参数
在前面追代码最终追到 ioctl(fd, VIDIOC_S_CTRL, &control);
往 V4L2 下发 control ,相关request 请求,保存在control 中
# kernel/msm-4.4/drivers/media/v4l2-core/v4l2-subdev.c
static long subdev_do_ioctl(struct file file, unsigned int cmd, void arg)
{
switch (cmd) {
case VIDIOC_G_CTRL:
return v4l2_g_ctrl(vfh->ctrl_handler, arg);
<span class="token keyword">case</span> VIDIOC_S_CTRL<span class="token operator">:</span>
<span class="token keyword">return</span> <span class="token function">v4l2_s_ctrl</span><span class="token punctuation">(</span>vfh<span class="token punctuation">,</span> vfh<span class="token operator">-</span><span class="token operator">></span>ctrl_handler<span class="token punctuation">,</span> arg<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
在 v4l2-ctrls.c 中
# kernel/msm-4.4/drivers/media/v4l2-core/v4l2-ctrls.c
int v4l2_s_ctrl(struct v4l2_fh fh, struct v4l2_ctrl_handler hdl, struct v4l2_control control)
{
struct v4l2_ctrl ctrl = v4l2_ctrl_find(hdl, control->id);
struct v4l2_ext_control c = { control->id };
int ret;
<span class="token keyword">if</span> <span class="token punctuation">(</span>ctrl<span class="token operator">-></span>flags <span class="token operator">&</span> V4L2_CTRL_FLAG_READ_ONLY<span class="token punctuation">)</span>
<span class="token keyword">return</span> <span class="token operator">-</span>EACCES<span class="token punctuation">;</span>
c<span class="token punctuation">.</span>value <span class="token operator">=</span> control<span class="token operator">-></span>value<span class="token punctuation">;</span>
ret <span class="token operator">=</span> <span class="token function">set_ctrl_lock</span><span class="token punctuation">(</span>fh<span class="token punctuation">,</span> ctrl<span class="token punctuation">,</span> <span class="token operator">&</span>c<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">=</span><span class="token operator">></span>
<span class="token function">user_to_new</span><span class="token punctuation">(</span>c<span class="token punctuation">,</span> ctrl<span class="token punctuation">)</span><span class="token punctuation">;</span>
ret <span class="token operator">=</span> <span class="token function">set_ctrl</span><span class="token punctuation">(</span>fh<span class="token punctuation">,</span> ctrl<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">></span>
<span class="token keyword">return</span> <span class="token function">try_or_set_cluster</span><span class="token punctuation">(</span>fh<span class="token punctuation">,</span> master<span class="token punctuation">,</span> true<span class="token punctuation">,</span> ch_flags<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token operator"><=</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span><span class="token operator">==</span>
control<span class="token operator">-></span>value <span class="token operator">=</span> c<span class="token punctuation">.</span>value<span class="token punctuation">;</span>
<span class="token keyword">return</span> ret<span class="token punctuation">;</span>
}
EXPORT_SYMBOL(v4l2_s_ctrl);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
在 try_or_set_cluster() 中
# kernel/msm-4.4/drivers/media/v4l2-core/v4l2-ctrls.c /* Core function that calls try/s_ctrl and ensures that the new value is copied to the current value on a set. Must be called with ctrl->handler->lock held. */ static int try_or_set_cluster(struct v4l2_fh *fh, struct v4l2_ctrl *master, bool set, u32 ch_flags) { ret = call_op(master, try_ctrl);
ret <span class="token operator">=</span> <span class="token function">call_op</span><span class="token punctuation">(</span>master<span class="token punctuation">,</span> s_ctrl<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* If OK, then make the new values permanent. */</span> update_flag <span class="token operator">=</span> <span class="token function">is_cur_manual</span><span class="token punctuation">(</span>master<span class="token punctuation">)</span> <span class="token operator">!=</span> <span class="token function">is_new_manual</span><span class="token punctuation">(</span>master<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">for</span> <span class="token punctuation">(</span>i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> master<span class="token operator">-></span>ncontrols<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token function">new_to_cur</span><span class="token punctuation">(</span>fh<span class="token punctuation">,</span> master<span class="token operator">-></span>cluster<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> ch_flags <span class="token operator">|</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>update_flag <span class="token operator">&&</span> i <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token operator">?</span> V4L2_EVENT_CTRL_CH_FLAGS <span class="token punctuation">:</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
接下来调用 call_op(master, s_ctrl)
, 进行参数设置。 call_op 定义如下
kernel/msm-4.4/drivers/media/v4l2-core/v4l2-ctrls.c
#define call_op(master, op) \
(has_op(master, op) ? master->ops->op(master) : 0)
因为 mastart 的类型为 struct v4l2_ctrl *
struct v4l2_ctrl {
const struct v4l2_ctrl_ops ops;
const struct v4l2_ctrl_type_ops type_ops;
–––––––––––––––––––––
# kernel/msm-4.4/include/media/v4l2-ctrls.h
v4l2_ctrl_ops定义为
struct v4l2_ctrl_ops {
int (g_volatile_ctrl)(struct v4l2_ctrl ctrl);
int (try_ctrl)(struct v4l2_ctrl ctrl);
int (s_ctrl)(struct v4l2_ctrl ctrl);
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
const struct v4l2_ctrl_ops *ops;
是在v4l2_ctrl_new()
中初始化的
/* Add a new control */
static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
const struct v4l2_ctrl_type_ops *type_ops,
u32 id, const char *name, enum v4l2_ctrl_type type,
s64 min, s64 max, u64 step, s64 def,
const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size,
u32 flags, const char * const *qmenu,
const s64 *qmenu_int, void *priv)
{
ctrl->handler = hdl;
ctrl->ops = ops;
ctrl->type_ops = type_ops ? type_ops : &std_type_ops;
ctrl->id = id;
ctrl->name = name;
ctrl->type = type;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
3.1.1.3 V4L2_Ctrl 的作用是啥
我们随便找个代码,如: kernel/msm-4.4/drivers/media/i2c/ov7670.c
虽然这个代码际不会跑,但我们参考学习 ctrl 是啥 ,还是合适的。
在probe 初始化时,初始化了大量的ctrl, 以 V4L2_CID_BRIGHTNESSb 为例,看下面代码追踪,可以发现,最终跑到了写寄存器的地方。
这样就很清晰了。
# kernel/msm-4.4/drivers/media/i2c/ov7670.c
static int ov7670_probe(struct i2c_client *client,const struct i2c_device_id *id)
{
v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops, V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops,V4L2_CID_CONTRAST, 0, 127, 1, 64);
v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops,V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops,V4L2_CID_HFLIP, 0, 1, 1, 0);
info->saturation = v4l2_ctrl_new_std(&info->hdl, &ov7670_ctrl_ops,V4L2_CID_SATURATION, 0, 256, 1, 128);
}
static const struct v4l2_ctrl_ops ov7670_ctrl_ops = {
.s_ctrl = ov7670_s_ctrl,
.g_volatile_ctrl = ov7670_g_volatile_ctrl,
};
static int ov7670_s_ctrl(struct v4l2_ctrl ctrl)
{
struct v4l2_subdev sd = to_sd(ctrl);
struct ov7670_info *info = to_state(sd);
<span class="token keyword">switch</span> <span class="token punctuation">(</span>ctrl<span class="token operator">-</span><span class="token operator">></span>id<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">case</span> V4L2_CID_BRIGHTNESS<span class="token operator">:</span>
<span class="token keyword">return</span> <span class="token function">ov7670_s_brightness</span><span class="token punctuation">(</span>sd<span class="token punctuation">,</span> ctrl<span class="token operator">-</span><span class="token operator">></span>val<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">case</span> V4L2_CID_CONTRAST<span class="token operator">:</span>
<span class="token keyword">return</span> <span class="token function">ov7670_s_contrast</span><span class="token punctuation">(</span>sd<span class="token punctuation">,</span> ctrl<span class="token operator">-</span><span class="token operator">></span>val<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">case</span> V4L2_CID_SATURATION<span class="token operator">:</span>
<span class="token keyword">return</span> <span class="token function">ov7670_s_sat_hue</span><span class="token punctuation">(</span>sd<span class="token punctuation">,</span>info<span class="token operator">-</span><span class="token operator">></span>saturation<span class="token operator">-</span><span class="token operator">></span>val<span class="token punctuation">,</span> info<span class="token operator">-</span><span class="token operator">></span>hue<span class="token operator">-</span><span class="token operator">></span>val<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token operator">-</span>EINVAL<span class="token punctuation">;</span>
}
static int ov7670_s_brightness(struct v4l2_subdev *sd, int value)
{
unsigned char com8 = 0, v;
int ret;
<span class="token function">ov7670_read</span><span class="token punctuation">(</span>sd<span class="token punctuation">,</span> REG_COM8<span class="token punctuation">,</span> <span class="token operator">&</span>com8<span class="token punctuation">)</span><span class="token punctuation">;</span>
com8 <span class="token operator">&</span><span class="token operator">=</span> <span class="token operator">~</span>COM8_AEC<span class="token punctuation">;</span>
<span class="token function">ov7670_write</span><span class="token punctuation">(</span>sd<span class="token punctuation">,</span> REG_COM8<span class="token punctuation">,</span> com8<span class="token punctuation">)</span><span class="token punctuation">;</span>
v <span class="token operator">=</span> <span class="token function">ov7670_abs_to_sm</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
ret <span class="token operator">=</span> <span class="token function">ov7670_write</span><span class="token punctuation">(</span>sd<span class="token punctuation">,</span> REG_BRIGHT<span class="token punctuation">,</span> v<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> ret<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
3.2 CameraMetadata 下发参数总结
在前面 3.1 中,我们详细跟踪代码看了CameraMetadata 下发参数的过程。
- 初始化
mMetadata
对像,获取 TAG 为CAMERA3_TEMPLATE_PREVIEW
的 Metadata - 调用
mMetadata->update
更新Metadata
参数,调用setStreamingRequest
下发参数 - 在
Camera3Device.cpp
中,最终将 request 放入mRequestQueue
中 - 在
Camera3Device::RequestThread::threadLoop()
来对mRequestQueue
消息进行处理 - 调用hardware层的
process_capture_request()
方法,处理request 请求 - 在hardware 层
QCamera3HardwareInterface::orchestrateRequest()
中处理上层下发的 request 请求 - 最终通过
ioctl(fd, VIDIOC_S_CTRL, &control);
往 V4L2 下发参数。 - 在V4L2 中,根据具体设备注册
V4L2_ctrl
时的 ops ,调用不同的操作函数,来更新具体的硬件寄存器。
四、CameraMetadata.cpp 代码分析
4.1 CameraMetadata 方法定义
# frameworks/av/include/camera/CameraMetadata.h class CameraMetadata: public Parcelable { public: /** Creates an empty object; best used when expecting to acquire contents from elsewhere */ CameraMetadata(); /** Creates an object with space for entryCapacity entries, with dataCapacity extra storage */ CameraMetadata(size_t entryCapacity, size_t dataCapacity = 10); /** Takes ownership of passed-in buffer */ CameraMetadata(camera_metadata_t *buffer); /** Clones the metadata */ CameraMetadata(const CameraMetadata &other);
<span class="token comment">/* Update metadata entry. Will create entry if it doesn't exist already, and * will reallocate the buffer if insufficient space exists. Overloaded for * the various types of valid data. */</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">uint8_t</span> <span class="token operator">*</span>data<span class="token punctuation">,</span> size_t data_count<span class="token punctuation">)</span><span class="token punctuation">;</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">int32_t</span> <span class="token operator">*</span>data<span class="token punctuation">,</span> size_t data_count<span class="token punctuation">)</span><span class="token punctuation">;</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">float</span> <span class="token operator">*</span>data<span class="token punctuation">,</span> size_t data_count<span class="token punctuation">)</span><span class="token punctuation">;</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">int64_t</span> <span class="token operator">*</span>data<span class="token punctuation">,</span> size_t data_count<span class="token punctuation">)</span><span class="token punctuation">;</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> <span class="token keyword">const</span> <span class="token keyword">double</span> <span class="token operator">*</span>data<span class="token punctuation">,</span> size_t data_count<span class="token punctuation">)</span><span class="token punctuation">;</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> <span class="token keyword">const</span> camera_metadata_rational_t <span class="token operator">*</span>data<span class="token punctuation">,</span> size_t data_count<span class="token punctuation">)</span><span class="token punctuation">;</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> <span class="token keyword">const</span> String8 <span class="token operator">&</span>string<span class="token punctuation">)</span><span class="token punctuation">;</span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">const</span> camera_metadata_ro_entry <span class="token operator">&</span>entry<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">template</span><span class="token operator"><</span><span class="token keyword">typename</span> T<span class="token operator">></span> status_t <span class="token function">update</span><span class="token punctuation">(</span><span class="token keyword">uint32_t</span> tag<span class="token punctuation">,</span> Vector<span class="token operator"><</span>T<span class="token operator">></span> data<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token function">update</span><span class="token punctuation">(</span>tag<span class="token punctuation">,</span> data<span class="token punctuation">.</span><span class="token function">array</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> data<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">// Metadata object is unchanged when reading from parcel fails.</span> <span class="token keyword">virtual</span> status_t <span class="token function">readFromParcel</span><span class="token punctuation">(</span><span class="token keyword">const</span> Parcel <span class="token operator">*</span>parcel<span class="token punctuation">)</span> override<span class="token punctuation">;</span> <span class="token keyword">virtual</span> status_t <span class="token function">writeToParcel</span><span class="token punctuation">(</span>Parcel <span class="token operator">*</span>parcel<span class="token punctuation">)</span> <span class="token keyword">const</span> override<span class="token punctuation">;</span> <span class="token comment">/* Caller becomes the owner of the new metadata * 'const Parcel' doesnt prevent us from calling the read functions. * which is interesting since it changes the internal state * * NULL can be returned when no metadata was sent, OR if there was an issue * unpacking the serialized data (i.e. bad parcel or invalid structure).*/</span> <span class="token keyword">static</span> status_t <span class="token function">readFromParcel</span><span class="token punctuation">(</span><span class="token keyword">const</span> Parcel <span class="token operator">&</span>parcel<span class="token punctuation">,</span> camera_metadata_t<span class="token operator">*</span><span class="token operator">*</span> out<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">/* Caller retains ownership of metadata * - Write 2 (int32 + blob) args in the current position */</span> <span class="token keyword">static</span> status_t <span class="token function">writeToParcel</span><span class="token punctuation">(</span>Parcel <span class="token operator">&</span>parcel<span class="token punctuation">,</span> <span class="token keyword">const</span> camera_metadata_t<span class="token operator">*</span> metadata<span class="token punctuation">)</span><span class="token punctuation">;</span>
private:
camera_metadata_t *mBuffer;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
4.2 修改MetaData 内存数据 CameraMetadata::update()
当需要修改 metadata 数据时,调用 update 方法,如下
# frameworks/av/camera/CameraMetadata.cpp
status_t CameraMetadata::update(uint32_t tag, const int32_t *data, size_t data_count) {
return updateImpl(tag, (const void*)data, data_count);
}
- 1
- 2
- 3
- 4
可以看出,最终调用的都是 CameraMetadata::updateImpl()
方法,我们来看下它的具体实现
可以看出,它处理方法是,如果entry 已经有了,则更新其数据,如果不存在,则新增一个entry。
最终,metadata 在保存在内存中, 注意,由于此时参数并没有下发,所以此时参数肯定是不生效的。