blob: e5c2f251de939cd7b15ba3f759ac87aaf9864561 [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
Igor Murashkin555aac82012-11-15 10:54:57 -080034#define DATA_ALIGNMENT _Alignas(camera_metadata_data_t)
Eino-Ville Talvala31540362012-11-07 16:36:50 -080035
36#define ALIGN_TO(val, alignment) \
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -080037 (((uint32_t)(val) + ((alignment) - 1)) & ~((alignment) - 1))
Eino-Ville Talvala31540362012-11-07 16:36:50 -080038
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 Talvalab10d56a2012-11-13 11:45:12 -080096 ptrdiff_t entries_start; // Offset from camera_metadata
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -080097 size_t data_count;
98 size_t data_capacity;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -080099 ptrdiff_t data_start; // Offset from camera_metadata
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
Igor Murashkin555aac82012-11-15 10:54:57 -0800104/**
105 * A datum of metadata. This corresponds to camera_metadata_entry_t::data
106 * with the difference that each element is not a pointer. We need to have a
107 * non-pointer type description in order to figure out the largest alignment
108 * requirement for data (DATA_ALIGNMENT).
109 */
110typedef union camera_metadata_data {
111 uint8_t u8;
112 int32_t i32;
113 float f;
114 int64_t i64;
115 double d;
116 camera_metadata_rational_t r;
117} camera_metadata_data_t;
118
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700119/** Versioning information */
120#define CURRENT_METADATA_VERSION 1
121
122/** Flag definitions */
123#define FLAG_SORTED 0x00000001
124
125/** Tag information */
126
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800127typedef struct tag_info {
128 const char *tag_name;
129 uint8_t tag_type;
130} tag_info_t;
131
132#include "camera_metadata_tag_info.c"
133
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700134const size_t camera_metadata_type_size[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800135 [TYPE_BYTE] = sizeof(uint8_t),
136 [TYPE_INT32] = sizeof(int32_t),
137 [TYPE_FLOAT] = sizeof(float),
138 [TYPE_INT64] = sizeof(int64_t),
139 [TYPE_DOUBLE] = sizeof(double),
140 [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
141};
142
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700143const char *camera_metadata_type_names[NUM_TYPES] = {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800144 [TYPE_BYTE] = "byte",
145 [TYPE_INT32] = "int32",
146 [TYPE_FLOAT] = "float",
147 [TYPE_INT64] = "int64",
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700148 [TYPE_DOUBLE] = "double",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800149 [TYPE_RATIONAL] = "rational"
150};
151
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800152static camera_metadata_buffer_entry_t *get_entries(
153 const camera_metadata_t *metadata) {
154 return (camera_metadata_buffer_entry_t*)
155 ((uint8_t*)metadata + metadata->entries_start);
156}
157
158static uint8_t *get_data(const camera_metadata_t *metadata) {
159 return (uint8_t*)metadata + metadata->data_start;
160}
161
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800162camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
163 size_t data_capacity) {
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700164 if (entry_capacity == 0) return NULL;
165
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800166 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
167 data_capacity);
168 void *buffer = malloc(memory_needed);
169 return place_camera_metadata(buffer, memory_needed,
170 entry_capacity,
171 data_capacity);
172}
173
174camera_metadata_t *place_camera_metadata(void *dst,
175 size_t dst_size,
176 size_t entry_capacity,
177 size_t data_capacity) {
178 if (dst == NULL) return NULL;
179 if (entry_capacity == 0) return NULL;
180
181 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
182 data_capacity);
183 if (memory_needed > dst_size) return NULL;
184
185 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700186 metadata->version = CURRENT_METADATA_VERSION;
187 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800188 metadata->entry_count = 0;
189 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800190 metadata->entries_start =
191 ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800192 metadata->data_count = 0;
193 metadata->data_capacity = data_capacity;
194 metadata->size = memory_needed;
195 if (metadata->data_capacity != 0) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800196 size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
197 metadata->entry_capacity) - (uint8_t*)metadata;
198 metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800199 } else {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800200 metadata->data_start = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800201 }
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700202 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800203
204 return metadata;
205}
206void free_camera_metadata(camera_metadata_t *metadata) {
207 free(metadata);
208}
209
210size_t calculate_camera_metadata_size(size_t entry_count,
211 size_t data_count) {
212 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800213 // Start entry list at aligned boundary
214 memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700215 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800216 // Start buffer list at aligned boundary
217 memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800218 memory_needed += sizeof(uint8_t[data_count]);
219 return memory_needed;
220}
221
222size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
223 if (metadata == NULL) return ERROR;
224
225 return metadata->size;
226}
227
228size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
229 if (metadata == NULL) return ERROR;
230
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800231 return calculate_camera_metadata_size(metadata->entry_count,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800232 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800233}
234
235size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
236 return metadata->entry_count;
237}
238
239size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
240 return metadata->entry_capacity;
241}
242
243size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
244 return metadata->data_count;
245}
246
247size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
248 return metadata->data_capacity;
249}
250
251camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
252 const camera_metadata_t *src) {
253 size_t memory_needed = get_camera_metadata_compact_size(src);
254
255 if (dst == NULL) return NULL;
256 if (dst_size < memory_needed) return NULL;
257
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800258 camera_metadata_t *metadata =
259 place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800260
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700261 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800262 metadata->entry_count = src->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800263 metadata->data_count = src->data_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800264
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800265 memcpy(get_entries(metadata), get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700266 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800267 memcpy(get_data(metadata), get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800268 sizeof(uint8_t[metadata->data_count]));
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700269 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800270
271 return metadata;
272}
273
274int append_camera_metadata(camera_metadata_t *dst,
275 const camera_metadata_t *src) {
276 if (dst == NULL || src == NULL ) return ERROR;
277
278 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
279 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
280
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800281 memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700282 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800283 memcpy(get_data(dst) + dst->data_count, get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800284 sizeof(uint8_t[src->data_count]));
285 if (dst->data_count != 0) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800286 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
287 for (size_t i = 0; i < src->entry_count; i++, entry++) {
288 if ( calculate_camera_metadata_entry_data_size(entry->type,
289 entry->count) > 0 ) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800290 entry->data.offset += dst->data_count;
291 }
292 }
293 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700294 if (dst->entry_count == 0) {
295 // Appending onto empty buffer, keep sorted state
296 dst->flags |= src->flags & FLAG_SORTED;
297 } else if (src->entry_count != 0) {
298 // Both src, dst are nonempty, cannot assume sort remains
299 dst->flags &= ~FLAG_SORTED;
300 } else {
301 // Src is empty, keep dst sorted state
302 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800303 dst->entry_count += src->entry_count;
304 dst->data_count += src->data_count;
305
306 return OK;
307}
308
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700309camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700310 int res;
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700311 if (src == NULL) return NULL;
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700312 camera_metadata_t *clone = allocate_camera_metadata(
313 get_camera_metadata_entry_count(src),
314 get_camera_metadata_data_count(src));
315 if (clone != NULL) {
316 res = append_camera_metadata(clone, src);
317 if (res != OK) {
318 free_camera_metadata(clone);
319 clone = NULL;
320 }
321 }
322 return clone;
323}
324
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800325size_t calculate_camera_metadata_entry_data_size(uint8_t type,
326 size_t data_count) {
327 if (type >= NUM_TYPES) return 0;
328 size_t data_bytes = data_count *
329 camera_metadata_type_size[type];
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800330 return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800331}
332
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700333static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800334 uint32_t tag,
335 uint8_t type,
336 const void *data,
337 size_t data_count) {
338
339 if (dst == NULL) return ERROR;
340 if (dst->entry_count == dst->entry_capacity) return ERROR;
341 if (data == NULL) return ERROR;
342
343 size_t data_bytes =
344 calculate_camera_metadata_entry_data_size(type, data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800345 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800346
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800347 size_t data_payload_bytes =
348 data_count * camera_metadata_type_size[type];
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800349 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800350 entry->tag = tag;
351 entry->type = type;
352 entry->count = data_count;
353
354 if (data_bytes == 0) {
355 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800356 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800357 } else {
358 entry->data.offset = dst->data_count;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800359 memcpy(get_data(dst) + entry->data.offset, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800360 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800361 dst->data_count += data_bytes;
362 }
363 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700364 dst->flags &= ~FLAG_SORTED;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800365 return OK;
366}
367
368int add_camera_metadata_entry(camera_metadata_t *dst,
369 uint32_t tag,
370 const void *data,
371 size_t data_count) {
372
373 int type = get_camera_metadata_tag_type(tag);
374 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700375 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800376 return ERROR;
377 }
378
379 return add_camera_metadata_entry_raw(dst,
380 tag,
381 type,
382 data,
383 data_count);
384}
385
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700386static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700387 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
388 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700389 return tag1 < tag2 ? -1 :
390 tag1 == tag2 ? 0 :
391 1;
392}
393
394int sort_camera_metadata(camera_metadata_t *dst) {
395 if (dst == NULL) return ERROR;
396 if (dst->flags & FLAG_SORTED) return OK;
397
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800398 qsort(get_entries(dst), dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700399 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700400 compare_entry_tags);
401 dst->flags |= FLAG_SORTED;
402
403 return OK;
404}
405
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800406int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700407 size_t index,
408 camera_metadata_entry_t *entry) {
409 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800410 if (index >= src->entry_count) return ERROR;
411
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800412 camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800413
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700414 entry->index = index;
415 entry->tag = buffer_entry->tag;
416 entry->type = buffer_entry->type;
417 entry->count = buffer_entry->count;
418 if (buffer_entry->count *
419 camera_metadata_type_size[buffer_entry->type] > 4) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800420 entry->data.u8 = get_data(src) + buffer_entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700421 } else {
422 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700423 }
424 return OK;
425}
426
427int find_camera_metadata_entry(camera_metadata_t *src,
428 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700429 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700430 if (src == NULL) return ERROR;
431
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700432 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700433 if (src->flags & FLAG_SORTED) {
434 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700435 camera_metadata_buffer_entry_t *search_entry = NULL;
436 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700437 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700438 search_entry = bsearch(&key,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800439 get_entries(src),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700440 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700441 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700442 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700443 if (search_entry == NULL) return NOT_FOUND;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800444 index = search_entry - get_entries(src);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800445 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700446 // Not sorted, linear search
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800447 camera_metadata_buffer_entry_t *search_entry = get_entries(src);
448 for (index = 0; index < src->entry_count; index++, search_entry++) {
449 if (search_entry->tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700450 break;
451 }
452 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700453 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700454 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700455
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700456 return get_camera_metadata_entry(src, index,
457 entry);
458}
459
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700460int find_camera_metadata_ro_entry(const camera_metadata_t *src,
461 uint32_t tag,
462 camera_metadata_ro_entry_t *entry) {
463 return find_camera_metadata_entry((camera_metadata_t*)src, tag,
464 (camera_metadata_entry_t*)entry);
465}
466
467
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700468int delete_camera_metadata_entry(camera_metadata_t *dst,
469 size_t index) {
470 if (dst == NULL) return ERROR;
471 if (index >= dst->entry_count) return ERROR;
472
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800473 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700474 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
475 entry->count);
476
477 if (data_bytes > 0) {
478 // Shift data buffer to overwrite deleted data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800479 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700480 uint8_t *end = start + data_bytes;
481 size_t length = dst->data_count - entry->data.offset - data_bytes;
482 memmove(start, end, length);
483
484 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800485 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700486 size_t i;
487 for (i = 0; i < dst->entry_count; i++) {
488 if (calculate_camera_metadata_entry_data_size(
489 e->type, e->count) > 0 &&
490 e->data.offset > entry->data.offset) {
491 e->data.offset -= data_bytes;
492 }
493 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700494 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700495 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800496 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700497 // Shift entry array
498 memmove(entry, entry + 1,
499 sizeof(camera_metadata_buffer_entry_t) *
500 (dst->entry_count - index - 1) );
501 dst->entry_count -= 1;
502
503 return OK;
504}
505
506int update_camera_metadata_entry(camera_metadata_t *dst,
507 size_t index,
508 const void *data,
509 size_t data_count,
510 camera_metadata_entry_t *updated_entry) {
511 if (dst == NULL) return ERROR;
512 if (index >= dst->entry_count) return ERROR;
513
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800514 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700515
516 size_t data_bytes =
517 calculate_camera_metadata_entry_data_size(entry->type,
518 data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800519 size_t data_payload_bytes =
520 data_count * camera_metadata_type_size[entry->type];
521
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700522 size_t entry_bytes =
523 calculate_camera_metadata_entry_data_size(entry->type,
524 entry->count);
525 if (data_bytes != entry_bytes) {
526 // May need to shift/add to data array
527 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
528 // No room
529 return ERROR;
530 }
531 if (entry_bytes != 0) {
532 // Remove old data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800533 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700534 uint8_t *end = start + entry_bytes;
535 size_t length = dst->data_count - entry->data.offset - entry_bytes;
536 memmove(start, end, length);
537 dst->data_count -= entry_bytes;
538
539 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800540 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700541 size_t i;
542 for (i = 0; i < dst->entry_count; i++) {
543 if (calculate_camera_metadata_entry_data_size(
544 e->type, e->count) > 0 &&
545 e->data.offset > entry->data.offset) {
546 e->data.offset -= entry_bytes;
547 }
548 ++e;
549 }
550 }
551
552 if (data_bytes != 0) {
553 // Append new data
554 entry->data.offset = dst->data_count;
555
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800556 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700557 dst->data_count += data_bytes;
558 }
559 } else if (data_bytes != 0) {
560 // data size unchanged, reuse same data location
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800561 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700562 }
563
564 if (data_bytes == 0) {
565 // Data fits into entry
566 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800567 data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700568 }
569
570 entry->count = data_count;
571
572 if (updated_entry != NULL) {
573 get_camera_metadata_entry(dst,
574 index,
575 updated_entry);
576 }
577
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800578 return OK;
579}
580
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700581int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
582 if (dst == NULL) return ERROR;
583 dst->user = user;
584 return OK;
585}
586
587int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
588 if (dst == NULL) return ERROR;
589 *user = dst->user;
590 return OK;
591}
592
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800593static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
594
595const char *get_camera_metadata_section_name(uint32_t tag) {
596 uint32_t tag_section = tag >> 16;
597 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700598 return vendor_tag_ops->get_camera_vendor_section_name(
599 vendor_tag_ops,
600 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800601 }
602 if (tag_section >= ANDROID_SECTION_COUNT) {
603 return NULL;
604 }
605 return camera_metadata_section_names[tag_section];
606}
607
608const char *get_camera_metadata_tag_name(uint32_t tag) {
609 uint32_t tag_section = tag >> 16;
610 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700611 return vendor_tag_ops->get_camera_vendor_tag_name(
612 vendor_tag_ops,
613 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800614 }
615 if (tag_section >= ANDROID_SECTION_COUNT ||
616 tag >= camera_metadata_section_bounds[tag_section][1] ) {
617 return NULL;
618 }
619 uint32_t tag_index = tag & 0xFFFF;
620 return tag_info[tag_section][tag_index].tag_name;
621}
622
623int get_camera_metadata_tag_type(uint32_t tag) {
624 uint32_t tag_section = tag >> 16;
625 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700626 return vendor_tag_ops->get_camera_vendor_tag_type(
627 vendor_tag_ops,
628 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800629 }
630 if (tag_section >= ANDROID_SECTION_COUNT ||
631 tag >= camera_metadata_section_bounds[tag_section][1] ) {
632 return -1;
633 }
634 uint32_t tag_index = tag & 0xFFFF;
635 return tag_info[tag_section][tag_index].tag_type;
636}
637
638int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
639 vendor_tag_ops = query_ops;
640 return OK;
641}
642
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700643static void print_data(int fd, const uint8_t *data_ptr, int type, int count,
644 int indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800645
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700646void dump_camera_metadata(const camera_metadata_t *metadata,
647 int fd,
648 int verbosity) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700649 dump_indented_camera_metadata(metadata, fd, verbosity, 0);
650}
651
652void dump_indented_camera_metadata(const camera_metadata_t *metadata,
653 int fd,
654 int verbosity,
655 int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800656 if (metadata == NULL) {
Eino-Ville Talvala94879bd2012-10-01 16:33:03 -0700657 fdprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700658 indentation, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800659 return;
660 }
661 unsigned int i;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700662 fdprintf(fd,
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700663 "%*sDumping camera metadata array: %d / %d entries, "
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700664 "%d / %d bytes of extra data.\n", indentation, "",
665 metadata->entry_count, metadata->entry_capacity,
666 metadata->data_count, metadata->data_capacity);
667 fdprintf(fd, "%*sVersion: %d, Flags: %08x\n",
668 indentation + 2, "",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700669 metadata->version, metadata->flags);
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800670 camera_metadata_buffer_entry_t *entry = get_entries(metadata);
671 for (i=0; i < metadata->entry_count; i++, entry++) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800672
673 const char *tag_name, *tag_section;
674 tag_section = get_camera_metadata_section_name(entry->tag);
675 if (tag_section == NULL) {
676 tag_section = "unknownSection";
677 }
678 tag_name = get_camera_metadata_tag_name(entry->tag);
679 if (tag_name == NULL) {
680 tag_name = "unknownTag";
681 }
682 const char *type_name;
683 if (entry->type >= NUM_TYPES) {
684 type_name = "unknown";
685 } else {
686 type_name = camera_metadata_type_names[entry->type];
687 }
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700688 fdprintf(fd, "%*s%s.%s (%05x): %s[%d]\n",
689 indentation + 2, "",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800690 tag_section,
691 tag_name,
692 entry->tag,
693 type_name,
694 entry->count);
695
696 if (verbosity < 1) continue;
697
698 if (entry->type >= NUM_TYPES) continue;
699
700 size_t type_size = camera_metadata_type_size[entry->type];
701 uint8_t *data_ptr;
702 if ( type_size * entry->count > 4 ) {
703 if (entry->data.offset >= metadata->data_count) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700704 ALOGE("%s: Malformed entry data offset: %d (max %d)",
705 __FUNCTION__,
706 entry->data.offset,
707 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800708 continue;
709 }
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800710 data_ptr = get_data(metadata) + entry->data.offset;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800711 } else {
712 data_ptr = entry->data.value;
713 }
714 int count = entry->count;
715 if (verbosity < 2 && count > 16) count = 16;
716
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700717 print_data(fd, data_ptr, entry->type, count, indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800718 }
719}
720
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700721static void print_data(int fd, const uint8_t *data_ptr,
722 int type, int count, int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800723 static int values_per_line[NUM_TYPES] = {
724 [TYPE_BYTE] = 16,
725 [TYPE_INT32] = 4,
726 [TYPE_FLOAT] = 8,
727 [TYPE_INT64] = 2,
728 [TYPE_DOUBLE] = 4,
729 [TYPE_RATIONAL] = 2,
730 };
731 size_t type_size = camera_metadata_type_size[type];
732
733 int lines = count / values_per_line[type];
734 if (count % values_per_line[type] != 0) lines++;
735
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800736 int index = 0;
737 int j, k;
738 for (j = 0; j < lines; j++) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700739 fdprintf(fd, "%*s[", indentation + 4, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800740 for (k = 0;
741 k < values_per_line[type] && count > 0;
742 k++, count--, index += type_size) {
743
744 switch (type) {
745 case TYPE_BYTE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700746 fdprintf(fd, "%hhu ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800747 *(data_ptr + index));
748 break;
749 case TYPE_INT32:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700750 fdprintf(fd, "%d ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800751 *(int32_t*)(data_ptr + index));
752 break;
753 case TYPE_FLOAT:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700754 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800755 *(float*)(data_ptr + index));
756 break;
757 case TYPE_INT64:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700758 fdprintf(fd, "%lld ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800759 *(int64_t*)(data_ptr + index));
760 break;
761 case TYPE_DOUBLE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700762 fdprintf(fd, "%0.2f ",
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800763 *(double*)(data_ptr + index));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800764 break;
765 case TYPE_RATIONAL: {
766 int32_t numerator = *(int32_t*)(data_ptr + index);
767 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700768 fdprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800769 numerator, denominator);
770 break;
771 }
772 default:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700773 fdprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800774 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800775 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700776 fdprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800777 }
778}