blob: 4e34ac69a3d0e812b4512747432300f636cdb884 [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>
Igor Murashkind1cecc12013-04-30 17:21:54 -070018
19#define LOG_TAG "camera_metadata"
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080020#include <cutils/log.h>
Alex Ray151389f2013-11-12 18:09:31 -080021#include <assert.h>
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070022#include <stdio.h>
23#include <stdlib.h>
24#include <errno.h>
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080025
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070026#define OK 0
27#define ERROR 1
28#define NOT_FOUND -ENOENT
Eino-Ville Talvala31540362012-11-07 16:36:50 -080029
30#define _Alignas(T) \
31 ({struct _AlignasStruct { char c; T field; }; \
32 offsetof(struct _AlignasStruct, field); })
33
34// Align entry buffers as the compiler would
35#define ENTRY_ALIGNMENT _Alignas(camera_metadata_buffer_entry_t)
36// Align data buffer to largest supported data type
Igor Murashkin555aac82012-11-15 10:54:57 -080037#define DATA_ALIGNMENT _Alignas(camera_metadata_data_t)
Eino-Ville Talvala31540362012-11-07 16:36:50 -080038
39#define ALIGN_TO(val, alignment) \
Igor Murashkind1cecc12013-04-30 17:21:54 -070040 (((uintptr_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
41
42typedef size_t uptrdiff_t;
Eino-Ville Talvala31540362012-11-07 16:36:50 -080043
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080044/**
45 * A single metadata entry, storing an array of values of a given type. If the
46 * array is no larger than 4 bytes in size, it is stored in the data.value[]
47 * array; otherwise, it can found in the parent's data array at index
48 * data.offset.
49 */
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070050typedef struct camera_metadata_buffer_entry {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080051 uint32_t tag;
52 size_t count;
53 union {
54 size_t offset;
55 uint8_t value[4];
56 } data;
57 uint8_t type;
58 uint8_t reserved[3];
Eino-Ville Talvala31540362012-11-07 16:36:50 -080059} camera_metadata_buffer_entry_t;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080060
61/**
62 * A packet of metadata. This is a list of entries, each of which may point to
63 * its values stored at an offset in data.
64 *
65 * It is assumed by the utility functions that the memory layout of the packet
66 * is as follows:
67 *
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070068 * |-----------------------------------------------|
69 * | camera_metadata_t |
70 * | |
71 * |-----------------------------------------------|
72 * | reserved for future expansion |
73 * |-----------------------------------------------|
74 * | camera_metadata_buffer_entry_t #0 |
75 * |-----------------------------------------------|
76 * | .... |
77 * |-----------------------------------------------|
78 * | camera_metadata_buffer_entry_t #entry_count-1 |
79 * |-----------------------------------------------|
80 * | free space for |
81 * | (entry_capacity-entry_count) entries |
82 * |-----------------------------------------------|
83 * | start of camera_metadata.data |
84 * | |
85 * |-----------------------------------------------|
86 * | free space for |
87 * | (data_capacity-data_count) bytes |
88 * |-----------------------------------------------|
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080089 *
90 * With the total length of the whole packet being camera_metadata.size bytes.
91 *
92 * In short, the entries and data are contiguous in memory after the metadata
93 * header.
94 */
95struct camera_metadata {
96 size_t size;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070097 uint32_t version;
98 uint32_t flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080099 size_t entry_count;
100 size_t entry_capacity;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700101 uptrdiff_t entries_start; // Offset from camera_metadata
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800102 size_t data_count;
103 size_t data_capacity;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700104 uptrdiff_t data_start; // Offset from camera_metadata
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700105 void *user; // User set pointer, not copied with buffer
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800106 uint8_t reserved[0];
107};
108
Igor Murashkin555aac82012-11-15 10:54:57 -0800109/**
110 * A datum of metadata. This corresponds to camera_metadata_entry_t::data
111 * with the difference that each element is not a pointer. We need to have a
112 * non-pointer type description in order to figure out the largest alignment
113 * requirement for data (DATA_ALIGNMENT).
114 */
115typedef union camera_metadata_data {
116 uint8_t u8;
117 int32_t i32;
118 float f;
119 int64_t i64;
120 double d;
121 camera_metadata_rational_t r;
122} camera_metadata_data_t;
123
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700124/** Versioning information */
125#define CURRENT_METADATA_VERSION 1
126
127/** Flag definitions */
128#define FLAG_SORTED 0x00000001
129
130/** Tag information */
131
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800132typedef struct tag_info {
133 const char *tag_name;
134 uint8_t tag_type;
135} tag_info_t;
136
137#include "camera_metadata_tag_info.c"
138
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700139const size_t camera_metadata_type_size[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800140 [TYPE_BYTE] = sizeof(uint8_t),
141 [TYPE_INT32] = sizeof(int32_t),
142 [TYPE_FLOAT] = sizeof(float),
143 [TYPE_INT64] = sizeof(int64_t),
144 [TYPE_DOUBLE] = sizeof(double),
145 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
146};
147
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700148const char *camera_metadata_type_names[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800149 [TYPE_BYTE] = "byte",
150 [TYPE_INT32] = "int32",
151 [TYPE_FLOAT] = "float",
152 [TYPE_INT64] = "int64",
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700153 [TYPE_DOUBLE] = "double",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800154 [TYPE_RATIONAL] = "rational"
155};
156
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800157static camera_metadata_buffer_entry_t *get_entries(
158 const camera_metadata_t *metadata) {
159 return (camera_metadata_buffer_entry_t*)
160 ((uint8_t*)metadata + metadata->entries_start);
161}
162
163static uint8_t *get_data(const camera_metadata_t *metadata) {
164 return (uint8_t*)metadata + metadata->data_start;
165}
166
Igor Murashkind1cecc12013-04-30 17:21:54 -0700167camera_metadata_t *allocate_copy_camera_metadata_checked(
168 const camera_metadata_t *src,
169 size_t src_size) {
170
171 if (src == NULL) {
172 return NULL;
173 }
174
175 void *buffer = malloc(src_size);
176 memcpy(buffer, src, src_size);
177
178 camera_metadata_t *metadata = (camera_metadata_t*) buffer;
179 if (validate_camera_metadata_structure(metadata, &src_size) != OK) {
180 free(buffer);
181 return NULL;
182 }
183
184 return metadata;
185}
186
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800187camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
188 size_t data_capacity) {
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700189 if (entry_capacity == 0) return NULL;
190
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800191 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
192 data_capacity);
193 void *buffer = malloc(memory_needed);
194 return place_camera_metadata(buffer, memory_needed,
195 entry_capacity,
196 data_capacity);
197}
198
199camera_metadata_t *place_camera_metadata(void *dst,
200 size_t dst_size,
201 size_t entry_capacity,
202 size_t data_capacity) {
203 if (dst == NULL) return NULL;
204 if (entry_capacity == 0) return NULL;
205
206 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
207 data_capacity);
208 if (memory_needed > dst_size) return NULL;
209
210 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700211 metadata->version = CURRENT_METADATA_VERSION;
212 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800213 metadata->entry_count = 0;
214 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800215 metadata->entries_start =
216 ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800217 metadata->data_count = 0;
218 metadata->data_capacity = data_capacity;
219 metadata->size = memory_needed;
Igor Murashkind1cecc12013-04-30 17:21:54 -0700220 size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
221 metadata->entry_capacity) - (uint8_t*)metadata;
222 metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700223 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800224
Alex Ray151389f2013-11-12 18:09:31 -0800225 assert(validate_camera_metadata_structure(metadata, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800226 return metadata;
227}
228void free_camera_metadata(camera_metadata_t *metadata) {
229 free(metadata);
230}
231
232size_t calculate_camera_metadata_size(size_t entry_count,
233 size_t data_count) {
234 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800235 // Start entry list at aligned boundary
236 memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700237 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800238 // Start buffer list at aligned boundary
239 memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800240 memory_needed += sizeof(uint8_t[data_count]);
241 return memory_needed;
242}
243
244size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
245 if (metadata == NULL) return ERROR;
246
247 return metadata->size;
248}
249
250size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
251 if (metadata == NULL) return ERROR;
252
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800253 return calculate_camera_metadata_size(metadata->entry_count,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800254 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800255}
256
257size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
258 return metadata->entry_count;
259}
260
261size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
262 return metadata->entry_capacity;
263}
264
265size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
266 return metadata->data_count;
267}
268
269size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
270 return metadata->data_capacity;
271}
272
273camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
274 const camera_metadata_t *src) {
275 size_t memory_needed = get_camera_metadata_compact_size(src);
276
277 if (dst == NULL) return NULL;
278 if (dst_size < memory_needed) return NULL;
279
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800280 camera_metadata_t *metadata =
281 place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800282
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700283 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800284 metadata->entry_count = src->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800285 metadata->data_count = src->data_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800286
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800287 memcpy(get_entries(metadata), get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700288 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800289 memcpy(get_data(metadata), get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800290 sizeof(uint8_t[metadata->data_count]));
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700291 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800292
Alex Ray151389f2013-11-12 18:09:31 -0800293 assert(validate_camera_metadata_structure(metadata, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800294 return metadata;
295}
296
Igor Murashkind1cecc12013-04-30 17:21:54 -0700297int validate_camera_metadata_structure(const camera_metadata_t *metadata,
298 const size_t *expected_size) {
299
300 if (metadata == NULL) {
301 return ERROR;
302 }
303
304 // Check that the metadata pointer is well-aligned first.
305 {
306 struct {
307 const char *name;
308 size_t alignment;
309 } alignments[] = {
310 {
311 .name = "camera_metadata",
312 .alignment = _Alignas(struct camera_metadata)
313 },
314 {
315 .name = "camera_metadata_buffer_entry",
316 .alignment = _Alignas(struct camera_metadata_buffer_entry)
317 },
318 {
319 .name = "camera_metadata_data",
320 .alignment = _Alignas(union camera_metadata_data)
321 },
322 };
323
324 for (size_t i = 0; i < sizeof(alignments)/sizeof(alignments[0]); ++i) {
325 uintptr_t aligned_ptr = ALIGN_TO(metadata, alignments[i].alignment);
326
327 if ((uintptr_t)metadata != aligned_ptr) {
328 ALOGE("%s: Metadata pointer is not aligned (actual %p, "
329 "expected %p) to type %s",
330 __FUNCTION__, metadata,
331 (void*)aligned_ptr, alignments[i].name);
332 return ERROR;
333 }
334 }
335 }
336
337 /**
338 * Check that the metadata contents are correct
339 */
340
341 if (expected_size != NULL && metadata->size > *expected_size) {
342 ALOGE("%s: Metadata size (%u) should be <= expected size (%u)",
343 __FUNCTION__, metadata->size, *expected_size);
344 return ERROR;
345 }
346
347 if (metadata->entry_count > metadata->entry_capacity) {
348 ALOGE("%s: Entry count (%u) should be <= entry capacity (%u)",
349 __FUNCTION__, metadata->entry_count, metadata->entry_capacity);
350 return ERROR;
351 }
352
353 uptrdiff_t entries_end = metadata->entries_start + metadata->entry_capacity;
354 if (entries_end < metadata->entries_start || // overflow check
355 entries_end > metadata->data_start) {
356
357 ALOGE("%s: Entry start + capacity (%u) should be <= data start (%u)",
358 __FUNCTION__,
359 (metadata->entries_start + metadata->entry_capacity),
360 metadata->data_start);
361 return ERROR;
362 }
363
364 uptrdiff_t data_end = metadata->data_start + metadata->data_capacity;
365 if (data_end < metadata->data_start || // overflow check
366 data_end > metadata->size) {
367
368 ALOGE("%s: Data start + capacity (%u) should be <= total size (%u)",
369 __FUNCTION__,
370 (metadata->data_start + metadata->data_capacity),
371 metadata->size);
372 return ERROR;
373 }
374
375 // Validate each entry
376 size_t entry_count = metadata->entry_count;
377 camera_metadata_buffer_entry_t *entries = get_entries(metadata);
378
379 for (size_t i = 0; i < entry_count; ++i) {
380
381 if ((uintptr_t)&entries[i] != ALIGN_TO(&entries[i], ENTRY_ALIGNMENT)) {
382 ALOGE("%s: Entry index %u had bad alignment (address %p),"
383 " expected alignment %d",
384 __FUNCTION__, i, &entries[i], ENTRY_ALIGNMENT);
385 return ERROR;
386 }
387
388 camera_metadata_buffer_entry_t entry = entries[i];
389
390 if (entry.type >= NUM_TYPES) {
391 ALOGE("%s: Entry index %u had a bad type %d",
392 __FUNCTION__, i, entry.type);
393 return ERROR;
394 }
395
396 // TODO: fix vendor_tag_ops across processes so we don't need to special
397 // case vendor-specific tags
398 uint32_t tag_section = entry.tag >> 16;
399 int tag_type = get_camera_metadata_tag_type(entry.tag);
400 if (tag_type != (int)entry.type && tag_section < VENDOR_SECTION) {
401 ALOGE("%s: Entry index %u had tag type %d, but the type was %d",
402 __FUNCTION__, i, tag_type, entry.type);
403 return ERROR;
404 }
405
406 size_t data_size =
407 calculate_camera_metadata_entry_data_size(entry.type,
408 entry.count);
409
410 if (data_size != 0) {
411 camera_metadata_data_t *data =
412 (camera_metadata_data_t*) (get_data(metadata) +
413 entry.data.offset);
414
415 if ((uintptr_t)data != ALIGN_TO(data, DATA_ALIGNMENT)) {
416 ALOGE("%s: Entry index %u had bad data alignment (address %p),"
417 " expected align %d, (tag name %s, data size %u)",
418 __FUNCTION__, i, data, DATA_ALIGNMENT,
419 get_camera_metadata_tag_name(entry.tag) ?: "unknown",
420 data_size);
421 return ERROR;
422 }
423
424 size_t data_entry_end = entry.data.offset + data_size;
425 if (data_entry_end < entry.data.offset || // overflow check
426 data_entry_end > metadata->data_capacity) {
427
428 ALOGE("%s: Entry index %u data ends (%u) beyond the capacity "
429 "%u", __FUNCTION__, i, data_entry_end,
430 metadata->data_capacity);
431 return ERROR;
432 }
433
434 } else if (entry.count == 0) {
435 if (entry.data.offset != 0) {
436 ALOGE("%s: Entry index %u had 0 items, but offset was non-0 "
Zhijun He3064d312013-07-15 13:55:11 -0700437 "(%u), tag name: %s", __FUNCTION__, i, entry.data.offset,
438 get_camera_metadata_tag_name(entry.tag) ?: "unknown");
Igor Murashkind1cecc12013-04-30 17:21:54 -0700439 return ERROR;
440 }
441 } // else data stored inline, so we look at value which can be anything.
442 }
443
444 return OK;
445}
446
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800447int append_camera_metadata(camera_metadata_t *dst,
448 const camera_metadata_t *src) {
449 if (dst == NULL || src == NULL ) return ERROR;
450
451 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
452 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
453
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800454 memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700455 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800456 memcpy(get_data(dst) + dst->data_count, get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800457 sizeof(uint8_t[src->data_count]));
458 if (dst->data_count != 0) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800459 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
460 for (size_t i = 0; i < src->entry_count; i++, entry++) {
461 if ( calculate_camera_metadata_entry_data_size(entry->type,
462 entry->count) > 0 ) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800463 entry->data.offset += dst->data_count;
464 }
465 }
466 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700467 if (dst->entry_count == 0) {
468 // Appending onto empty buffer, keep sorted state
469 dst->flags |= src->flags & FLAG_SORTED;
470 } else if (src->entry_count != 0) {
471 // Both src, dst are nonempty, cannot assume sort remains
472 dst->flags &= ~FLAG_SORTED;
473 } else {
474 // Src is empty, keep dst sorted state
475 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800476 dst->entry_count += src->entry_count;
477 dst->data_count += src->data_count;
478
Alex Ray151389f2013-11-12 18:09:31 -0800479 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800480 return OK;
481}
482
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700483camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700484 int res;
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700485 if (src == NULL) return NULL;
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700486 camera_metadata_t *clone = allocate_camera_metadata(
487 get_camera_metadata_entry_count(src),
488 get_camera_metadata_data_count(src));
489 if (clone != NULL) {
490 res = append_camera_metadata(clone, src);
491 if (res != OK) {
492 free_camera_metadata(clone);
493 clone = NULL;
494 }
495 }
Alex Ray151389f2013-11-12 18:09:31 -0800496 assert(validate_camera_metadata_structure(clone, NULL) == OK);
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700497 return clone;
498}
499
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800500size_t calculate_camera_metadata_entry_data_size(uint8_t type,
501 size_t data_count) {
502 if (type >= NUM_TYPES) return 0;
503 size_t data_bytes = data_count *
504 camera_metadata_type_size[type];
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800505 return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800506}
507
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700508static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800509 uint32_t tag,
510 uint8_t type,
511 const void *data,
512 size_t data_count) {
513
514 if (dst == NULL) return ERROR;
515 if (dst->entry_count == dst->entry_capacity) return ERROR;
516 if (data == NULL) return ERROR;
517
518 size_t data_bytes =
519 calculate_camera_metadata_entry_data_size(type, data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800520 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800521
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800522 size_t data_payload_bytes =
523 data_count * camera_metadata_type_size[type];
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800524 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
Zhijun He3064d312013-07-15 13:55:11 -0700525 memset(entry, 0, sizeof(camera_metadata_buffer_entry_t));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800526 entry->tag = tag;
527 entry->type = type;
528 entry->count = data_count;
529
530 if (data_bytes == 0) {
531 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800532 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800533 } else {
534 entry->data.offset = dst->data_count;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800535 memcpy(get_data(dst) + entry->data.offset, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800536 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800537 dst->data_count += data_bytes;
538 }
539 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700540 dst->flags &= ~FLAG_SORTED;
Alex Ray151389f2013-11-12 18:09:31 -0800541 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800542 return OK;
543}
544
545int add_camera_metadata_entry(camera_metadata_t *dst,
546 uint32_t tag,
547 const void *data,
548 size_t data_count) {
549
550 int type = get_camera_metadata_tag_type(tag);
551 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700552 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800553 return ERROR;
554 }
555
556 return add_camera_metadata_entry_raw(dst,
557 tag,
558 type,
559 data,
560 data_count);
561}
562
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700563static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700564 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
565 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700566 return tag1 < tag2 ? -1 :
567 tag1 == tag2 ? 0 :
568 1;
569}
570
571int sort_camera_metadata(camera_metadata_t *dst) {
572 if (dst == NULL) return ERROR;
573 if (dst->flags & FLAG_SORTED) return OK;
574
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800575 qsort(get_entries(dst), dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700576 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700577 compare_entry_tags);
578 dst->flags |= FLAG_SORTED;
579
Alex Ray151389f2013-11-12 18:09:31 -0800580 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700581 return OK;
582}
583
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800584int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700585 size_t index,
586 camera_metadata_entry_t *entry) {
587 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800588 if (index >= src->entry_count) return ERROR;
589
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800590 camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800591
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700592 entry->index = index;
593 entry->tag = buffer_entry->tag;
594 entry->type = buffer_entry->type;
595 entry->count = buffer_entry->count;
596 if (buffer_entry->count *
597 camera_metadata_type_size[buffer_entry->type] > 4) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800598 entry->data.u8 = get_data(src) + buffer_entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700599 } else {
600 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700601 }
602 return OK;
603}
604
Alex Ray71fe0f82013-10-21 12:57:05 -0700605int get_camera_metadata_ro_entry(const camera_metadata_t *src,
606 size_t index,
607 camera_metadata_ro_entry_t *entry) {
608 return get_camera_metadata_entry((camera_metadata_t*)src, index,
609 (camera_metadata_entry_t*)entry);
610}
611
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700612int find_camera_metadata_entry(camera_metadata_t *src,
613 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700614 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700615 if (src == NULL) return ERROR;
616
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700617 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700618 if (src->flags & FLAG_SORTED) {
619 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700620 camera_metadata_buffer_entry_t *search_entry = NULL;
621 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700622 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700623 search_entry = bsearch(&key,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800624 get_entries(src),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700625 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700626 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700627 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700628 if (search_entry == NULL) return NOT_FOUND;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800629 index = search_entry - get_entries(src);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800630 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700631 // Not sorted, linear search
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800632 camera_metadata_buffer_entry_t *search_entry = get_entries(src);
633 for (index = 0; index < src->entry_count; index++, search_entry++) {
634 if (search_entry->tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700635 break;
636 }
637 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700638 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700639 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700640
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700641 return get_camera_metadata_entry(src, index,
642 entry);
643}
644
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700645int find_camera_metadata_ro_entry(const camera_metadata_t *src,
646 uint32_t tag,
647 camera_metadata_ro_entry_t *entry) {
648 return find_camera_metadata_entry((camera_metadata_t*)src, tag,
649 (camera_metadata_entry_t*)entry);
650}
651
652
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700653int delete_camera_metadata_entry(camera_metadata_t *dst,
654 size_t index) {
655 if (dst == NULL) return ERROR;
656 if (index >= dst->entry_count) return ERROR;
657
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800658 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700659 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
660 entry->count);
661
662 if (data_bytes > 0) {
663 // Shift data buffer to overwrite deleted data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800664 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700665 uint8_t *end = start + data_bytes;
666 size_t length = dst->data_count - entry->data.offset - data_bytes;
667 memmove(start, end, length);
668
669 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800670 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700671 size_t i;
672 for (i = 0; i < dst->entry_count; i++) {
673 if (calculate_camera_metadata_entry_data_size(
674 e->type, e->count) > 0 &&
675 e->data.offset > entry->data.offset) {
676 e->data.offset -= data_bytes;
677 }
678 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700679 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700680 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800681 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700682 // Shift entry array
683 memmove(entry, entry + 1,
684 sizeof(camera_metadata_buffer_entry_t) *
685 (dst->entry_count - index - 1) );
686 dst->entry_count -= 1;
687
Alex Ray151389f2013-11-12 18:09:31 -0800688 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700689 return OK;
690}
691
692int update_camera_metadata_entry(camera_metadata_t *dst,
693 size_t index,
694 const void *data,
695 size_t data_count,
696 camera_metadata_entry_t *updated_entry) {
697 if (dst == NULL) return ERROR;
698 if (index >= dst->entry_count) return ERROR;
699
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800700 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700701
702 size_t data_bytes =
703 calculate_camera_metadata_entry_data_size(entry->type,
704 data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800705 size_t data_payload_bytes =
706 data_count * camera_metadata_type_size[entry->type];
707
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700708 size_t entry_bytes =
709 calculate_camera_metadata_entry_data_size(entry->type,
710 entry->count);
711 if (data_bytes != entry_bytes) {
712 // May need to shift/add to data array
713 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
714 // No room
715 return ERROR;
716 }
717 if (entry_bytes != 0) {
718 // Remove old data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800719 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700720 uint8_t *end = start + entry_bytes;
721 size_t length = dst->data_count - entry->data.offset - entry_bytes;
722 memmove(start, end, length);
723 dst->data_count -= entry_bytes;
724
725 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800726 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700727 size_t i;
728 for (i = 0; i < dst->entry_count; i++) {
729 if (calculate_camera_metadata_entry_data_size(
730 e->type, e->count) > 0 &&
731 e->data.offset > entry->data.offset) {
732 e->data.offset -= entry_bytes;
733 }
734 ++e;
735 }
736 }
737
738 if (data_bytes != 0) {
739 // Append new data
740 entry->data.offset = dst->data_count;
741
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800742 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700743 dst->data_count += data_bytes;
744 }
745 } else if (data_bytes != 0) {
746 // data size unchanged, reuse same data location
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800747 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700748 }
749
750 if (data_bytes == 0) {
751 // Data fits into entry
752 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800753 data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700754 }
755
756 entry->count = data_count;
757
758 if (updated_entry != NULL) {
759 get_camera_metadata_entry(dst,
760 index,
761 updated_entry);
762 }
763
Alex Ray151389f2013-11-12 18:09:31 -0800764 assert(validate_camera_metadata_structure(dst, NULL) == OK);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800765 return OK;
766}
767
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700768int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
769 if (dst == NULL) return ERROR;
770 dst->user = user;
771 return OK;
772}
773
774int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
775 if (dst == NULL) return ERROR;
776 *user = dst->user;
777 return OK;
778}
779
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800780static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
781
782const char *get_camera_metadata_section_name(uint32_t tag) {
783 uint32_t tag_section = tag >> 16;
784 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700785 return vendor_tag_ops->get_camera_vendor_section_name(
786 vendor_tag_ops,
787 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800788 }
789 if (tag_section >= ANDROID_SECTION_COUNT) {
790 return NULL;
791 }
792 return camera_metadata_section_names[tag_section];
793}
794
795const char *get_camera_metadata_tag_name(uint32_t tag) {
796 uint32_t tag_section = tag >> 16;
797 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700798 return vendor_tag_ops->get_camera_vendor_tag_name(
799 vendor_tag_ops,
800 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800801 }
802 if (tag_section >= ANDROID_SECTION_COUNT ||
803 tag >= camera_metadata_section_bounds[tag_section][1] ) {
804 return NULL;
805 }
806 uint32_t tag_index = tag & 0xFFFF;
807 return tag_info[tag_section][tag_index].tag_name;
808}
809
810int get_camera_metadata_tag_type(uint32_t tag) {
811 uint32_t tag_section = tag >> 16;
812 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700813 return vendor_tag_ops->get_camera_vendor_tag_type(
814 vendor_tag_ops,
815 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800816 }
817 if (tag_section >= ANDROID_SECTION_COUNT ||
818 tag >= camera_metadata_section_bounds[tag_section][1] ) {
819 return -1;
820 }
821 uint32_t tag_index = tag & 0xFFFF;
822 return tag_info[tag_section][tag_index].tag_type;
823}
824
825int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
826 vendor_tag_ops = query_ops;
827 return OK;
828}
829
Igor Murashkin375cfd32012-12-03 13:55:33 -0800830static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag, int type,
831 int count,
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700832 int indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800833
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700834void dump_camera_metadata(const camera_metadata_t *metadata,
835 int fd,
836 int verbosity) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700837 dump_indented_camera_metadata(metadata, fd, verbosity, 0);
838}
839
840void dump_indented_camera_metadata(const camera_metadata_t *metadata,
841 int fd,
842 int verbosity,
843 int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800844 if (metadata == NULL) {
Eino-Ville Talvala94879bd2012-10-01 16:33:03 -0700845 fdprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700846 indentation, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800847 return;
848 }
849 unsigned int i;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700850 fdprintf(fd,
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700851 "%*sDumping camera metadata array: %d / %d entries, "
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700852 "%d / %d bytes of extra data.\n", indentation, "",
853 metadata->entry_count, metadata->entry_capacity,
854 metadata->data_count, metadata->data_capacity);
855 fdprintf(fd, "%*sVersion: %d, Flags: %08x\n",
856 indentation + 2, "",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700857 metadata->version, metadata->flags);
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800858 camera_metadata_buffer_entry_t *entry = get_entries(metadata);
859 for (i=0; i < metadata->entry_count; i++, entry++) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800860
861 const char *tag_name, *tag_section;
862 tag_section = get_camera_metadata_section_name(entry->tag);
863 if (tag_section == NULL) {
864 tag_section = "unknownSection";
865 }
866 tag_name = get_camera_metadata_tag_name(entry->tag);
867 if (tag_name == NULL) {
868 tag_name = "unknownTag";
869 }
870 const char *type_name;
871 if (entry->type >= NUM_TYPES) {
872 type_name = "unknown";
873 } else {
874 type_name = camera_metadata_type_names[entry->type];
875 }
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700876 fdprintf(fd, "%*s%s.%s (%05x): %s[%d]\n",
877 indentation + 2, "",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800878 tag_section,
879 tag_name,
880 entry->tag,
881 type_name,
882 entry->count);
883
884 if (verbosity < 1) continue;
885
886 if (entry->type >= NUM_TYPES) continue;
887
888 size_t type_size = camera_metadata_type_size[entry->type];
889 uint8_t *data_ptr;
890 if ( type_size * entry->count > 4 ) {
891 if (entry->data.offset >= metadata->data_count) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700892 ALOGE("%s: Malformed entry data offset: %d (max %d)",
893 __FUNCTION__,
894 entry->data.offset,
895 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800896 continue;
897 }
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800898 data_ptr = get_data(metadata) + entry->data.offset;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800899 } else {
900 data_ptr = entry->data.value;
901 }
902 int count = entry->count;
903 if (verbosity < 2 && count > 16) count = 16;
904
Igor Murashkin375cfd32012-12-03 13:55:33 -0800905 print_data(fd, data_ptr, entry->tag, entry->type, count, indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800906 }
907}
908
Igor Murashkin375cfd32012-12-03 13:55:33 -0800909static void print_data(int fd, const uint8_t *data_ptr, uint32_t tag,
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700910 int type, int count, int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800911 static int values_per_line[NUM_TYPES] = {
912 [TYPE_BYTE] = 16,
913 [TYPE_INT32] = 4,
914 [TYPE_FLOAT] = 8,
915 [TYPE_INT64] = 2,
916 [TYPE_DOUBLE] = 4,
917 [TYPE_RATIONAL] = 2,
918 };
919 size_t type_size = camera_metadata_type_size[type];
Igor Murashkin375cfd32012-12-03 13:55:33 -0800920 char value_string_tmp[CAMERA_METADATA_ENUM_STRING_MAX_SIZE];
921 uint32_t value;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800922
923 int lines = count / values_per_line[type];
924 if (count % values_per_line[type] != 0) lines++;
925
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800926 int index = 0;
927 int j, k;
928 for (j = 0; j < lines; j++) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700929 fdprintf(fd, "%*s[", indentation + 4, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800930 for (k = 0;
931 k < values_per_line[type] && count > 0;
932 k++, count--, index += type_size) {
933
934 switch (type) {
935 case TYPE_BYTE:
Igor Murashkin375cfd32012-12-03 13:55:33 -0800936 value = *(data_ptr + index);
937 if (camera_metadata_enum_snprint(tag,
938 value,
939 value_string_tmp,
940 sizeof(value_string_tmp))
941 == OK) {
942 fdprintf(fd, "%s ", value_string_tmp);
943 } else {
944 fdprintf(fd, "%hhu ",
945 *(data_ptr + index));
946 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800947 break;
948 case TYPE_INT32:
Igor Murashkin375cfd32012-12-03 13:55:33 -0800949 value =
950 *(int32_t*)(data_ptr + index);
951 if (camera_metadata_enum_snprint(tag,
952 value,
953 value_string_tmp,
954 sizeof(value_string_tmp))
955 == OK) {
956 fdprintf(fd, "%s ", value_string_tmp);
957 } else {
958 fdprintf(fd, "%d ",
959 *(int32_t*)(data_ptr + index));
960 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800961 break;
962 case TYPE_FLOAT:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700963 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800964 *(float*)(data_ptr + index));
965 break;
966 case TYPE_INT64:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700967 fdprintf(fd, "%lld ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800968 *(int64_t*)(data_ptr + index));
969 break;
970 case TYPE_DOUBLE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700971 fdprintf(fd, "%0.2f ",
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800972 *(double*)(data_ptr + index));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800973 break;
974 case TYPE_RATIONAL: {
975 int32_t numerator = *(int32_t*)(data_ptr + index);
976 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700977 fdprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800978 numerator, denominator);
979 break;
980 }
981 default:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700982 fdprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800983 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800984 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700985 fdprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800986 }
987}