blob: ee00ee602b1ea1b6c2fe3551ae545eeddb4c95fa [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;
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -070087 void *user; // User set pointer, not copied with buffer
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080088 uint8_t reserved[0];
89};
90
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070091/** Versioning information */
92#define CURRENT_METADATA_VERSION 1
93
94/** Flag definitions */
95#define FLAG_SORTED 0x00000001
96
97/** Tag information */
98
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080099typedef struct tag_info {
100 const char *tag_name;
101 uint8_t tag_type;
102} tag_info_t;
103
104#include "camera_metadata_tag_info.c"
105
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700106const size_t camera_metadata_type_size[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800107 [TYPE_BYTE] = sizeof(uint8_t),
108 [TYPE_INT32] = sizeof(int32_t),
109 [TYPE_FLOAT] = sizeof(float),
110 [TYPE_INT64] = sizeof(int64_t),
111 [TYPE_DOUBLE] = sizeof(double),
112 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
113};
114
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700115const char *camera_metadata_type_names[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800116 [TYPE_BYTE] = "byte",
117 [TYPE_INT32] = "int32",
118 [TYPE_FLOAT] = "float",
119 [TYPE_INT64] = "int64",
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700120 [TYPE_DOUBLE] = "double",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800121 [TYPE_RATIONAL] = "rational"
122};
123
124camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
125 size_t data_capacity) {
126 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
127 data_capacity);
128 void *buffer = malloc(memory_needed);
129 return place_camera_metadata(buffer, memory_needed,
130 entry_capacity,
131 data_capacity);
132}
133
134camera_metadata_t *place_camera_metadata(void *dst,
135 size_t dst_size,
136 size_t entry_capacity,
137 size_t data_capacity) {
138 if (dst == NULL) return NULL;
139 if (entry_capacity == 0) return NULL;
140
141 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
142 data_capacity);
143 if (memory_needed > dst_size) return NULL;
144
145 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700146 metadata->version = CURRENT_METADATA_VERSION;
147 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800148 metadata->entry_count = 0;
149 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700150 metadata->entries = (camera_metadata_buffer_entry_t*)(metadata + 1);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800151 metadata->data_count = 0;
152 metadata->data_capacity = data_capacity;
153 metadata->size = memory_needed;
154 if (metadata->data_capacity != 0) {
155 metadata->data =
156 (uint8_t*)(metadata->entries + metadata->entry_capacity);
157 } else {
158 metadata->data = NULL;
159 }
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700160 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800161
162 return metadata;
163}
164void free_camera_metadata(camera_metadata_t *metadata) {
165 free(metadata);
166}
167
168size_t calculate_camera_metadata_size(size_t entry_count,
169 size_t data_count) {
170 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700171 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800172 memory_needed += sizeof(uint8_t[data_count]);
173 return memory_needed;
174}
175
176size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
177 if (metadata == NULL) return ERROR;
178
179 return metadata->size;
180}
181
182size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
183 if (metadata == NULL) return ERROR;
184
185 ptrdiff_t reserved_size = metadata->size -
186 calculate_camera_metadata_size(metadata->entry_capacity,
187 metadata->data_capacity);
188
189 return calculate_camera_metadata_size(metadata->entry_count,
190 metadata->data_count) + reserved_size;
191}
192
193size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
194 return metadata->entry_count;
195}
196
197size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
198 return metadata->entry_capacity;
199}
200
201size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
202 return metadata->data_count;
203}
204
205size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
206 return metadata->data_capacity;
207}
208
209camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
210 const camera_metadata_t *src) {
211 size_t memory_needed = get_camera_metadata_compact_size(src);
212
213 if (dst == NULL) return NULL;
214 if (dst_size < memory_needed) return NULL;
215
216 // If copying a newer version of the structure, there may be additional
217 // header fields we don't know about but need to copy
218 ptrdiff_t reserved_size = src->size -
219 calculate_camera_metadata_size(src->entry_capacity,
220 src->data_capacity);
221
222 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700223 metadata->version = CURRENT_METADATA_VERSION;
224 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800225 metadata->entry_count = src->entry_count;
226 metadata->entry_capacity = src->entry_count;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700227 metadata->entries = (camera_metadata_buffer_entry_t*)
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800228 ((uint8_t *)(metadata + 1) + reserved_size);
229 metadata->data_count = src->data_count;
230 metadata->data_capacity = src->data_count;
231 metadata->data = (uint8_t *)(metadata->entries + metadata->entry_capacity);
232 metadata->size = memory_needed;
233
234 if (reserved_size > 0) {
235 memcpy(metadata->reserved, src->reserved, reserved_size);
236 }
237 memcpy(metadata->entries, src->entries,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700238 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800239 memcpy(metadata->data, src->data,
240 sizeof(uint8_t[metadata->data_count]));
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700241 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800242
243 return metadata;
244}
245
246int append_camera_metadata(camera_metadata_t *dst,
247 const camera_metadata_t *src) {
248 if (dst == NULL || src == NULL ) return ERROR;
249
250 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
251 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
252
253 memcpy(dst->entries + dst->entry_count, src->entries,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700254 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800255 memcpy(dst->data + dst->data_count, src->data,
256 sizeof(uint8_t[src->data_count]));
257 if (dst->data_count != 0) {
258 unsigned int i;
259 for (i = dst->entry_count;
260 i < dst->entry_count + src->entry_count;
261 i++) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700262 camera_metadata_buffer_entry_t *entry = dst->entries + i;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800263 if ( camera_metadata_type_size[entry->type] * entry->count > 4 ) {
264 entry->data.offset += dst->data_count;
265 }
266 }
267 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700268 if (dst->entry_count == 0) {
269 // Appending onto empty buffer, keep sorted state
270 dst->flags |= src->flags & FLAG_SORTED;
271 } else if (src->entry_count != 0) {
272 // Both src, dst are nonempty, cannot assume sort remains
273 dst->flags &= ~FLAG_SORTED;
274 } else {
275 // Src is empty, keep dst sorted state
276 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800277 dst->entry_count += src->entry_count;
278 dst->data_count += src->data_count;
279
280 return OK;
281}
282
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700283camera_metadata_t *clone_camera_metadata(camera_metadata_t *src) {
284 int res;
285 camera_metadata_t *clone = allocate_camera_metadata(
286 get_camera_metadata_entry_count(src),
287 get_camera_metadata_data_count(src));
288 if (clone != NULL) {
289 res = append_camera_metadata(clone, src);
290 if (res != OK) {
291 free_camera_metadata(clone);
292 clone = NULL;
293 }
294 }
295 return clone;
296}
297
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800298size_t calculate_camera_metadata_entry_data_size(uint8_t type,
299 size_t data_count) {
300 if (type >= NUM_TYPES) return 0;
301 size_t data_bytes = data_count *
302 camera_metadata_type_size[type];
303 return data_bytes <= 4 ? 0 : data_bytes;
304}
305
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700306static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800307 uint32_t tag,
308 uint8_t type,
309 const void *data,
310 size_t data_count) {
311
312 if (dst == NULL) return ERROR;
313 if (dst->entry_count == dst->entry_capacity) return ERROR;
314 if (data == NULL) return ERROR;
315
316 size_t data_bytes =
317 calculate_camera_metadata_entry_data_size(type, data_count);
318
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700319 camera_metadata_buffer_entry_t *entry = dst->entries + dst->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800320 entry->tag = tag;
321 entry->type = type;
322 entry->count = data_count;
323
324 if (data_bytes == 0) {
325 memcpy(entry->data.value, data,
326 data_count * camera_metadata_type_size[type] );
327 } else {
328 entry->data.offset = dst->data_count;
329 memcpy(dst->data + entry->data.offset, data, data_bytes);
330 dst->data_count += data_bytes;
331 }
332 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700333 dst->flags &= ~FLAG_SORTED;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800334 return OK;
335}
336
337int add_camera_metadata_entry(camera_metadata_t *dst,
338 uint32_t tag,
339 const void *data,
340 size_t data_count) {
341
342 int type = get_camera_metadata_tag_type(tag);
343 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700344 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800345 return ERROR;
346 }
347
348 return add_camera_metadata_entry_raw(dst,
349 tag,
350 type,
351 data,
352 data_count);
353}
354
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700355static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700356 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
357 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700358 return tag1 < tag2 ? -1 :
359 tag1 == tag2 ? 0 :
360 1;
361}
362
363int sort_camera_metadata(camera_metadata_t *dst) {
364 if (dst == NULL) return ERROR;
365 if (dst->flags & FLAG_SORTED) return OK;
366
367 qsort(dst->entries, dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700368 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700369 compare_entry_tags);
370 dst->flags |= FLAG_SORTED;
371
372 return OK;
373}
374
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800375int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700376 size_t index,
377 camera_metadata_entry_t *entry) {
378 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800379 if (index >= src->entry_count) return ERROR;
380
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700381 camera_metadata_buffer_entry_t *buffer_entry = src->entries + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800382
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700383 entry->index = index;
384 entry->tag = buffer_entry->tag;
385 entry->type = buffer_entry->type;
386 entry->count = buffer_entry->count;
387 if (buffer_entry->count *
388 camera_metadata_type_size[buffer_entry->type] > 4) {
389 entry->data.u8 = src->data + buffer_entry->data.offset;
390 } else {
391 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700392 }
393 return OK;
394}
395
396int find_camera_metadata_entry(camera_metadata_t *src,
397 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700398 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700399 if (src == NULL) return ERROR;
400
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700401 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700402 if (src->flags & FLAG_SORTED) {
403 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700404 camera_metadata_buffer_entry_t *search_entry = NULL;
405 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700406 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700407 search_entry = bsearch(&key,
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700408 src->entries,
409 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700410 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700411 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700412 if (search_entry == NULL) return NOT_FOUND;
413 index = search_entry - src->entries;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800414 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700415 // Not sorted, linear search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700416 for (index = 0; index < src->entry_count; index++) {
417 if (src->entries[index].tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700418 break;
419 }
420 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700421 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700422 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700423
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700424 return get_camera_metadata_entry(src, index,
425 entry);
426}
427
428int delete_camera_metadata_entry(camera_metadata_t *dst,
429 size_t index) {
430 if (dst == NULL) return ERROR;
431 if (index >= dst->entry_count) return ERROR;
432
433 camera_metadata_buffer_entry_t *entry = dst->entries + index;
434 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
435 entry->count);
436
437 if (data_bytes > 0) {
438 // Shift data buffer to overwrite deleted data
439 uint8_t *start = dst->data + entry->data.offset;
440 uint8_t *end = start + data_bytes;
441 size_t length = dst->data_count - entry->data.offset - data_bytes;
442 memmove(start, end, length);
443
444 // Update all entry indices to account for shift
445 camera_metadata_buffer_entry_t *e = dst->entries;
446 size_t i;
447 for (i = 0; i < dst->entry_count; i++) {
448 if (calculate_camera_metadata_entry_data_size(
449 e->type, e->count) > 0 &&
450 e->data.offset > entry->data.offset) {
451 e->data.offset -= data_bytes;
452 }
453 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700454 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700455 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800456 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700457 // Shift entry array
458 memmove(entry, entry + 1,
459 sizeof(camera_metadata_buffer_entry_t) *
460 (dst->entry_count - index - 1) );
461 dst->entry_count -= 1;
462
463 return OK;
464}
465
466int update_camera_metadata_entry(camera_metadata_t *dst,
467 size_t index,
468 const void *data,
469 size_t data_count,
470 camera_metadata_entry_t *updated_entry) {
471 if (dst == NULL) return ERROR;
472 if (index >= dst->entry_count) return ERROR;
473
474 camera_metadata_buffer_entry_t *entry = dst->entries + index;
475
476 size_t data_bytes =
477 calculate_camera_metadata_entry_data_size(entry->type,
478 data_count);
479 size_t entry_bytes =
480 calculate_camera_metadata_entry_data_size(entry->type,
481 entry->count);
482 if (data_bytes != entry_bytes) {
483 // May need to shift/add to data array
484 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
485 // No room
486 return ERROR;
487 }
488 if (entry_bytes != 0) {
489 // Remove old data
490 uint8_t *start = dst->data + entry->data.offset;
491 uint8_t *end = start + entry_bytes;
492 size_t length = dst->data_count - entry->data.offset - entry_bytes;
493 memmove(start, end, length);
494 dst->data_count -= entry_bytes;
495
496 // Update all entry indices to account for shift
497 camera_metadata_buffer_entry_t *e = dst->entries;
498 size_t i;
499 for (i = 0; i < dst->entry_count; i++) {
500 if (calculate_camera_metadata_entry_data_size(
501 e->type, e->count) > 0 &&
502 e->data.offset > entry->data.offset) {
503 e->data.offset -= entry_bytes;
504 }
505 ++e;
506 }
507 }
508
509 if (data_bytes != 0) {
510 // Append new data
511 entry->data.offset = dst->data_count;
512
513 memcpy(dst->data + entry->data.offset, data, data_bytes);
514 dst->data_count += data_bytes;
515 }
516 } else if (data_bytes != 0) {
517 // data size unchanged, reuse same data location
518 memcpy(dst->data + entry->data.offset, data, data_bytes);
519 }
520
521 if (data_bytes == 0) {
522 // Data fits into entry
523 memcpy(entry->data.value, data,
524 data_count * camera_metadata_type_size[entry->type]);
525 }
526
527 entry->count = data_count;
528
529 if (updated_entry != NULL) {
530 get_camera_metadata_entry(dst,
531 index,
532 updated_entry);
533 }
534
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800535 return OK;
536}
537
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700538int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
539 if (dst == NULL) return ERROR;
540 dst->user = user;
541 return OK;
542}
543
544int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
545 if (dst == NULL) return ERROR;
546 *user = dst->user;
547 return OK;
548}
549
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800550static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
551
552const char *get_camera_metadata_section_name(uint32_t tag) {
553 uint32_t tag_section = tag >> 16;
554 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700555 return vendor_tag_ops->get_camera_vendor_section_name(
556 vendor_tag_ops,
557 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800558 }
559 if (tag_section >= ANDROID_SECTION_COUNT) {
560 return NULL;
561 }
562 return camera_metadata_section_names[tag_section];
563}
564
565const char *get_camera_metadata_tag_name(uint32_t tag) {
566 uint32_t tag_section = tag >> 16;
567 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700568 return vendor_tag_ops->get_camera_vendor_tag_name(
569 vendor_tag_ops,
570 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800571 }
572 if (tag_section >= ANDROID_SECTION_COUNT ||
573 tag >= camera_metadata_section_bounds[tag_section][1] ) {
574 return NULL;
575 }
576 uint32_t tag_index = tag & 0xFFFF;
577 return tag_info[tag_section][tag_index].tag_name;
578}
579
580int get_camera_metadata_tag_type(uint32_t tag) {
581 uint32_t tag_section = tag >> 16;
582 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700583 return vendor_tag_ops->get_camera_vendor_tag_type(
584 vendor_tag_ops,
585 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800586 }
587 if (tag_section >= ANDROID_SECTION_COUNT ||
588 tag >= camera_metadata_section_bounds[tag_section][1] ) {
589 return -1;
590 }
591 uint32_t tag_index = tag & 0xFFFF;
592 return tag_info[tag_section][tag_index].tag_type;
593}
594
595int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
596 vendor_tag_ops = query_ops;
597 return OK;
598}
599
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700600static void print_data(int fd, const uint8_t *data_ptr, int type, int count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800601
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700602void dump_camera_metadata(const camera_metadata_t *metadata,
603 int fd,
604 int verbosity) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800605 if (metadata == NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700606 ALOGE("%s: Metadata is null.", __FUNCTION__);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800607 return;
608 }
609 unsigned int i;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700610 fdprintf(fd,
611 "Dumping camera metadata array. %d entries, "
612 "%d bytes of extra data.\n",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800613 metadata->entry_count, metadata->data_count);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700614 fdprintf(fd, " (%d entries and %d bytes data reserved)\n",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800615 metadata->entry_capacity, metadata->data_capacity);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700616 fdprintf(fd, " Version: %d, Flags: %08x\n",
617 metadata->version, metadata->flags);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800618 for (i=0; i < metadata->entry_count; i++) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700619 camera_metadata_buffer_entry_t *entry = metadata->entries + i;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800620
621 const char *tag_name, *tag_section;
622 tag_section = get_camera_metadata_section_name(entry->tag);
623 if (tag_section == NULL) {
624 tag_section = "unknownSection";
625 }
626 tag_name = get_camera_metadata_tag_name(entry->tag);
627 if (tag_name == NULL) {
628 tag_name = "unknownTag";
629 }
630 const char *type_name;
631 if (entry->type >= NUM_TYPES) {
632 type_name = "unknown";
633 } else {
634 type_name = camera_metadata_type_names[entry->type];
635 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700636 fdprintf(fd, "Tag: %s.%s (%05x): %s[%d]\n",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800637 tag_section,
638 tag_name,
639 entry->tag,
640 type_name,
641 entry->count);
642
643 if (verbosity < 1) continue;
644
645 if (entry->type >= NUM_TYPES) continue;
646
647 size_t type_size = camera_metadata_type_size[entry->type];
648 uint8_t *data_ptr;
649 if ( type_size * entry->count > 4 ) {
650 if (entry->data.offset >= metadata->data_count) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700651 ALOGE("%s: Malformed entry data offset: %d (max %d)",
652 __FUNCTION__,
653 entry->data.offset,
654 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800655 continue;
656 }
657 data_ptr = metadata->data + entry->data.offset;
658 } else {
659 data_ptr = entry->data.value;
660 }
661 int count = entry->count;
662 if (verbosity < 2 && count > 16) count = 16;
663
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700664 print_data(fd, data_ptr, entry->type, count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800665 }
666}
667
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700668static void print_data(int fd, const uint8_t *data_ptr, int type, int count) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800669 static int values_per_line[NUM_TYPES] = {
670 [TYPE_BYTE] = 16,
671 [TYPE_INT32] = 4,
672 [TYPE_FLOAT] = 8,
673 [TYPE_INT64] = 2,
674 [TYPE_DOUBLE] = 4,
675 [TYPE_RATIONAL] = 2,
676 };
677 size_t type_size = camera_metadata_type_size[type];
678
679 int lines = count / values_per_line[type];
680 if (count % values_per_line[type] != 0) lines++;
681
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800682 int index = 0;
683 int j, k;
684 for (j = 0; j < lines; j++) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700685 fdprintf(fd, " [");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800686 for (k = 0;
687 k < values_per_line[type] && count > 0;
688 k++, count--, index += type_size) {
689
690 switch (type) {
691 case TYPE_BYTE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700692 fdprintf(fd, "%hhu ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800693 *(data_ptr + index));
694 break;
695 case TYPE_INT32:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700696 fdprintf(fd, "%d ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800697 *(int32_t*)(data_ptr + index));
698 break;
699 case TYPE_FLOAT:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700700 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800701 *(float*)(data_ptr + index));
702 break;
703 case TYPE_INT64:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700704 fdprintf(fd, "%lld ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800705 *(int64_t*)(data_ptr + index));
706 break;
707 case TYPE_DOUBLE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700708 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800709 *(float*)(data_ptr + index));
710 break;
711 case TYPE_RATIONAL: {
712 int32_t numerator = *(int32_t*)(data_ptr + index);
713 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700714 fdprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800715 numerator, denominator);
716 break;
717 }
718 default:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700719 fdprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800720 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800721 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700722 fdprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800723 }
724}