blob: e04b32cda84a3fabc464c98819400bcd11ca7e0b [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) \
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
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
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800137static camera_metadata_buffer_entry_t *get_entries(
138 const camera_metadata_t *metadata) {
139 return (camera_metadata_buffer_entry_t*)
140 ((uint8_t*)metadata + metadata->entries_start);
141}
142
143static uint8_t *get_data(const camera_metadata_t *metadata) {
144 return (uint8_t*)metadata + metadata->data_start;
145}
146
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800147camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
148 size_t data_capacity) {
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700149 if (entry_capacity == 0) return NULL;
150
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800151 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
152 data_capacity);
153 void *buffer = malloc(memory_needed);
154 return place_camera_metadata(buffer, memory_needed,
155 entry_capacity,
156 data_capacity);
157}
158
159camera_metadata_t *place_camera_metadata(void *dst,
160 size_t dst_size,
161 size_t entry_capacity,
162 size_t data_capacity) {
163 if (dst == NULL) return NULL;
164 if (entry_capacity == 0) return NULL;
165
166 size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
167 data_capacity);
168 if (memory_needed > dst_size) return NULL;
169
170 camera_metadata_t *metadata = (camera_metadata_t*)dst;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700171 metadata->version = CURRENT_METADATA_VERSION;
172 metadata->flags = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800173 metadata->entry_count = 0;
174 metadata->entry_capacity = entry_capacity;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800175 metadata->entries_start =
176 ALIGN_TO(sizeof(camera_metadata_t), ENTRY_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800177 metadata->data_count = 0;
178 metadata->data_capacity = data_capacity;
179 metadata->size = memory_needed;
180 if (metadata->data_capacity != 0) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800181 size_t data_unaligned = (uint8_t*)(get_entries(metadata) +
182 metadata->entry_capacity) - (uint8_t*)metadata;
183 metadata->data_start = ALIGN_TO(data_unaligned, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800184 } else {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800185 metadata->data_start = 0;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800186 }
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700187 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800188
189 return metadata;
190}
191void free_camera_metadata(camera_metadata_t *metadata) {
192 free(metadata);
193}
194
195size_t calculate_camera_metadata_size(size_t entry_count,
196 size_t data_count) {
197 size_t memory_needed = sizeof(camera_metadata_t);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800198 // Start entry list at aligned boundary
199 memory_needed = ALIGN_TO(memory_needed, ENTRY_ALIGNMENT);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700200 memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800201 // Start buffer list at aligned boundary
202 memory_needed = ALIGN_TO(memory_needed, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800203 memory_needed += sizeof(uint8_t[data_count]);
204 return memory_needed;
205}
206
207size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
208 if (metadata == NULL) return ERROR;
209
210 return metadata->size;
211}
212
213size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
214 if (metadata == NULL) return ERROR;
215
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800216 return calculate_camera_metadata_size(metadata->entry_count,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800217 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800218}
219
220size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
221 return metadata->entry_count;
222}
223
224size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
225 return metadata->entry_capacity;
226}
227
228size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
229 return metadata->data_count;
230}
231
232size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
233 return metadata->data_capacity;
234}
235
236camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
237 const camera_metadata_t *src) {
238 size_t memory_needed = get_camera_metadata_compact_size(src);
239
240 if (dst == NULL) return NULL;
241 if (dst_size < memory_needed) return NULL;
242
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800243 camera_metadata_t *metadata =
244 place_camera_metadata(dst, dst_size, src->entry_count, src->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800245
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700246 metadata->flags = src->flags;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800247 metadata->entry_count = src->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800248 metadata->data_count = src->data_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800249
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800250 memcpy(get_entries(metadata), get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700251 sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800252 memcpy(get_data(metadata), get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800253 sizeof(uint8_t[metadata->data_count]));
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700254 metadata->user = NULL;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800255
256 return metadata;
257}
258
259int append_camera_metadata(camera_metadata_t *dst,
260 const camera_metadata_t *src) {
261 if (dst == NULL || src == NULL ) return ERROR;
262
263 if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
264 if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
265
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800266 memcpy(get_entries(dst) + dst->entry_count, get_entries(src),
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700267 sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800268 memcpy(get_data(dst) + dst->data_count, get_data(src),
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800269 sizeof(uint8_t[src->data_count]));
270 if (dst->data_count != 0) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800271 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
272 for (size_t i = 0; i < src->entry_count; i++, entry++) {
273 if ( calculate_camera_metadata_entry_data_size(entry->type,
274 entry->count) > 0 ) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800275 entry->data.offset += dst->data_count;
276 }
277 }
278 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700279 if (dst->entry_count == 0) {
280 // Appending onto empty buffer, keep sorted state
281 dst->flags |= src->flags & FLAG_SORTED;
282 } else if (src->entry_count != 0) {
283 // Both src, dst are nonempty, cannot assume sort remains
284 dst->flags &= ~FLAG_SORTED;
285 } else {
286 // Src is empty, keep dst sorted state
287 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800288 dst->entry_count += src->entry_count;
289 dst->data_count += src->data_count;
290
291 return OK;
292}
293
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700294camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700295 int res;
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700296 if (src == NULL) return NULL;
Eino-Ville Talvalafd258822012-06-06 17:22:42 -0700297 camera_metadata_t *clone = allocate_camera_metadata(
298 get_camera_metadata_entry_count(src),
299 get_camera_metadata_data_count(src));
300 if (clone != NULL) {
301 res = append_camera_metadata(clone, src);
302 if (res != OK) {
303 free_camera_metadata(clone);
304 clone = NULL;
305 }
306 }
307 return clone;
308}
309
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800310size_t calculate_camera_metadata_entry_data_size(uint8_t type,
311 size_t data_count) {
312 if (type >= NUM_TYPES) return 0;
313 size_t data_bytes = data_count *
314 camera_metadata_type_size[type];
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800315 return data_bytes <= 4 ? 0 : ALIGN_TO(data_bytes, DATA_ALIGNMENT);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800316}
317
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700318static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800319 uint32_t tag,
320 uint8_t type,
321 const void *data,
322 size_t data_count) {
323
324 if (dst == NULL) return ERROR;
325 if (dst->entry_count == dst->entry_capacity) return ERROR;
326 if (data == NULL) return ERROR;
327
328 size_t data_bytes =
329 calculate_camera_metadata_entry_data_size(type, data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800330 if (data_bytes + dst->data_count > dst->data_capacity) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800331
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800332 size_t data_payload_bytes =
333 data_count * camera_metadata_type_size[type];
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800334 camera_metadata_buffer_entry_t *entry = get_entries(dst) + dst->entry_count;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800335 entry->tag = tag;
336 entry->type = type;
337 entry->count = data_count;
338
339 if (data_bytes == 0) {
340 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800341 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800342 } else {
343 entry->data.offset = dst->data_count;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800344 memcpy(get_data(dst) + entry->data.offset, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800345 data_payload_bytes);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800346 dst->data_count += data_bytes;
347 }
348 dst->entry_count++;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700349 dst->flags &= ~FLAG_SORTED;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800350 return OK;
351}
352
353int add_camera_metadata_entry(camera_metadata_t *dst,
354 uint32_t tag,
355 const void *data,
356 size_t data_count) {
357
358 int type = get_camera_metadata_tag_type(tag);
359 if (type == -1) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700360 ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800361 return ERROR;
362 }
363
364 return add_camera_metadata_entry_raw(dst,
365 tag,
366 type,
367 data,
368 data_count);
369}
370
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700371static int compare_entry_tags(const void *p1, const void *p2) {
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700372 uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
373 uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700374 return tag1 < tag2 ? -1 :
375 tag1 == tag2 ? 0 :
376 1;
377}
378
379int sort_camera_metadata(camera_metadata_t *dst) {
380 if (dst == NULL) return ERROR;
381 if (dst->flags & FLAG_SORTED) return OK;
382
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800383 qsort(get_entries(dst), dst->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700384 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700385 compare_entry_tags);
386 dst->flags |= FLAG_SORTED;
387
388 return OK;
389}
390
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800391int get_camera_metadata_entry(camera_metadata_t *src,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700392 size_t index,
393 camera_metadata_entry_t *entry) {
394 if (src == NULL || entry == NULL) return ERROR;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800395 if (index >= src->entry_count) return ERROR;
396
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800397 camera_metadata_buffer_entry_t *buffer_entry = get_entries(src) + index;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800398
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700399 entry->index = index;
400 entry->tag = buffer_entry->tag;
401 entry->type = buffer_entry->type;
402 entry->count = buffer_entry->count;
403 if (buffer_entry->count *
404 camera_metadata_type_size[buffer_entry->type] > 4) {
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800405 entry->data.u8 = get_data(src) + buffer_entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700406 } else {
407 entry->data.u8 = buffer_entry->data.value;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700408 }
409 return OK;
410}
411
412int find_camera_metadata_entry(camera_metadata_t *src,
413 uint32_t tag,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700414 camera_metadata_entry_t *entry) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700415 if (src == NULL) return ERROR;
416
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700417 uint32_t index;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700418 if (src->flags & FLAG_SORTED) {
419 // Sorted entries, do a binary search
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700420 camera_metadata_buffer_entry_t *search_entry = NULL;
421 camera_metadata_buffer_entry_t key;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700422 key.tag = tag;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700423 search_entry = bsearch(&key,
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800424 get_entries(src),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700425 src->entry_count,
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700426 sizeof(camera_metadata_buffer_entry_t),
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700427 compare_entry_tags);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700428 if (search_entry == NULL) return NOT_FOUND;
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800429 index = search_entry - get_entries(src);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800430 } else {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700431 // Not sorted, linear search
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800432 camera_metadata_buffer_entry_t *search_entry = get_entries(src);
433 for (index = 0; index < src->entry_count; index++, search_entry++) {
434 if (search_entry->tag == tag) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700435 break;
436 }
437 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700438 if (index == src->entry_count) return NOT_FOUND;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700439 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700440
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700441 return get_camera_metadata_entry(src, index,
442 entry);
443}
444
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700445int find_camera_metadata_ro_entry(const camera_metadata_t *src,
446 uint32_t tag,
447 camera_metadata_ro_entry_t *entry) {
448 return find_camera_metadata_entry((camera_metadata_t*)src, tag,
449 (camera_metadata_entry_t*)entry);
450}
451
452
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700453int delete_camera_metadata_entry(camera_metadata_t *dst,
454 size_t index) {
455 if (dst == NULL) return ERROR;
456 if (index >= dst->entry_count) return ERROR;
457
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800458 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700459 size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
460 entry->count);
461
462 if (data_bytes > 0) {
463 // Shift data buffer to overwrite deleted data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800464 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700465 uint8_t *end = start + data_bytes;
466 size_t length = dst->data_count - entry->data.offset - data_bytes;
467 memmove(start, end, length);
468
469 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800470 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700471 size_t i;
472 for (i = 0; i < dst->entry_count; i++) {
473 if (calculate_camera_metadata_entry_data_size(
474 e->type, e->count) > 0 &&
475 e->data.offset > entry->data.offset) {
476 e->data.offset -= data_bytes;
477 }
478 ++e;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700479 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700480 dst->data_count -= data_bytes;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800481 }
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700482 // Shift entry array
483 memmove(entry, entry + 1,
484 sizeof(camera_metadata_buffer_entry_t) *
485 (dst->entry_count - index - 1) );
486 dst->entry_count -= 1;
487
488 return OK;
489}
490
491int update_camera_metadata_entry(camera_metadata_t *dst,
492 size_t index,
493 const void *data,
494 size_t data_count,
495 camera_metadata_entry_t *updated_entry) {
496 if (dst == NULL) return ERROR;
497 if (index >= dst->entry_count) return ERROR;
498
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800499 camera_metadata_buffer_entry_t *entry = get_entries(dst) + index;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700500
501 size_t data_bytes =
502 calculate_camera_metadata_entry_data_size(entry->type,
503 data_count);
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800504 size_t data_payload_bytes =
505 data_count * camera_metadata_type_size[entry->type];
506
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700507 size_t entry_bytes =
508 calculate_camera_metadata_entry_data_size(entry->type,
509 entry->count);
510 if (data_bytes != entry_bytes) {
511 // May need to shift/add to data array
512 if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
513 // No room
514 return ERROR;
515 }
516 if (entry_bytes != 0) {
517 // Remove old data
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800518 uint8_t *start = get_data(dst) + entry->data.offset;
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700519 uint8_t *end = start + entry_bytes;
520 size_t length = dst->data_count - entry->data.offset - entry_bytes;
521 memmove(start, end, length);
522 dst->data_count -= entry_bytes;
523
524 // Update all entry indices to account for shift
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800525 camera_metadata_buffer_entry_t *e = get_entries(dst);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700526 size_t i;
527 for (i = 0; i < dst->entry_count; i++) {
528 if (calculate_camera_metadata_entry_data_size(
529 e->type, e->count) > 0 &&
530 e->data.offset > entry->data.offset) {
531 e->data.offset -= entry_bytes;
532 }
533 ++e;
534 }
535 }
536
537 if (data_bytes != 0) {
538 // Append new data
539 entry->data.offset = dst->data_count;
540
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800541 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700542 dst->data_count += data_bytes;
543 }
544 } else if (data_bytes != 0) {
545 // data size unchanged, reuse same data location
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800546 memcpy(get_data(dst) + entry->data.offset, data, data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700547 }
548
549 if (data_bytes == 0) {
550 // Data fits into entry
551 memcpy(entry->data.value, data,
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800552 data_payload_bytes);
Eino-Ville Talvalaf5fb8a52012-05-10 14:22:28 -0700553 }
554
555 entry->count = data_count;
556
557 if (updated_entry != NULL) {
558 get_camera_metadata_entry(dst,
559 index,
560 updated_entry);
561 }
562
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800563 return OK;
564}
565
Eino-Ville Talvala98d02fd2012-05-21 14:46:49 -0700566int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
567 if (dst == NULL) return ERROR;
568 dst->user = user;
569 return OK;
570}
571
572int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
573 if (dst == NULL) return ERROR;
574 *user = dst->user;
575 return OK;
576}
577
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800578static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
579
580const char *get_camera_metadata_section_name(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_section_name(
584 vendor_tag_ops,
585 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800586 }
587 if (tag_section >= ANDROID_SECTION_COUNT) {
588 return NULL;
589 }
590 return camera_metadata_section_names[tag_section];
591}
592
593const char *get_camera_metadata_tag_name(uint32_t tag) {
594 uint32_t tag_section = tag >> 16;
595 if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700596 return vendor_tag_ops->get_camera_vendor_tag_name(
597 vendor_tag_ops,
598 tag);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800599 }
600 if (tag_section >= ANDROID_SECTION_COUNT ||
601 tag >= camera_metadata_section_bounds[tag_section][1] ) {
602 return NULL;
603 }
604 uint32_t tag_index = tag & 0xFFFF;
605 return tag_info[tag_section][tag_index].tag_name;
606}
607
608int get_camera_metadata_tag_type(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_type(
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 -1;
618 }
619 uint32_t tag_index = tag & 0xFFFF;
620 return tag_info[tag_section][tag_index].tag_type;
621}
622
623int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
624 vendor_tag_ops = query_ops;
625 return OK;
626}
627
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700628static void print_data(int fd, const uint8_t *data_ptr, int type, int count,
629 int indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800630
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700631void dump_camera_metadata(const camera_metadata_t *metadata,
632 int fd,
633 int verbosity) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700634 dump_indented_camera_metadata(metadata, fd, verbosity, 0);
635}
636
637void dump_indented_camera_metadata(const camera_metadata_t *metadata,
638 int fd,
639 int verbosity,
640 int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800641 if (metadata == NULL) {
Eino-Ville Talvala94879bd2012-10-01 16:33:03 -0700642 fdprintf(fd, "%*sDumping camera metadata array: Not allocated\n",
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700643 indentation, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800644 return;
645 }
646 unsigned int i;
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700647 fdprintf(fd,
Eino-Ville Talvala2f4aca62012-08-24 11:42:06 -0700648 "%*sDumping camera metadata array: %d / %d entries, "
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700649 "%d / %d bytes of extra data.\n", indentation, "",
650 metadata->entry_count, metadata->entry_capacity,
651 metadata->data_count, metadata->data_capacity);
652 fdprintf(fd, "%*sVersion: %d, Flags: %08x\n",
653 indentation + 2, "",
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700654 metadata->version, metadata->flags);
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800655 camera_metadata_buffer_entry_t *entry = get_entries(metadata);
656 for (i=0; i < metadata->entry_count; i++, entry++) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800657
658 const char *tag_name, *tag_section;
659 tag_section = get_camera_metadata_section_name(entry->tag);
660 if (tag_section == NULL) {
661 tag_section = "unknownSection";
662 }
663 tag_name = get_camera_metadata_tag_name(entry->tag);
664 if (tag_name == NULL) {
665 tag_name = "unknownTag";
666 }
667 const char *type_name;
668 if (entry->type >= NUM_TYPES) {
669 type_name = "unknown";
670 } else {
671 type_name = camera_metadata_type_names[entry->type];
672 }
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700673 fdprintf(fd, "%*s%s.%s (%05x): %s[%d]\n",
674 indentation + 2, "",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800675 tag_section,
676 tag_name,
677 entry->tag,
678 type_name,
679 entry->count);
680
681 if (verbosity < 1) continue;
682
683 if (entry->type >= NUM_TYPES) continue;
684
685 size_t type_size = camera_metadata_type_size[entry->type];
686 uint8_t *data_ptr;
687 if ( type_size * entry->count > 4 ) {
688 if (entry->data.offset >= metadata->data_count) {
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700689 ALOGE("%s: Malformed entry data offset: %d (max %d)",
690 __FUNCTION__,
691 entry->data.offset,
692 metadata->data_count);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800693 continue;
694 }
Eino-Ville Talvalab10d56a2012-11-13 11:45:12 -0800695 data_ptr = get_data(metadata) + entry->data.offset;
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800696 } else {
697 data_ptr = entry->data.value;
698 }
699 int count = entry->count;
700 if (verbosity < 2 && count > 16) count = 16;
701
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700702 print_data(fd, data_ptr, entry->type, count, indentation);
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800703 }
704}
705
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700706static void print_data(int fd, const uint8_t *data_ptr,
707 int type, int count, int indentation) {
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800708 static int values_per_line[NUM_TYPES] = {
709 [TYPE_BYTE] = 16,
710 [TYPE_INT32] = 4,
711 [TYPE_FLOAT] = 8,
712 [TYPE_INT64] = 2,
713 [TYPE_DOUBLE] = 4,
714 [TYPE_RATIONAL] = 2,
715 };
716 size_t type_size = camera_metadata_type_size[type];
717
718 int lines = count / values_per_line[type];
719 if (count % values_per_line[type] != 0) lines++;
720
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800721 int index = 0;
722 int j, k;
723 for (j = 0; j < lines; j++) {
Eino-Ville Talvala1d27e5b2012-07-30 10:46:22 -0700724 fdprintf(fd, "%*s[", indentation + 4, "");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800725 for (k = 0;
726 k < values_per_line[type] && count > 0;
727 k++, count--, index += type_size) {
728
729 switch (type) {
730 case TYPE_BYTE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700731 fdprintf(fd, "%hhu ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800732 *(data_ptr + index));
733 break;
734 case TYPE_INT32:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700735 fdprintf(fd, "%d ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800736 *(int32_t*)(data_ptr + index));
737 break;
738 case TYPE_FLOAT:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700739 fdprintf(fd, "%0.2f ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800740 *(float*)(data_ptr + index));
741 break;
742 case TYPE_INT64:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700743 fdprintf(fd, "%lld ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800744 *(int64_t*)(data_ptr + index));
745 break;
746 case TYPE_DOUBLE:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700747 fdprintf(fd, "%0.2f ",
Eino-Ville Talvala31540362012-11-07 16:36:50 -0800748 *(double*)(data_ptr + index));
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800749 break;
750 case TYPE_RATIONAL: {
751 int32_t numerator = *(int32_t*)(data_ptr + index);
752 int32_t denominator = *(int32_t*)(data_ptr + index + 4);
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700753 fdprintf(fd, "(%d / %d) ",
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800754 numerator, denominator);
755 break;
756 }
757 default:
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700758 fdprintf(fd, "??? ");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800759 }
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800760 }
Eino-Ville Talvala94c19012012-04-04 15:30:06 -0700761 fdprintf(fd, "]\n");
Eino-Ville Talvalad8afb4d2012-02-10 14:27:08 -0800762 }
763}