--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_METADATA_H
+#define SYSTEM_CORE_INCLUDE_ANDROID_CAMERA_METADATA_H
+
+#include <string.h>
+#include <stdint.h>
+#include <cutils/compiler.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Tag hierarchy and enum definitions for camera_metadata_entry
+ * =============================================================================
+ */
+
+/**
+ * Main enum definitions are in a separate file to make it easy to
+ * maintain
+ */
+#include "camera_metadata_tags.h"
+
+/**
+ * Enum range for each top-level category
+ */
+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];
+
+/**
+ * Type definitions for camera_metadata_entry
+ * =============================================================================
+ */
+enum {
+ // Unsigned 8-bit integer (uint8_t)
+ TYPE_BYTE = 0,
+ // Signed 32-bit integer (int32_t)
+ TYPE_INT32 = 1,
+ // 32-bit float (float)
+ TYPE_FLOAT = 2,
+ // Signed 64-bit integer (int64_t)
+ TYPE_INT64 = 3,
+ // 64-bit float (double)
+ TYPE_DOUBLE = 4,
+ // A 64-bit fraction (camera_metadata_rational_t)
+ TYPE_RATIONAL = 5,
+ // Number of type fields
+ NUM_TYPES
+};
+
+typedef struct camera_metadata_rational {
+ int32_t numerator;
+ int32_t denominator;
+} camera_metadata_rational_t;
+
+/**
+ * Size in bytes of each entry type
+ */
+ANDROID_API
+extern size_t camera_metadata_type_sizes[NUM_TYPES];
+
+/**
+ * Main definitions for the metadata entry and array structures
+ * =============================================================================
+ */
+
+/**
+ * A packet of metadata. This is a list of metadata entries, each of which has
+ * an integer tag to identify its meaning, 'type' and 'count' field, and the
+ * data, which contains a 'count' number of entries of type 'type'. The packet
+ * has a fixed capacity for entries and for extra data. A new entry uses up one
+ * entry slot, and possibly some amount of data capacity; the function
+ * calculate_camera_metadata_entry_data_size() provides the amount of data
+ * capacity that would be used up by an entry.
+ *
+ * Entries are not sorted, and are not forced to be unique - multiple entries
+ * with the same tag are allowed. The packet will not dynamically resize when
+ * full.
+ *
+ * The packet is contiguous in memory, with size in bytes given by
+ * get_camera_metadata_size(). Therefore, it can be copied safely with memcpy()
+ * to a buffer of sufficient size. The copy_camera_metadata() function is
+ * intended for eliminating unused capacity in the destination packet.
+ */
+struct camera_metadata;
+typedef struct camera_metadata camera_metadata_t;
+
+/**
+ * Functions for manipulating camera metadata
+ * =============================================================================
+ */
+
+/**
+ * Allocate a new camera_metadata structure, with some initial space for entries
+ * and extra data. The entry_capacity is measured in entry counts, and
+ * data_capacity in bytes. The resulting structure is all contiguous in memory,
+ * and can be freed with free_camera_metadata().
+ */
+ANDROID_API
+camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
+ size_t data_capacity);
+
+/**
+ * Place a camera metadata structure into an existing buffer. Returns NULL if
+ * the buffer is too small for the requested number of reserved entries and
+ * bytes of data. The entry_capacity is measured in entry counts, and
+ * data_capacity in bytes. If the buffer is larger than the required space,
+ * unused space will be left at the end. If successful, returns a pointer to the
+ * metadata header placed at the start of the buffer. It is the caller's
+ * responsibility to free the original buffer; do not call
+ * free_camera_metadata() with the returned pointer.
+ */
+ANDROID_API
+camera_metadata_t *place_camera_metadata(void *dst, size_t dst_size,
+ size_t entry_capacity,
+ size_t data_capacity);
+
+/**
+ * Free a camera_metadata structure. Should only be used with structures
+ * allocated with allocate_camera_metadata().
+ */
+ANDROID_API
+void free_camera_metadata(camera_metadata_t *metadata);
+
+/**
+ * Calculate the buffer size needed for a metadata structure of entry_count
+ * metadata entries, needing a total of data_count bytes of extra data storage.
+ */
+ANDROID_API
+size_t calculate_camera_metadata_size(size_t entry_count,
+ size_t data_count);
+
+/**
+ * Get current size of entire metadata structure in bytes, including reserved
+ * but unused space.
+ */
+ANDROID_API
+size_t get_camera_metadata_size(const camera_metadata_t *metadata);
+
+/**
+ * Get size of entire metadata buffer in bytes, not including reserved but
+ * unused space. This is the amount of space needed by copy_camera_metadata for
+ * its dst buffer.
+ */
+ANDROID_API
+size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata);
+
+/**
+ * Get the current number of entries in the metadata packet.
+ */
+ANDROID_API
+size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata);
+
+/**
+ * Get the maximum number of entries that could fit in the metadata packet.
+ */
+ANDROID_API
+size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata);
+
+/**
+ * Get the current count of bytes used for value storage in the metadata packet.
+ */
+ANDROID_API
+size_t get_camera_metadata_data_count(const camera_metadata_t *metadata);
+
+/**
+ * Get the maximum count of bytes that could be used for value storage in the
+ * metadata packet.
+ */
+ANDROID_API
+size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata);
+
+/**
+ * Copy a metadata structure to a memory buffer, compacting it along the
+ * way. That is, in the copied structure, entry_count == entry_capacity, and
+ * data_count == data_capacity.
+ *
+ * If dst_size > get_camera_metadata_compact_size(), the unused bytes are at the
+ * end of the buffer. If dst_size < get_camera_metadata_compact_size(), returns
+ * NULL. Otherwise returns a pointer to the metadata structure header placed at
+ * the start of dst.
+ *
+ * Since the buffer was not allocated by allocate_camera_metadata, the caller is
+ * responsible for freeing the underlying buffer when needed; do not call
+ * free_camera_metadata.
+ */
+ANDROID_API
+camera_metadata_t *copy_camera_metadata(void *dst, size_t dst_size,
+ const camera_metadata_t *src);
+
+/**
+ * Append camera metadata in src to an existing metadata structure in dst. This
+ * does not resize the destination structure, so if it is too small, a non-zero
+ * value is returned. On success, 0 is returned.
+ */
+ANDROID_API
+int append_camera_metadata(camera_metadata_t *dst, const camera_metadata_t *src);
+
+/**
+ * Calculate the number of bytes of extra data a given metadata entry will take
+ * up. That is, if entry of 'type' with a payload of 'data_count' values is
+ * added, how much will the value returned by get_camera_metadata_data_count()
+ * be increased? This value may be zero, if no extra data storage is needed.
+ */
+ANDROID_API
+size_t calculate_camera_metadata_entry_data_size(uint8_t type,
+ size_t data_count);
+
+/**
+ * Add a metadata entry to a metadata structure. Returns 0 if the addition
+ * succeeded. Returns a non-zero value if there is insufficient reserved space
+ * left to add the entry, or if the tag is unknown. data_count is the number of
+ * entries in the data array of the tag's type, not a count of
+ * bytes. Vendor-defined tags can not be added using this method, unless
+ * set_vendor_tag_query_ops() has been called first.
+ */
+ANDROID_API
+int add_camera_metadata_entry(camera_metadata_t *dst,
+ uint32_t tag,
+ const void *data,
+ size_t data_count);
+
+/**
+ * Get pointers to the fields for a metadata entry at position index in the
+ * entry array. The data pointer points either to the entry's data.value field
+ * or to the right offset in camera_metadata_t.data. Returns 0 on
+ * success. Data_count is the number of entries in the data array when cast to
+ * the tag's type, not a count of bytes.
+ *
+ * src and index are inputs; tag, type, data, and data_count are outputs.
+ */
+ANDROID_API
+int get_camera_metadata_entry(camera_metadata_t *src,
+ uint32_t index,
+ uint32_t *tag,
+ uint8_t *type,
+ void **data,
+ size_t *data_count);
+
+/**
+ * Retrieve human-readable name of section the tag is in. Returns NULL if
+ * no such tag is defined. Returns NULL for tags in the vendor section, unless
+ * set_vendor_tag_query_ops() has been used.
+ */
+ANDROID_API
+const char *get_camera_metadata_section_name(uint32_t tag);
+
+/**
+ * Retrieve human-readable name of tag (not including section). Returns NULL if
+ * no such tag is defined. Returns NULL for tags in the vendor section, unless
+ * set_vendor_tag_query_ops() has been used.
+ */
+ANDROID_API
+const char *get_camera_metadata_tag_name(uint32_t tag);
+
+/**
+ * Retrieve the type of a tag. Returns -1 if no such tag is defined. Returns -1
+ * for tags in the vendor section, unless set_vendor_tag_query_ops() has been
+ * used.
+ */
+ANDROID_API
+int get_camera_metadata_tag_type(uint32_t tag);
+
+/**
+ * Set up vendor-specific tag query methods. These are needed to properly add
+ * entries with vendor-specified tags and to use the
+ * get_camera_metadata_section_name, _tag_name, and _tag_type methods with
+ * vendor tags. Returns 0 on success.
+ */
+typedef struct vendor_tag_query_ops {
+ /**
+ * Get vendor section name for a vendor-specified entry tag. Only called for
+ * tags >= 0x80000000. The section name must start with the name of the
+ * vendor in the Java package style. For example, CameraZoom inc must prefix
+ * their sections with "com.camerazoom." Must return NULL if the tag is
+ * outside the bounds of vendor-defined sections.
+ */
+ const char *(*get_camera_vendor_section_name)(uint32_t tag);
+ /**
+ * Get tag name for a vendor-specified entry tag. Only called for tags >=
+ * 0x80000000. Must return NULL if the tag is outside the bounds of
+ * vendor-defined sections.
+ */
+ const char *(*get_camera_vendor_tag_name)(uint32_t tag);
+ /**
+ * Get tag type for a vendor-specified entry tag. Only called for tags >=
+ * 0x80000000. Must return -1 if the tag is outside the bounds of
+ * vendor-defined sections.
+ */
+ int (*get_camera_vendor_tag_type)(uint32_t tag);
+} vendor_tag_query_ops_t;
+
+ANDROID_API
+int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops);
+
+/**
+ * Print fields in the metadata to the log.
+ * verbosity = 0: Only tag entry information
+ * verbosity = 1: Tag entry information plus at most 16 data values
+ * verbosity = 2: All information
+ */
+ANDROID_API
+void dump_camera_metadata(const camera_metadata_t *metadata,
+ int verbosity);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * !! Do not include this file directly !!
+ *
+ * Include camera_metadata.h instead.
+ */
+
+/**
+ * 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.
+ */
+enum {
+ ANDROID_REQUEST = 0,
+ ANDROID_LENS,
+ ANDROID_LENS_INFO,
+ ANDROID_SENSOR,
+ ANDROID_SENSOR_INFO,
+ ANDROID_FLASH,
+ ANDROID_FLASH_INFO,
+ ANDROID_HOT_PIXEL,
+ ANDROID_HOT_PIXEL_INFO,
+ ANDROID_DEMOSAIC,
+ ANDROID_DEMOSAIC_INFO,
+ ANDROID_NOISE,
+ ANDROID_NOISE_INFO,
+ ANDROID_SHADING,
+ ANDROID_SHADING_INFO,
+ ANDROID_GEOMETRIC,
+ ANDROID_GEOMETRIC_INFO,
+ ANDROID_COLOR,
+ ANDROID_COLOR_INFO,
+ ANDROID_TONEMAP,
+ ANDROID_TONEMAP_INFO,
+ ANDROID_EDGE,
+ ANDROID_EDGE_INFO,
+ ANDROID_SCALER,
+ ANDROID_SCALER_INFO,
+ ANDROID_JPEG,
+ ANDROID_JPEG_INFO,
+ ANDROID_STATS,
+ ANDROID_STATS_INFO,
+ ANDROID_CONTROL,
+ ANDROID_CONTROL_INFO,
+ ANDROID_SECTION_COUNT,
+
+ VENDOR_SECTION = 0x8000
+};
+
+/**
+ * Hierarchy positions in enum space. All vendor extension tags must be
+ * defined with tag >= VENDOR_SECTION_START
+ */
+enum {
+ ANDROID_REQUEST_START = ANDROID_REQUEST << 16,
+ ANDROID_LENS_START = ANDROID_LENS << 16,
+ ANDROID_LENS_INFO_START = ANDROID_LENS_INFO << 16,
+ ANDROID_SENSOR_START = ANDROID_SENSOR << 16,
+ ANDROID_SENSOR_INFO_START = ANDROID_SENSOR_INFO << 16,
+ ANDROID_FLASH_START = ANDROID_FLASH << 16,
+ ANDROID_FLASH_INFO_START = ANDROID_FLASH_INFO << 16,
+ ANDROID_HOT_PIXEL_START = ANDROID_HOT_PIXEL << 16,
+ ANDROID_HOT_PIXEL_INFO_START = ANDROID_HOT_PIXEL_INFO << 16,
+ ANDROID_DEMOSAIC_START = ANDROID_DEMOSAIC << 16,
+ ANDROID_DEMOSAIC_INFO_START = ANDROID_DEMOSAIC_INFO << 16,
+ ANDROID_NOISE_START = ANDROID_NOISE << 16,
+ ANDROID_NOISE_INFO_START = ANDROID_NOISE_INFO << 16,
+ ANDROID_SHADING_START = ANDROID_SHADING << 16,
+ ANDROID_SHADING_INFO_START = ANDROID_SHADING_INFO << 16,
+ ANDROID_GEOMETRIC_START = ANDROID_GEOMETRIC << 16,
+ ANDROID_GEOMETRIC_INFO_START = ANDROID_GEOMETRIC_INFO << 16,
+ ANDROID_COLOR_START = ANDROID_COLOR << 16,
+ ANDROID_COLOR_INFO_START = ANDROID_COLOR_INFO << 16,
+ ANDROID_TONEMAP_START = ANDROID_TONEMAP << 16,
+ ANDROID_TONEMAP_INFO_START = ANDROID_TONEMAP_INFO << 16,
+ ANDROID_EDGE_START = ANDROID_EDGE << 16,
+ ANDROID_EDGE_INFO_START = ANDROID_EDGE_INFO << 16,
+ ANDROID_SCALER_START = ANDROID_SCALER << 16,
+ ANDROID_SCALER_INFO_START = ANDROID_SCALER_INFO << 16,
+ ANDROID_JPEG_START = ANDROID_JPEG << 16,
+ ANDROID_JPEG_INFO_START = ANDROID_JPEG_INFO << 16,
+ ANDROID_STATS_START = ANDROID_STATS << 16,
+ ANDROID_STATS_INFO_START = ANDROID_STATS_INFO << 16,
+ ANDROID_CONTROL_START = ANDROID_CONTROL << 16,
+ ANDROID_CONTROL_INFO_START = ANDROID_CONTROL_INFO << 16,
+ VENDOR_SECTION_START = VENDOR_SECTION << 16
+};
+
+/**
+ * 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
+ */
+enum {
+ ANDROID_REQUEST_ID = ANDROID_REQUEST_START,
+ ANDROID_REQUEST_METADATA_MODE,
+ ANDROID_REQUEST_OUTPUT_STREAMS,
+ ANDROID_REQUEST_FRAME_COUNT,
+ ANDROID_REQUEST_END,
+
+ ANDROID_LENS_FOCUS_DISTANCE = ANDROID_LENS_START,
+ ANDROID_LENS_APERTURE,
+ ANDROID_LENS_FOCAL_LENGTH,
+ ANDROID_LENS_FILTER_DENSITY,
+ ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
+ ANDROID_LENS_FOCUS_RANGE,
+ ANDROID_LENS_END,
+
+ ANDROID_LENS_MINIMUM_FOCUS_DISTANCE = ANDROID_LENS_INFO_START,
+ ANDROID_LENS_AVAILABLE_FOCAL_LENGTHS,
+ ANDROID_LENS_AVAILABLE_APERTURES,
+ ANDROID_LENS_AVAILABLE_FILTER_DENSITY,
+ ANDROID_LENS_AVAILABLE_OPTICAL_STABILIZATION,
+ ANDROID_LENS_SHADING_MAP,
+ ANDROID_LENS_GEOMETRIC_CORRECTION_MAP,
+ ANDROID_LENS_FACING,
+ ANDROID_LENS_POSITION,
+ ANDROID_LENS_INFO_END,
+
+ ANDROID_SENSOR_EXPOSURE_TIME = ANDROID_SENSOR_START,
+ ANDROID_SENSOR_FRAME_DURATION,
+ ANDROID_SENSOR_SENSITIVITY,
+ ANDROID_SENSOR_TIMESTAMP,
+ ANDROID_SENSOR_END,
+
+ ANDROID_SENSOR_EXPOSURE_TIME_RANGE = ANDROID_SENSOR_INFO_START,
+ ANDROID_SENSOR_MAX_FRAME_DURATION,
+ ANDROID_SENSOR_SENSITIVITY_RANGE,
+ ANDROID_SENSOR_COLOR_FILTER_ARRANGEMENT,
+ ANDROID_SENSOR_PIXEL_ARRAY_SIZE,
+ ANDROID_SENSOR_ACTIVE_ARRAY_SIZE,
+ ANDROID_SENSOR_WHITE_LEVEL,
+ ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
+ ANDROID_SENSOR_COLOR_TRANSFORM_1,
+ ANDROID_SENSOR_COLOR_TRANSFORM_2,
+ ANDROID_SENSOR_REFERENCE_ILLUMINANT_1,
+ ANDROID_SENSOR_REFERENCE_ILLUMINANT_2,
+ ANDROID_SENSOR_FORWARD_MATRIX_1,
+ ANDROID_SENSOR_FORWARD_MATRIX_2,
+ ANDROID_SENSOR_CALIBRATION_TRANSFORM_1,
+ ANDROID_SENSOR_CALIBRATION_TRANSFORM_2,
+ ANDROID_SENSOR_BASE_GAIN_FACTOR,
+ ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
+ ANDROID_SENSOR_NOISE_MODEL_COEFFICIENTS,
+ ANDROID_SENSOR_ORIENTATION,
+ ANDROID_SENSOR_INFO_END,
+
+ ANDROID_FLASH_MODE = ANDROID_FLASH_START,
+ ANDROID_FLASH_FIRING_POWER,
+ ANDROID_FLASH_FIRING_TIME,
+ ANDROID_FLASH_END,
+
+ ANDROID_FLASH_AVAILABLE_MODES = ANDROID_FLASH_INFO_START,
+ ANDROID_FLASH_CHARGE_DURATION,
+ ANDROID_FLASH_INFO_END,
+
+ ANDROID_HOT_PIXEL_MODE = ANDROID_HOT_PIXEL_START,
+ ANDROID_HOT_PIXEL_END,
+
+ ANDROID_HOT_PIXEL_INFO_END = ANDROID_HOT_PIXEL_INFO_START,
+
+ ANDROID_DEMOSAIC_MODE = ANDROID_DEMOSAIC_START,
+ ANDROID_DEMOSAIC_END,
+
+ ANDROID_DEMOSAIC_INFO_END = ANDROID_DEMOSAIC_INFO_START,
+
+ ANDROID_NOISE_MODE = ANDROID_NOISE_START,
+ ANDROID_NOISE_STRENGTH,
+ ANDROID_NOISE_END,
+
+ ANDROID_NOISE_INFO_END = ANDROID_NOISE_INFO_START,
+
+ ANDROID_SHADING_MODE = ANDROID_SHADING_START,
+ ANDROID_SHADING_END,
+
+ ANDROID_SHADING_INFO_END = ANDROID_SHADING_INFO_START,
+
+ ANDROID_GEOMETRIC_MODE = ANDROID_GEOMETRIC_START,
+ ANDROID_GEOMETRIC_END,
+
+ ANDROID_GEOMETRIC_INFO_END = ANDROID_GEOMETRIC_INFO_START,
+
+ ANDROID_COLOR_MODE = ANDROID_COLOR_START,
+ ANDROID_COLOR_TRANSFORM,
+ ANDROID_COLOR_END,
+
+ ANDROID_COLOR_AVAILABLE_MODES = ANDROID_COLOR_INFO_START,
+ ANDROID_COLOR_INFO_END,
+
+ ANDROID_TONEMAP_MODE = ANDROID_TONEMAP_START,
+ ANDROID_TONEMAP_CURVE_RED,
+ ANDROID_TONEMAP_CURVE_GREEN,
+ ANDROID_TONEMAP_CURVE_BLUE,
+ ANDROID_TONEMAP_END,
+
+ ANDROID_TONEMAP_MAX_CURVE_POINTS = ANDROID_TONEMAP_INFO_START,
+ ANDROID_TONEMAP_INFO_END,
+
+ ANDROID_EDGE_MODE = ANDROID_EDGE_START,
+ ANDROID_EDGE_STRENGTH,
+ ANDROID_EDGE_END,
+
+ ANDROID_EDGE_INFO_END = ANDROID_EDGE_INFO_START,
+
+ ANDROID_SCALER_SIZE = ANDROID_SCALER_START,
+ ANDROID_SCALER_FORMAT,
+ ANDROID_SCALER_CROP_REGION,
+ ANDROID_SCALER_ROTATION,
+ ANDROID_SCALER_END,
+
+ ANDROID_SCALER_AVAILABLE_FORMATS = ANDROID_SCALER_INFO_START,
+ ANDROID_SCALER_AVAILABLE_SIZES_PER_FORMAT,
+ ANDROID_SCALER_AVAILABLE_SIZES,
+ ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
+ ANDROID_SCALER_AVAILABLE_MAX_ZOOM,
+ ANDROID_SCALER_INFO_END,
+
+ ANDROID_JPEG_QUALITY = ANDROID_JPEG_START,
+ ANDROID_JPEG_THUMBNAIL_SIZE,
+ ANDROID_JPEG_THUMBNAIL_QUALITY,
+ ANDROID_JPEG_GPS_COORDINATES,
+ ANDROID_JPEG_GPS_PROCESSING_METHOD,
+ ANDROID_JPEG_GPS_TIMESTAMP,
+ ANDROID_JPEG_ORIENTATION,
+ ANDROID_JPEG_END,
+
+ ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES = ANDROID_JPEG_INFO_START,
+ ANDROID_JPEG_INFO_END,
+
+ ANDROID_STATS_FACE_DETECT_MODE = ANDROID_STATS_START,
+ ANDROID_STATS_HISTOGRAM_MODE,
+ ANDROID_STATS_SHARPNESS_MAP_MODE,
+ ANDROID_STATS_FACE_RECTANGLES,
+ ANDROID_STATS_FACE_SCORES,
+ ANDROID_STATS_FACE_LANDMARKS,
+ ANDROID_STATS_FACE_IDS,
+ ANDROID_STATS_HISTOGRAM,
+ ANDROID_STATS_SHARPNESS_MAP,
+ ANDROID_STATS_END,
+
+ ANDROID_STATS_AVAILABLE_FACE_DETECT_MODES = ANDROID_STATS_INFO_START,
+ ANDROID_STATS_MAX_FACE_COUNT,
+ ANDROID_STATS_HISTOGRAM_BUCKET_COUNT,
+ ANDROID_STATS_MAX_HISTOGRAM_COUNT,
+ ANDROID_STATS_SHARPNESS_MAP_SIZE,
+ ANDROID_STATS_MAX_SHARPNESS_MAP_VALUE,
+ ANDROID_STATS_INFO_END,
+
+ ANDROID_CONTROL_MODE = ANDROID_CONTROL_START,
+ ANDROID_CONTROL_AE_MODE,
+ ANDROID_CONTROL_AE_REGIONS,
+ ANDROID_CONTROL_AE_EXP_COMPENSATION,
+ ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
+ ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+ ANDROID_CONTROL_AWB_MODE,
+ ANDROID_CONTROL_AWB_REGIONS,
+ ANDROID_CONTROL_AF_MODE,
+ ANDROID_CONTROL_AF_REGIONS,
+ ANDROID_CONTROL_AF_TRIGGER,
+ ANDROID_CONTROL_AF_STATE,
+ ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+ ANDROID_CONTROL_END,
+
+ ANDROID_CONTROL_AVAILABLE_MODES = ANDROID_CONTROL_INFO_START,
+ ANDROID_CONTROL_MAX_REGIONS,
+ ANDROID_CONTROL_AE_AVAILABLE_MODES,
+ ANDROID_CONTROL_AE_EXP_COMPENSATION_STEP,
+ ANDROID_CONTROL_AE_EXP_COMPENSATION_RANGE,
+ ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
+ ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
+ ANDROID_CONTROL_AWB_AVAILABLE_MODES,
+ ANDROID_CONTROL_AF_AVAILABLE_MODES,
+ ANDROID_CONTROL_INFO_END
+};
--- /dev/null
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ camera_metadata.c
+
+LOCAL_C_INCLUDES:= \
+ system/media/camera/include
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils
+
+LOCAL_MODULE := libcamera_metadata
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS += \
+ -Wall \
+ -fvisibility=hidden \
+
+
+include $(BUILD_SHARED_LIBRARY)
+
+
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <system/camera_metadata.h>
+#include <cutils/log.h>
+
+#define OK 0
+#define ERROR 1
+
+/**
+ * A single metadata entry, storing an array of values of a given type. If the
+ * array is no larger than 4 bytes in size, it is stored in the data.value[]
+ * array; otherwise, it can found in the parent's data array at index
+ * data.offset.
+ */
+typedef struct camera_metadata_entry {
+ uint32_t tag;
+ size_t count;
+ union {
+ size_t offset;
+ uint8_t value[4];
+ } data;
+ uint8_t type;
+ uint8_t reserved[3];
+} __attribute__((packed)) camera_metadata_entry_t;
+
+/**
+ * A packet of metadata. This is a list of entries, each of which may point to
+ * its values stored at an offset in data.
+ *
+ * It is assumed by the utility functions that the memory layout of the packet
+ * is as follows:
+ *
+ * |----------------------------------------|
+ * | camera_metadata_t |
+ * | |
+ * |----------------------------------------|
+ * | reserved for future expansion |
+ * |----------------------------------------|
+ * | camera_metadata_entry_t #0 |
+ * |----------------------------------------|
+ * | .... |
+ * |----------------------------------------|
+ * | camera_metadata_entry_t #entry_count-1 |
+ * |----------------------------------------|
+ * | free space for |
+ * | (entry_capacity-entry_count) entries |
+ * |----------------------------------------|
+ * | start of camera_metadata.data |
+ * | |
+ * |----------------------------------------|
+ * | free space for |
+ * | (data_capacity-data_count) bytes |
+ * |----------------------------------------|
+ *
+ * With the total length of the whole packet being camera_metadata.size bytes.
+ *
+ * In short, the entries and data are contiguous in memory after the metadata
+ * header.
+ */
+struct camera_metadata {
+ size_t size;
+ size_t entry_count;
+ size_t entry_capacity;
+ camera_metadata_entry_t *entries;
+ size_t data_count;
+ size_t data_capacity;
+ uint8_t *data;
+ uint8_t reserved[0];
+};
+
+typedef struct tag_info {
+ const char *tag_name;
+ uint8_t tag_type;
+} tag_info_t;
+
+#include "camera_metadata_tag_info.c"
+
+size_t camera_metadata_type_size[NUM_TYPES] = {
+ [TYPE_BYTE] = sizeof(uint8_t),
+ [TYPE_INT32] = sizeof(int32_t),
+ [TYPE_FLOAT] = sizeof(float),
+ [TYPE_INT64] = sizeof(int64_t),
+ [TYPE_DOUBLE] = sizeof(double),
+ [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
+};
+
+char *camera_metadata_type_names[NUM_TYPES] = {
+ [TYPE_BYTE] = "byte",
+ [TYPE_INT32] = "int32",
+ [TYPE_FLOAT] = "float",
+ [TYPE_INT64] = "int64",
+ [TYPE_RATIONAL] = "rational"
+};
+
+camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
+ size_t data_capacity) {
+ size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
+ data_capacity);
+ void *buffer = malloc(memory_needed);
+ 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->entry_count = 0;
+ metadata->entry_capacity = entry_capacity;
+ metadata->entries = (camera_metadata_entry_t*)(metadata + 1);
+ metadata->data_count = 0;
+ metadata->data_capacity = data_capacity;
+ metadata->size = memory_needed;
+ if (metadata->data_capacity != 0) {
+ metadata->data =
+ (uint8_t*)(metadata->entries + metadata->entry_capacity);
+ } else {
+ metadata->data = NULL;
+ }
+
+ return metadata;
+}
+void free_camera_metadata(camera_metadata_t *metadata) {
+ free(metadata);
+}
+
+size_t calculate_camera_metadata_size(size_t entry_count,
+ size_t data_count) {
+ size_t memory_needed = sizeof(camera_metadata_t);
+ memory_needed += sizeof(camera_metadata_entry_t[entry_count]);
+ memory_needed += sizeof(uint8_t[data_count]);
+ return memory_needed;
+}
+
+size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
+ if (metadata == NULL) return ERROR;
+
+ return metadata->size;
+}
+
+size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
+ if (metadata == NULL) return ERROR;
+
+ ptrdiff_t reserved_size = metadata->size -
+ calculate_camera_metadata_size(metadata->entry_capacity,
+ metadata->data_capacity);
+
+ return calculate_camera_metadata_size(metadata->entry_count,
+ metadata->data_count) + reserved_size;
+}
+
+size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
+ return metadata->entry_count;
+}
+
+size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
+ return metadata->entry_capacity;
+}
+
+size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
+ return metadata->data_count;
+}
+
+size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
+ return metadata->data_capacity;
+}
+
+camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
+ const camera_metadata_t *src) {
+ size_t memory_needed = get_camera_metadata_compact_size(src);
+
+ if (dst == NULL) return NULL;
+ if (dst_size < memory_needed) return NULL;
+
+ // If copying a newer version of the structure, there may be additional
+ // header fields we don't know about but need to copy
+ ptrdiff_t reserved_size = src->size -
+ calculate_camera_metadata_size(src->entry_capacity,
+ src->data_capacity);
+
+ camera_metadata_t *metadata = (camera_metadata_t*)dst;
+ metadata->entry_count = src->entry_count;
+ metadata->entry_capacity = src->entry_count;
+ metadata->entries = (camera_metadata_entry_t*)
+ ((uint8_t *)(metadata + 1) + reserved_size);
+ metadata->data_count = src->data_count;
+ metadata->data_capacity = src->data_count;
+ metadata->data = (uint8_t *)(metadata->entries + metadata->entry_capacity);
+ metadata->size = memory_needed;
+
+ if (reserved_size > 0) {
+ memcpy(metadata->reserved, src->reserved, reserved_size);
+ }
+ memcpy(metadata->entries, src->entries,
+ sizeof(camera_metadata_entry_t[metadata->entry_count]));
+ memcpy(metadata->data, src->data,
+ sizeof(uint8_t[metadata->data_count]));
+
+ return metadata;
+}
+
+int append_camera_metadata(camera_metadata_t *dst,
+ const camera_metadata_t *src) {
+ if (dst == NULL || src == NULL ) return ERROR;
+
+ if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
+ if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
+
+ memcpy(dst->entries + dst->entry_count, src->entries,
+ sizeof(camera_metadata_entry_t[src->entry_count]));
+ memcpy(dst->data + dst->data_count, src->data,
+ sizeof(uint8_t[src->data_count]));
+ if (dst->data_count != 0) {
+ unsigned int i;
+ for (i = dst->entry_count;
+ i < dst->entry_count + src->entry_count;
+ i++) {
+ camera_metadata_entry_t *entry = dst->entries + i;
+ if ( camera_metadata_type_size[entry->type] * entry->count > 4 ) {
+ entry->data.offset += dst->data_count;
+ }
+ }
+ }
+ dst->entry_count += src->entry_count;
+ dst->data_count += src->data_count;
+
+ return OK;
+}
+
+size_t calculate_camera_metadata_entry_data_size(uint8_t type,
+ size_t data_count) {
+ if (type >= NUM_TYPES) return 0;
+ size_t data_bytes = data_count *
+ camera_metadata_type_size[type];
+ return data_bytes <= 4 ? 0 : data_bytes;
+}
+
+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);
+
+ camera_metadata_entry_t *entry = dst->entries + dst->entry_count;
+ entry->tag = tag;
+ entry->type = type;
+ entry->count = data_count;
+
+ if (data_bytes == 0) {
+ memcpy(entry->data.value, data,
+ data_count * camera_metadata_type_size[type] );
+ } else {
+ entry->data.offset = dst->data_count;
+ memcpy(dst->data + entry->data.offset, data, data_bytes);
+ dst->data_count += data_bytes;
+ }
+ dst->entry_count++;
+ return OK;
+}
+
+int add_camera_metadata_entry(camera_metadata_t *dst,
+ uint32_t tag,
+ const void *data,
+ size_t data_count) {
+
+ int type = get_camera_metadata_tag_type(tag);
+ if (type == -1) {
+ ALOGE("Unknown tag %04x (can't find type)", tag);
+ return ERROR;
+ }
+
+ return add_camera_metadata_entry_raw(dst,
+ tag,
+ type,
+ data,
+ data_count);
+}
+
+int get_camera_metadata_entry(camera_metadata_t *src,
+ uint32_t index,
+ uint32_t *tag,
+ uint8_t *type,
+ void **data,
+ size_t *data_count) {
+ if (src == NULL ) return ERROR;
+ if (tag == NULL) return ERROR;
+ if (type == NULL ) return ERROR;
+ if (data == NULL) return ERROR;
+ if (data_count == NULL) return ERROR;
+
+ if (index >= src->entry_count) return ERROR;
+
+ camera_metadata_entry_t *entry = src->entries + index;
+
+ *tag = entry->tag;
+ *type = entry->type;
+ *data_count = entry->count;
+ if (entry->count * camera_metadata_type_size[entry->type] > 4) {
+ *data = src->data + entry->data.offset;
+ } else {
+ *data = entry->data.value;
+ }
+ return OK;
+}
+
+static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
+
+const char *get_camera_metadata_section_name(uint32_t tag) {
+ uint32_t tag_section = tag >> 16;
+ if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
+ return vendor_tag_ops->get_camera_vendor_section_name(tag);
+ }
+ if (tag_section >= ANDROID_SECTION_COUNT) {
+ return NULL;
+ }
+ return camera_metadata_section_names[tag_section];
+}
+
+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_camera_vendor_tag_name(tag);
+ }
+ if (tag_section >= ANDROID_SECTION_COUNT ||
+ tag >= camera_metadata_section_bounds[tag_section][1] ) {
+ return NULL;
+ }
+ uint32_t tag_index = tag & 0xFFFF;
+ return tag_info[tag_section][tag_index].tag_name;
+}
+
+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_camera_vendor_tag_type(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;
+}
+
+int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
+ vendor_tag_ops = query_ops;
+ return OK;
+}
+
+void print_data(const uint8_t *data_ptr, int type, int count);
+
+void dump_camera_metadata(const camera_metadata_t *metadata, int verbosity) {
+ if (metadata == NULL) {
+ ALOGE("Metadata is null.");
+ return;
+ }
+ unsigned int i;
+ ALOGD("Dumping camera metadata array. %d entries, %d bytes of extra data.",
+ metadata->entry_count, metadata->data_count);
+ ALOGD(" (%d entries and %d bytes data reserved)",
+ metadata->entry_capacity, metadata->data_capacity);
+ for (i=0; i < metadata->entry_count; i++) {
+ camera_metadata_entry_t *entry = metadata->entries + i;
+
+ const char *tag_name, *tag_section;
+ tag_section = get_camera_metadata_section_name(entry->tag);
+ if (tag_section == NULL) {
+ tag_section = "unknownSection";
+ }
+ tag_name = get_camera_metadata_tag_name(entry->tag);
+ if (tag_name == NULL) {
+ tag_name = "unknownTag";
+ }
+ const char *type_name;
+ if (entry->type >= NUM_TYPES) {
+ type_name = "unknown";
+ } else {
+ type_name = camera_metadata_type_names[entry->type];
+ }
+ ALOGD("Tag: %s.%s (%05x): %s[%d]",
+ tag_section,
+ tag_name,
+ entry->tag,
+ type_name,
+ entry->count);
+
+ if (verbosity < 1) continue;
+
+ if (entry->type >= NUM_TYPES) continue;
+
+ size_t type_size = camera_metadata_type_size[entry->type];
+ uint8_t *data_ptr;
+ if ( type_size * entry->count > 4 ) {
+ if (entry->data.offset >= metadata->data_count) {
+ ALOGE("Malformed entry data offset: %d (max %d)",
+ entry->data.offset,
+ metadata->data_count);
+ continue;
+ }
+ data_ptr = metadata->data + entry->data.offset;
+ } else {
+ data_ptr = entry->data.value;
+ }
+ int count = entry->count;
+ if (verbosity < 2 && count > 16) count = 16;
+
+ print_data(data_ptr, entry->type, count);
+ }
+}
+
+void print_data(const uint8_t *data_ptr, int type, int count) {
+ static int values_per_line[NUM_TYPES] = {
+ [TYPE_BYTE] = 16,
+ [TYPE_INT32] = 4,
+ [TYPE_FLOAT] = 8,
+ [TYPE_INT64] = 2,
+ [TYPE_DOUBLE] = 4,
+ [TYPE_RATIONAL] = 2,
+ };
+ size_t type_size = camera_metadata_type_size[type];
+
+ int lines = count / values_per_line[type];
+ if (count % values_per_line[type] != 0) lines++;
+
+ char tmp1[80], tmp2[80];
+
+ int index = 0;
+ int j, k;
+ for (j = 0; j < lines; j++) {
+ tmp1[0] = 0;
+ for (k = 0;
+ k < values_per_line[type] && count > 0;
+ k++, count--, index += type_size) {
+
+ switch (type) {
+ case TYPE_BYTE:
+ snprintf(tmp2, sizeof(tmp2), "%hhu ",
+ *(data_ptr + index));
+ break;
+ case TYPE_INT32:
+ snprintf(tmp2, sizeof(tmp2), "%d ",
+ *(int32_t*)(data_ptr + index));
+ break;
+ case TYPE_FLOAT:
+ snprintf(tmp2, sizeof(tmp2), "%0.2f ",
+ *(float*)(data_ptr + index));
+ break;
+ case TYPE_INT64:
+ snprintf(tmp2, sizeof(tmp2), "%lld ",
+ *(int64_t*)(data_ptr + index));
+ break;
+ case TYPE_DOUBLE:
+ snprintf(tmp2, sizeof(tmp2), "%0.2f ",
+ *(float*)(data_ptr + index));
+ break;
+ case TYPE_RATIONAL: {
+ int32_t numerator = *(int32_t*)(data_ptr + index);
+ int32_t denominator = *(int32_t*)(data_ptr + index + 4);
+ snprintf(tmp2, sizeof(tmp2), "(%d / %d) ",
+ numerator, denominator);
+ break;
+ }
+ default:
+ snprintf(tmp2, sizeof(tmp2), "??? ");
+ }
+ strncat(tmp1, tmp2, sizeof(tmp1));
+ }
+ ALOGD(" [ %s]", tmp1);
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * !! Do not reference this file directly !!
+ *
+ * It is logically a part of camera_metadata.c. It is broken out for ease of
+ * maintaining the tag info.
+ */
+
+const char *camera_metadata_section_names[ANDROID_SECTION_COUNT] = {
+ "android.request",
+ "android.control",
+ "android.control.info",
+ "android.sensor",
+ "android.sensor.info",
+ "android.lens",
+ "android.lens.info",
+ "android.flash",
+ "android.flash.info",
+ "android.hotPixel",
+ "android.hotPixel.info",
+ "android.demosaic",
+ "android.demosaic.info",
+ "android.noiseReduction",
+ "android.noiseReduction.info",
+ "android.shadingCorrection",
+ "android.shadingCorrection.info",
+ "android.geometricCorrection",
+ "android.geometricCorrection.info",
+ "android.colorCorrection",
+ "android.colorCorrection.info",
+ "android.tonemap",
+ "android.tonemap.info",
+ "android.edge",
+ "android.edge.info",
+ "android.scaler",
+ "android.scaler.info",
+ "android.jpeg",
+ "android.jpeg.info",
+ "android.statistics",
+ "android.statistics.info"
+};
+
+unsigned int camera_metadata_section_bounds[ANDROID_SECTION_COUNT][2] = {
+ { ANDROID_REQUEST_START, ANDROID_REQUEST_END },
+ { ANDROID_LENS_START, ANDROID_LENS_END },
+ { ANDROID_LENS_INFO_START, ANDROID_LENS_INFO_END },
+ { ANDROID_SENSOR_START, ANDROID_SENSOR_END },
+ { ANDROID_SENSOR_INFO_START, ANDROID_SENSOR_INFO_END },
+ { ANDROID_FLASH_START, ANDROID_FLASH_END },
+ { ANDROID_FLASH_INFO_START, ANDROID_FLASH_INFO_END },
+ { ANDROID_HOT_PIXEL_START, ANDROID_HOT_PIXEL_END },
+ { ANDROID_HOT_PIXEL_INFO_START, ANDROID_HOT_PIXEL_INFO_END },
+ { ANDROID_DEMOSAIC_START, ANDROID_DEMOSAIC_END },
+ { ANDROID_DEMOSAIC_INFO_START, ANDROID_DEMOSAIC_INFO_END },
+ { ANDROID_NOISE_START, ANDROID_NOISE_END },
+ { ANDROID_NOISE_INFO_START, ANDROID_NOISE_INFO_END },
+ { ANDROID_SHADING_START, ANDROID_SHADING_END },
+ { ANDROID_SHADING_INFO_START, ANDROID_SHADING_INFO_END },
+ { ANDROID_GEOMETRIC_START, ANDROID_GEOMETRIC_END },
+ { ANDROID_GEOMETRIC_INFO_START, ANDROID_GEOMETRIC_INFO_END },
+ { ANDROID_COLOR_START, ANDROID_COLOR_END },
+ { ANDROID_COLOR_INFO_START, ANDROID_COLOR_INFO_END },
+ { ANDROID_TONEMAP_START, ANDROID_TONEMAP_END },
+ { ANDROID_TONEMAP_INFO_START, ANDROID_TONEMAP_INFO_END },
+ { ANDROID_EDGE_START, ANDROID_EDGE_END },
+ { ANDROID_EDGE_INFO_START, ANDROID_EDGE_INFO_END },
+ { ANDROID_SCALER_START, ANDROID_SCALER_END },
+ { ANDROID_SCALER_INFO_START, ANDROID_SCALER_INFO_END },
+ { ANDROID_JPEG_START, ANDROID_JPEG_END },
+ { ANDROID_JPEG_INFO_START, ANDROID_JPEG_INFO_END },
+ { ANDROID_STATS_START, ANDROID_STATS_END },
+ { ANDROID_STATS_INFO_START, ANDROID_STATS_INFO_END },
+ { ANDROID_CONTROL_START, ANDROID_CONTROL_END },
+ { ANDROID_CONTROL_INFO_START, ANDROID_CONTROL_INFO_END }
+};
+
+tag_info_t android_request[ANDROID_REQUEST_END -
+ ANDROID_REQUEST_START] = {
+ { "id", TYPE_INT32 },
+ { "metadataMode", TYPE_BYTE },
+ { "outputStreams", TYPE_BYTE },
+ { "frameCount", TYPE_INT32 }
+};
+
+tag_info_t android_control[ANDROID_CONTROL_END -
+ ANDROID_CONTROL_START] = {
+ { "mode", TYPE_BYTE },
+ { "aeMode", TYPE_BYTE },
+ { "aeRegions", TYPE_INT32 },
+ { "aeExposureCompensation", TYPE_INT32 },
+ { "aeTargetFpsRange", TYPE_INT32 },
+ { "aeAntibandingMode", TYPE_BYTE },
+ { "awbMode", TYPE_BYTE },
+ { "awbRegions", TYPE_INT32 },
+ { "afMode", TYPE_BYTE },
+ { "afRegions", TYPE_INT32 },
+ { "afTrigger", TYPE_BYTE },
+ { "afState", TYPE_BYTE },
+ { "videoStabilizationMode", TYPE_BYTE }
+};
+
+tag_info_t android_control_info[ANDROID_CONTROL_INFO_END -
+ ANDROID_CONTROL_INFO_START] = {
+ { "availableModes", TYPE_BYTE },
+ { "maxRegions", TYPE_INT32 },
+ { "aeAvailableModes", TYPE_BYTE },
+ { "aeCompensationStep", TYPE_RATIONAL },
+ { "aeCompensationRange", TYPE_INT32 },
+ { "aeAvailableTargetFpsRanges", TYPE_INT32 },
+ { "aeAvailableAntibandingModes", TYPE_BYTE },
+ { "awbAvailableModes", TYPE_BYTE },
+ { "afAvailableModes", TYPE_BYTE }
+};
+
+tag_info_t android_sensor[ANDROID_SENSOR_END -
+ ANDROID_SENSOR_START] = {
+ { "exposureTime", TYPE_INT64 },
+ { "frameDuration", TYPE_INT64 },
+ { "sensitivity", TYPE_INT32 },
+ { "timestamp", TYPE_INT64 }
+};
+
+tag_info_t android_sensor_info[ANDROID_SENSOR_INFO_END -
+ ANDROID_SENSOR_INFO_START] = {
+ { "exposureTimeRange", TYPE_INT64 },
+ { "maxFrameDuration", TYPE_INT64 },
+ { "sensitivityRange", TYPE_INT32 },
+ { "colorFilterArrangement", TYPE_BYTE },
+ { "pixelArraySize", TYPE_INT32 },
+ { "activeArraySize", TYPE_INT32 },
+ { "whiteLevel", TYPE_INT32 },
+ { "blackLevelPattern", TYPE_INT32 },
+ { "colorTransform1", TYPE_RATIONAL },
+ { "colorTransform2", TYPE_RATIONAL },
+ { "referenceIlluminant1", TYPE_BYTE },
+ { "referenceIlluminant2", TYPE_BYTE },
+ { "forwardMatrix1", TYPE_RATIONAL },
+ { "forwardMatrix2", TYPE_RATIONAL },
+ { "calibrationTransform1", TYPE_RATIONAL },
+ { "calibrationTransform2", TYPE_RATIONAL },
+ { "baseGainFactor", TYPE_RATIONAL },
+ { "maxAnalogSensitivity", TYPE_INT32 },
+ { "noiseModelCoefficients", TYPE_FLOAT },
+ { "orientation", TYPE_INT32 }
+};
+
+tag_info_t android_lens[ANDROID_LENS_END -
+ ANDROID_LENS_START] = {
+ { "focusDistance", TYPE_FLOAT },
+ { "aperture", TYPE_FLOAT },
+ { "focalLength", TYPE_FLOAT },
+ { "filterDensity", TYPE_FLOAT },
+ { "opticalStabilizationMode", TYPE_BYTE },
+ { "focusRange", TYPE_FLOAT }
+};
+
+tag_info_t android_lens_info[ANDROID_LENS_INFO_END -
+ ANDROID_LENS_INFO_START] = {
+ { "minimumFocusDistance", TYPE_FLOAT },
+ { "availableFocalLengths", TYPE_FLOAT },
+ { "availableApertures", TYPE_FLOAT },
+ { "availableFilterDensities", TYPE_FLOAT },
+ { "availableOpticalStabilizationModes", TYPE_BYTE },
+ { "shadingMap", TYPE_FLOAT },
+ { "geometricCorrectionMap", TYPE_FLOAT },
+ { "facing", TYPE_BYTE },
+ { "position", TYPE_FLOAT }
+};
+
+tag_info_t android_flash[ANDROID_FLASH_END -
+ ANDROID_FLASH_START] = {
+ { "mode", TYPE_BYTE },
+ { "firingPower", TYPE_BYTE },
+ { "firingTime", TYPE_INT64 }
+};
+
+tag_info_t android_flash_info[ANDROID_FLASH_INFO_END -
+ ANDROID_FLASH_INFO_START] = {
+ { "available", TYPE_BYTE },
+ { "chargeDuration", TYPE_INT64 },
+};
+
+tag_info_t android_hot_pixel[ANDROID_HOT_PIXEL_END -
+ ANDROID_HOT_PIXEL_START] = {
+ { "mode", TYPE_BYTE }
+};
+
+tag_info_t android_hot_pixel_info[ANDROID_HOT_PIXEL_INFO_END -
+ ANDROID_HOT_PIXEL_INFO_START];
+
+tag_info_t android_demosaic[ANDROID_DEMOSAIC_END -
+ ANDROID_DEMOSAIC_START] = {
+ { "mode", TYPE_BYTE }
+};
+
+tag_info_t android_demosaic_info[ANDROID_DEMOSAIC_INFO_END -
+ ANDROID_DEMOSAIC_INFO_START];
+
+tag_info_t android_noise[ANDROID_NOISE_END -
+ ANDROID_NOISE_START] = {
+ { "mode", TYPE_BYTE },
+ { "strength", TYPE_BYTE }
+};
+
+tag_info_t android_noise_info[ANDROID_NOISE_INFO_END -
+ ANDROID_NOISE_INFO_START];
+
+tag_info_t android_shading[ANDROID_SHADING_END -
+ ANDROID_SHADING_START] = {
+ { "mode", TYPE_BYTE }
+};
+
+tag_info_t android_shading_info[ANDROID_SHADING_INFO_END -
+ ANDROID_SHADING_INFO_START];
+
+tag_info_t android_geometric[ANDROID_GEOMETRIC_END -
+ ANDROID_GEOMETRIC_START] = {
+ { "mode", TYPE_BYTE }
+};
+
+tag_info_t android_geometric_info[ANDROID_GEOMETRIC_INFO_END -
+ ANDROID_GEOMETRIC_INFO_START];
+
+tag_info_t android_color[ANDROID_COLOR_END -
+ ANDROID_COLOR_START] = {
+ { "mode", TYPE_BYTE },
+ { "transform", TYPE_FLOAT }
+};
+
+tag_info_t android_color_info[ANDROID_COLOR_INFO_END -
+ ANDROID_COLOR_INFO_START] = {
+ { "availableModes", TYPE_INT32 }
+};
+
+tag_info_t android_tonemap[ANDROID_TONEMAP_END -
+ ANDROID_TONEMAP_START] = {
+ { "mode", TYPE_BYTE },
+ { "curveRed", TYPE_FLOAT },
+ { "curveGreen", TYPE_FLOAT },
+ { "curveBlue", TYPE_FLOAT }
+};
+
+tag_info_t android_tonemap_info[ANDROID_TONEMAP_INFO_END -
+ ANDROID_TONEMAP_INFO_START] = {
+ { "maxCurvePoints", TYPE_INT32 }
+};
+
+tag_info_t android_edge[ANDROID_EDGE_END -
+ ANDROID_EDGE_START] = {
+ { "mode", TYPE_BYTE },
+ { "strength", TYPE_BYTE }
+};
+
+tag_info_t android_edge_info[ANDROID_EDGE_INFO_END -
+ ANDROID_EDGE_INFO_START];
+
+tag_info_t android_scaler[ANDROID_SCALER_END -
+ ANDROID_SCALER_START] = {
+ { "size", TYPE_INT32 },
+ { "format", TYPE_BYTE },
+ { "cropRegion", TYPE_INT32 },
+ { "rotation", TYPE_INT32 },
+};
+
+tag_info_t android_scaler_info[ANDROID_SCALER_INFO_END -
+ ANDROID_SCALER_INFO_START] = {
+ { "availableFormats", TYPE_INT32 },
+ { "availableSizesPerFormat", TYPE_INT32 },
+ { "availableSizes", TYPE_INT32 },
+ { "availableMinFrameDurations", TYPE_INT32 },
+ { "availableMaxDigitalZoom", TYPE_INT32 }
+};
+
+tag_info_t android_jpeg[ANDROID_JPEG_END -
+ ANDROID_JPEG_START] = {
+ { "quality", TYPE_INT32 },
+ { "thumbnailSize", TYPE_INT32 },
+ { "thumbnailQuality", TYPE_INT32 },
+ { "gpsCoordinates", TYPE_DOUBLE },
+ { "gpsProcessingMethod", TYPE_BYTE },
+ { "gpsTimestamp", TYPE_INT64 },
+ { "orientation", TYPE_INT32 }
+};
+
+tag_info_t android_jpeg_info[ANDROID_JPEG_INFO_END -
+ ANDROID_JPEG_INFO_START] = {
+ { "availableThumbnailSizes", TYPE_INT32 }
+};
+
+tag_info_t android_stats[ANDROID_STATS_END -
+ ANDROID_STATS_START] = {
+ { "faceDetectMode", TYPE_BYTE },
+ { "faceRectangles", TYPE_INT32 },
+ { "faceScores", TYPE_BYTE },
+ { "faceLandmarks", TYPE_INT32 },
+ { "faceIds", TYPE_INT32 },
+ { "histogramMode", TYPE_BYTE },
+ { "histogram", TYPE_INT32 },
+ { "sharpnessMapMode", TYPE_BYTE },
+ { "sharpnessMap", TYPE_INT32 }
+};
+
+tag_info_t android_stats_info[ANDROID_STATS_INFO_END -
+ ANDROID_STATS_INFO_START] = {
+ { "availableFaceDetectModes", TYPE_BYTE },
+ { "maxFaceCount", TYPE_INT32 },
+ { "histogramBucketCount", TYPE_INT32 },
+ { "maxHistogramCount", TYPE_INT32 },
+ { "sharpnessMapSize", TYPE_INT32 },
+ { "maxSharpnessMapValue", TYPE_INT32 }
+};
+
+tag_info_t *tag_info[ANDROID_SECTION_COUNT] = {
+ android_request,
+ android_lens,
+ android_lens_info,
+ android_sensor,
+ android_sensor_info,
+ android_flash,
+ android_flash_info,
+ android_hot_pixel,
+ android_hot_pixel_info,
+ android_demosaic,
+ android_demosaic_info,
+ android_noise,
+ android_noise_info,
+ android_shading,
+ android_shading_info,
+ android_geometric,
+ android_geometric_info,
+ android_color,
+ android_color_info,
+ android_tonemap,
+ android_tonemap_info,
+ android_edge,
+ android_edge_info,
+ android_scaler,
+ android_scaler_info,
+ android_jpeg,
+ android_jpeg_info,
+ android_stats,
+ android_stats_info,
+ android_control,
+ android_control_info
+};
--- /dev/null
+# Build the unit tests.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SHARED_LIBRARIES := \
+ libutils \
+ libstlport \
+ libcamera_metadata
+
+LOCAL_STATIC_LIBRARIES := \
+ libgtest \
+ libgtest_main
+
+LOCAL_C_INCLUDES := \
+ bionic \
+ bionic/libstdc++/include \
+ external/gtest/include \
+ external/stlport/stlport \
+ system/media/camera/include \
+
+LOCAL_SRC_FILES := \
+ camera_metadata_tests.cpp
+
+LOCAL_MODULE := camera_metadata_tests
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_EXECUTABLE)
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "gtest/gtest.h"
+#include "system/camera_metadata.h"
+
+#include "camera_metadata_tests_fake_vendor.h"
+
+#define EXPECT_NULL(x) EXPECT_EQ((void*)0, x)
+#define EXPECT_NOT_NULL(x) EXPECT_NE((void*)0, x)
+
+#define OK 0
+#define ERROR 1
+
+TEST(camera_metadata, allocate_normal) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 32;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ EXPECT_NOT_NULL(m);
+ EXPECT_EQ((size_t)0, get_camera_metadata_entry_count(m));
+ EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m));
+ EXPECT_EQ((size_t)0, get_camera_metadata_data_count(m));
+ EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m));
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, allocate_nodata) {
+ camera_metadata_t *m = NULL;
+
+ m = allocate_camera_metadata(1, 0);
+
+ EXPECT_NOT_NULL(m);
+ EXPECT_EQ((size_t)0, get_camera_metadata_entry_count(m));
+ EXPECT_EQ((size_t)1, get_camera_metadata_entry_capacity(m));
+ EXPECT_EQ((size_t)0, get_camera_metadata_data_count(m));
+ EXPECT_EQ((size_t)0, get_camera_metadata_data_capacity(m));
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, allocate_nothing) {
+ camera_metadata_t *m = NULL;
+
+ m = allocate_camera_metadata(0, 0);
+
+ EXPECT_NULL(m);
+}
+
+TEST(camera_metadata, place_normal) {
+ camera_metadata_t *m = NULL;
+ void *buf = NULL;
+
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 32;
+
+ size_t buf_size = calculate_camera_metadata_size(entry_capacity,
+ data_capacity);
+
+ EXPECT_TRUE(buf_size > 0);
+
+ buf = malloc(buf_size);
+
+ EXPECT_NOT_NULL(buf);
+
+ m = place_camera_metadata(buf, buf_size, entry_capacity, data_capacity);
+
+ EXPECT_EQ(buf, (uint8_t*)m);
+ EXPECT_EQ((size_t)0, get_camera_metadata_entry_count(m));
+ EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m));
+ EXPECT_EQ((size_t)0, get_camera_metadata_data_count(m));
+ EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m));
+
+ free(buf);
+}
+
+TEST(camera_metadata, place_nospace) {
+ camera_metadata_t *m = NULL;
+ void *buf = NULL;
+
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 32;
+
+ size_t buf_size = calculate_camera_metadata_size(entry_capacity,
+ data_capacity);
+
+ EXPECT_GT(buf_size, (size_t)0);
+
+ buf_size--;
+
+ buf = malloc(buf_size);
+
+ EXPECT_NOT_NULL(buf);
+
+ m = place_camera_metadata(buf, buf_size, entry_capacity, data_capacity);
+
+ EXPECT_NULL(m);
+
+ free(buf);
+}
+
+TEST(camera_metadata, place_extraspace) {
+ camera_metadata_t *m = NULL;
+ uint8_t *buf = NULL;
+
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 32;
+ const size_t extra_space = 10;
+
+ size_t buf_size = calculate_camera_metadata_size(entry_capacity,
+ data_capacity);
+
+ EXPECT_GT(buf_size, (size_t)0);
+
+ buf_size += extra_space;
+
+ buf = (uint8_t*)malloc(buf_size);
+
+ EXPECT_NOT_NULL(buf);
+
+ m = place_camera_metadata(buf, buf_size, entry_capacity, data_capacity);
+
+ EXPECT_EQ((uint8_t*)m, buf);
+ EXPECT_EQ((size_t)0, get_camera_metadata_entry_count(m));
+ EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m));
+ EXPECT_EQ((size_t)0, get_camera_metadata_data_count(m));
+ EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m));
+ EXPECT_EQ(buf + buf_size - extra_space, (uint8_t*)m + get_camera_metadata_size(m));
+
+ free(buf);
+}
+
+TEST(camera_metadata, get_size) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 32;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ EXPECT_EQ(calculate_camera_metadata_size(entry_capacity, data_capacity),
+ get_camera_metadata_size(m) );
+
+ EXPECT_EQ(calculate_camera_metadata_size(0,0),
+ get_camera_metadata_compact_size(m) );
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, add_get_normal) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 80;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ int result;
+ size_t data_used = 0;
+ size_t entries_used = 0;
+
+ // INT64
+
+ int64_t exposure_time = 1000000000;
+ result = add_camera_metadata_entry(m,
+ ANDROID_SENSOR_EXPOSURE_TIME,
+ &exposure_time, 1);
+ EXPECT_EQ(OK, result);
+ data_used += calculate_camera_metadata_entry_data_size(
+ get_camera_metadata_tag_type(ANDROID_SENSOR_EXPOSURE_TIME), 1);
+ entries_used++;
+
+ // INT32
+
+ int32_t sensitivity = 800;
+ result = add_camera_metadata_entry(m,
+ ANDROID_SENSOR_SENSITIVITY,
+ &sensitivity, 1);
+ EXPECT_EQ(OK, result);
+ data_used += calculate_camera_metadata_entry_data_size(
+ get_camera_metadata_tag_type(ANDROID_SENSOR_SENSITIVITY), 1);
+ entries_used++;
+
+ // FLOAT
+
+ float focusDistance = 0.5f;
+ result = add_camera_metadata_entry(m,
+ ANDROID_LENS_FOCUS_DISTANCE,
+ &focusDistance, 1);
+ EXPECT_EQ(OK, result);
+ data_used += calculate_camera_metadata_entry_data_size(
+ get_camera_metadata_tag_type(ANDROID_LENS_FOCUS_DISTANCE), 1);
+ entries_used++;
+
+ // Array of FLOAT
+
+ float colorTransform[9] = {
+ 0.9f, 0.0f, 0.0f,
+ 0.2f, 0.5f, 0.0f,
+ 0.0f, 0.1f, 0.7f
+ };
+ result = add_camera_metadata_entry(m,
+ ANDROID_COLOR_TRANSFORM,
+ colorTransform, 9);
+ EXPECT_EQ(OK, result);
+ data_used += calculate_camera_metadata_entry_data_size(
+ get_camera_metadata_tag_type(ANDROID_COLOR_TRANSFORM), 9);
+ entries_used++;
+
+ // Check added entries
+
+ uint32_t tag = 0;
+ uint8_t type = 0;
+ int32_t *data_int32;
+ int64_t *data_int64;
+ float *data_float;
+ size_t data_count = 0;
+
+ result = get_camera_metadata_entry(m,
+ 0, &tag, &type, (void**)&data_int64, &data_count);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, tag);
+ EXPECT_EQ(TYPE_INT64, type);
+ EXPECT_EQ((size_t)1, data_count);
+ EXPECT_EQ(exposure_time, *data_int64);
+
+ result = get_camera_metadata_entry(m,
+ 1, &tag, &type, (void**)&data_int32, &data_count);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(ANDROID_SENSOR_SENSITIVITY, tag);
+ EXPECT_EQ(TYPE_INT32, type);
+ EXPECT_EQ((size_t)1, data_count);
+ EXPECT_EQ(sensitivity, *data_int32);
+
+ result = get_camera_metadata_entry(m,
+ 2, &tag, &type, (void**)&data_float, &data_count);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(ANDROID_LENS_FOCUS_DISTANCE, tag);
+ EXPECT_EQ(TYPE_FLOAT, type);
+ EXPECT_EQ((size_t)1, data_count);
+ EXPECT_EQ(focusDistance, *data_float);
+
+ result = get_camera_metadata_entry(m,
+ 3, &tag, &type, (void**)&data_float, &data_count);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(ANDROID_COLOR_TRANSFORM, tag);
+ EXPECT_EQ(TYPE_FLOAT, type);
+ EXPECT_EQ((size_t)9, data_count);
+ for (unsigned int i=0; i < data_count; i++) {
+ EXPECT_EQ(colorTransform[i], data_float[i] );
+ }
+
+ EXPECT_EQ(calculate_camera_metadata_size(entry_capacity, data_capacity),
+ get_camera_metadata_size(m) );
+
+ EXPECT_EQ(calculate_camera_metadata_size(entries_used, data_used),
+ get_camera_metadata_compact_size(m) );
+
+ dump_camera_metadata(m, 2);
+
+ free_camera_metadata(m);
+}
+
+void add_test_metadata(camera_metadata_t *m, int entry_count) {
+
+ EXPECT_NOT_NULL(m);
+
+ int result;
+ size_t data_used = 0;
+ size_t entries_used = 0;
+ int64_t exposure_time;
+ for (int i=0; i < entry_count; i++ ) {
+ exposure_time = 100 + i * 100;
+ result = add_camera_metadata_entry(m,
+ ANDROID_SENSOR_EXPOSURE_TIME,
+ &exposure_time, 1);
+ EXPECT_EQ(OK, result);
+ data_used += calculate_camera_metadata_entry_data_size(
+ get_camera_metadata_tag_type(ANDROID_SENSOR_EXPOSURE_TIME), 1);
+ entries_used++;
+ }
+ EXPECT_EQ(data_used, get_camera_metadata_data_count(m));
+ EXPECT_EQ(entries_used, get_camera_metadata_entry_count(m));
+ EXPECT_GT(get_camera_metadata_data_capacity(m),
+ get_camera_metadata_data_count(m));
+}
+
+TEST(camera_metadata, add_get_toomany) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 50;
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, entry_capacity);
+
+ int32_t sensitivity = 100;
+ result = add_camera_metadata_entry(m,
+ ANDROID_SENSOR_SENSITIVITY,
+ &sensitivity, 1);
+
+ EXPECT_EQ(ERROR, result);
+
+ uint32_t tag = 0;
+ uint8_t type = 0;
+ int32_t *data_int32;
+ size_t data_count = 0;
+ for (unsigned int i=0; i < entry_capacity; i++) {
+ int64_t exposure_time = 100 + i * 100;
+ result = get_camera_metadata_entry(m,
+ i, &tag, &type, (void**)&data_int32, &data_count);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, tag);
+ EXPECT_EQ(TYPE_INT64, type);
+ EXPECT_EQ((size_t)1, data_count);
+ EXPECT_EQ(exposure_time, *data_int32);
+ }
+ tag = 0;
+ type = 0;
+ data_int32 = NULL;
+ data_count = 0;
+ result = get_camera_metadata_entry(m,
+ entry_capacity, &tag, &type, (void**)&data_int32, &data_count);
+ EXPECT_EQ(ERROR, result);
+ EXPECT_EQ((uint32_t)0, tag);
+ EXPECT_EQ((uint8_t)0, type);
+ EXPECT_EQ((size_t)0, data_count);
+ EXPECT_EQ(NULL, data_int32);
+
+ dump_camera_metadata(m, 2);
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, copy_metadata) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 50;
+ const size_t data_capacity = 450;
+
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, entry_capacity);
+
+ size_t buf_size = get_camera_metadata_compact_size(m);
+ EXPECT_LT((size_t)0, buf_size);
+
+ uint8_t *buf = (uint8_t*)malloc(buf_size);
+ EXPECT_NOT_NULL(buf);
+
+ camera_metadata_t *m2 = copy_camera_metadata(buf, buf_size, m);
+ EXPECT_NOT_NULL(m2);
+ EXPECT_EQ(buf, (uint8_t*)m2);
+ EXPECT_EQ(get_camera_metadata_entry_count(m),
+ get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_count(m),
+ get_camera_metadata_data_count(m2));
+ EXPECT_EQ(get_camera_metadata_entry_capacity(m2),
+ get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_capacity(m2),
+ get_camera_metadata_data_count(m2));
+
+ for (unsigned int i=0; i < get_camera_metadata_entry_count(m); i++) {
+ uint32_t tag, tag2;
+ uint8_t type, type2;
+ uint8_t *data, *data2;
+ size_t data_count, data_count2;
+
+ int result;
+ result = get_camera_metadata_entry(m,
+ i, &tag, &type, (void**)&data, &data_count);
+ EXPECT_EQ(OK, result);
+ result = get_camera_metadata_entry(m2,
+ i, &tag2, &type2, (void**)&data2, &data_count2);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(tag, tag2);
+ EXPECT_EQ(type, type2);
+ EXPECT_EQ(data_count, data_count2);
+ for (unsigned int j=0; j < data_count; j++) {
+ EXPECT_EQ(data[j], data2[j]);
+ }
+ }
+
+ free(buf);
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, copy_metadata_extraspace) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 12;
+ const size_t data_capacity = 100;
+
+ const size_t extra_space = 10;
+
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, entry_capacity);
+
+ size_t buf_size = get_camera_metadata_compact_size(m);
+ EXPECT_LT((size_t)0, buf_size);
+ buf_size += extra_space;
+
+ uint8_t *buf = (uint8_t*)malloc(buf_size);
+ EXPECT_NOT_NULL(buf);
+
+ camera_metadata_t *m2 = copy_camera_metadata(buf, buf_size, m);
+ EXPECT_NOT_NULL(m2);
+ EXPECT_EQ(buf, (uint8_t*)m2);
+ EXPECT_EQ(get_camera_metadata_entry_count(m),
+ get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_count(m),
+ get_camera_metadata_data_count(m2));
+ EXPECT_EQ(get_camera_metadata_entry_capacity(m2),
+ get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_capacity(m2),
+ get_camera_metadata_data_count(m2));
+ EXPECT_EQ(buf + buf_size - extra_space,
+ (uint8_t*)m2 + get_camera_metadata_size(m2) );
+
+ for (unsigned int i=0; i < get_camera_metadata_entry_count(m); i++) {
+ uint32_t tag, tag2;
+ uint8_t type, type2;
+ uint8_t *data, *data2;
+ size_t data_count, data_count2;
+
+ int result;
+ result = get_camera_metadata_entry(m,
+ i, &tag, &type, (void**)&data, &data_count);
+ EXPECT_EQ(OK, result);
+ result = get_camera_metadata_entry(m2,
+ i, &tag2, &type2, (void**)&data2, &data_count2);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(tag, tag2);
+ EXPECT_EQ(type, type2);
+ EXPECT_EQ(data_count, data_count2);
+ for (unsigned int j=0; j < data_count; j++) {
+ EXPECT_EQ(data[j], data2[j]);
+ }
+ }
+
+ free(buf);
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, copy_metadata_nospace) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 50;
+
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, entry_capacity);
+
+ size_t buf_size = get_camera_metadata_compact_size(m);
+ EXPECT_LT((size_t)0, buf_size);
+
+ buf_size--;
+
+ uint8_t *buf = (uint8_t*)malloc(buf_size);
+ EXPECT_NOT_NULL(buf);
+
+ camera_metadata_t *m2 = copy_camera_metadata(buf, buf_size, m);
+ EXPECT_NULL(m2);
+
+ free(buf);
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, append_metadata) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 50;
+
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, entry_capacity);
+
+ camera_metadata_t *m2 = NULL;
+
+ m2 = allocate_camera_metadata(entry_capacity*2, data_capacity*2);
+ EXPECT_NOT_NULL(m2);
+
+ result = append_camera_metadata(m2, m);
+
+ EXPECT_EQ(OK, result);
+
+ EXPECT_EQ(get_camera_metadata_entry_count(m), get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_count(m), get_camera_metadata_data_count(m2));
+ EXPECT_EQ(entry_capacity*2, get_camera_metadata_entry_capacity(m2));
+ EXPECT_EQ(data_capacity*2, get_camera_metadata_data_capacity(m2));
+
+ for (unsigned int i=0; i < get_camera_metadata_entry_count(m); i++) {
+ uint32_t tag, tag2;
+ uint8_t type, type2;
+ uint8_t *data, *data2;
+ size_t data_count, data_count2;
+
+ int result;
+ result = get_camera_metadata_entry(m,
+ i, &tag, &type, (void**)&data, &data_count);
+ EXPECT_EQ(OK, result);
+ result = get_camera_metadata_entry(m2,
+ i, &tag2, &type2, (void**)&data2, &data_count2);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(tag, tag2);
+ EXPECT_EQ(type, type2);
+ EXPECT_EQ(data_count, data_count2);
+ for (unsigned int j=0; j < data_count; j++) {
+ EXPECT_EQ(data[j], data2[j]);
+ }
+ }
+
+ result = append_camera_metadata(m2, m);
+
+ EXPECT_EQ(OK, result);
+
+ EXPECT_EQ(get_camera_metadata_entry_count(m)*2, get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_count(m)*2, get_camera_metadata_data_count(m2));
+ EXPECT_EQ(entry_capacity*2, get_camera_metadata_entry_capacity(m2));
+ EXPECT_EQ(data_capacity*2, get_camera_metadata_data_capacity(m2));
+
+ for (unsigned int i=0; i < get_camera_metadata_entry_count(m2); i++) {
+ uint32_t tag, tag2;
+ uint8_t type, type2;
+ uint8_t *data, *data2;
+ size_t data_count, data_count2;
+
+ int result;
+ result = get_camera_metadata_entry(m,
+ i % entry_capacity, &tag, &type, (void**)&data, &data_count);
+ EXPECT_EQ(OK, result);
+ result = get_camera_metadata_entry(m2,
+ i, &tag2, &type2, (void**)&data2, &data_count2);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(tag, tag2);
+ EXPECT_EQ(type, type2);
+ EXPECT_EQ(data_count, data_count2);
+ for (unsigned int j=0; j < data_count; j++) {
+ EXPECT_EQ(data[j], data2[j]);
+ }
+ }
+
+ free_camera_metadata(m);
+ free_camera_metadata(m2);
+}
+
+TEST(camera_metadata, append_metadata_nospace) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 50;
+
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, entry_capacity);
+
+ camera_metadata_t *m2 = NULL;
+
+ m2 = allocate_camera_metadata(entry_capacity-1, data_capacity);
+ EXPECT_NOT_NULL(m2);
+
+ result = append_camera_metadata(m2, m);
+
+ EXPECT_EQ(ERROR, result);
+ EXPECT_EQ((size_t)0, get_camera_metadata_entry_count(m2));
+ EXPECT_EQ((size_t)0, get_camera_metadata_data_count(m2));
+
+ free_camera_metadata(m);
+ free_camera_metadata(m2);
+}
+
+TEST(camera_metadata, append_metadata_onespace) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 50;
+ const size_t entry_capacity2 = entry_capacity * 2 - 2;
+ const size_t data_capacity2 = data_capacity * 2;
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ add_test_metadata(m, entry_capacity);
+
+ camera_metadata_t *m2 = NULL;
+
+ m2 = allocate_camera_metadata(entry_capacity2, data_capacity2);
+ EXPECT_NOT_NULL(m2);
+
+ result = append_camera_metadata(m2, m);
+
+ EXPECT_EQ(OK, result);
+
+ EXPECT_EQ(get_camera_metadata_entry_count(m), get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_count(m), get_camera_metadata_data_count(m2));
+ EXPECT_EQ(entry_capacity2, get_camera_metadata_entry_capacity(m2));
+ EXPECT_EQ(data_capacity2, get_camera_metadata_data_capacity(m2));
+
+ for (unsigned int i=0; i < get_camera_metadata_entry_count(m); i++) {
+ uint32_t tag, tag2;
+ uint8_t type, type2;
+ uint8_t *data, *data2;
+ size_t data_count, data_count2;
+
+ int result;
+ result = get_camera_metadata_entry(m,
+ i, &tag, &type, (void**)&data, &data_count);
+ EXPECT_EQ(OK, result);
+ result = get_camera_metadata_entry(m2,
+ i, &tag2, &type2, (void**)&data2, &data_count2);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(tag, tag2);
+ EXPECT_EQ(type, type2);
+ EXPECT_EQ(data_count, data_count2);
+ for (unsigned int j=0; j < data_count; j++) {
+ EXPECT_EQ(data[j], data2[j]);
+ }
+ }
+
+ result = append_camera_metadata(m2, m);
+
+ EXPECT_EQ(ERROR, result);
+ EXPECT_EQ(entry_capacity, get_camera_metadata_entry_count(m2));
+ EXPECT_EQ(get_camera_metadata_data_count(m),
+ get_camera_metadata_data_count(m2));
+ EXPECT_EQ(entry_capacity2, get_camera_metadata_entry_capacity(m2));
+ EXPECT_EQ(data_capacity2, get_camera_metadata_data_capacity(m2));
+
+ for (unsigned int i=0; i < get_camera_metadata_entry_count(m2); i++) {
+ uint32_t tag, tag2;
+ uint8_t type, type2;
+ uint8_t *data, *data2;
+ size_t data_count, data_count2;
+
+ int result;
+ result = get_camera_metadata_entry(m,
+ i % entry_capacity, &tag, &type, (void**)&data, &data_count);
+ EXPECT_EQ(OK, result);
+ result = get_camera_metadata_entry(m2,
+ i, &tag2, &type2, (void**)&data2, &data_count2);
+ EXPECT_EQ(OK, result);
+ EXPECT_EQ(tag, tag2);
+ EXPECT_EQ(type, type2);
+ EXPECT_EQ(data_count, data_count2);
+ for (unsigned int j=0; j < data_count; j++) {
+ EXPECT_EQ(data[j], data2[j]);
+ }
+ }
+
+ free_camera_metadata(m);
+ free_camera_metadata(m2);
+}
+
+TEST(camera_metadata, vendor_tags) {
+ camera_metadata_t *m = NULL;
+ const size_t entry_capacity = 5;
+ const size_t data_capacity = 50;
+ int result;
+
+ m = allocate_camera_metadata(entry_capacity, data_capacity);
+
+ uint8_t superMode = 5;
+ result = add_camera_metadata_entry(m,
+ FAKEVENDOR_SENSOR_SUPERMODE,
+ &superMode, 1);
+ EXPECT_EQ(ERROR, result);
+
+ result = add_camera_metadata_entry(m,
+ ANDROID_REQUEST_METADATA_MODE,
+ &superMode, 1);
+ EXPECT_EQ(OK, result);
+
+ EXPECT_NULL(get_camera_metadata_section_name(FAKEVENDOR_SENSOR_SUPERMODE));
+ EXPECT_NULL(get_camera_metadata_tag_name(FAKEVENDOR_SENSOR_SUPERMODE));
+ EXPECT_EQ(-1, get_camera_metadata_tag_type(FAKEVENDOR_SENSOR_SUPERMODE));
+
+ set_camera_metadata_vendor_tag_ops(&fakevendor_query_ops);
+
+ result = add_camera_metadata_entry(m,
+ FAKEVENDOR_SENSOR_SUPERMODE,
+ &superMode, 1);
+ EXPECT_EQ(OK, result);
+
+ result = add_camera_metadata_entry(m,
+ ANDROID_REQUEST_METADATA_MODE,
+ &superMode, 1);
+ EXPECT_EQ(OK, result);
+
+ result = add_camera_metadata_entry(m,
+ FAKEVENDOR_SCALER_END,
+ &superMode, 1);
+ EXPECT_EQ(ERROR, result);
+
+ EXPECT_STREQ("com.fakevendor.sensor",
+ get_camera_metadata_section_name(FAKEVENDOR_SENSOR_SUPERMODE));
+ EXPECT_STREQ("superMode",
+ get_camera_metadata_tag_name(FAKEVENDOR_SENSOR_SUPERMODE));
+ EXPECT_EQ(TYPE_BYTE,
+ get_camera_metadata_tag_type(FAKEVENDOR_SENSOR_SUPERMODE));
+
+ EXPECT_STREQ("com.fakevendor.scaler",
+ get_camera_metadata_section_name(FAKEVENDOR_SCALER_END));
+ EXPECT_NULL(get_camera_metadata_tag_name(FAKEVENDOR_SCALER_END));
+ EXPECT_EQ(-1, get_camera_metadata_tag_type(FAKEVENDOR_SCALER_END));
+
+ set_camera_metadata_vendor_tag_ops(NULL);
+
+ result = add_camera_metadata_entry(m,
+ FAKEVENDOR_SENSOR_SUPERMODE,
+ &superMode, 1);
+ EXPECT_EQ(ERROR, result);
+
+ result = add_camera_metadata_entry(m,
+ ANDROID_REQUEST_METADATA_MODE,
+ &superMode, 1);
+ EXPECT_EQ(OK, result);
+
+ EXPECT_NULL(get_camera_metadata_section_name(FAKEVENDOR_SENSOR_SUPERMODE));
+ EXPECT_NULL(get_camera_metadata_tag_name(FAKEVENDOR_SENSOR_SUPERMODE));
+ EXPECT_EQ(-1, get_camera_metadata_tag_type(FAKEVENDOR_SENSOR_SUPERMODE));
+
+ free_camera_metadata(m);
+}
+
+TEST(camera_metadata, add_all_tags) {
+ int total_tag_count = 0;
+ for (int i = 0; i < ANDROID_SECTION_COUNT; i++) {
+ total_tag_count += camera_metadata_section_bounds[i][1] -
+ camera_metadata_section_bounds[i][0];
+ }
+ int entry_data_count = 3;
+ int conservative_data_space = total_tag_count * entry_data_count * 8;
+ uint8_t data[entry_data_count * 8];
+ int32_t *data_int32 = (int32_t *)data;
+ float *data_float = (float *)data;
+ int64_t *data_int64 = (int64_t *)data;
+ double *data_double = (double *)data;
+ camera_metadata_rational_t *data_rational = (camera_metadata_rational_t *)data;
+
+ camera_metadata_t *m = allocate_camera_metadata(total_tag_count, conservative_data_space);
+
+ ASSERT_NE((void*)NULL, (void*)m);
+
+ int result;
+
+ int counter = 0;
+ for (int i = 0; i < ANDROID_SECTION_COUNT; i++) {
+ for (uint32_t tag = camera_metadata_section_bounds[i][0];
+ tag < camera_metadata_section_bounds[i][1];
+ tag++, counter++) {
+ int type = get_camera_metadata_tag_type(tag);
+ ASSERT_NE(-1, type);
+
+ switch (type) {
+ case TYPE_BYTE:
+ data[0] = tag & 0xFF;
+ data[1] = (tag >> 8) & 0xFF;
+ data[2] = (tag >> 16) & 0xFF;
+ break;
+ case TYPE_INT32:
+ data_int32[0] = tag;
+ data_int32[1] = i;
+ data_int32[2] = counter;
+ break;
+ case TYPE_FLOAT:
+ data_float[0] = tag;
+ data_float[1] = i;
+ data_float[2] = counter / (float)total_tag_count;
+ break;
+ case TYPE_INT64:
+ data_int64[0] = (int64_t)tag | ( (int64_t)tag << 32);
+ data_int64[1] = i;
+ data_int64[2] = counter;
+ break;
+ case TYPE_DOUBLE:
+ data_double[0] = tag;
+ data_double[1] = i;
+ data_double[2] = counter / (double)total_tag_count;
+ break;
+ case TYPE_RATIONAL:
+ data_rational[0].numerator = tag;
+ data_rational[0].denominator = 1;
+ data_rational[1].numerator = i;
+ data_rational[1].denominator = 1;
+ data_rational[2].numerator = counter;
+ data_rational[2].denominator = total_tag_count;
+ break;
+ default:
+ FAIL() << "Unknown type field encountered:" << type;
+ break;
+ }
+ result = add_camera_metadata_entry(m,
+ tag,
+ data,
+ entry_data_count);
+ ASSERT_EQ(OK, result);
+
+ }
+ }
+
+ dump_camera_metadata(m, 2);
+
+ free_camera_metadata(m);
+}
--- /dev/null
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Fake vendor extensions for testing
+ */
+
+#ifndef TESTING_CAMERA_METADATA_FAKEVENDOR_H
+#define TESTING_CAMERA_METADATA_FAKEVENDOR_H
+
+enum vendor_extension_section {
+ FAKEVENDOR_SENSOR = VENDOR_SECTION,
+ FAKEVENDOR_SENSOR_INFO,
+ FAKEVENDOR_COLORCORRECTION,
+ FAKEVENDOR_SCALER,
+ FAKEVENDOR_SECTION_END
+};
+
+const int FAKEVENDOR_SECTION_COUNT = FAKEVENDOR_SECTION_END - VENDOR_SECTION;
+
+enum vendor_extension_section_ranges {
+ FAKEVENDOR_SENSOR_START = FAKEVENDOR_SENSOR << 16,
+ FAKEVENDOR_SENSOR_I_START = FAKEVENDOR_SENSOR_INFO << 16,
+ FAKEVENDOR_COLORCORRECTION_START = FAKEVENDOR_COLORCORRECTION << 16,
+ FAKEVENDOR_SCALER_START = FAKEVENDOR_SCALER << 16
+};
+
+enum vendor_extension_tags {
+ FAKEVENDOR_SENSOR_SUPERMODE = FAKEVENDOR_SENSOR_START,
+ FAKEVENDOR_SENSOR_DOUBLE_EXPOSURE,
+ FAKEVENDOR_SENSOR_END,
+
+ FAKEVENDOR_SENSOR_AVAILABLE_SUPERMODES = FAKEVENDOR_SENSOR_I_START,
+ FAKEVENDOR_SENSOR_I_END,
+
+ FAKEVENDOR_COLORCORRECTION_3DLUT_MODE = FAKEVENDOR_COLORCORRECTION_START,
+ FAKEVENDOR_COLORCORRECTION_3DLUT_TABLES,
+ FAKEVENDOR_COLORCORRECTION_END,
+
+ FAKEVENDOR_SCALER_DOWNSCALE_MODE = FAKEVENDOR_SCALER_START,
+ FAKEVENDOR_SCALER_DOWNSCALE_COEFF,
+ FAKEVENDOR_SCALER_END
+};
+
+typedef struct vendor_tag_info {
+ const char *tag_name;
+ uint8_t tag_type;
+} vendor_tag_info_t;
+
+const char *fakevendor_section_names[FAKEVENDOR_SECTION_COUNT] = {
+ "com.fakevendor.sensor",
+ "com.fakevendor.sensor.info",
+ "com.fakevendor.colorCorrection",
+ "com.fakevendor.scaler"
+};
+
+unsigned int fakevendor_section_bounds[FAKEVENDOR_SECTION_COUNT][2] = {
+ { FAKEVENDOR_SENSOR_START, FAKEVENDOR_SENSOR_END },
+ { FAKEVENDOR_SENSOR_I_START, FAKEVENDOR_SENSOR_I_END },
+ { FAKEVENDOR_COLORCORRECTION_START, FAKEVENDOR_COLORCORRECTION_END },
+ { FAKEVENDOR_SCALER_START, FAKEVENDOR_SCALER_END}
+};
+
+vendor_tag_info_t fakevendor_sensor[FAKEVENDOR_SENSOR_END -
+ FAKEVENDOR_SENSOR_START] = {
+ { "superMode", TYPE_BYTE },
+ { "doubleExposure", TYPE_INT64 }
+};
+
+vendor_tag_info_t fakevendor_sensor_info[FAKEVENDOR_SENSOR_I_END -
+ FAKEVENDOR_SENSOR_I_START] = {
+ { "availableSuperModes", TYPE_BYTE }
+};
+
+vendor_tag_info_t fakevendor_color_correction[FAKEVENDOR_COLORCORRECTION_END -
+ FAKEVENDOR_COLORCORRECTION_START] = {
+ { "3dLutMode", TYPE_BYTE },
+ { "3dLutTables", TYPE_FLOAT }
+};
+
+vendor_tag_info_t fakevendor_scaler[FAKEVENDOR_SCALER_END -
+ FAKEVENDOR_SCALER_START] = {
+ { "downscaleMode", TYPE_BYTE },
+ { "downscaleCoefficients", TYPE_FLOAT }
+};
+
+vendor_tag_info_t *fakevendor_tag_info[FAKEVENDOR_SECTION_COUNT] = {
+ fakevendor_sensor,
+ fakevendor_sensor_info,
+ fakevendor_color_correction,
+ fakevendor_scaler
+};
+
+const char *get_fakevendor_section_name(uint32_t tag) {
+ int tag_section = (tag >> 16) - VENDOR_SECTION;
+ if (tag_section < 0 ||
+ tag_section >= FAKEVENDOR_SECTION_COUNT) return NULL;
+
+ return fakevendor_section_names[tag_section];
+}
+
+const char *get_fakevendor_tag_name(uint32_t tag) {
+ int tag_section = (tag >> 16) - VENDOR_SECTION;
+ if (tag_section < 0
+ || tag_section >= FAKEVENDOR_SECTION_COUNT
+ || tag >= fakevendor_section_bounds[tag_section][1]) return NULL;
+ int tag_index = tag & 0xFFFF;
+ return fakevendor_tag_info[tag_section][tag_index].tag_name;
+}
+
+int get_fakevendor_tag_type(uint32_t tag) {
+ int tag_section = (tag >> 16) - VENDOR_SECTION;
+ if (tag_section < 0
+ || tag_section >= FAKEVENDOR_SECTION_COUNT
+ || tag >= fakevendor_section_bounds[tag_section][1]) return -1;
+ int tag_index = tag & 0xFFFF;
+ return fakevendor_tag_info[tag_section][tag_index].tag_type;
+}
+
+static const vendor_tag_query_ops_t fakevendor_query_ops = {
+ get_fakevendor_section_name,
+ get_fakevendor_tag_name,
+ get_fakevendor_tag_type
+};
+
+#endif