Eino-Ville Talvala | d8afb4d | 2012-02-10 14:27:08 -0800 | [diff] [blame^] | 1 | /* |
| 2 | * Copyright (C) 2012 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include <system/camera_metadata.h> |
| 18 | #include <cutils/log.h> |
| 19 | |
| 20 | #define OK 0 |
| 21 | #define ERROR 1 |
| 22 | |
| 23 | /** |
| 24 | * A single metadata entry, storing an array of values of a given type. If the |
| 25 | * array is no larger than 4 bytes in size, it is stored in the data.value[] |
| 26 | * array; otherwise, it can found in the parent's data array at index |
| 27 | * data.offset. |
| 28 | */ |
| 29 | typedef struct camera_metadata_entry { |
| 30 | uint32_t tag; |
| 31 | size_t count; |
| 32 | union { |
| 33 | size_t offset; |
| 34 | uint8_t value[4]; |
| 35 | } data; |
| 36 | uint8_t type; |
| 37 | uint8_t reserved[3]; |
| 38 | } __attribute__((packed)) camera_metadata_entry_t; |
| 39 | |
| 40 | /** |
| 41 | * A packet of metadata. This is a list of entries, each of which may point to |
| 42 | * its values stored at an offset in data. |
| 43 | * |
| 44 | * It is assumed by the utility functions that the memory layout of the packet |
| 45 | * is as follows: |
| 46 | * |
| 47 | * |----------------------------------------| |
| 48 | * | camera_metadata_t | |
| 49 | * | | |
| 50 | * |----------------------------------------| |
| 51 | * | reserved for future expansion | |
| 52 | * |----------------------------------------| |
| 53 | * | camera_metadata_entry_t #0 | |
| 54 | * |----------------------------------------| |
| 55 | * | .... | |
| 56 | * |----------------------------------------| |
| 57 | * | camera_metadata_entry_t #entry_count-1 | |
| 58 | * |----------------------------------------| |
| 59 | * | free space for | |
| 60 | * | (entry_capacity-entry_count) entries | |
| 61 | * |----------------------------------------| |
| 62 | * | start of camera_metadata.data | |
| 63 | * | | |
| 64 | * |----------------------------------------| |
| 65 | * | free space for | |
| 66 | * | (data_capacity-data_count) bytes | |
| 67 | * |----------------------------------------| |
| 68 | * |
| 69 | * With the total length of the whole packet being camera_metadata.size bytes. |
| 70 | * |
| 71 | * In short, the entries and data are contiguous in memory after the metadata |
| 72 | * header. |
| 73 | */ |
| 74 | struct camera_metadata { |
| 75 | size_t size; |
| 76 | size_t entry_count; |
| 77 | size_t entry_capacity; |
| 78 | camera_metadata_entry_t *entries; |
| 79 | size_t data_count; |
| 80 | size_t data_capacity; |
| 81 | uint8_t *data; |
| 82 | uint8_t reserved[0]; |
| 83 | }; |
| 84 | |
| 85 | typedef struct tag_info { |
| 86 | const char *tag_name; |
| 87 | uint8_t tag_type; |
| 88 | } tag_info_t; |
| 89 | |
| 90 | #include "camera_metadata_tag_info.c" |
| 91 | |
| 92 | size_t camera_metadata_type_size[NUM_TYPES] = { |
| 93 | [TYPE_BYTE] = sizeof(uint8_t), |
| 94 | [TYPE_INT32] = sizeof(int32_t), |
| 95 | [TYPE_FLOAT] = sizeof(float), |
| 96 | [TYPE_INT64] = sizeof(int64_t), |
| 97 | [TYPE_DOUBLE] = sizeof(double), |
| 98 | [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t) |
| 99 | }; |
| 100 | |
| 101 | char *camera_metadata_type_names[NUM_TYPES] = { |
| 102 | [TYPE_BYTE] = "byte", |
| 103 | [TYPE_INT32] = "int32", |
| 104 | [TYPE_FLOAT] = "float", |
| 105 | [TYPE_INT64] = "int64", |
| 106 | [TYPE_RATIONAL] = "rational" |
| 107 | }; |
| 108 | |
| 109 | camera_metadata_t *allocate_camera_metadata(size_t entry_capacity, |
| 110 | size_t data_capacity) { |
| 111 | size_t memory_needed = calculate_camera_metadata_size(entry_capacity, |
| 112 | data_capacity); |
| 113 | void *buffer = malloc(memory_needed); |
| 114 | return place_camera_metadata(buffer, memory_needed, |
| 115 | entry_capacity, |
| 116 | data_capacity); |
| 117 | } |
| 118 | |
| 119 | camera_metadata_t *place_camera_metadata(void *dst, |
| 120 | size_t dst_size, |
| 121 | size_t entry_capacity, |
| 122 | size_t data_capacity) { |
| 123 | if (dst == NULL) return NULL; |
| 124 | if (entry_capacity == 0) return NULL; |
| 125 | |
| 126 | size_t memory_needed = calculate_camera_metadata_size(entry_capacity, |
| 127 | data_capacity); |
| 128 | if (memory_needed > dst_size) return NULL; |
| 129 | |
| 130 | camera_metadata_t *metadata = (camera_metadata_t*)dst; |
| 131 | metadata->entry_count = 0; |
| 132 | metadata->entry_capacity = entry_capacity; |
| 133 | metadata->entries = (camera_metadata_entry_t*)(metadata + 1); |
| 134 | metadata->data_count = 0; |
| 135 | metadata->data_capacity = data_capacity; |
| 136 | metadata->size = memory_needed; |
| 137 | if (metadata->data_capacity != 0) { |
| 138 | metadata->data = |
| 139 | (uint8_t*)(metadata->entries + metadata->entry_capacity); |
| 140 | } else { |
| 141 | metadata->data = NULL; |
| 142 | } |
| 143 | |
| 144 | return metadata; |
| 145 | } |
| 146 | void free_camera_metadata(camera_metadata_t *metadata) { |
| 147 | free(metadata); |
| 148 | } |
| 149 | |
| 150 | size_t calculate_camera_metadata_size(size_t entry_count, |
| 151 | size_t data_count) { |
| 152 | size_t memory_needed = sizeof(camera_metadata_t); |
| 153 | memory_needed += sizeof(camera_metadata_entry_t[entry_count]); |
| 154 | memory_needed += sizeof(uint8_t[data_count]); |
| 155 | return memory_needed; |
| 156 | } |
| 157 | |
| 158 | size_t get_camera_metadata_size(const camera_metadata_t *metadata) { |
| 159 | if (metadata == NULL) return ERROR; |
| 160 | |
| 161 | return metadata->size; |
| 162 | } |
| 163 | |
| 164 | size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) { |
| 165 | if (metadata == NULL) return ERROR; |
| 166 | |
| 167 | ptrdiff_t reserved_size = metadata->size - |
| 168 | calculate_camera_metadata_size(metadata->entry_capacity, |
| 169 | metadata->data_capacity); |
| 170 | |
| 171 | return calculate_camera_metadata_size(metadata->entry_count, |
| 172 | metadata->data_count) + reserved_size; |
| 173 | } |
| 174 | |
| 175 | size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) { |
| 176 | return metadata->entry_count; |
| 177 | } |
| 178 | |
| 179 | size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) { |
| 180 | return metadata->entry_capacity; |
| 181 | } |
| 182 | |
| 183 | size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) { |
| 184 | return metadata->data_count; |
| 185 | } |
| 186 | |
| 187 | size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) { |
| 188 | return metadata->data_capacity; |
| 189 | } |
| 190 | |
| 191 | camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size, |
| 192 | const camera_metadata_t *src) { |
| 193 | size_t memory_needed = get_camera_metadata_compact_size(src); |
| 194 | |
| 195 | if (dst == NULL) return NULL; |
| 196 | if (dst_size < memory_needed) return NULL; |
| 197 | |
| 198 | // If copying a newer version of the structure, there may be additional |
| 199 | // header fields we don't know about but need to copy |
| 200 | ptrdiff_t reserved_size = src->size - |
| 201 | calculate_camera_metadata_size(src->entry_capacity, |
| 202 | src->data_capacity); |
| 203 | |
| 204 | camera_metadata_t *metadata = (camera_metadata_t*)dst; |
| 205 | metadata->entry_count = src->entry_count; |
| 206 | metadata->entry_capacity = src->entry_count; |
| 207 | metadata->entries = (camera_metadata_entry_t*) |
| 208 | ((uint8_t *)(metadata + 1) + reserved_size); |
| 209 | metadata->data_count = src->data_count; |
| 210 | metadata->data_capacity = src->data_count; |
| 211 | metadata->data = (uint8_t *)(metadata->entries + metadata->entry_capacity); |
| 212 | metadata->size = memory_needed; |
| 213 | |
| 214 | if (reserved_size > 0) { |
| 215 | memcpy(metadata->reserved, src->reserved, reserved_size); |
| 216 | } |
| 217 | memcpy(metadata->entries, src->entries, |
| 218 | sizeof(camera_metadata_entry_t[metadata->entry_count])); |
| 219 | memcpy(metadata->data, src->data, |
| 220 | sizeof(uint8_t[metadata->data_count])); |
| 221 | |
| 222 | return metadata; |
| 223 | } |
| 224 | |
| 225 | int append_camera_metadata(camera_metadata_t *dst, |
| 226 | const camera_metadata_t *src) { |
| 227 | if (dst == NULL || src == NULL ) return ERROR; |
| 228 | |
| 229 | if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR; |
| 230 | if (dst->data_capacity < src->data_count + dst->data_count) return ERROR; |
| 231 | |
| 232 | memcpy(dst->entries + dst->entry_count, src->entries, |
| 233 | sizeof(camera_metadata_entry_t[src->entry_count])); |
| 234 | memcpy(dst->data + dst->data_count, src->data, |
| 235 | sizeof(uint8_t[src->data_count])); |
| 236 | if (dst->data_count != 0) { |
| 237 | unsigned int i; |
| 238 | for (i = dst->entry_count; |
| 239 | i < dst->entry_count + src->entry_count; |
| 240 | i++) { |
| 241 | camera_metadata_entry_t *entry = dst->entries + i; |
| 242 | if ( camera_metadata_type_size[entry->type] * entry->count > 4 ) { |
| 243 | entry->data.offset += dst->data_count; |
| 244 | } |
| 245 | } |
| 246 | } |
| 247 | dst->entry_count += src->entry_count; |
| 248 | dst->data_count += src->data_count; |
| 249 | |
| 250 | return OK; |
| 251 | } |
| 252 | |
| 253 | size_t calculate_camera_metadata_entry_data_size(uint8_t type, |
| 254 | size_t data_count) { |
| 255 | if (type >= NUM_TYPES) return 0; |
| 256 | size_t data_bytes = data_count * |
| 257 | camera_metadata_type_size[type]; |
| 258 | return data_bytes <= 4 ? 0 : data_bytes; |
| 259 | } |
| 260 | |
| 261 | int add_camera_metadata_entry_raw(camera_metadata_t *dst, |
| 262 | uint32_t tag, |
| 263 | uint8_t type, |
| 264 | const void *data, |
| 265 | size_t data_count) { |
| 266 | |
| 267 | if (dst == NULL) return ERROR; |
| 268 | if (dst->entry_count == dst->entry_capacity) return ERROR; |
| 269 | if (data == NULL) return ERROR; |
| 270 | |
| 271 | size_t data_bytes = |
| 272 | calculate_camera_metadata_entry_data_size(type, data_count); |
| 273 | |
| 274 | camera_metadata_entry_t *entry = dst->entries + dst->entry_count; |
| 275 | entry->tag = tag; |
| 276 | entry->type = type; |
| 277 | entry->count = data_count; |
| 278 | |
| 279 | if (data_bytes == 0) { |
| 280 | memcpy(entry->data.value, data, |
| 281 | data_count * camera_metadata_type_size[type] ); |
| 282 | } else { |
| 283 | entry->data.offset = dst->data_count; |
| 284 | memcpy(dst->data + entry->data.offset, data, data_bytes); |
| 285 | dst->data_count += data_bytes; |
| 286 | } |
| 287 | dst->entry_count++; |
| 288 | return OK; |
| 289 | } |
| 290 | |
| 291 | int add_camera_metadata_entry(camera_metadata_t *dst, |
| 292 | uint32_t tag, |
| 293 | const void *data, |
| 294 | size_t data_count) { |
| 295 | |
| 296 | int type = get_camera_metadata_tag_type(tag); |
| 297 | if (type == -1) { |
| 298 | ALOGE("Unknown tag %04x (can't find type)", tag); |
| 299 | return ERROR; |
| 300 | } |
| 301 | |
| 302 | return add_camera_metadata_entry_raw(dst, |
| 303 | tag, |
| 304 | type, |
| 305 | data, |
| 306 | data_count); |
| 307 | } |
| 308 | |
| 309 | int get_camera_metadata_entry(camera_metadata_t *src, |
| 310 | uint32_t index, |
| 311 | uint32_t *tag, |
| 312 | uint8_t *type, |
| 313 | void **data, |
| 314 | size_t *data_count) { |
| 315 | if (src == NULL ) return ERROR; |
| 316 | if (tag == NULL) return ERROR; |
| 317 | if (type == NULL ) return ERROR; |
| 318 | if (data == NULL) return ERROR; |
| 319 | if (data_count == NULL) return ERROR; |
| 320 | |
| 321 | if (index >= src->entry_count) return ERROR; |
| 322 | |
| 323 | camera_metadata_entry_t *entry = src->entries + index; |
| 324 | |
| 325 | *tag = entry->tag; |
| 326 | *type = entry->type; |
| 327 | *data_count = entry->count; |
| 328 | if (entry->count * camera_metadata_type_size[entry->type] > 4) { |
| 329 | *data = src->data + entry->data.offset; |
| 330 | } else { |
| 331 | *data = entry->data.value; |
| 332 | } |
| 333 | return OK; |
| 334 | } |
| 335 | |
| 336 | static const vendor_tag_query_ops_t *vendor_tag_ops = NULL; |
| 337 | |
| 338 | const char *get_camera_metadata_section_name(uint32_t tag) { |
| 339 | uint32_t tag_section = tag >> 16; |
| 340 | if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) { |
| 341 | return vendor_tag_ops->get_camera_vendor_section_name(tag); |
| 342 | } |
| 343 | if (tag_section >= ANDROID_SECTION_COUNT) { |
| 344 | return NULL; |
| 345 | } |
| 346 | return camera_metadata_section_names[tag_section]; |
| 347 | } |
| 348 | |
| 349 | const char *get_camera_metadata_tag_name(uint32_t tag) { |
| 350 | uint32_t tag_section = tag >> 16; |
| 351 | if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) { |
| 352 | return vendor_tag_ops->get_camera_vendor_tag_name(tag); |
| 353 | } |
| 354 | if (tag_section >= ANDROID_SECTION_COUNT || |
| 355 | tag >= camera_metadata_section_bounds[tag_section][1] ) { |
| 356 | return NULL; |
| 357 | } |
| 358 | uint32_t tag_index = tag & 0xFFFF; |
| 359 | return tag_info[tag_section][tag_index].tag_name; |
| 360 | } |
| 361 | |
| 362 | int get_camera_metadata_tag_type(uint32_t tag) { |
| 363 | uint32_t tag_section = tag >> 16; |
| 364 | if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) { |
| 365 | return vendor_tag_ops->get_camera_vendor_tag_type(tag); |
| 366 | } |
| 367 | if (tag_section >= ANDROID_SECTION_COUNT || |
| 368 | tag >= camera_metadata_section_bounds[tag_section][1] ) { |
| 369 | return -1; |
| 370 | } |
| 371 | uint32_t tag_index = tag & 0xFFFF; |
| 372 | return tag_info[tag_section][tag_index].tag_type; |
| 373 | } |
| 374 | |
| 375 | int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) { |
| 376 | vendor_tag_ops = query_ops; |
| 377 | return OK; |
| 378 | } |
| 379 | |
| 380 | void print_data(const uint8_t *data_ptr, int type, int count); |
| 381 | |
| 382 | void dump_camera_metadata(const camera_metadata_t *metadata, int verbosity) { |
| 383 | if (metadata == NULL) { |
| 384 | ALOGE("Metadata is null."); |
| 385 | return; |
| 386 | } |
| 387 | unsigned int i; |
| 388 | ALOGD("Dumping camera metadata array. %d entries, %d bytes of extra data.", |
| 389 | metadata->entry_count, metadata->data_count); |
| 390 | ALOGD(" (%d entries and %d bytes data reserved)", |
| 391 | metadata->entry_capacity, metadata->data_capacity); |
| 392 | for (i=0; i < metadata->entry_count; i++) { |
| 393 | camera_metadata_entry_t *entry = metadata->entries + i; |
| 394 | |
| 395 | const char *tag_name, *tag_section; |
| 396 | tag_section = get_camera_metadata_section_name(entry->tag); |
| 397 | if (tag_section == NULL) { |
| 398 | tag_section = "unknownSection"; |
| 399 | } |
| 400 | tag_name = get_camera_metadata_tag_name(entry->tag); |
| 401 | if (tag_name == NULL) { |
| 402 | tag_name = "unknownTag"; |
| 403 | } |
| 404 | const char *type_name; |
| 405 | if (entry->type >= NUM_TYPES) { |
| 406 | type_name = "unknown"; |
| 407 | } else { |
| 408 | type_name = camera_metadata_type_names[entry->type]; |
| 409 | } |
| 410 | ALOGD("Tag: %s.%s (%05x): %s[%d]", |
| 411 | tag_section, |
| 412 | tag_name, |
| 413 | entry->tag, |
| 414 | type_name, |
| 415 | entry->count); |
| 416 | |
| 417 | if (verbosity < 1) continue; |
| 418 | |
| 419 | if (entry->type >= NUM_TYPES) continue; |
| 420 | |
| 421 | size_t type_size = camera_metadata_type_size[entry->type]; |
| 422 | uint8_t *data_ptr; |
| 423 | if ( type_size * entry->count > 4 ) { |
| 424 | if (entry->data.offset >= metadata->data_count) { |
| 425 | ALOGE("Malformed entry data offset: %d (max %d)", |
| 426 | entry->data.offset, |
| 427 | metadata->data_count); |
| 428 | continue; |
| 429 | } |
| 430 | data_ptr = metadata->data + entry->data.offset; |
| 431 | } else { |
| 432 | data_ptr = entry->data.value; |
| 433 | } |
| 434 | int count = entry->count; |
| 435 | if (verbosity < 2 && count > 16) count = 16; |
| 436 | |
| 437 | print_data(data_ptr, entry->type, count); |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | void print_data(const uint8_t *data_ptr, int type, int count) { |
| 442 | static int values_per_line[NUM_TYPES] = { |
| 443 | [TYPE_BYTE] = 16, |
| 444 | [TYPE_INT32] = 4, |
| 445 | [TYPE_FLOAT] = 8, |
| 446 | [TYPE_INT64] = 2, |
| 447 | [TYPE_DOUBLE] = 4, |
| 448 | [TYPE_RATIONAL] = 2, |
| 449 | }; |
| 450 | size_t type_size = camera_metadata_type_size[type]; |
| 451 | |
| 452 | int lines = count / values_per_line[type]; |
| 453 | if (count % values_per_line[type] != 0) lines++; |
| 454 | |
| 455 | char tmp1[80], tmp2[80]; |
| 456 | |
| 457 | int index = 0; |
| 458 | int j, k; |
| 459 | for (j = 0; j < lines; j++) { |
| 460 | tmp1[0] = 0; |
| 461 | for (k = 0; |
| 462 | k < values_per_line[type] && count > 0; |
| 463 | k++, count--, index += type_size) { |
| 464 | |
| 465 | switch (type) { |
| 466 | case TYPE_BYTE: |
| 467 | snprintf(tmp2, sizeof(tmp2), "%hhu ", |
| 468 | *(data_ptr + index)); |
| 469 | break; |
| 470 | case TYPE_INT32: |
| 471 | snprintf(tmp2, sizeof(tmp2), "%d ", |
| 472 | *(int32_t*)(data_ptr + index)); |
| 473 | break; |
| 474 | case TYPE_FLOAT: |
| 475 | snprintf(tmp2, sizeof(tmp2), "%0.2f ", |
| 476 | *(float*)(data_ptr + index)); |
| 477 | break; |
| 478 | case TYPE_INT64: |
| 479 | snprintf(tmp2, sizeof(tmp2), "%lld ", |
| 480 | *(int64_t*)(data_ptr + index)); |
| 481 | break; |
| 482 | case TYPE_DOUBLE: |
| 483 | snprintf(tmp2, sizeof(tmp2), "%0.2f ", |
| 484 | *(float*)(data_ptr + index)); |
| 485 | break; |
| 486 | case TYPE_RATIONAL: { |
| 487 | int32_t numerator = *(int32_t*)(data_ptr + index); |
| 488 | int32_t denominator = *(int32_t*)(data_ptr + index + 4); |
| 489 | snprintf(tmp2, sizeof(tmp2), "(%d / %d) ", |
| 490 | numerator, denominator); |
| 491 | break; |
| 492 | } |
| 493 | default: |
| 494 | snprintf(tmp2, sizeof(tmp2), "??? "); |
| 495 | } |
| 496 | strncat(tmp1, tmp2, sizeof(tmp1)); |
| 497 | } |
| 498 | ALOGD(" [ %s]", tmp1); |
| 499 | } |
| 500 | } |