blob: a16b5b786cada268ecaba05576a295425f58ad3f [file] [log] [blame]
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -08001/*
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 */
Eino-Ville Talvala623ff652012-04-11 16:15:50 -070016#define _GNU_SOURCE // for fdprintf
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080017#include <system/camera_metadata.h>
18#include <cutils/log.h>
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070019#include <stdio.h>
20#include <stdlib.h>
21#include <errno.h>
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080022
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070023#define OK 0
24#define ERROR 1
25#define NOT_FOUND -ENOENT
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080026/**
27 * A single metadata entry, storing an array of values of a given type. If the
28 * array is no larger than 4 bytes in size, it is stored in the data.value[]
29 * array; otherwise, it can found in the parent's data array at index
30 * data.offset.
31 */
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070032typedef struct camera_metadata_buffer_entry {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080033 uint32_t tag;
34 size_t count;
35 union {
36 size_t offset;
37 uint8_t value[4];
38 } data;
39 uint8_t type;
40 uint8_t reserved[3];
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070041} __attribute__((packed)) camera_metadata_buffer_entry_t;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080042
43/**
44 * A packet of metadata. This is a list of entries, each of which may point to
45 * its values stored at an offset in data.
46 *
47 * It is assumed by the utility functions that the memory layout of the packet
48 * is as follows:
49 *
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070050 * |-----------------------------------------------|
51 * | camera_metadata_t |
52 * | |
53 * |-----------------------------------------------|
54 * | reserved for future expansion |
55 * |-----------------------------------------------|
56 * | camera_metadata_buffer_entry_t #0 |
57 * |-----------------------------------------------|
58 * | .... |
59 * |-----------------------------------------------|
60 * | camera_metadata_buffer_entry_t #entry_count-1 |
61 * |-----------------------------------------------|
62 * | free space for |
63 * | (entry_capacity-entry_count) entries |
64 * |-----------------------------------------------|
65 * | start of camera_metadata.data |
66 * | |
67 * |-----------------------------------------------|
68 * | free space for |
69 * | (data_capacity-data_count) bytes |
70 * |-----------------------------------------------|
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080071 *
72 * With the total length of the whole packet being camera_metadata.size bytes.
73 *
74 * In short, the entries and data are contiguous in memory after the metadata
75 * header.
76 */
77struct camera_metadata {
78 size_t size;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070079 uint32_t version;
80 uint32_t flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080081 size_t entry_count;
82 size_t entry_capacity;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070083 camera_metadata_buffer_entry_t *entries;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080084 size_t data_count;
85 size_t data_capacity;
86 uint8_t *data;
87 uint8_t reserved[0];
88};
89
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070090/** Versioning information */
91#define CURRENT_METADATA_VERSION 1
92
93/** Flag definitions */
94#define FLAG_SORTED 0x00000001
95
96/** Tag information */
97
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080098typedef struct tag_info {
99 const char *tag_name;
100 uint8_t tag_type;
101} tag_info_t;
102
103#include "camera_metadata_tag_info.c"
104
105size_t camera_metadata_type_size[NUM_TYPES] = {
106 [TYPE_BYTE] = sizeof(uint8_t),
107 [TYPE_INT32] = sizeof(int32_t),
108 [TYPE_FLOAT] = sizeof(float),
109 [TYPE_INT64] = sizeof(int64_t),
110 [TYPE_DOUBLE] = sizeof(double),
111 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
112};
113
114char *camera_metadata_type_names[NUM_TYPES] = {
115 [TYPE_BYTE] = "byte",
116 [TYPE_INT32] = "int32",
117 [TYPE_FLOAT] = "float",
118 [TYPE_INT64] = "int64",
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700119 [TYPE_DOUBLE] = "double",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800120 [TYPE_RATIONAL] = "rational"
121};
122
123camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
124 size_t data_capacity) {
125 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
126 data_capacity);
127 void *buffer = malloc(memory_needed);
128 return place_camera_metadata(buffer, memory_needed,
129 entry_capacity,
130 data_capacity);
131}
132
133camera_metadata_t *place_camera_metadata(void *dst,
134 size_t dst_size,
135 size_t entry_capacity,
136 size_t data_capacity) {
137 if (dst == NULL) return NULL;
138 if (entry_capacity == 0) return NULL;
139
140 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
141 data_capacity);
142 if (memory_needed > dst_size) return NULL;
143
144 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700145 metadata->version = CURRENT_METADATA_VERSION;
146 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800147 metadata->entry_count = 0;
148 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700149 metadata->entries = (camera_metadata_buffer_entry_t*)(metadata + 1);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800150 metadata->data_count = 0;
151 metadata->data_capacity = data_capacity;
152 metadata->size = memory_needed;
153 if (metadata->data_capacity != 0) {
154 metadata->data =
155 (uint8_t*)(metadata->entries + metadata->entry_capacity);
156 } else {
157 metadata->data = NULL;
158 }
159
160 return metadata;
161}
162void free_camera_metadata(camera_metadata_t *metadata) {
163 free(metadata);
164}
165
166size_t calculate_camera_metadata_size(size_t entry_count,
167 size_t data_count) {
168 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700169 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800170 memory_needed += sizeof(uint8_t[data_count]);
171 return memory_needed;
172}
173
174size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
175 if (metadata == NULL) return ERROR;
176
177 return metadata->size;
178}
179
180size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
181 if (metadata == NULL) return ERROR;
182
183 ptrdiff_t reserved_size = metadata->size -
184 calculate_camera_metadata_size(metadata->entry_capacity,
185 metadata->data_capacity);
186
187 return calculate_camera_metadata_size(metadata->entry_count,
188 metadata->data_count) + reserved_size;
189}
190
191size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
192 return metadata->entry_count;
193}
194
195size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
196 return metadata->entry_capacity;
197}
198
199size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
200 return metadata->data_count;
201}
202
203size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
204 return metadata->data_capacity;
205}
206
207camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
208 const camera_metadata_t *src) {
209 size_t memory_needed = get_camera_metadata_compact_size(src);
210
211 if (dst == NULL) return NULL;
212 if (dst_size < memory_needed) return NULL;
213
214 // If copying a newer version of the structure, there may be additional
215 // header fields we don't know about but need to copy
216 ptrdiff_t reserved_size = src->size -
217 calculate_camera_metadata_size(src->entry_capacity,
218 src->data_capacity);
219
220 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700221 metadata->version = CURRENT_METADATA_VERSION;
222 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800223 metadata->entry_count = src->entry_count;
224 metadata->entry_capacity = src->entry_count;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700225 metadata->entries = (camera_metadata_buffer_entry_t*)
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800226 ((uint8_t *)(metadata + 1) + reserved_size);
227 metadata->data_count = src->data_count;
228 metadata->data_capacity = src->data_count;
229 metadata->data = (uint8_t *)(metadata->entries + metadata->entry_capacity);
230 metadata->size = memory_needed;
231
232 if (reserved_size > 0) {
233 memcpy(metadata->reserved, src->reserved, reserved_size);
234 }
235 memcpy(metadata->entries, src->entries,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700236 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800237 memcpy(metadata->data, src->data,
238 sizeof(uint8_t[metadata->data_count]));
239
240 return metadata;
241}
242
243int append_camera_metadata(camera_metadata_t *dst,
244 const camera_metadata_t *src) {
245 if (dst == NULL || src == NULL ) return ERROR;
246
247 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
248 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
249
250 memcpy(dst->entries + dst->entry_count, src->entries,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700251 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800252 memcpy(dst->data + dst->data_count, src->data,
253 sizeof(uint8_t[src->data_count]));
254 if (dst->data_count != 0) {
255 unsigned int i;
256 for (i = dst->entry_count;
257 i < dst->entry_count + src->entry_count;
258 i++) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700259 camera_metadata_buffer_entry_t *entry = dst->entries + i;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800260 if ( camera_metadata_type_size[entry->type] * entry->count > 4 ) {
261 entry->data.offset += dst->data_count;
262 }
263 }
264 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700265 if (dst->entry_count == 0) {
266 // Appending onto empty buffer, keep sorted state
267 dst->flags |= src->flags & FLAG_SORTED;
268 } else if (src->entry_count != 0) {
269 // Both src, dst are nonempty, cannot assume sort remains
270 dst->flags &= ~FLAG_SORTED;
271 } else {
272 // Src is empty, keep dst sorted state
273 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800274 dst->entry_count += src->entry_count;
275 dst->data_count += src->data_count;
276
277 return OK;
278}
279
280size_t calculate_camera_metadata_entry_data_size(uint8_t type,
281 size_t data_count) {
282 if (type >= NUM_TYPES) return 0;
283 size_t data_bytes = data_count *
284 camera_metadata_type_size[type];
285 return data_bytes <= 4 ? 0 : data_bytes;
286}
287
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700288static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800289 uint32_t tag,
290 uint8_t type,
291 const void *data,
292 size_t data_count) {
293
294 if (dst == NULL) return ERROR;
295 if (dst->entry_count == dst->entry_capacity) return ERROR;
296 if (data == NULL) return ERROR;
297
298 size_t data_bytes =
299 calculate_camera_metadata_entry_data_size(type, data_count);
300
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700301 camera_metadata_buffer_entry_t *entry = dst->entries + dst->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800302 entry->tag = tag;
303 entry->type = type;
304 entry->count = data_count;
305
306 if (data_bytes == 0) {
307 memcpy(entry->data.value, data,
308 data_count * camera_metadata_type_size[type] );
309 } else {
310 entry->data.offset = dst->data_count;
311 memcpy(dst->data + entry->data.offset, data, data_bytes);
312 dst->data_count += data_bytes;
313 }
314 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700315 dst->flags &= ~FLAG_SORTED;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800316 return OK;
317}
318
319int add_camera_metadata_entry(camera_metadata_t *dst,
320 uint32_t tag,
321 const void *data,
322 size_t data_count) {
323
324 int type = get_camera_metadata_tag_type(tag);
325 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700326 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800327 return ERROR;
328 }
329
330 return add_camera_metadata_entry_raw(dst,
331 tag,
332 type,
333 data,
334 data_count);
335}
336
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700337static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700338 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
339 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700340 return tag1 < tag2 ? -1 :
341 tag1 == tag2 ? 0 :
342 1;
343}
344
345int sort_camera_metadata(camera_metadata_t *dst) {
346 if (dst == NULL) return ERROR;
347 if (dst->flags & FLAG_SORTED) return OK;
348
349 qsort(dst->entries, dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700350 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700351 compare_entry_tags);
352 dst->flags |= FLAG_SORTED;
353
354 return OK;
355}
356
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800357int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700358 size_t index,
359 camera_metadata_entry_t *entry) {
360 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800361 if (index >= src->entry_count) return ERROR;
362
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700363 camera_metadata_buffer_entry_t *buffer_entry = src->entries + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800364
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700365 entry->index = index;
366 entry->tag = buffer_entry->tag;
367 entry->type = buffer_entry->type;
368 entry->count = buffer_entry->count;
369 if (buffer_entry->count *
370 camera_metadata_type_size[buffer_entry->type] > 4) {
371 entry->data.u8 = src->data + buffer_entry->data.offset;
372 } else {
373 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700374 }
375 return OK;
376}
377
378int find_camera_metadata_entry(camera_metadata_t *src,
379 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700380 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700381 if (src == NULL) return ERROR;
382
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700383 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700384 if (src->flags & FLAG_SORTED) {
385 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700386 camera_metadata_buffer_entry_t *search_entry = NULL;
387 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700388 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700389 search_entry = bsearch(&key,
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700390 src->entries,
391 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700392 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700393 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700394 if (search_entry == NULL) return NOT_FOUND;
395 index = search_entry - src->entries;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800396 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700397 // Not sorted, linear search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700398 for (index = 0; index < src->entry_count; index++) {
399 if (src->entries[index].tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700400 break;
401 }
402 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700403 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700404 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700405
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700406 return get_camera_metadata_entry(src, index,
407 entry);
408}
409
410int delete_camera_metadata_entry(camera_metadata_t *dst,
411 size_t index) {
412 if (dst == NULL) return ERROR;
413 if (index >= dst->entry_count) return ERROR;
414
415 camera_metadata_buffer_entry_t *entry = dst->entries + index;
416 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
417 entry->count);
418
419 if (data_bytes > 0) {
420 // Shift data buffer to overwrite deleted data
421 uint8_t *start = dst->data + entry->data.offset;
422 uint8_t *end = start + data_bytes;
423 size_t length = dst->data_count - entry->data.offset - data_bytes;
424 memmove(start, end, length);
425
426 // Update all entry indices to account for shift
427 camera_metadata_buffer_entry_t *e = dst->entries;
428 size_t i;
429 for (i = 0; i < dst->entry_count; i++) {
430 if (calculate_camera_metadata_entry_data_size(
431 e->type, e->count) > 0 &&
432 e->data.offset > entry->data.offset) {
433 e->data.offset -= data_bytes;
434 }
435 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700436 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700437 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800438 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700439 // Shift entry array
440 memmove(entry, entry + 1,
441 sizeof(camera_metadata_buffer_entry_t) *
442 (dst->entry_count - index - 1) );
443 dst->entry_count -= 1;
444
445 return OK;
446}
447
448int update_camera_metadata_entry(camera_metadata_t *dst,
449 size_t index,
450 const void *data,
451 size_t data_count,
452 camera_metadata_entry_t *updated_entry) {
453 if (dst == NULL) return ERROR;
454 if (index >= dst->entry_count) return ERROR;
455
456 camera_metadata_buffer_entry_t *entry = dst->entries + index;
457
458 size_t data_bytes =
459 calculate_camera_metadata_entry_data_size(entry->type,
460 data_count);
461 size_t entry_bytes =
462 calculate_camera_metadata_entry_data_size(entry->type,
463 entry->count);
464 if (data_bytes != entry_bytes) {
465 // May need to shift/add to data array
466 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
467 // No room
468 return ERROR;
469 }
470 if (entry_bytes != 0) {
471 // Remove old data
472 uint8_t *start = dst->data + entry->data.offset;
473 uint8_t *end = start + entry_bytes;
474 size_t length = dst->data_count - entry->data.offset - entry_bytes;
475 memmove(start, end, length);
476 dst->data_count -= entry_bytes;
477
478 // Update all entry indices to account for shift
479 camera_metadata_buffer_entry_t *e = dst->entries;
480 size_t i;
481 for (i = 0; i < dst->entry_count; i++) {
482 if (calculate_camera_metadata_entry_data_size(
483 e->type, e->count) > 0 &&
484 e->data.offset > entry->data.offset) {
485 e->data.offset -= entry_bytes;
486 }
487 ++e;
488 }
489 }
490
491 if (data_bytes != 0) {
492 // Append new data
493 entry->data.offset = dst->data_count;
494
495 memcpy(dst->data + entry->data.offset, data, data_bytes);
496 dst->data_count += data_bytes;
497 }
498 } else if (data_bytes != 0) {
499 // data size unchanged, reuse same data location
500 memcpy(dst->data + entry->data.offset, data, data_bytes);
501 }
502
503 if (data_bytes == 0) {
504 // Data fits into entry
505 memcpy(entry->data.value, data,
506 data_count * camera_metadata_type_size[entry->type]);
507 }
508
509 entry->count = data_count;
510
511 if (updated_entry != NULL) {
512 get_camera_metadata_entry(dst,
513 index,
514 updated_entry);
515 }
516
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800517 return OK;
518}
519
520static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
521
522const char *get_camera_metadata_section_name(uint32_t tag) {
523 uint32_t tag_section = tag >> 16;
524 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700525 return vendor_tag_ops->get_camera_vendor_section_name(
526 vendor_tag_ops,
527 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800528 }
529 if (tag_section >= ANDROID_SECTION_COUNT) {
530 return NULL;
531 }
532 return camera_metadata_section_names[tag_section];
533}
534
535const char *get_camera_metadata_tag_name(uint32_t tag) {
536 uint32_t tag_section = tag >> 16;
537 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700538 return vendor_tag_ops->get_camera_vendor_tag_name(
539 vendor_tag_ops,
540 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800541 }
542 if (tag_section >= ANDROID_SECTION_COUNT ||
543 tag >= camera_metadata_section_bounds[tag_section][1] ) {
544 return NULL;
545 }
546 uint32_t tag_index = tag & 0xFFFF;
547 return tag_info[tag_section][tag_index].tag_name;
548}
549
550int get_camera_metadata_tag_type(uint32_t tag) {
551 uint32_t tag_section = tag >> 16;
552 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700553 return vendor_tag_ops->get_camera_vendor_tag_type(
554 vendor_tag_ops,
555 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800556 }
557 if (tag_section >= ANDROID_SECTION_COUNT ||
558 tag >= camera_metadata_section_bounds[tag_section][1] ) {
559 return -1;
560 }
561 uint32_t tag_index = tag & 0xFFFF;
562 return tag_info[tag_section][tag_index].tag_type;
563}
564
565int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
566 vendor_tag_ops = query_ops;
567 return OK;
568}
569
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700570static void print_data(int fd, const uint8_t *data_ptr, int type, int count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800571
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700572void dump_camera_metadata(const camera_metadata_t *metadata,
573 int fd,
574 int verbosity) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800575 if (metadata == NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700576 ALOGE("%s: Metadata is null.", __FUNCTION__);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800577 return;
578 }
579 unsigned int i;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700580 fdprintf(fd,
581 "Dumping camera metadata array. %d entries, "
582 "%d bytes of extra data.\n",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800583 metadata->entry_count, metadata->data_count);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700584 fdprintf(fd, " (%d entries and %d bytes data reserved)\n",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800585 metadata->entry_capacity, metadata->data_capacity);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700586 fdprintf(fd, " Version: %d, Flags: %08x\n",
587 metadata->version, metadata->flags);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800588 for (i=0; i < metadata->entry_count; i++) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700589 camera_metadata_buffer_entry_t *entry = metadata->entries + i;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800590
591 const char *tag_name, *tag_section;
592 tag_section = get_camera_metadata_section_name(entry->tag);
593 if (tag_section == NULL) {
594 tag_section = "unknownSection";
595 }
596 tag_name = get_camera_metadata_tag_name(entry->tag);
597 if (tag_name == NULL) {
598 tag_name = "unknownTag";
599 }
600 const char *type_name;
601 if (entry->type >= NUM_TYPES) {
602 type_name = "unknown";
603 } else {
604 type_name = camera_metadata_type_names[entry->type];
605 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700606 fdprintf(fd, "Tag: %s.%s (%05x): %s[%d]\n",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800607 tag_section,
608 tag_name,
609 entry->tag,
610 type_name,
611 entry->count);
612
613 if (verbosity < 1) continue;
614
615 if (entry->type >= NUM_TYPES) continue;
616
617 size_t type_size = camera_metadata_type_size[entry->type];
618 uint8_t *data_ptr;
619 if ( type_size * entry->count > 4 ) {
620 if (entry->data.offset >= metadata->data_count) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700621 ALOGE("%s: Malformed entry data offset: %d (max %d)",
622 __FUNCTION__,
623 entry->data.offset,
624 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800625 continue;
626 }
627 data_ptr = metadata->data + entry->data.offset;
628 } else {
629 data_ptr = entry->data.value;
630 }
631 int count = entry->count;
632 if (verbosity < 2 && count > 16) count = 16;
633
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700634 print_data(fd, data_ptr, entry->type, count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800635 }
636}
637
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700638static void print_data(int fd, const uint8_t *data_ptr, int type, int count) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800639 static int values_per_line[NUM_TYPES] = {
640 [TYPE_BYTE] = 16,
641 [TYPE_INT32] = 4,
642 [TYPE_FLOAT] = 8,
643 [TYPE_INT64] = 2,
644 [TYPE_DOUBLE] = 4,
645 [TYPE_RATIONAL] = 2,
646 };
647 size_t type_size = camera_metadata_type_size[type];
648
649 int lines = count / values_per_line[type];
650 if (count % values_per_line[type] != 0) lines++;
651
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800652 int index = 0;
653 int j, k;
654 for (j = 0; j < lines; j++) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700655 fdprintf(fd, " [");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800656 for (k = 0;
657 k < values_per_line[type] && count > 0;
658 k++, count--, index += type_size) {
659
660 switch (type) {
661 case TYPE_BYTE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700662 fdprintf(fd, "%hhu ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800663 *(data_ptr + index));
664 break;
665 case TYPE_INT32:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700666 fdprintf(fd, "%d ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800667 *(int32_t*)(data_ptr + index));
668 break;
669 case TYPE_FLOAT:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700670 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800671 *(float*)(data_ptr + index));
672 break;
673 case TYPE_INT64:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700674 fdprintf(fd, "%lld ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800675 *(int64_t*)(data_ptr + index));
676 break;
677 case TYPE_DOUBLE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700678 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800679 *(float*)(data_ptr + index));
680 break;
681 case TYPE_RATIONAL: {
682 int32_t numerator = *(int32_t*)(data_ptr + index);
683 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700684 fdprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800685 numerator, denominator);
686 break;
687 }
688 default:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700689 fdprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800690 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800691 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700692 fdprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800693 }
694}