From f5fb8a5516876c5a48cc44b4f1c99504e0b9f245 Mon Sep 17 00:00:00 2001 From: Eino-Ville Talvala Date: Thu, 10 May 2012 14:22:28 -0700 Subject: [PATCH] Improvements to camera metadata handling. - Cleaner interface to get/find - Adds delete entry, an expensive O(n) operation - Adds update entry, which is O(n) sometimes - Minor bugfixes: - Keep sorted state when appending empty buffers - Misspelling of camera_metadata_type_size in header - Missing entry in type name array Bug: 6243944 Change-Id: I316507d6adcc22aff6e7c464c6c484f31ef1510d --- camera/include/system/camera_metadata.h | 93 +++- camera/src/camera_metadata.c | 249 ++++++--- camera/tests/camera_metadata_tests.cpp | 943 ++++++++++++++++++++++++++------ 3 files changed, 1028 insertions(+), 257 deletions(-) diff --git a/camera/include/system/camera_metadata.h b/camera/include/system/camera_metadata.h index 6a11cfb3..a1d19b31 100644 --- a/camera/include/system/camera_metadata.h +++ b/camera/include/system/camera_metadata.h @@ -71,10 +71,32 @@ typedef struct camera_metadata_rational { } camera_metadata_rational_t; /** + * A reference to a metadata entry in a buffer. + * + * The data union pointers point to the real data in the buffer, and can be + * modified in-place if the count does not need to change. The count is the + * number of entries in data of the entry's type, not a count of bytes. + */ +typedef struct camera_metadata_entry { + size_t index; + uint32_t tag; + uint8_t type; + size_t count; + union { + uint8_t *u8; + int32_t *i32; + float *f; + int64_t *i64; + double *d; + camera_metadata_rational_t *r; + } data; +} camera_metadata_entry_t; + +/** * Size in bytes of each entry type */ ANDROID_API -extern size_t camera_metadata_type_sizes[NUM_TYPES]; +extern size_t camera_metadata_type_size[NUM_TYPES]; /** * Main definitions for the metadata entry and array structures @@ -90,9 +112,9 @@ extern size_t camera_metadata_type_sizes[NUM_TYPES]; * 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. + * Entries are not sorted by default, 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() @@ -241,46 +263,63 @@ int add_camera_metadata_entry(camera_metadata_t *dst, size_t data_count); /** - * Sort the metadata buffer for fast searching. If already sorted, does - * nothing. Adding or appending entries to the buffer will place the buffer back - * into an unsorted state. + * Sort the metadata buffer for fast searching. If already marked as sorted, + * does nothing. Adding or appending entries to the buffer will place the buffer + * back into an unsorted state. */ ANDROID_API int sort_camera_metadata(camera_metadata_t *dst); /** - * 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. + * Get metadata entry at position index in the metadata buffer. * - * src and index are inputs; tag, type, data, and data_count are outputs. Any of - * the outputs can be set to NULL to skip reading that value. + * src and index are inputs; the passed-in entry is updated with the details of + * the entry. The data pointer points to the real data in the buffer, and can be + * updated as long as the data count does not change. */ 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); + size_t index, + camera_metadata_entry_t *entry); /** * Find an entry with given tag value. If not found, returns -ENOENT. Otherwise, - * returns entry contents like get_camera_metadata_entry. Any of - * the outputs can be set to NULL to skip reading that value. + * returns entry contents like get_camera_metadata_entry. * - * Note: Returns only the first entry with a given tag. To speed up searching - * for tags, sort the metadata structure first by calling - * sort_camera_metadata(). + * If multiple entries with the same tag exist, does not have any guarantees on + * which is returned. To speed up searching for tags, sort the metadata + * structure first by calling sort_camera_metadata(). */ ANDROID_API int find_camera_metadata_entry(camera_metadata_t *src, uint32_t tag, - uint8_t *type, - void **data, - size_t *data_count); + camera_metadata_entry_t *entry); + +/** + * Delete an entry at given index. This is an expensive operation, since it + * requires repacking entries and possibly entry data. This also invalidates any + * existing camera_metadata_entry.data pointers to this buffer. Sorting is + * maintained. + */ +ANDROID_API +int delete_camera_metadata_entry(camera_metadata_t *dst, + size_t index); + +/** + * Updates a metadata entry with new data. If the data size is changing, may + * need to adjust the data array, making this an O(N) operation. If the data + * size is the same or still fits in the entry space, this is O(1). Maintains + * sorting, but invalidates camera_metadata_entry instances that point to the + * updated entry. If a non-NULL value is passed in to entry, the entry structure + * is updated to match the new buffer state. Returns a non-zero value if there + * is no room for the new data in the buffer. + */ +ANDROID_API +int update_camera_metadata_entry(camera_metadata_t *dst, + size_t index, + const void *data, + size_t data_count, + camera_metadata_entry_t *updated_entry); /** * Retrieve human-readable name of section the tag is in. Returns NULL if diff --git a/camera/src/camera_metadata.c b/camera/src/camera_metadata.c index 1991835a..a16b5b78 100644 --- a/camera/src/camera_metadata.c +++ b/camera/src/camera_metadata.c @@ -29,7 +29,7 @@ * array; otherwise, it can found in the parent's data array at index * data.offset. */ -typedef struct camera_metadata_entry { +typedef struct camera_metadata_buffer_entry { uint32_t tag; size_t count; union { @@ -38,7 +38,7 @@ typedef struct camera_metadata_entry { } data; uint8_t type; uint8_t reserved[3]; -} __attribute__((packed)) camera_metadata_entry_t; +} __attribute__((packed)) camera_metadata_buffer_entry_t; /** * A packet of metadata. This is a list of entries, each of which may point to @@ -47,27 +47,27 @@ typedef struct camera_metadata_entry { * 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 | - * |----------------------------------------| + * |-----------------------------------------------| + * | camera_metadata_t | + * | | + * |-----------------------------------------------| + * | reserved for future expansion | + * |-----------------------------------------------| + * | camera_metadata_buffer_entry_t #0 | + * |-----------------------------------------------| + * | .... | + * |-----------------------------------------------| + * | camera_metadata_buffer_entry_t #entry_count-1 | + * |-----------------------------------------------| + * | free space for | + * | (entry_capacity-entry_count) entries | + * |-----------------------------------------------| + * | start of camera_metadata.data | + * | | + * |-----------------------------------------------| + * | free space for | + * | (data_capacity-data_count) bytes | + * |-----------------------------------------------| * * With the total length of the whole packet being camera_metadata.size bytes. * @@ -80,7 +80,7 @@ struct camera_metadata { uint32_t flags; size_t entry_count; size_t entry_capacity; - camera_metadata_entry_t *entries; + camera_metadata_buffer_entry_t *entries; size_t data_count; size_t data_capacity; uint8_t *data; @@ -116,6 +116,7 @@ char *camera_metadata_type_names[NUM_TYPES] = { [TYPE_INT32] = "int32", [TYPE_FLOAT] = "float", [TYPE_INT64] = "int64", + [TYPE_DOUBLE] = "double", [TYPE_RATIONAL] = "rational" }; @@ -145,7 +146,7 @@ camera_metadata_t *place_camera_metadata(void *dst, metadata->flags = 0; metadata->entry_count = 0; metadata->entry_capacity = entry_capacity; - metadata->entries = (camera_metadata_entry_t*)(metadata + 1); + metadata->entries = (camera_metadata_buffer_entry_t*)(metadata + 1); metadata->data_count = 0; metadata->data_capacity = data_capacity; metadata->size = memory_needed; @@ -165,7 +166,7 @@ void free_camera_metadata(camera_metadata_t *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(camera_metadata_buffer_entry_t[entry_count]); memory_needed += sizeof(uint8_t[data_count]); return memory_needed; } @@ -221,7 +222,7 @@ camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size, metadata->flags = src->flags; metadata->entry_count = src->entry_count; metadata->entry_capacity = src->entry_count; - metadata->entries = (camera_metadata_entry_t*) + metadata->entries = (camera_metadata_buffer_entry_t*) ((uint8_t *)(metadata + 1) + reserved_size); metadata->data_count = src->data_count; metadata->data_capacity = src->data_count; @@ -232,7 +233,7 @@ camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size, memcpy(metadata->reserved, src->reserved, reserved_size); } memcpy(metadata->entries, src->entries, - sizeof(camera_metadata_entry_t[metadata->entry_count])); + sizeof(camera_metadata_buffer_entry_t[metadata->entry_count])); memcpy(metadata->data, src->data, sizeof(uint8_t[metadata->data_count])); @@ -247,7 +248,7 @@ int append_camera_metadata(camera_metadata_t *dst, 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])); + sizeof(camera_metadata_buffer_entry_t[src->entry_count])); memcpy(dst->data + dst->data_count, src->data, sizeof(uint8_t[src->data_count])); if (dst->data_count != 0) { @@ -255,15 +256,23 @@ int append_camera_metadata(camera_metadata_t *dst, for (i = dst->entry_count; i < dst->entry_count + src->entry_count; i++) { - camera_metadata_entry_t *entry = dst->entries + i; + camera_metadata_buffer_entry_t *entry = dst->entries + i; if ( camera_metadata_type_size[entry->type] * entry->count > 4 ) { entry->data.offset += dst->data_count; } } } + if (dst->entry_count == 0) { + // Appending onto empty buffer, keep sorted state + dst->flags |= src->flags & FLAG_SORTED; + } else if (src->entry_count != 0) { + // Both src, dst are nonempty, cannot assume sort remains + dst->flags &= ~FLAG_SORTED; + } else { + // Src is empty, keep dst sorted state + } dst->entry_count += src->entry_count; dst->data_count += src->data_count; - dst->flags &= ~FLAG_SORTED; return OK; } @@ -289,7 +298,7 @@ static int add_camera_metadata_entry_raw(camera_metadata_t *dst, size_t data_bytes = calculate_camera_metadata_entry_data_size(type, data_count); - camera_metadata_entry_t *entry = dst->entries + dst->entry_count; + camera_metadata_buffer_entry_t *entry = dst->entries + dst->entry_count; entry->tag = tag; entry->type = type; entry->count = data_count; @@ -326,8 +335,8 @@ int add_camera_metadata_entry(camera_metadata_t *dst, } static int compare_entry_tags(const void *p1, const void *p2) { - uint32_t tag1 = ((camera_metadata_entry_t*)p1)->tag; - uint32_t tag2 = ((camera_metadata_entry_t*)p2)->tag; + uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag; + uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag; return tag1 < tag2 ? -1 : tag1 == tag2 ? 0 : 1; @@ -338,7 +347,7 @@ int sort_camera_metadata(camera_metadata_t *dst) { if (dst->flags & FLAG_SORTED) return OK; qsort(dst->entries, dst->entry_count, - sizeof(camera_metadata_entry_t), + sizeof(camera_metadata_buffer_entry_t), compare_entry_tags); dst->flags |= FLAG_SORTED; @@ -346,67 +355,165 @@ int sort_camera_metadata(camera_metadata_t *dst) { } 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; + size_t index, + camera_metadata_entry_t *entry) { + if (src == NULL || entry == NULL) return ERROR; if (index >= src->entry_count) return ERROR; - camera_metadata_entry_t *entry = src->entries + index; + camera_metadata_buffer_entry_t *buffer_entry = src->entries + index; - if (tag != NULL) *tag = entry->tag; - if (type != NULL) *type = entry->type; - if (data_count != NULL) *data_count = entry->count; - if (data != NULL) { - if (entry->count * camera_metadata_type_size[entry->type] > 4) { - *data = src->data + entry->data.offset; - } else { - *data = entry->data.value; - } + entry->index = index; + entry->tag = buffer_entry->tag; + entry->type = buffer_entry->type; + entry->count = buffer_entry->count; + if (buffer_entry->count * + camera_metadata_type_size[buffer_entry->type] > 4) { + entry->data.u8 = src->data + buffer_entry->data.offset; + } else { + entry->data.u8 = buffer_entry->data.value; } return OK; } int find_camera_metadata_entry(camera_metadata_t *src, uint32_t tag, - uint8_t *type, - void **data, - size_t *data_count) { + camera_metadata_entry_t *entry) { if (src == NULL) return ERROR; - camera_metadata_entry_t *entry = NULL; + uint32_t index; if (src->flags & FLAG_SORTED) { // Sorted entries, do a binary search - camera_metadata_entry_t key; + camera_metadata_buffer_entry_t *search_entry = NULL; + camera_metadata_buffer_entry_t key; key.tag = tag; - entry = bsearch(&key, + search_entry = bsearch(&key, src->entries, src->entry_count, - sizeof(camera_metadata_entry_t), + sizeof(camera_metadata_buffer_entry_t), compare_entry_tags); + if (search_entry == NULL) return NOT_FOUND; + index = search_entry - src->entries; } else { // Not sorted, linear search - unsigned int i; - for (i = 0; i < src->entry_count; i++) { - if (src->entries[i].tag == tag) { - entry = src->entries + i; + for (index = 0; index < src->entry_count; index++) { + if (src->entries[index].tag == tag) { break; } } + if (index == src->entry_count) return NOT_FOUND; } - if (entry == NULL) return NOT_FOUND; - if (type != NULL) *type = entry->type; - if (data_count != NULL) *data_count = entry->count; - if (data != NULL) { - if (entry->count * camera_metadata_type_size[entry->type] > 4) { - *data = src->data + entry->data.offset; - } else { - *data = entry->data.value; + return get_camera_metadata_entry(src, index, + entry); +} + +int delete_camera_metadata_entry(camera_metadata_t *dst, + size_t index) { + if (dst == NULL) return ERROR; + if (index >= dst->entry_count) return ERROR; + + camera_metadata_buffer_entry_t *entry = dst->entries + index; + size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type, + entry->count); + + if (data_bytes > 0) { + // Shift data buffer to overwrite deleted data + uint8_t *start = dst->data + entry->data.offset; + uint8_t *end = start + data_bytes; + size_t length = dst->data_count - entry->data.offset - data_bytes; + memmove(start, end, length); + + // Update all entry indices to account for shift + camera_metadata_buffer_entry_t *e = dst->entries; + size_t i; + for (i = 0; i < dst->entry_count; i++) { + if (calculate_camera_metadata_entry_data_size( + e->type, e->count) > 0 && + e->data.offset > entry->data.offset) { + e->data.offset -= data_bytes; + } + ++e; } + dst->data_count -= data_bytes; } + // Shift entry array + memmove(entry, entry + 1, + sizeof(camera_metadata_buffer_entry_t) * + (dst->entry_count - index - 1) ); + dst->entry_count -= 1; + + return OK; +} + +int update_camera_metadata_entry(camera_metadata_t *dst, + size_t index, + const void *data, + size_t data_count, + camera_metadata_entry_t *updated_entry) { + if (dst == NULL) return ERROR; + if (index >= dst->entry_count) return ERROR; + + camera_metadata_buffer_entry_t *entry = dst->entries + index; + + size_t data_bytes = + calculate_camera_metadata_entry_data_size(entry->type, + data_count); + size_t entry_bytes = + calculate_camera_metadata_entry_data_size(entry->type, + entry->count); + if (data_bytes != entry_bytes) { + // May need to shift/add to data array + if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) { + // No room + return ERROR; + } + if (entry_bytes != 0) { + // Remove old data + uint8_t *start = dst->data + entry->data.offset; + uint8_t *end = start + entry_bytes; + size_t length = dst->data_count - entry->data.offset - entry_bytes; + memmove(start, end, length); + dst->data_count -= entry_bytes; + + // Update all entry indices to account for shift + camera_metadata_buffer_entry_t *e = dst->entries; + size_t i; + for (i = 0; i < dst->entry_count; i++) { + if (calculate_camera_metadata_entry_data_size( + e->type, e->count) > 0 && + e->data.offset > entry->data.offset) { + e->data.offset -= entry_bytes; + } + ++e; + } + } + + if (data_bytes != 0) { + // Append new data + entry->data.offset = dst->data_count; + + memcpy(dst->data + entry->data.offset, data, data_bytes); + dst->data_count += data_bytes; + } + } else if (data_bytes != 0) { + // data size unchanged, reuse same data location + memcpy(dst->data + entry->data.offset, data, data_bytes); + } + + if (data_bytes == 0) { + // Data fits into entry + memcpy(entry->data.value, data, + data_count * camera_metadata_type_size[entry->type]); + } + + entry->count = data_count; + + if (updated_entry != NULL) { + get_camera_metadata_entry(dst, + index, + updated_entry); + } + return OK; } @@ -479,7 +586,7 @@ void dump_camera_metadata(const camera_metadata_t *metadata, fdprintf(fd, " Version: %d, Flags: %08x\n", metadata->version, metadata->flags); for (i=0; i < metadata->entry_count; i++) { - camera_metadata_entry_t *entry = metadata->entries + i; + camera_metadata_buffer_entry_t *entry = metadata->entries + i; const char *tag_name, *tag_section; tag_section = get_camera_metadata_section_name(entry->tag); diff --git a/camera/tests/camera_metadata_tests.cpp b/camera/tests/camera_metadata_tests.cpp index 53a4c456..6bac8db7 100644 --- a/camera/tests/camera_metadata_tests.cpp +++ b/camera/tests/camera_metadata_tests.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +#define LOG_NDEBUG 1 +#define LOG_TAG "camera_metadata_tests" +#include "cutils/log.h" + #include #include "gtest/gtest.h" @@ -226,45 +230,43 @@ TEST(camera_metadata, add_get_normal) { // 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; - + camera_metadata_entry entry; result = get_camera_metadata_entry(m, - 0, &tag, &type, (void**)&data_int64, &data_count); + 0, &entry); 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); + EXPECT_EQ(0, (int)entry.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, entry.tag); + EXPECT_EQ(TYPE_INT64, entry.type); + EXPECT_EQ((size_t)1, entry.count); + EXPECT_EQ(exposure_time, *entry.data.i64); result = get_camera_metadata_entry(m, - 1, &tag, &type, (void**)&data_int32, &data_count); + 1, &entry); 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); + EXPECT_EQ((size_t)1, entry.index); + EXPECT_EQ(ANDROID_SENSOR_SENSITIVITY, entry.tag); + EXPECT_EQ(TYPE_INT32, entry.type); + EXPECT_EQ((size_t)1, entry.count); + EXPECT_EQ(sensitivity, *entry.data.i32); result = get_camera_metadata_entry(m, - 2, &tag, &type, (void**)&data_float, &data_count); + 2, &entry); 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); + EXPECT_EQ((size_t)2, entry.index); + EXPECT_EQ(ANDROID_LENS_FOCUS_DISTANCE, entry.tag); + EXPECT_EQ(TYPE_FLOAT, entry.type); + EXPECT_EQ((size_t)1, entry.count); + EXPECT_EQ(focusDistance, *entry.data.f); result = get_camera_metadata_entry(m, - 3, &tag, &type, (void**)&data_float, &data_count); + 3, &entry); 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((size_t)3, entry.index); + EXPECT_EQ(ANDROID_COLOR_TRANSFORM, entry.tag); + EXPECT_EQ(TYPE_FLOAT, entry.type); + EXPECT_EQ((size_t)9, entry.count); + for (unsigned int i=0; i < entry.count; i++) { + EXPECT_EQ(colorTransform[i], entry.data.f[i] ); } EXPECT_EQ(calculate_camera_metadata_size(entry_capacity, data_capacity), @@ -273,7 +275,9 @@ TEST(camera_metadata, add_get_normal) { EXPECT_EQ(calculate_camera_metadata_size(entries_used, data_used), get_camera_metadata_compact_size(m) ); - dump_camera_metadata(m, 0, 2); + IF_ALOGV() { + dump_camera_metadata(m, 0, 2); + } free_camera_metadata(m); } @@ -319,33 +323,33 @@ TEST(camera_metadata, add_get_toomany) { EXPECT_EQ(ERROR, result); - uint32_t tag = 0; - uint8_t type = 0; - int32_t *data_int32; - size_t data_count = 0; + camera_metadata_entry entry; 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); + i, &entry); 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); + EXPECT_EQ(i, entry.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, entry.tag); + EXPECT_EQ(TYPE_INT64, entry.type); + EXPECT_EQ((size_t)1, entry.count); + EXPECT_EQ(exposure_time, *entry.data.i64); } - tag = 0; - type = 0; - data_int32 = NULL; - data_count = 0; + entry.tag = 1234; + entry.type = 56; + entry.data.u8 = NULL; + entry.count = 7890; result = get_camera_metadata_entry(m, - entry_capacity, &tag, &type, (void**)&data_int32, &data_count); + entry_capacity, &entry); 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); + EXPECT_EQ((uint32_t)1234, entry.tag); + EXPECT_EQ((uint8_t)56, entry.type); + EXPECT_EQ(NULL, entry.data.u8); + EXPECT_EQ((size_t)7890, entry.count); - dump_camera_metadata(m, 0, 2); + IF_ALOGV() { + dump_camera_metadata(m, 0, 2); + } free_camera_metadata(m); } @@ -380,23 +384,20 @@ TEST(camera_metadata, copy_metadata) { 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; - + camera_metadata_entry e1, e2; int result; - result = get_camera_metadata_entry(m, - i, &tag, &type, (void**)&data, &data_count); + result = get_camera_metadata_entry(m, i, &e1); EXPECT_EQ(OK, result); - result = get_camera_metadata_entry(m2, - i, &tag2, &type2, (void**)&data2, &data_count2); + result = get_camera_metadata_entry(m2, i, &e2); 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]); + EXPECT_EQ(e1.index, e2.index); + EXPECT_EQ(e1.tag, e2.tag); + EXPECT_EQ(e1.type, e2.type); + EXPECT_EQ(e1.count, e2.count); + for (unsigned int j=0; + j < e1.count * camera_metadata_type_size[e1.type]; + j++) { + EXPECT_EQ(e1.data.u8[j], e2.data.u8[j]); } } @@ -440,23 +441,22 @@ TEST(camera_metadata, copy_metadata_extraspace) { (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; + camera_metadata_entry e1, e2; int result; - result = get_camera_metadata_entry(m, - i, &tag, &type, (void**)&data, &data_count); + result = get_camera_metadata_entry(m, i, &e1); EXPECT_EQ(OK, result); - result = get_camera_metadata_entry(m2, - i, &tag2, &type2, (void**)&data2, &data_count2); + EXPECT_EQ(i, e1.index); + result = get_camera_metadata_entry(m2, i, &e2); 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]); + EXPECT_EQ(e1.index, e2.index); + EXPECT_EQ(e1.tag, e2.tag); + EXPECT_EQ(e1.type, e2.type); + EXPECT_EQ(e1.count, e2.count); + for (unsigned int j=0; + j < e1.count * camera_metadata_type_size[e1.type]; + j++) { + EXPECT_EQ(e1.data.u8[j], e2.data.u8[j]); } } @@ -512,29 +512,29 @@ TEST(camera_metadata, append_metadata) { 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(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; - + camera_metadata_entry e1, e2; int result; - result = get_camera_metadata_entry(m, - i, &tag, &type, (void**)&data, &data_count); + result = get_camera_metadata_entry(m, i, &e1); EXPECT_EQ(OK, result); - result = get_camera_metadata_entry(m2, - i, &tag2, &type2, (void**)&data2, &data_count2); + EXPECT_EQ(i, e1.index); + result = get_camera_metadata_entry(m2, i, &e2); 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]); + EXPECT_EQ(e1.index, e2.index); + EXPECT_EQ(e1.tag, e2.tag); + EXPECT_EQ(e1.type, e2.type); + EXPECT_EQ(e1.count, e2.count); + for (unsigned int j=0; + j < e1.count * camera_metadata_type_size[e1.type]; + j++) { + EXPECT_EQ(e1.data.u8[j], e2.data.u8[j]); } } @@ -542,29 +542,32 @@ TEST(camera_metadata, append_metadata) { 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(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; + camera_metadata_entry e1, e2; int result; result = get_camera_metadata_entry(m, - i % entry_capacity, &tag, &type, (void**)&data, &data_count); + i % entry_capacity, &e1); EXPECT_EQ(OK, result); + EXPECT_EQ(i % entry_capacity, e1.index); result = get_camera_metadata_entry(m2, - i, &tag2, &type2, (void**)&data2, &data_count2); + i, &e2); 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]); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(e1.tag, e2.tag); + EXPECT_EQ(e1.type, e2.type); + EXPECT_EQ(e1.count, e2.count); + for (unsigned int j=0; + j < e1.count * camera_metadata_type_size[e1.type]; + j++) { + EXPECT_EQ(e1.data.u8[j], e2.data.u8[j]); } } @@ -619,29 +622,30 @@ TEST(camera_metadata, append_metadata_onespace) { 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(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; + camera_metadata_entry e1, e2; int result; - result = get_camera_metadata_entry(m, - i, &tag, &type, (void**)&data, &data_count); + result = get_camera_metadata_entry(m, i, &e1); EXPECT_EQ(OK, result); - result = get_camera_metadata_entry(m2, - i, &tag2, &type2, (void**)&data2, &data_count2); + EXPECT_EQ(i, e1.index); + result = get_camera_metadata_entry(m2, i, &e2); 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]); + EXPECT_EQ(e1.index, e2.index); + EXPECT_EQ(e1.tag, e2.tag); + EXPECT_EQ(e1.type, e2.type); + EXPECT_EQ(e1.count, e2.count); + for (unsigned int j=0; + j < e1.count * camera_metadata_type_size[e1.type]; + j++) { + EXPECT_EQ(e1.data.u8[j], e2.data.u8[j]); } } @@ -655,23 +659,23 @@ TEST(camera_metadata, append_metadata_onespace) { 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; + camera_metadata_entry e1, e2; int result; result = get_camera_metadata_entry(m, - i % entry_capacity, &tag, &type, (void**)&data, &data_count); + i % entry_capacity, &e1); EXPECT_EQ(OK, result); - result = get_camera_metadata_entry(m2, - i, &tag2, &type2, (void**)&data2, &data_count2); + EXPECT_EQ(i % entry_capacity, e1.index); + result = get_camera_metadata_entry(m2, i, &e2); 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]); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(e1.tag, e2.tag); + EXPECT_EQ(e1.type, e2.type); + EXPECT_EQ(e1.count, e2.count); + for (unsigned int j=0; + j < e1.count * camera_metadata_type_size[e1.type]; + j++) { + EXPECT_EQ(e1.data.u8[j], e2.data.u8[j]); } } @@ -763,9 +767,11 @@ TEST(camera_metadata, add_all_tags) { 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_rational_t *data_rational = + (camera_metadata_rational_t *)data; - camera_metadata_t *m = allocate_camera_metadata(total_tag_count, conservative_data_space); + camera_metadata_t *m = allocate_camera_metadata(total_tag_count, + conservative_data_space); ASSERT_NE((void*)NULL, (void*)m); @@ -826,7 +832,9 @@ TEST(camera_metadata, add_all_tags) { } } - dump_camera_metadata(m, 0, 2); + IF_ALOGV() { + dump_camera_metadata(m, 0, 2); + } free_camera_metadata(m); } @@ -871,55 +879,672 @@ TEST(camera_metadata, sort_metadata) { EXPECT_EQ(OK, result); // Test unsorted find - uint8_t type; - float *f; - size_t data_count; + camera_metadata_entry_t entry; result = find_camera_metadata_entry(m, ANDROID_LENS_FOCUS_DISTANCE, - &type, - (void**)&f, - &data_count); + &entry); EXPECT_EQ(OK, result); - EXPECT_EQ(TYPE_FLOAT, type); - EXPECT_EQ(1, (int)data_count); - EXPECT_EQ(focus_distance, *f); + EXPECT_EQ(ANDROID_LENS_FOCUS_DISTANCE, entry.tag); + EXPECT_EQ((size_t)1, entry.index); + EXPECT_EQ(TYPE_FLOAT, entry.type); + EXPECT_EQ((size_t)1, entry.count); + EXPECT_EQ(focus_distance, *entry.data.f); result = find_camera_metadata_entry(m, ANDROID_NOISE_STRENGTH, - &type, - (void**)&f, - &data_count); + &entry); EXPECT_EQ(NOT_FOUND, result); + EXPECT_EQ((size_t)1, entry.index); + EXPECT_EQ(ANDROID_LENS_FOCUS_DISTANCE, entry.tag); + EXPECT_EQ(TYPE_FLOAT, entry.type); + EXPECT_EQ((size_t)1, entry.count); + EXPECT_EQ(focus_distance, *entry.data.f); // Sort - std::cout << "Pre-sorted metadata" << std::endl; - dump_camera_metadata(m, 0, 2); + IF_ALOGV() { + std::cout << "Pre-sorted metadata" << std::endl; + dump_camera_metadata(m, 0, 2); + } result = sort_camera_metadata(m); EXPECT_EQ(OK, result); - std::cout << "Sorted metadata" << std::endl; - dump_camera_metadata(m, 0, 2); + IF_ALOGV() { + std::cout << "Sorted metadata" << std::endl; + dump_camera_metadata(m, 0, 2); + } // Test sorted find result = find_camera_metadata_entry(m, ANDROID_LENS_FOCUS_DISTANCE, - &type, - (void**)&f, - &data_count); + &entry); EXPECT_EQ(OK, result); - EXPECT_EQ(TYPE_FLOAT, type); - EXPECT_EQ(1, (int)data_count); - EXPECT_EQ(focus_distance, *f); + EXPECT_EQ((size_t)0, entry.index); + EXPECT_EQ(ANDROID_LENS_FOCUS_DISTANCE, entry.tag); + EXPECT_EQ(TYPE_FLOAT, entry.type); + EXPECT_EQ((size_t)1, (size_t)entry.count); + EXPECT_EQ(focus_distance, *entry.data.f); result = find_camera_metadata_entry(m, ANDROID_NOISE_STRENGTH, - &type, - (void**)&f, - &data_count); + &entry); EXPECT_EQ(NOT_FOUND, result); + EXPECT_EQ((size_t)0, entry.index); + EXPECT_EQ(ANDROID_LENS_FOCUS_DISTANCE, entry.tag); + EXPECT_EQ(TYPE_FLOAT, entry.type); + EXPECT_EQ((size_t)1, entry.count); + EXPECT_EQ(focus_distance, *entry.data.f); free_camera_metadata(m); } + +TEST(camera_metadata, delete_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); + + size_t num_entries = 5; + size_t data_per_entry = + calculate_camera_metadata_entry_data_size(TYPE_INT64, 1); + size_t num_data = num_entries * data_per_entry; + + // Delete an entry with data + + add_test_metadata(m, num_entries); + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + + result = delete_camera_metadata_entry(m, 1); + EXPECT_EQ(OK, result); + num_entries--; + num_data -= data_per_entry; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + result = delete_camera_metadata_entry(m, 4); + EXPECT_EQ(ERROR, result); + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + for (size_t i = 0; i < num_entries; i++) { + camera_metadata_entry e; + result = get_camera_metadata_entry(m, i, &e); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + int64_t exposureTime = i < 1 ? 100 : 200 + 100 * i; + EXPECT_EQ(exposureTime, *e.data.i64); + } + + // Delete an entry with no data, at end of array + + int32_t frameCount = 12; + result = add_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, + &frameCount, 1); + EXPECT_EQ(OK, result); + num_entries++; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + camera_metadata_entry e; + result = get_camera_metadata_entry(m, 4, &e); + EXPECT_EQ(OK, result); + + EXPECT_EQ((size_t)4, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(frameCount, *e.data.i32); + + result = delete_camera_metadata_entry(m, 4); + EXPECT_EQ(OK, result); + + num_entries--; + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + result = delete_camera_metadata_entry(m, 4); + EXPECT_EQ(ERROR, result); + + result = get_camera_metadata_entry(m, 4, &e); + EXPECT_EQ(ERROR, result); + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + // Delete with extra data on end of array + result = delete_camera_metadata_entry(m, 3); + EXPECT_EQ(OK, result); + num_entries--; + num_data -= data_per_entry; + + for (size_t i = 0; i < num_entries; i++) { + camera_metadata_entry e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = i < 1 ? 100 : 200 + 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Delete without extra data in front of array + + frameCount = 1001; + result = add_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, + &frameCount, 1); + EXPECT_EQ(OK, result); + num_entries++; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + result = sort_camera_metadata(m); + EXPECT_EQ(OK, result); + + result = find_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, &e); + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(frameCount, *e.data.i32); + + result = delete_camera_metadata_entry(m, e.index); + EXPECT_EQ(OK, result); + num_entries--; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + for (size_t i = 0; i < num_entries; i++) { + camera_metadata_entry e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = i < 1 ? 100 : 200 + 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } +} + +TEST(camera_metadata, update_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); + + size_t num_entries = 5; + size_t data_per_entry = + calculate_camera_metadata_entry_data_size(TYPE_INT64, 1); + size_t num_data = num_entries * data_per_entry; + + add_test_metadata(m, num_entries); + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + + // Update with same-size data, doesn't fit in entry + + int64_t newExposureTime = 1000; + camera_metadata_entry_t e; + result = update_camera_metadata_entry(m, + 0, &newExposureTime, 1, &e); + EXPECT_EQ(OK, result); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newExposureTime, *e.data.i64); + + e.count = 0; + result = get_camera_metadata_entry(m, + 0, &e); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newExposureTime, *e.data.i64); + + for (size_t i = 1; i < num_entries; i++) { + camera_metadata_entry e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 + 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Update with larger data + int64_t newExposures[2] = { 5000, 6000 }; + result = update_camera_metadata_entry(m, + 0, newExposures, 2, &e); + EXPECT_EQ(OK, result); + num_data += data_per_entry; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)2, e.count); + EXPECT_EQ(newExposures[0], e.data.i64[0]); + EXPECT_EQ(newExposures[1], e.data.i64[1]); + + e.count = 0; + result = get_camera_metadata_entry(m, + 0, &e); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)2, e.count); + EXPECT_EQ(newExposures[0], e.data.i64[0]); + EXPECT_EQ(newExposures[1], e.data.i64[1]); + + for (size_t i = 1; i < num_entries; i++) { + camera_metadata_entry e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 + 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Update with smaller data + newExposureTime = 100; + result = update_camera_metadata_entry(m, + 0, &newExposureTime, 1, &e); + EXPECT_EQ(OK, result); + + num_data -= data_per_entry; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newExposureTime, *e.data.i64); + + e.count = 0; + result = get_camera_metadata_entry(m, + 0, &e); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newExposureTime, *e.data.i64); + + for (size_t i = 1; i < num_entries; i++) { + camera_metadata_entry e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 + 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Update with size fitting in entry + + int32_t frameCount = 1001; + result = add_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, + &frameCount, 1); + EXPECT_EQ(OK, result); + num_entries++; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(entry_capacity, get_camera_metadata_entry_capacity(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + EXPECT_EQ(data_capacity, get_camera_metadata_data_capacity(m)); + + result = sort_camera_metadata(m); + EXPECT_EQ(OK, result); + + result = find_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, &e); + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(frameCount, *e.data.i32); + + int32_t newFrameCount = 0x12349876; + result = update_camera_metadata_entry(m, + 0, &newFrameCount, 1, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + result = find_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + for (size_t i = 1; i < num_entries; i++) { + camera_metadata_entry e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Update to bigger than entry + + int32_t newFrameCounts[4] = { 0x0, 0x1, 0x10, 0x100 }; + + result = update_camera_metadata_entry(m, + 0, &newFrameCounts, 4, &e); + + EXPECT_EQ(OK, result); + + num_data += calculate_camera_metadata_entry_data_size(TYPE_INT32, + 4); + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)4, e.count); + EXPECT_EQ(newFrameCounts[0], e.data.i32[0]); + EXPECT_EQ(newFrameCounts[1], e.data.i32[1]); + EXPECT_EQ(newFrameCounts[2], e.data.i32[2]); + EXPECT_EQ(newFrameCounts[3], e.data.i32[3]); + + e.count = 0; + + result = find_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)4, e.count); + EXPECT_EQ(newFrameCounts[0], e.data.i32[0]); + EXPECT_EQ(newFrameCounts[1], e.data.i32[1]); + EXPECT_EQ(newFrameCounts[2], e.data.i32[2]); + EXPECT_EQ(newFrameCounts[3], e.data.i32[3]); + + for (size_t i = 1; i < num_entries; i++) { + camera_metadata_entry e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Update to smaller than entry + result = update_camera_metadata_entry(m, + 0, &newFrameCount, 1, &e); + + EXPECT_EQ(OK, result); + + num_data -= camera_metadata_type_size[TYPE_INT32] * 4; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + result = find_camera_metadata_entry(m, + ANDROID_REQUEST_FRAME_COUNT, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + for (size_t i = 1; i < num_entries; i++) { + camera_metadata_entry_t e2; + result = get_camera_metadata_entry(m, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Setup new buffer with no spare data space + + result = update_camera_metadata_entry(m, + 1, newExposures, 2, &e); + EXPECT_EQ(OK, result); + + num_data += data_per_entry; + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m)); + + EXPECT_EQ((size_t)1, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)2, e.count); + EXPECT_EQ(newExposures[0], e.data.i64[0]); + EXPECT_EQ(newExposures[1], e.data.i64[1]); + + camera_metadata_t *m2; + m2 = allocate_camera_metadata(get_camera_metadata_entry_count(m), + get_camera_metadata_data_count(m)); + EXPECT_NOT_NULL(m2); + + result = append_camera_metadata(m2, m); + EXPECT_EQ(OK, result); + + result = find_camera_metadata_entry(m2, + ANDROID_REQUEST_FRAME_COUNT, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + // Update when there's no more room + + result = update_camera_metadata_entry(m2, + 0, &newFrameCounts, 4, &e); + EXPECT_EQ(ERROR, result); + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m2)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m2)); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + // Update when there's no data room, but change fits into entry + + newFrameCount = 5; + result = update_camera_metadata_entry(m2, + 0, &newFrameCount, 1, &e); + EXPECT_EQ(OK, result); + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m2)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m2)); + + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + result = find_camera_metadata_entry(m2, + ANDROID_REQUEST_FRAME_COUNT, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + result = get_camera_metadata_entry(m2, 1, &e); + EXPECT_EQ((size_t)1, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)2, e.count); + EXPECT_EQ(newExposures[0], e.data.i64[0]); + EXPECT_EQ(newExposures[1], e.data.i64[1]); + + for (size_t i = 2; i < num_entries; i++) { + camera_metadata_entry_t e2; + result = get_camera_metadata_entry(m2, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Update when there's no data room, but data size doesn't change + + newExposures[0] = 1000; + + result = update_camera_metadata_entry(m2, + 1, newExposures, 2, &e); + EXPECT_EQ(OK, result); + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m2)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m2)); + + EXPECT_EQ((size_t)1, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)2, e.count); + EXPECT_EQ(newExposures[0], e.data.i64[0]); + EXPECT_EQ(newExposures[1], e.data.i64[1]); + + result = find_camera_metadata_entry(m2, + ANDROID_REQUEST_FRAME_COUNT, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + for (size_t i = 2; i < num_entries; i++) { + camera_metadata_entry_t e2; + result = get_camera_metadata_entry(m2, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + + // Update when there's no data room, but data size shrinks + + result = update_camera_metadata_entry(m2, + 1, &newExposureTime, 1, &e); + EXPECT_EQ(OK, result); + + num_data -= calculate_camera_metadata_entry_data_size(TYPE_INT64, 2); + num_data += calculate_camera_metadata_entry_data_size(TYPE_INT64, 1); + + EXPECT_EQ(num_entries, get_camera_metadata_entry_count(m2)); + EXPECT_EQ(num_data, get_camera_metadata_data_count(m2)); + + EXPECT_EQ((size_t)1, e.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e.tag); + EXPECT_EQ(TYPE_INT64, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newExposureTime, e.data.i64[0]); + + result = find_camera_metadata_entry(m2, + ANDROID_REQUEST_FRAME_COUNT, &e); + + EXPECT_EQ(OK, result); + EXPECT_EQ((size_t)0, e.index); + EXPECT_EQ(ANDROID_REQUEST_FRAME_COUNT, e.tag); + EXPECT_EQ(TYPE_INT32, e.type); + EXPECT_EQ((size_t)1, e.count); + EXPECT_EQ(newFrameCount, *e.data.i32); + + for (size_t i = 2; i < num_entries; i++) { + camera_metadata_entry_t e2; + result = get_camera_metadata_entry(m2, i, &e2); + EXPECT_EQ(OK, result); + EXPECT_EQ(i, e2.index); + EXPECT_EQ(ANDROID_SENSOR_EXPOSURE_TIME, e2.tag); + EXPECT_EQ(TYPE_INT64, e2.type); + int64_t exposureTime = 100 * i; + EXPECT_EQ(exposureTime, *e2.data.i64); + } + +} -- 2.11.0