blob: c922c7fcb0b7be2b25870834a590d7f78e7628b0 [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 Talvala31540362012-11-07 16:36:50 -080026
27#define _Alignas(T) \
28 ({struct _AlignasStruct { char c; T field; }; \
29 offsetof(struct _AlignasStruct, field); })
30
31// Align entry buffers as the compiler would
32#define ENTRY_ALIGNMENT _Alignas(camera_metadata_buffer_entry_t)
33// Align data buffer to largest supported data type
34#define DATA_ALIGNMENT _Alignas(camera_metadata_rational_t)
35
36#define ALIGN_TO(val, alignment) \
37 (typeof(val))(((uint32_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
38
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080039/**
40 * A single metadata entry, storing an array of values of a given type. If the
41 * array is no larger than 4 bytes in size, it is stored in the data.value[]
42 * array; otherwise, it can found in the parent's data array at index
43 * data.offset.
44 */
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070045typedef struct camera_metadata_buffer_entry {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080046 uint32_t tag;
47 size_t count;
48 union {
49 size_t offset;
50 uint8_t value[4];
51 } data;
52 uint8_t type;
53 uint8_t reserved[3];
Eino-Ville Talvala31540362012-11-07 16:36:50 -080054} camera_metadata_buffer_entry_t;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080055
56/**
57 * A packet of metadata. This is a list of entries, each of which may point to
58 * its values stored at an offset in data.
59 *
60 * It is assumed by the utility functions that the memory layout of the packet
61 * is as follows:
62 *
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070063 * |-----------------------------------------------|
64 * | camera_metadata_t |
65 * | |
66 * |-----------------------------------------------|
67 * | reserved for future expansion |
68 * |-----------------------------------------------|
69 * | camera_metadata_buffer_entry_t #0 |
70 * |-----------------------------------------------|
71 * | .... |
72 * |-----------------------------------------------|
73 * | camera_metadata_buffer_entry_t #entry_count-1 |
74 * |-----------------------------------------------|
75 * | free space for |
76 * | (entry_capacity-entry_count) entries |
77 * |-----------------------------------------------|
78 * | start of camera_metadata.data |
79 * | |
80 * |-----------------------------------------------|
81 * | free space for |
82 * | (data_capacity-data_count) bytes |
83 * |-----------------------------------------------|
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080084 *
85 * With the total length of the whole packet being camera_metadata.size bytes.
86 *
87 * In short, the entries and data are contiguous in memory after the metadata
88 * header.
89 */
90struct camera_metadata {
91 size_t size;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -070092 uint32_t version;
93 uint32_t flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080094 size_t entry_count;
95 size_t entry_capacity;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -070096 camera_metadata_buffer_entry_t *entries;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080097 size_t data_count;
98 size_t data_capacity;
99 uint8_t *data;
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700100 void *user; // User set pointer, not copied with buffer
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800101 uint8_t reserved[0];
102};
103
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700104/** Versioning information */
105#define CURRENT_METADATA_VERSION 1
106
107/** Flag definitions */
108#define FLAG_SORTED 0x00000001
109
110/** Tag information */
111
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800112typedef struct tag_info {
113 const char *tag_name;
114 uint8_t tag_type;
115} tag_info_t;
116
117#include "camera_metadata_tag_info.c"
118
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700119const size_t camera_metadata_type_size[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800120 [TYPE_BYTE] = sizeof(uint8_t),
121 [TYPE_INT32] = sizeof(int32_t),
122 [TYPE_FLOAT] = sizeof(float),
123 [TYPE_INT64] = sizeof(int64_t),
124 [TYPE_DOUBLE] = sizeof(double),
125 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
126};
127
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700128const char *camera_metadata_type_names[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800129 [TYPE_BYTE] = "byte",
130 [TYPE_INT32] = "int32",
131 [TYPE_FLOAT] = "float",
132 [TYPE_INT64] = "int64",
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700133 [TYPE_DOUBLE] = "double",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800134 [TYPE_RATIONAL] = "rational"
135};
136
137camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
138 size_t data_capacity) {
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700139 if (entry_capacity == 0) return NULL;
140
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800141 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
142 data_capacity);
143 void *buffer = malloc(memory_needed);
144 return place_camera_metadata(buffer, memory_needed,
145 entry_capacity,
146 data_capacity);
147}
148
149camera_metadata_t *place_camera_metadata(void *dst,
150 size_t dst_size,
151 size_t entry_capacity,
152 size_t data_capacity) {
153 if (dst == NULL) return NULL;
154 if (entry_capacity == 0) return NULL;
155
156 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
157 data_capacity);
158 if (memory_needed > dst_size) return NULL;
159
160 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700161 metadata->version = CURRENT_METADATA_VERSION;
162 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800163 metadata->entry_count = 0;
164 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800165 camera_metadata_buffer_entry_t* entries_unaligned =
166 (camera_metadata_buffer_entry_t*)(metadata + 1);
167 metadata->entries = ALIGN_TO(entries_unaligned, ENTRY_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800168 metadata->data_count = 0;
169 metadata->data_capacity = data_capacity;
170 metadata->size = memory_needed;
171 if (metadata->data_capacity != 0) {
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800172 uint8_t *data_unaligned = (uint8_t*)(metadata->entries + metadata->entry_capacity);
173 metadata->data = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800174 } else {
175 metadata->data = NULL;
176 }
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700177 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800178
179 return metadata;
180}
181void free_camera_metadata(camera_metadata_t *metadata) {
182 free(metadata);
183}
184
185size_t calculate_camera_metadata_size(size_t entry_count,
186 size_t data_count) {
187 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800188 // Start entry list at aligned boundary
189 memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700190 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800191 // Start buffer list at aligned boundary
192 memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800193 memory_needed += sizeof(uint8_t[data_count]);
194 return memory_needed;
195}
196
197size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
198 if (metadata == NULL) return ERROR;
199
200 return metadata->size;
201}
202
203size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
204 if (metadata == NULL) return ERROR;
205
206 ptrdiff_t reserved_size = metadata->size -
207 calculate_camera_metadata_size(metadata->entry_capacity,
208 metadata->data_capacity);
209
210 return calculate_camera_metadata_size(metadata->entry_count,
211 metadata->data_count) + reserved_size;
212}
213
214size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
215 return metadata->entry_count;
216}
217
218size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
219 return metadata->entry_capacity;
220}
221
222size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
223 return metadata->data_count;
224}
225
226size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
227 return metadata->data_capacity;
228}
229
230camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
231 const camera_metadata_t *src) {
232 size_t memory_needed = get_camera_metadata_compact_size(src);
233
234 if (dst == NULL) return NULL;
235 if (dst_size < memory_needed) return NULL;
236
237 // If copying a newer version of the structure, there may be additional
238 // header fields we don't know about but need to copy
239 ptrdiff_t reserved_size = src->size -
240 calculate_camera_metadata_size(src->entry_capacity,
241 src->data_capacity);
242
243 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700244 metadata->version = CURRENT_METADATA_VERSION;
245 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800246 metadata->entry_count = src->entry_count;
247 metadata->entry_capacity = src->entry_count;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700248 metadata->entries = (camera_metadata_buffer_entry_t*)
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800249 ((uint8_t *)(metadata + 1) + reserved_size);
250 metadata->data_count = src->data_count;
251 metadata->data_capacity = src->data_count;
252 metadata->data = (uint8_t *)(metadata->entries + metadata->entry_capacity);
253 metadata->size = memory_needed;
254
255 if (reserved_size > 0) {
256 memcpy(metadata->reserved, src->reserved, reserved_size);
257 }
258 memcpy(metadata->entries, src->entries,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700259 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800260 memcpy(metadata->data, src->data,
261 sizeof(uint8_t[metadata->data_count]));
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700262 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800263
264 return metadata;
265}
266
267int append_camera_metadata(camera_metadata_t *dst,
268 const camera_metadata_t *src) {
269 if (dst == NULL || src == NULL ) return ERROR;
270
271 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
272 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
273
274 memcpy(dst->entries + dst->entry_count, src->entries,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700275 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800276 memcpy(dst->data + dst->data_count, src->data,
277 sizeof(uint8_t[src->data_count]));
278 if (dst->data_count != 0) {
279 unsigned int i;
280 for (i = dst->entry_count;
281 i < dst->entry_count + src->entry_count;
282 i++) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700283 camera_metadata_buffer_entry_t *entry = dst->entries + i;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800284 if ( camera_metadata_type_size[entry->type] * entry->count > 4 ) {
285 entry->data.offset += dst->data_count;
286 }
287 }
288 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700289 if (dst->entry_count == 0) {
290 // Appending onto empty buffer, keep sorted state
291 dst->flags |= src->flags & FLAG_SORTED;
292 } else if (src->entry_count != 0) {
293 // Both src, dst are nonempty, cannot assume sort remains
294 dst->flags &= ~FLAG_SORTED;
295 } else {
296 // Src is empty, keep dst sorted state
297 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800298 dst->entry_count += src->entry_count;
299 dst->data_count += src->data_count;
300
301 return OK;
302}
303
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700304camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700305 int res;
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700306 if (src == NULL) return NULL;
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700307 camera_metadata_t *clone = allocate_camera_metadata(
308 get_camera_metadata_entry_count(src),
309 get_camera_metadata_data_count(src));
310 if (clone != NULL) {
311 res = append_camera_metadata(clone, src);
312 if (res != OK) {
313 free_camera_metadata(clone);
314 clone = NULL;
315 }
316 }
317 return clone;
318}
319
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800320size_t calculate_camera_metadata_entry_data_size(uint8_t type,
321 size_t data_count) {
322 if (type >= NUM_TYPES) return 0;
323 size_t data_bytes = data_count *
324 camera_metadata_type_size[type];
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800325 return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800326}
327
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700328static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800329 uint32_t tag,
330 uint8_t type,
331 const void *data,
332 size_t data_count) {
333
334 if (dst == NULL) return ERROR;
335 if (dst->entry_count == dst->entry_capacity) return ERROR;
336 if (data == NULL) return ERROR;
337
338 size_t data_bytes =
339 calculate_camera_metadata_entry_data_size(type, data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800340 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800341
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800342 size_t data_payload_bytes =
343 data_count * camera_metadata_type_size[type];
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700344 camera_metadata_buffer_entry_t *entry = dst->entries + dst->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800345 entry->tag = tag;
346 entry->type = type;
347 entry->count = data_count;
348
349 if (data_bytes == 0) {
350 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800351 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800352 } else {
353 entry->data.offset = dst->data_count;
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800354 memcpy(dst->data + entry->data.offset, data,
355 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800356 dst->data_count += data_bytes;
357 }
358 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700359 dst->flags &= ~FLAG_SORTED;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800360 return OK;
361}
362
363int add_camera_metadata_entry(camera_metadata_t *dst,
364 uint32_t tag,
365 const void *data,
366 size_t data_count) {
367
368 int type = get_camera_metadata_tag_type(tag);
369 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700370 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800371 return ERROR;
372 }
373
374 return add_camera_metadata_entry_raw(dst,
375 tag,
376 type,
377 data,
378 data_count);
379}
380
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700381static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700382 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
383 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700384 return tag1 < tag2 ? -1 :
385 tag1 == tag2 ? 0 :
386 1;
387}
388
389int sort_camera_metadata(camera_metadata_t *dst) {
390 if (dst == NULL) return ERROR;
391 if (dst->flags & FLAG_SORTED) return OK;
392
393 qsort(dst->entries, dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700394 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700395 compare_entry_tags);
396 dst->flags |= FLAG_SORTED;
397
398 return OK;
399}
400
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800401int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700402 size_t index,
403 camera_metadata_entry_t *entry) {
404 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800405 if (index >= src->entry_count) return ERROR;
406
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700407 camera_metadata_buffer_entry_t *buffer_entry = src->entries + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800408
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700409 entry->index = index;
410 entry->tag = buffer_entry->tag;
411 entry->type = buffer_entry->type;
412 entry->count = buffer_entry->count;
413 if (buffer_entry->count *
414 camera_metadata_type_size[buffer_entry->type] > 4) {
415 entry->data.u8 = src->data + buffer_entry->data.offset;
416 } else {
417 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700418 }
419 return OK;
420}
421
422int find_camera_metadata_entry(camera_metadata_t *src,
423 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700424 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700425 if (src == NULL) return ERROR;
426
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700427 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700428 if (src->flags & FLAG_SORTED) {
429 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700430 camera_metadata_buffer_entry_t *search_entry = NULL;
431 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700432 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700433 search_entry = bsearch(&key,
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700434 src->entries,
435 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700436 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700437 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700438 if (search_entry == NULL) return NOT_FOUND;
439 index = search_entry - src->entries;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800440 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700441 // Not sorted, linear search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700442 for (index = 0; index < src->entry_count; index++) {
443 if (src->entries[index].tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700444 break;
445 }
446 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700447 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700448 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700449
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700450 return get_camera_metadata_entry(src, index,
451 entry);
452}
453
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700454int find_camera_metadata_ro_entry(const camera_metadata_t *src,
455 uint32_t tag,
456 camera_metadata_ro_entry_t *entry) {
457 return find_camera_metadata_entry((camera_metadata_t*)src, tag,
458 (camera_metadata_entry_t*)entry);
459}
460
461
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700462int delete_camera_metadata_entry(camera_metadata_t *dst,
463 size_t index) {
464 if (dst == NULL) return ERROR;
465 if (index >= dst->entry_count) return ERROR;
466
467 camera_metadata_buffer_entry_t *entry = dst->entries + index;
468 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
469 entry->count);
470
471 if (data_bytes > 0) {
472 // Shift data buffer to overwrite deleted data
473 uint8_t *start = dst->data + entry->data.offset;
474 uint8_t *end = start + data_bytes;
475 size_t length = dst->data_count - entry->data.offset - data_bytes;
476 memmove(start, end, length);
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 -= data_bytes;
486 }
487 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700488 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700489 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800490 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700491 // Shift entry array
492 memmove(entry, entry + 1,
493 sizeof(camera_metadata_buffer_entry_t) *
494 (dst->entry_count - index - 1) );
495 dst->entry_count -= 1;
496
497 return OK;
498}
499
500int update_camera_metadata_entry(camera_metadata_t *dst,
501 size_t index,
502 const void *data,
503 size_t data_count,
504 camera_metadata_entry_t *updated_entry) {
505 if (dst == NULL) return ERROR;
506 if (index >= dst->entry_count) return ERROR;
507
508 camera_metadata_buffer_entry_t *entry = dst->entries + index;
509
510 size_t data_bytes =
511 calculate_camera_metadata_entry_data_size(entry->type,
512 data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800513 size_t data_payload_bytes =
514 data_count * camera_metadata_type_size[entry->type];
515
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700516 size_t entry_bytes =
517 calculate_camera_metadata_entry_data_size(entry->type,
518 entry->count);
519 if (data_bytes != entry_bytes) {
520 // May need to shift/add to data array
521 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
522 // No room
523 return ERROR;
524 }
525 if (entry_bytes != 0) {
526 // Remove old data
527 uint8_t *start = dst->data + entry->data.offset;
528 uint8_t *end = start + entry_bytes;
529 size_t length = dst->data_count - entry->data.offset - entry_bytes;
530 memmove(start, end, length);
531 dst->data_count -= entry_bytes;
532
533 // Update all entry indices to account for shift
534 camera_metadata_buffer_entry_t *e = dst->entries;
535 size_t i;
536 for (i = 0; i < dst->entry_count; i++) {
537 if (calculate_camera_metadata_entry_data_size(
538 e->type, e->count) > 0 &&
539 e->data.offset > entry->data.offset) {
540 e->data.offset -= entry_bytes;
541 }
542 ++e;
543 }
544 }
545
546 if (data_bytes != 0) {
547 // Append new data
548 entry->data.offset = dst->data_count;
549
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800550 memcpy(dst->data + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700551 dst->data_count += data_bytes;
552 }
553 } else if (data_bytes != 0) {
554 // data size unchanged, reuse same data location
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800555 memcpy(dst->data + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700556 }
557
558 if (data_bytes == 0) {
559 // Data fits into entry
560 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800561 data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700562 }
563
564 entry->count = data_count;
565
566 if (updated_entry != NULL) {
567 get_camera_metadata_entry(dst,
568 index,
569 updated_entry);
570 }
571
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800572 return OK;
573}
574
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700575int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
576 if (dst == NULL) return ERROR;
577 dst->user = user;
578 return OK;
579}
580
581int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
582 if (dst == NULL) return ERROR;
583 *user = dst->user;
584 return OK;
585}
586
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800587static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
588
589const char *get_camera_metadata_section_name(uint32_t tag) {
590 uint32_t tag_section = tag >> 16;
591 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700592 return vendor_tag_ops->get_camera_vendor_section_name(
593 vendor_tag_ops,
594 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800595 }
596 if (tag_section >= ANDROID_SECTION_COUNT) {
597 return NULL;
598 }
599 return camera_metadata_section_names[tag_section];
600}
601
602const char *get_camera_metadata_tag_name(uint32_t tag) {
603 uint32_t tag_section = tag >> 16;
604 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700605 return vendor_tag_ops->get_camera_vendor_tag_name(
606 vendor_tag_ops,
607 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800608 }
609 if (tag_section >= ANDROID_SECTION_COUNT ||
610 tag >= camera_metadata_section_bounds[tag_section][1] ) {
611 return NULL;
612 }
613 uint32_t tag_index = tag & 0xFFFF;
614 return tag_info[tag_section][tag_index].tag_name;
615}
616
617int get_camera_metadata_tag_type(uint32_t tag) {
618 uint32_t tag_section = tag >> 16;
619 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700620 return vendor_tag_ops->get_camera_vendor_tag_type(
621 vendor_tag_ops,
622 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800623 }
624 if (tag_section >= ANDROID_SECTION_COUNT ||
625 tag >= camera_metadata_section_bounds[tag_section][1] ) {
626 return -1;
627 }
628 uint32_t tag_index = tag & 0xFFFF;
629 return tag_info[tag_section][tag_index].tag_type;
630}
631
632int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
633 vendor_tag_ops = query_ops;
634 return OK;
635}
636
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700637static void print_data(int fd, const uint8_t *data_ptr, int type, int count,
638 int indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800639
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700640void dump_camera_metadata(const camera_metadata_t *metadata,
641 int fd,
642 int verbosity) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700643 dump_indented_camera_metadata(metadata, fd, verbosity, 0);
644}
645
646void dump_indented_camera_metadata(const camera_metadata_t *metadata,
647 int fd,
648 int verbosity,
649 int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800650 if (metadata == NULL) {
Eino-Ville Talvala94879bd2012-10-01 16:33:03 -0700651 fdprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700652 indentation, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800653 return;
654 }
655 unsigned int i;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700656 fdprintf(fd,
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700657 "%*sDumping camera metadata array: %d / %d entries, "
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700658 "%d / %d bytes of extra data.\n", indentation, "",
659 metadata->entry_count, metadata->entry_capacity,
660 metadata->data_count, metadata->data_capacity);
661 fdprintf(fd, "%*sVersion: %d, Flags: %08x\n",
662 indentation + 2, "",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700663 metadata->version, metadata->flags);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800664 for (i=0; i < metadata->entry_count; i++) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700665 camera_metadata_buffer_entry_t *entry = metadata->entries + i;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800666
667 const char *tag_name, *tag_section;
668 tag_section = get_camera_metadata_section_name(entry->tag);
669 if (tag_section == NULL) {
670 tag_section = "unknownSection";
671 }
672 tag_name = get_camera_metadata_tag_name(entry->tag);
673 if (tag_name == NULL) {
674 tag_name = "unknownTag";
675 }
676 const char *type_name;
677 if (entry->type >= NUM_TYPES) {
678 type_name = "unknown";
679 } else {
680 type_name = camera_metadata_type_names[entry->type];
681 }
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700682 fdprintf(fd, "%*s%s.%s (%05x): %s[%d]\n",
683 indentation + 2, "",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800684 tag_section,
685 tag_name,
686 entry->tag,
687 type_name,
688 entry->count);
689
690 if (verbosity < 1) continue;
691
692 if (entry->type >= NUM_TYPES) continue;
693
694 size_t type_size = camera_metadata_type_size[entry->type];
695 uint8_t *data_ptr;
696 if ( type_size * entry->count > 4 ) {
697 if (entry->data.offset >= metadata->data_count) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700698 ALOGE("%s: Malformed entry data offset: %d (max %d)",
699 __FUNCTION__,
700 entry->data.offset,
701 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800702 continue;
703 }
704 data_ptr = metadata->data + entry->data.offset;
705 } else {
706 data_ptr = entry->data.value;
707 }
708 int count = entry->count;
709 if (verbosity < 2 && count > 16) count = 16;
710
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700711 print_data(fd, data_ptr, entry->type, count, indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800712 }
713}
714
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700715static void print_data(int fd, const uint8_t *data_ptr,
716 int type, int count, int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800717 static int values_per_line[NUM_TYPES] = {
718 [TYPE_BYTE] = 16,
719 [TYPE_INT32] = 4,
720 [TYPE_FLOAT] = 8,
721 [TYPE_INT64] = 2,
722 [TYPE_DOUBLE] = 4,
723 [TYPE_RATIONAL] = 2,
724 };
725 size_t type_size = camera_metadata_type_size[type];
726
727 int lines = count / values_per_line[type];
728 if (count % values_per_line[type] != 0) lines++;
729
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800730 int index = 0;
731 int j, k;
732 for (j = 0; j < lines; j++) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700733 fdprintf(fd, "%*s[", indentation + 4, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800734 for (k = 0;
735 k < values_per_line[type] && count > 0;
736 k++, count--, index += type_size) {
737
738 switch (type) {
739 case TYPE_BYTE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700740 fdprintf(fd, "%hhu ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800741 *(data_ptr + index));
742 break;
743 case TYPE_INT32:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700744 fdprintf(fd, "%d ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800745 *(int32_t*)(data_ptr + index));
746 break;
747 case TYPE_FLOAT:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700748 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800749 *(float*)(data_ptr + index));
750 break;
751 case TYPE_INT64:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700752 fdprintf(fd, "%lld ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800753 *(int64_t*)(data_ptr + index));
754 break;
755 case TYPE_DOUBLE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700756 fdprintf(fd, "%0.2f ",
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800757 *(double*)(data_ptr + index));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800758 break;
759 case TYPE_RATIONAL: {
760 int32_t numerator = *(int32_t*)(data_ptr + index);
761 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700762 fdprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800763 numerator, denominator);
764 break;
765 }
766 default:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700767 fdprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800768 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800769 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700770 fdprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800771 }
772}