1、camera_metadata簡介java
Camera API2/HAL3架構下使用了全新的CameraMetadata結構取代了以前的SetParameter/Paramters等操做,實現了Java到native到HAL3的參數傳遞。引入了管道的概念將安卓設備和攝像頭之間聯繫起來,系統向攝像頭髮送 Capture 請求,而攝像頭會返回 CameraMetadata,這一切創建在一個叫做 CameraCaptureSession 的會話中。android
2、Framework到HAL層的轉換數組
Camera2Client 使用 API1 傳遞參數採用的邏輯是仍是在Java層預留了setParameters接口,只是當Parameter在設置時比起CameraClient而言,是將這個Parameter根據不一樣的TAG形式直接綁定到CameraMetadata mPreviewRequest/mRecordRequest/mCaptureRequest中,這些數據會由Capture_Request轉爲camera3_capture_request中的camera_metadata_t settings完成參數從Java到native到HAL3的傳遞。session
可是在Camera API2下,再也不須要那麼複雜的轉換過程,在Java層中直接對參數進行設置並將其封裝到Capture_Request便可,即參數控制由Java層來完成。這也體現了API2中Request和Result在APP中就大量存在的緣由。對此爲了和Framework Native層相關TAG數據的統一,在Java層中大量出現的參數設置是經過Section Tag的name來交由Native完成轉換生成在Java層的TAG。數據結構
(1)Java層對應代碼位置:frameworks\base\core\java\android\hardware\camera2\impl\CameraMetadataNative.java架構
private <T> T getBase(Key<T> key) { int tag = nativeGetTagFromKeyLocal(key.getName()); byte[] values = readValues(tag); if (values == null) { // If the key returns null, use the fallback key if exists. // This is to support old key names for the newly published keys. if (key.mFallbackName == null) { return null; } tag = nativeGetTagFromKeyLocal(key.mFallbackName); values = readValues(tag); if (values == null) { return null; } } int nativeType = nativeGetTypeFromTagLocal(tag); Marshaler<T> marshaler = getMarshalerForKey(key, nativeType); ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder()); return marshaler.unmarshal(buffer); }
(2)Native層對應代碼位置:frameworks/base/core/jni/android_hardware_camera2_CameraMetadata.cppapp
static const JNINativeMethod gCameraMetadataMethods[] = { // static methods { "nativeGetTagFromKey", "(Ljava/lang/String;J)I", (void *)CameraMetadata_getTagFromKey }, { "nativeGetTypeFromTag", "(IJ)I", (void *)CameraMetadata_getTypeFromTag }, { "nativeSetupGlobalVendorTagDescriptor", "()I", (void*)CameraMetadata_setupGlobalVendorTagDescriptor }, // instance methods ......
其中CameraMetadata_getTagFromKey是實現將一個Java層的string轉爲一個tag的值,如:android.control.mode。對比最初不一樣的Section name就能夠發現前面兩個x.y的字符串就是表明是Section name.然後面mode便是在該section下的tag數值,因此經過對這個string的分析可知,就能夠定位對應的section以及tag值,這樣返回到Java層的就是key相應的tag值了。繼續追蹤到 \system\media\camera\src\camera_metadata.c:函數
// Declared in system/media/private/camera/include/camera_metadata_hidden.h const char *get_local_camera_metadata_tag_name_vendor_id(uint32_t tag, metadata_vendor_id_t id) { uint32_t tag_section = tag >> 16; if (tag_section >= VENDOR_SECTION && vendor_cache_ops != NULL && id != CAMERA_METADATA_INVALID_VENDOR_ID) { return vendor_cache_ops->get_tag_name(tag, id); } else if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) { return vendor_tag_ops->get_tag_name( vendor_tag_ops, tag); } if (tag_section >= ANDROID_SECTION_COUNT || tag >= camera_metadata_section_bounds[tag_section][1] ) { // 關鍵是camera_metadata_section_bounds這個數組,保存了各個tag的綁定信息 return NULL; } uint32_t tag_index = tag & 0xFFFF; return tag_info[tag_section][tag_index].tag_name; }
其餘相關文件的調用關係以下圖:佈局
其中 camera_metadata_tags.h 包含了全部的基本宏,每個section的大小是64K(每一個枚舉值左移16位):大數據
/** * !! Do not include this file directly !! * * Include camera_metadata.h instead. */ /** * ! Do not edit this file directly ! * * Generated automatically from camera_metadata_tags.mako */ /** TODO: Nearly every enum in this file needs a description */ /** * Top level hierarchy definitions for camera metadata. *_INFO sections are for * the static metadata that can be retrived without opening the camera device. * New sections must be added right before ANDROID_SECTION_COUNT to maintain * existing enumerations. */ typedef enum camera_metadata_section { ANDROID_COLOR_CORRECTION, ANDROID_CONTROL, ANDROID_DEMOSAIC, ANDROID_EDGE, ANDROID_FLASH, ANDROID_FLASH_INFO, ANDROID_HOT_PIXEL, ANDROID_JPEG, ANDROID_LENS, ANDROID_LENS_INFO, ANDROID_NOISE_REDUCTION, ANDROID_QUIRKS, ANDROID_REQUEST, ANDROID_SCALER, ANDROID_SENSOR, ANDROID_SENSOR_INFO, ANDROID_SHADING, ANDROID_STATISTICS, ANDROID_STATISTICS_INFO, ANDROID_TONEMAP, ANDROID_LED, ANDROID_INFO, ANDROID_BLACK_LEVEL, ANDROID_SYNC, ANDROID_REPROCESS, ANDROID_DEPTH, ANDROID_LOGICAL_MULTI_CAMERA, ANDROID_DISTORTION_CORRECTION, ANDROID_SECTION_COUNT, VENDOR_SECTION = 0x8000 } camera_metadata_section_t; /** * 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, ANDROID_LOGICAL_MULTI_CAMERA_START = ANDROID_LOGICAL_MULTI_CAMERA << 16, ANDROID_DISTORTION_CORRECTION_START = ANDROID_DISTORTION_CORRECTION << 16, VENDOR_SECTION_START = VENDOR_SECTION << 16 } camera_metadata_section_start_t;
而每一個MODE的END值是根據START後的填充枚舉變量偏移所得:
/** * Main enum for defining camera metadata tags. New entries must always go * before the section _END tag to preserve existing enumeration values. In * addition, the name and type of the tag needs to be added to * system/media/camera/src/camera_metadata_tag_info.c */ typedef enum camera_metadata_tag { ANDROID_COLOR_CORRECTION_MODE = // enum | public | HIDL v3.2 ANDROID_COLOR_CORRECTION_START, ANDROID_COLOR_CORRECTION_TRANSFORM, // rational[] | public | HIDL v3.2 ANDROID_COLOR_CORRECTION_GAINS, // float[] | public | HIDL v3.2 ANDROID_COLOR_CORRECTION_ABERRATION_MODE, // enum | public | HIDL v3.2 ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES, // byte[] | public | HIDL v3.2 ANDROID_COLOR_CORRECTION_END, ANDROID_CONTROL_AE_ANTIBANDING_MODE = // enum | public | HIDL v3.2 ANDROID_CONTROL_START, ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, // int32 | public | HIDL v3.2 ANDROID_CONTROL_AE_LOCK, // enum | public | HIDL v3.2 ANDROID_CONTROL_AE_MODE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AE_REGIONS, // int32[] | public | HIDL v3.2 ANDROID_CONTROL_AE_TARGET_FPS_RANGE, // int32[] | public | HIDL v3.2 ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER, // enum | public | HIDL v3.2 ANDROID_CONTROL_AF_MODE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AF_REGIONS, // int32[] | public | HIDL v3.2 ANDROID_CONTROL_AF_TRIGGER, // enum | public | HIDL v3.2 ANDROID_CONTROL_AWB_LOCK, // enum | public | HIDL v3.2 ANDROID_CONTROL_AWB_MODE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AWB_REGIONS, // int32[] | public | HIDL v3.2 ANDROID_CONTROL_CAPTURE_INTENT, // enum | public | HIDL v3.2 ANDROID_CONTROL_EFFECT_MODE, // enum | public | HIDL v3.2 ANDROID_CONTROL_MODE, // enum | public | HIDL v3.2 ANDROID_CONTROL_SCENE_MODE, // enum | public | HIDL v3.2 ANDROID_CONTROL_VIDEO_STABILIZATION_MODE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_AE_AVAILABLE_MODES, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, // int32[] | public | HIDL v3.2 ANDROID_CONTROL_AE_COMPENSATION_RANGE, // int32[] | public | HIDL v3.2 ANDROID_CONTROL_AE_COMPENSATION_STEP, // rational | public | HIDL v3.2 ANDROID_CONTROL_AF_AVAILABLE_MODES, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_AVAILABLE_EFFECTS, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_AVAILABLE_SCENE_MODES, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_AWB_AVAILABLE_MODES, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_MAX_REGIONS, // int32[] | ndk_public | HIDL v3.2 ANDROID_CONTROL_SCENE_MODE_OVERRIDES, // byte[] | system | HIDL v3.2 ANDROID_CONTROL_AE_PRECAPTURE_ID, // int32 | system | HIDL v3.2 ANDROID_CONTROL_AE_STATE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AF_STATE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AF_TRIGGER_ID, // int32 | system | HIDL v3.2 ANDROID_CONTROL_AWB_STATE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS, // int32[] | hidden | HIDL v3.2 ANDROID_CONTROL_AE_LOCK_AVAILABLE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AWB_LOCK_AVAILABLE, // enum | public | HIDL v3.2 ANDROID_CONTROL_AVAILABLE_MODES, // byte[] | public | HIDL v3.2 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE, // int32[] | public | HIDL v3.2 ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST, // int32 | public | HIDL v3.2 ANDROID_CONTROL_ENABLE_ZSL, // enum | public | HIDL v3.2 ANDROID_CONTROL_AF_SCENE_CHANGE, // enum | public | HIDL v3.3 ANDROID_CONTROL_END,
......
對應關係如圖所示:
而後在 camera_metadata_tag_info.c 中進行了映射和綁定,前面Native層CameraMetadata_getTagFromKey調用的camera_metadata_section_bounds實如今這裏:
/** * ! Do not edit this file directly ! * * Generated automatically from camera_metadata_tag_info.mako */ 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", [ANDROID_LOGICAL_MULTI_CAMERA] = "android.logicalMultiCamera", [ANDROID_DISTORTION_CORRECTION] = "android.distortionCorrection", }; unsigned int camera_metadata_section_bounds[ANDROID_SECTION_COUNT][2] = { [ANDROID_COLOR_CORRECTION] = { ANDROID_COLOR_CORRECTION_START, ANDROID_COLOR_CORRECTION_END }, [ANDROID_CONTROL] = { ANDROID_CONTROL_START, ANDROID_CONTROL_END }, [ANDROID_DEMOSAIC] = { ANDROID_DEMOSAIC_START, ANDROID_DEMOSAIC_END }, [ANDROID_EDGE] = { ANDROID_EDGE_START, ANDROID_EDGE_END }, [ANDROID_FLASH] = { ANDROID_FLASH_START, ANDROID_FLASH_END }, [ANDROID_FLASH_INFO] = { ANDROID_FLASH_INFO_START, ANDROID_FLASH_INFO_END }, [ANDROID_HOT_PIXEL] = { ANDROID_HOT_PIXEL_START, ANDROID_HOT_PIXEL_END }, [ANDROID_JPEG] = { ANDROID_JPEG_START, ANDROID_JPEG_END }, [ANDROID_LENS] = { ANDROID_LENS_START, ANDROID_LENS_END }, [ANDROID_LENS_INFO] = { ANDROID_LENS_INFO_START, ANDROID_LENS_INFO_END }, [ANDROID_NOISE_REDUCTION] = { ANDROID_NOISE_REDUCTION_START, ANDROID_NOISE_REDUCTION_END }, [ANDROID_QUIRKS] = { ANDROID_QUIRKS_START, ANDROID_QUIRKS_END }, [ANDROID_REQUEST] = { ANDROID_REQUEST_START, ANDROID_REQUEST_END }, [ANDROID_SCALER] = { ANDROID_SCALER_START, ANDROID_SCALER_END }, [ANDROID_SENSOR] = { ANDROID_SENSOR_START, ANDROID_SENSOR_END }, [ANDROID_SENSOR_INFO] = { ANDROID_SENSOR_INFO_START, ANDROID_SENSOR_INFO_END }, [ANDROID_SHADING] = { ANDROID_SHADING_START, ANDROID_SHADING_END }, [ANDROID_STATISTICS] = { ANDROID_STATISTICS_START, ANDROID_STATISTICS_END }, [ANDROID_STATISTICS_INFO] = { ANDROID_STATISTICS_INFO_START, ANDROID_STATISTICS_INFO_END }, [ANDROID_TONEMAP] = { ANDROID_TONEMAP_START, ANDROID_TONEMAP_END }, [ANDROID_LED] = { ANDROID_LED_START, ANDROID_LED_END }, [ANDROID_INFO] = { ANDROID_INFO_START, ANDROID_INFO_END }, [ANDROID_BLACK_LEVEL] = { ANDROID_BLACK_LEVEL_START, ANDROID_BLACK_LEVEL_END }, [ANDROID_SYNC] = { ANDROID_SYNC_START, ANDROID_SYNC_END }, [ANDROID_REPROCESS] = { ANDROID_REPROCESS_START, ANDROID_REPROCESS_END }, [ANDROID_DEPTH] = { ANDROID_DEPTH_START, ANDROID_DEPTH_END }, [ANDROID_LOGICAL_MULTI_CAMERA] = { ANDROID_LOGICAL_MULTI_CAMERA_START, ANDROID_LOGICAL_MULTI_CAMERA_END }, [ANDROID_DISTORTION_CORRECTION] = { ANDROID_DISTORTION_CORRECTION_START, ANDROID_DISTORTION_CORRECTION_END }, };
由 tag_info 結構體統一管理:
static tag_info_t android_color_correction[ANDROID_COLOR_CORRECTION_END - ANDROID_COLOR_CORRECTION_START] = { [ ANDROID_COLOR_CORRECTION_MODE - ANDROID_COLOR_CORRECTION_START ] = { "mode", TYPE_BYTE }, [ ANDROID_COLOR_CORRECTION_TRANSFORM - ANDROID_COLOR_CORRECTION_START ] = { "transform", TYPE_RATIONAL }, [ ANDROID_COLOR_CORRECTION_GAINS - ANDROID_COLOR_CORRECTION_START ] = { "gains", TYPE_FLOAT }, [ ANDROID_COLOR_CORRECTION_ABERRATION_MODE - ANDROID_COLOR_CORRECTION_START ] = { "aberrationMode", TYPE_BYTE }, [ ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES - ANDROID_COLOR_CORRECTION_START ] = { "availableAberrationModes", TYPE_BYTE }, }; ------------------------------------------------------------- tag_info_t *tag_info[ANDROID_SECTION_COUNT] = { android_color_correction, android_control, android_demosaic, android_edge, android_flash, android_flash_info, android_hot_pixel, android_jpeg, android_lens, android_lens_info, android_noise_reduction, android_quirks, android_request, android_scaler, android_sensor, android_sensor_info, android_shading, android_statistics, android_statistics_info, android_tonemap, android_led, android_info, android_black_level, android_sync, android_reprocess, android_depth, android_logical_multi_camera, android_distortion_correction, };
下圖是Camera Metadata對不一樣section以及相應section下不一樣tag的佈局圖,以最多見的android.control Section爲例進行描述:
若是要寫數據,那麼在native一樣須要一個CameraMetadata對象,這裏是在Java構造CameraMetadataNative時實現的,調用的native接口是nativeAllocate():
// instance methods { "nativeAllocate", "()J", (void*)CameraMetadata_allocate },
static jlong CameraMetadata_allocate(JNIEnv *env, jobject thiz) { ALOGV("%s", __FUNCTION__); return reinterpret_cast<jlong>(new CameraMetadata()); }
CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) : mLocked(false) { mBuffer = allocate_camera_metadata(entryCapacity, dataCapacity); }
函數allocate_camera_metadata()是從新根據入口數和數據大小計算、申請buffer。緊接着第二個place_camera_metadata()就是對剛申請的buffer,初始化一些變量,爲後面更新,插入tag數據作準備。
camera_metadata_t *allocate_camera_metadata(size_t entry_capacity, size_t data_capacity) { //傳入的參數是(2,0) if (entry_capacity == 0) return NULL; size_t memory_needed = calculate_camera_metadata_size(entry_capacity, //返回的是header+2*sizeof(entry)大小 data_capacity);
void *buffer = malloc(memory_needed); //malloc申請一塊連續的內存, return place_camera_metadata(buffer, memory_needed, //並初始化。 entry_capacity, data_capacity); } camera_metadata_t *place_camera_metadata(void *dst, size_t dst_size, size_t entry_capacity, size_t data_capacity) { if (dst == NULL) return NULL; if (entry_capacity == 0) return NULL; size_t memory_needed = calculate_camera_metadata_size(entry_capacity, //再一次計算須要的內存大小,爲什麼?? data_capacity); if (memory_needed > dst_size) return NULL; camera_metadata_t *metadata = (camera_metadata_t*)dst; metadata->version = CURRENT_METADATA_VERSION; //版本號, metadata->flags = 0;//沒有排序標誌 metadata->entry_count = 0; //初始化entry_count =0 metadata->entry_capacity = entry_capacity; //最大的入口數量,針對ANDROID_FLASH_MODE這裏是2個。 metadata->entries_start = ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT); //entry數據域的開始處緊挨着camera_metadata_t 頭部。 metadata->data_count = 0; //初始化爲0 metadata->data_capacity = data_capacity; //由於沒有申請內存,這裏也是0 metadata->size = memory_needed; //總的內存大小 size_t data_unaligned = (uint8_t*)(get_entries(metadata) + metadata->entry_capacity) - (uint8_t*)metadata; metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT); //計算data數據區域的偏移地址。數據區域緊挨着entry區域末尾。 return metadata;
}
//根據入口數量和數據數量,計算實際camera_metadata須要的內存塊大小(header+sizeof(camera_entry)+sizeof(data)。 size_t calculate_camera_metadata_size(size_t entry_count, size_t data_count) { //針對咱們上面講的例子,傳入的參數是(2,0) size_t memory_needed = sizeof(camera_metadata_t); //這裏計算header大小了。 // Start entry list at aligned boundary memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT); //按字節對齊後的大小 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]); //緊接着是entry數據區的大小了,這裏申請了2個entry內存空間。 // Start buffer list at aligned boundary memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT); //一樣對齊 memory_needed += sizeof(uint8_t[data_count]); //data_count = 0 return memory_needed; //返回的最後算出的大小 }
CameraMetadata數據內存塊中組成的最小基本單元是struct camera_metadata_buffer_entry,總的entry數目等信息須要struct camera_metadata_t來維護。
結構圖以下:
在HAL層代碼中經過以下方式獲取/更新 entry:
{ UINT32 SensorTimestampTag = 0x000E0010; camera_metadata_entry_t entry = { 0 }; camera_metadata_t* pMetadata = const_cast<camera_metadata_t*>(static_cast<const camera_metadata_t*>(pResult->pResultMetadata)); UINT64 timestamp = m_shutterTimestamp[applicationFrameNum % MaxOutstandingRequests]; INT32 status = find_camera_metadata_entry(pMetadata, SensorTimestampTag, &entry); if (-ENOENT == status) //沒有查找到tag時,則認爲是一個新的tag,須要添加到大數據結構中 { status = add_camera_metadata_entry(pMetadata, SensorTimestampTag, ×tamp, 1); } else if (0 == status) { status = update_camera_metadata_entry(pMetadata, entry.index, ×tamp, 1, NULL); } }
find_camera_metadata_entry函數很是好理解,獲取對應tag的entry結構體,並將數據保存在entry傳入的參數中。
注:struct camera_metadata_buffer_entry_t; //內部使用記錄tag數據
struct camera_metadata_entry_t; //外部引用
int find_camera_metadata_entry(camera_metadata_t *src, uint32_t tag, camera_metadata_entry_t *entry) { if (src == NULL) return ERROR; uint32_t index; if (src->flags & FLAG_SORTED) { //以前初始化時,flags = 0,這裏不成立,跳到else處 // Sorted entries, do a binary search camera_metadata_buffer_entry_t *search_entry = NULL; camera_metadata_buffer_entry_t key; key.tag = tag; search_entry = bsearch(&key, get_entries(src), src->entry_count, sizeof(camera_metadata_buffer_entry_t), compare_entry_tags); if (search_entry == NULL) return NOT_FOUND; index = search_entry - get_entries(src); } else { // Not sorted, linear search camera_metadata_buffer_entry_t *search_entry = get_entries(src); for (index = 0; index < src->entry_count; index++, search_entry++) { //這裏因爲entry_count =0 由於根本就沒有添加任何東西。 if (search_entry->tag == tag) { break; } } if (index == src->entry_count) return NOT_FOUND; //返回NOT_FOUNT } return get_camera_metadata_entry(src, index, //找到index的tag entry entry); } int add_camera_metadata_entry(camera_metadata_t *dst, uint32_t tag, const void *data, size_t data_count) { //這裏傳入的參數爲(mBuffer,ANDROID_FLASH_MODE,5,1) int type = get_camera_metadata_tag_type(tag); if (type == -1) { ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag); return ERROR; } return add_camera_metadata_entry_raw(dst, //這裏傳入的參數爲(mBuffer,ANDROID_FLASH_MODE,BYTE_TYPE,5,1) DOWN tag, type, data, data_count); }
//下面是真正幹實事的方法,這裏會將外部傳入的tag信息,存放到各自的家中 static int add_camera_metadata_entry_raw(camera_metadata_t *dst, uint32_t tag, uint8_t type, const void *data, size_t data_count) { if (dst == NULL) return ERROR; if (dst->entry_count == dst->entry_capacity) return ERROR; //若是成立,就沒有空間了。 if (data == NULL) return ERROR; size_t data_bytes = calculate_camera_metadata_entry_data_size(type, data_count); //計算要使用的內存大小這裏1*1,可是返回的是0 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR; //用的空間+當前數據位置指針,不能大於數據最大空間。 size_t data_payload_bytes = data_count * camera_metadata_type_size[type]; //data_count =1,data_payload_bytes =1; camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;//獲得當前空閒的entry對象。 memset(entry, 0, sizeof(camera_metadata_buffer_entry_t)); //清0 entry->tag = tag; //ANDROID_FLASH_MODE. entry->type = type; //BYTE_TYPE entry->count = data_count; //沒有佔用data數據域,這裏就是0了。 if (data_bytes == 0) { memcpy(entry->data.value, data, data_payload_bytes); //小於4字節的,直接放到entry數據域。 } else { entry->data.offset = dst->data_count; memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes); dst->data_count += data_bytes; } dst->entry_count++; //入口位置記錄指針+1. dst->flags &= ~FLAG_SORTED; return OK; //到這裏ANDROID_FLASH_MODE就添加進去了。 }
update更新並創建參數過程:CameraMetadata支持不一樣類型的數據更新或者保存到camera_metadata_t中tag所在的entry當中去,以一個更新單字節的數據爲例,data_count指定了數據的個數,而tag指定了要更新的entry。
status_t CameraMetadata::update(uint32_t tag, const int32_t *data, size_t data_count) { status_t res; if (mLocked) { ALOGE("%s: CameraMetadata is locked", __FUNCTION__); return INVALID_OPERATION; } if ( (res = checkType(tag, TYPE_INT32)) != OK) { return res; } return updateImpl(tag, (const void*)data, data_count); }
首先是經過checkType,主要是經過tag找到get_camera_metadata_tag_type其所應當支持的tag_type(由於具體的TAG是已經經過camera_metadata_tag_info.c源文件中的tag_info這個表指定了其應該具有的tag_type),比較二者是否一致,一致後才容許後續的操做。如這裏須要TYPE_BYTE一致:
const char *get_camera_metadata_tag_name(uint32_t tag) { uint32_t tag_section = tag >> 16; if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) { return vendor_tag_ops->get_tag_name( vendor_tag_ops, tag); } if (tag_section >= ANDROID_SECTION_COUNT || tag >= camera_metadata_section_bounds[tag_section][1] ) { return NULL; } uint32_t tag_index = tag & 0xFFFF;//取tag在section中的index,低16位 return tag_info[tag_section][tag_index].tag_name;//定位section而後再說tag } int get_camera_metadata_tag_type(uint32_t tag) { uint32_t tag_section = tag >> 16; if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) { return vendor_tag_ops->get_tag_type( vendor_tag_ops, tag); } if (tag_section >= ANDROID_SECTION_COUNT || tag >= camera_metadata_section_bounds[tag_section][1] ) { return -1; } uint32_t tag_index = tag & 0xFFFF; return tag_info[tag_section][tag_index].tag_type; }
分別是經過tag取貨section id即tag>>16,就定位到所屬的section tag_info_t[],再經過在在該section中定位tag index通常是tag&0xFFFF的低16位爲在該tag在section中的偏移值,進而找到tag自身的struct tag_info_t.
updataImpl函數主要是講全部要寫入的數據進行update操做:
status_t CameraMetadata::updateImpl(uint32_t tag, const void *data, size_t data_count) { status_t res; if (mLocked) { ALOGE("%s: CameraMetadata is locked", __FUNCTION__); return INVALID_OPERATION; } int type = get_camera_metadata_tag_type(tag); if (type == -1) { ALOGE("%s: Tag %d not found", __FUNCTION__, tag); return BAD_VALUE; } size_t data_size = calculate_camera_metadata_entry_data_size(type, data_count); res = resizeIfNeeded(1, data_size);//新建camera_metadata_t if (res == OK) { camera_metadata_entry_t entry; res = find_camera_metadata_entry(mBuffer, tag, &entry); if (res == NAME_NOT_FOUND) { res = add_camera_metadata_entry(mBuffer, tag, data, data_count);//將當前新的tag以及數據加入到camera_metadata_t } else if (res == OK) { res = update_camera_metadata_entry(mBuffer, entry.index, data, data_count, NULL); } } if (res != OK) { ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)", __FUNCTION__, get_camera_metadata_section_name(tag), get_camera_metadata_tag_name(tag), tag, strerror(-res), res); } IF_ALOGV() { ALOGE_IF(validate_camera_metadata_structure(mBuffer, /*size*/NULL) != OK, "%s: Failed to validate metadata structure after update %p", __FUNCTION__, mBuffer); } return res; }
流程框圖以下:
最終能夠明確的是CameraMetadata相關的參數是被Java層來set/get,但本質是在native層進行了實現,後續若是相關控制參數是被打包到CaptureRequest中時傳入到native時即操做的仍是native中的CameraMetadata。
3、設置AF的工做模式示例
下面以API2中java層中設置AF的工做模式爲例,來講明這個參數設置的過程:
//Java部分代碼
mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); session.setRepeatingRequest(mPreviewBuilder.build(), mSessionCaptureCallback, mHandler);
其中CONTROL_AF_MODE定義在CaptureRequest.java中以下以一個Key的形式存在:
/* @see #CONTROL_AF_MODE_OFF
* @see #CONTROL_AF_MODE_AUTO
* @see #CONTROL_AF_MODE_MACRO
* @see #CONTROL_AF_MODE_CONTINUOUS_VIDEO
* @see #CONTROL_AF_MODE_CONTINUOUS_PICTURE
* @see #CONTROL_AF_MODE_EDOF
*/
public static final Key<Integer> CONTROL_AF_MODE = new Key<Integer>("android.control.afMode", int.class);
public Key(String name, Class<T> type) { mKey = new CameraMetadataNative.Key<T>(name, type); }
在CameraMetadataNative.java中Key的構造:
public Key(String name, Class<T> type) { if (name == null) { throw new NullPointerException("Key needs a valid name"); } else if (type == null) { throw new NullPointerException("Type needs to be non-null"); } mName = name; mType = type; mTypeReference = TypeReference.createSpecializedTypeReference(type); mHash = mName.hashCode() ^ mTypeReference.hashCode(); }
其中CONTROL_AF_MODE_CONTINUOUS_PICTURE定義在CameraMetadata.java中
public static final int CONTROL_AF_MODE_CONTINUOUS_PICTURE = 4;
逐必定位set的入口:
a. mPreviewBuilder是CaptureRequest.java的build類,其會構建一個CaptureRequest:
public Builder(CameraMetadataNative template) { mRequest = new CaptureRequest(template); }
private CaptureRequest() { mSettings = new CameraMetadataNative(); mSurfaceSet = new HashSet<Surface>(); }
mSetting創建的是一個CameraMetadataNative對象,主要用於和Native層進行接口交互,構造以下:
public CameraMetadataNative() { super(); mMetadataPtr = nativeAllocate(); if (mMetadataPtr == 0) { throw new OutOfMemoryError("Failed to allocate native CameraMetadata"); } }
b. CaptureRequest.Build.set()
public <T> void set(Key<T> key, T value) { mRequest.mSettings.set(key, value); }
public <T> void set(CaptureRequest.Key<T> key, T value) { set(key.getNativeKey(), value); }
考慮到CaptureRequest extend CameraMetadata,則CaptureRequest.java中getNativeKey:
public CameraMetadataNative.Key<T> getNativeKey() { return mKey; }
mKey即爲以前構造的CameraMetadataNative.Key:
public <T> void set(Key<T> key, T value) { SetCommand s = sSetCommandMap.get(key); if (s != null) { s.setValue(this, value); return; } setBase(key, value); }
private <T> void setBase(Key<T> key, T value) { int tag = key.getTag(); if (value == null) { // Erase the entry writeValues(tag, /*src*/null); return; } // else update the entry to a new value Marshaler<T> marshaler = getMarshalerForKey(key); int size = marshaler.calculateMarshalSize(value); // TODO: Optimization. Cache the byte[] and reuse if the size is big enough. byte[] values = new byte[size]; ByteBuffer buffer = ByteBuffer.wrap(values).order(ByteOrder.nativeOrder()); marshaler.marshal(value, buffer); writeValues(tag, values); }
首先來看key.getTag()函數的實現,他是將這個key交由Native層後轉爲一個真正的在Java層中的tag值:
public final int getTag() { if (!mHasTag) { mTag = CameraMetadataNative.getTag(mName); mHasTag = true; } return mTag; }
public static int getTag(String key) { return nativeGetTagFromKey(key); }
是將Java層的String交由Native來轉爲一個Java層的tag值。
再來看writeValues的實現,一樣調用的是一個native接口,很好的闡明瞭CameraMetadataNative的意思:
public void writeValues(int tag, byte[] src) { nativeWriteValues(tag, src); }
一樣和開頭native層代碼部分對應起來了。
-end-