OSDN Git Service

Camera: Add methods for read-only access to metadata.
[android-x86/system-media.git] / camera / src / camera_metadata.c
1 /*
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  */
16 #define _GNU_SOURCE // for fdprintf
17 #include <system/camera_metadata.h>
18 #include <cutils/log.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <errno.h>
22
23 #define OK         0
24 #define ERROR      1
25 #define NOT_FOUND -ENOENT
26 /**
27  * A single metadata entry, storing an array of values of a given type. If the
28  * array is no larger than 4 bytes in size, it is stored in the data.value[]
29  * array; otherwise, it can found in the parent's data array at index
30  * data.offset.
31  */
32 typedef struct camera_metadata_buffer_entry {
33     uint32_t tag;
34     size_t   count;
35     union {
36         size_t  offset;
37         uint8_t value[4];
38     } data;
39     uint8_t  type;
40     uint8_t  reserved[3];
41 } __attribute__((packed)) camera_metadata_buffer_entry_t;
42
43 /**
44  * A packet of metadata. This is a list of entries, each of which may point to
45  * its values stored at an offset in data.
46  *
47  * It is assumed by the utility functions that the memory layout of the packet
48  * is as follows:
49  *
50  *   |-----------------------------------------------|
51  *   | camera_metadata_t                             |
52  *   |                                               |
53  *   |-----------------------------------------------|
54  *   | reserved for future expansion                 |
55  *   |-----------------------------------------------|
56  *   | camera_metadata_buffer_entry_t #0             |
57  *   |-----------------------------------------------|
58  *   | ....                                          |
59  *   |-----------------------------------------------|
60  *   | camera_metadata_buffer_entry_t #entry_count-1 |
61  *   |-----------------------------------------------|
62  *   | free space for                                |
63  *   | (entry_capacity-entry_count) entries          |
64  *   |-----------------------------------------------|
65  *   | start of camera_metadata.data                 |
66  *   |                                               |
67  *   |-----------------------------------------------|
68  *   | free space for                                |
69  *   | (data_capacity-data_count) bytes              |
70  *   |-----------------------------------------------|
71  *
72  * With the total length of the whole packet being camera_metadata.size bytes.
73  *
74  * In short, the entries and data are contiguous in memory after the metadata
75  * header.
76  */
77 struct camera_metadata {
78     size_t                   size;
79     uint32_t                 version;
80     uint32_t                 flags;
81     size_t                   entry_count;
82     size_t                   entry_capacity;
83     camera_metadata_buffer_entry_t *entries;
84     size_t                   data_count;
85     size_t                   data_capacity;
86     uint8_t                 *data;
87     void                    *user; // User set pointer, not copied with buffer
88     uint8_t                  reserved[0];
89 };
90
91 /** Versioning information */
92 #define CURRENT_METADATA_VERSION 1
93
94 /** Flag definitions */
95 #define FLAG_SORTED 0x00000001
96
97 /** Tag information */
98
99 typedef struct tag_info {
100     const char *tag_name;
101     uint8_t     tag_type;
102 } tag_info_t;
103
104 #include "camera_metadata_tag_info.c"
105
106 const size_t camera_metadata_type_size[NUM_TYPES] = {
107     [TYPE_BYTE]     = sizeof(uint8_t),
108     [TYPE_INT32]    = sizeof(int32_t),
109     [TYPE_FLOAT]    = sizeof(float),
110     [TYPE_INT64]    = sizeof(int64_t),
111     [TYPE_DOUBLE]   = sizeof(double),
112     [TYPE_RATIONAL] = sizeof(camera_metadata_rational_t)
113 };
114
115 const char *camera_metadata_type_names[NUM_TYPES] = {
116     [TYPE_BYTE]     = "byte",
117     [TYPE_INT32]    = "int32",
118     [TYPE_FLOAT]    = "float",
119     [TYPE_INT64]    = "int64",
120     [TYPE_DOUBLE]   = "double",
121     [TYPE_RATIONAL] = "rational"
122 };
123
124 camera_metadata_t *allocate_camera_metadata(size_t entry_capacity,
125                                             size_t data_capacity) {
126     if (entry_capacity == 0) return NULL;
127
128     size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
129                                                           data_capacity);
130     void *buffer = malloc(memory_needed);
131     return place_camera_metadata(buffer, memory_needed,
132                                  entry_capacity,
133                                  data_capacity);
134 }
135
136 camera_metadata_t *place_camera_metadata(void *dst,
137                                          size_t dst_size,
138                                          size_t entry_capacity,
139                                          size_t data_capacity) {
140     if (dst == NULL) return NULL;
141     if (entry_capacity == 0) return NULL;
142
143     size_t memory_needed = calculate_camera_metadata_size(entry_capacity,
144                                                           data_capacity);
145     if (memory_needed > dst_size) return NULL;
146
147     camera_metadata_t *metadata = (camera_metadata_t*)dst;
148     metadata->version = CURRENT_METADATA_VERSION;
149     metadata->flags = 0;
150     metadata->entry_count = 0;
151     metadata->entry_capacity = entry_capacity;
152     metadata->entries = (camera_metadata_buffer_entry_t*)(metadata + 1);
153     metadata->data_count = 0;
154     metadata->data_capacity = data_capacity;
155     metadata->size = memory_needed;
156     if (metadata->data_capacity != 0) {
157         metadata->data =
158                 (uint8_t*)(metadata->entries + metadata->entry_capacity);
159     } else {
160         metadata->data = NULL;
161     }
162     metadata->user = NULL;
163
164     return metadata;
165 }
166 void free_camera_metadata(camera_metadata_t *metadata) {
167     free(metadata);
168 }
169
170 size_t calculate_camera_metadata_size(size_t entry_count,
171                                       size_t data_count) {
172     size_t memory_needed = sizeof(camera_metadata_t);
173     memory_needed += sizeof(camera_metadata_buffer_entry_t[entry_count]);
174     memory_needed += sizeof(uint8_t[data_count]);
175     return memory_needed;
176 }
177
178 size_t get_camera_metadata_size(const camera_metadata_t *metadata) {
179     if (metadata == NULL) return ERROR;
180
181     return metadata->size;
182 }
183
184 size_t get_camera_metadata_compact_size(const camera_metadata_t *metadata) {
185     if (metadata == NULL) return ERROR;
186
187     ptrdiff_t reserved_size = metadata->size -
188             calculate_camera_metadata_size(metadata->entry_capacity,
189                                            metadata->data_capacity);
190
191     return calculate_camera_metadata_size(metadata->entry_count,
192                                           metadata->data_count) + reserved_size;
193 }
194
195 size_t get_camera_metadata_entry_count(const camera_metadata_t *metadata) {
196     return metadata->entry_count;
197 }
198
199 size_t get_camera_metadata_entry_capacity(const camera_metadata_t *metadata) {
200     return metadata->entry_capacity;
201 }
202
203 size_t get_camera_metadata_data_count(const camera_metadata_t *metadata) {
204     return metadata->data_count;
205 }
206
207 size_t get_camera_metadata_data_capacity(const camera_metadata_t *metadata) {
208     return metadata->data_capacity;
209 }
210
211 camera_metadata_t* copy_camera_metadata(void *dst, size_t dst_size,
212         const camera_metadata_t *src) {
213     size_t memory_needed = get_camera_metadata_compact_size(src);
214
215     if (dst == NULL) return NULL;
216     if (dst_size < memory_needed) return NULL;
217
218     // If copying a newer version of the structure, there may be additional
219     // header fields we don't know about but need to copy
220     ptrdiff_t reserved_size = src->size -
221             calculate_camera_metadata_size(src->entry_capacity,
222                                            src->data_capacity);
223
224     camera_metadata_t *metadata = (camera_metadata_t*)dst;
225     metadata->version = CURRENT_METADATA_VERSION;
226     metadata->flags = src->flags;
227     metadata->entry_count = src->entry_count;
228     metadata->entry_capacity = src->entry_count;
229     metadata->entries = (camera_metadata_buffer_entry_t*)
230              ((uint8_t *)(metadata + 1) + reserved_size);
231     metadata->data_count = src->data_count;
232     metadata->data_capacity = src->data_count;
233     metadata->data = (uint8_t *)(metadata->entries + metadata->entry_capacity);
234     metadata->size = memory_needed;
235
236     if (reserved_size > 0) {
237         memcpy(metadata->reserved, src->reserved, reserved_size);
238     }
239     memcpy(metadata->entries, src->entries,
240             sizeof(camera_metadata_buffer_entry_t[metadata->entry_count]));
241     memcpy(metadata->data, src->data,
242             sizeof(uint8_t[metadata->data_count]));
243     metadata->user = NULL;
244
245     return metadata;
246 }
247
248 int append_camera_metadata(camera_metadata_t *dst,
249         const camera_metadata_t *src) {
250     if (dst == NULL || src == NULL ) return ERROR;
251
252     if (dst->entry_capacity < src->entry_count + dst->entry_count) return ERROR;
253     if (dst->data_capacity < src->data_count + dst->data_count) return ERROR;
254
255     memcpy(dst->entries + dst->entry_count, src->entries,
256             sizeof(camera_metadata_buffer_entry_t[src->entry_count]));
257     memcpy(dst->data + dst->data_count, src->data,
258             sizeof(uint8_t[src->data_count]));
259     if (dst->data_count != 0) {
260         unsigned int i;
261         for (i = dst->entry_count;
262              i < dst->entry_count + src->entry_count;
263              i++) {
264             camera_metadata_buffer_entry_t *entry = dst->entries + i;
265             if ( camera_metadata_type_size[entry->type] * entry->count > 4 ) {
266                 entry->data.offset += dst->data_count;
267             }
268         }
269     }
270     if (dst->entry_count == 0) {
271         // Appending onto empty buffer, keep sorted state
272         dst->flags |= src->flags & FLAG_SORTED;
273     } else if (src->entry_count != 0) {
274         // Both src, dst are nonempty, cannot assume sort remains
275         dst->flags &= ~FLAG_SORTED;
276     } else {
277         // Src is empty, keep dst sorted state
278     }
279     dst->entry_count += src->entry_count;
280     dst->data_count += src->data_count;
281
282     return OK;
283 }
284
285 camera_metadata_t *clone_camera_metadata(const camera_metadata_t *src) {
286     int res;
287     if (src == NULL) return NULL;
288     camera_metadata_t *clone = allocate_camera_metadata(
289         get_camera_metadata_entry_count(src),
290         get_camera_metadata_data_count(src));
291     if (clone != NULL) {
292         res = append_camera_metadata(clone, src);
293         if (res != OK) {
294             free_camera_metadata(clone);
295             clone = NULL;
296         }
297     }
298     return clone;
299 }
300
301 size_t calculate_camera_metadata_entry_data_size(uint8_t type,
302         size_t data_count) {
303     if (type >= NUM_TYPES) return 0;
304     size_t data_bytes = data_count *
305             camera_metadata_type_size[type];
306     return data_bytes <= 4 ? 0 : data_bytes;
307 }
308
309 static int add_camera_metadata_entry_raw(camera_metadata_t *dst,
310         uint32_t tag,
311         uint8_t  type,
312         const void *data,
313         size_t data_count) {
314
315     if (dst == NULL) return ERROR;
316     if (dst->entry_count == dst->entry_capacity) return ERROR;
317     if (data == NULL) return ERROR;
318
319     size_t data_bytes =
320             calculate_camera_metadata_entry_data_size(type, data_count);
321
322     camera_metadata_buffer_entry_t *entry = dst->entries + dst->entry_count;
323     entry->tag = tag;
324     entry->type = type;
325     entry->count = data_count;
326
327     if (data_bytes == 0) {
328         memcpy(entry->data.value, data,
329                 data_count * camera_metadata_type_size[type] );
330     } else {
331         entry->data.offset = dst->data_count;
332         memcpy(dst->data + entry->data.offset, data, data_bytes);
333         dst->data_count += data_bytes;
334     }
335     dst->entry_count++;
336     dst->flags &= ~FLAG_SORTED;
337     return OK;
338 }
339
340 int add_camera_metadata_entry(camera_metadata_t *dst,
341         uint32_t tag,
342         const void *data,
343         size_t data_count) {
344
345     int type = get_camera_metadata_tag_type(tag);
346     if (type == -1) {
347         ALOGE("%s: Unknown tag %04x.", __FUNCTION__, tag);
348         return ERROR;
349     }
350
351     return add_camera_metadata_entry_raw(dst,
352             tag,
353             type,
354             data,
355             data_count);
356 }
357
358 static int compare_entry_tags(const void *p1, const void *p2) {
359     uint32_t tag1 = ((camera_metadata_buffer_entry_t*)p1)->tag;
360     uint32_t tag2 = ((camera_metadata_buffer_entry_t*)p2)->tag;
361     return  tag1 < tag2 ? -1 :
362             tag1 == tag2 ? 0 :
363             1;
364 }
365
366 int sort_camera_metadata(camera_metadata_t *dst) {
367     if (dst == NULL) return ERROR;
368     if (dst->flags & FLAG_SORTED) return OK;
369
370     qsort(dst->entries, dst->entry_count,
371             sizeof(camera_metadata_buffer_entry_t),
372             compare_entry_tags);
373     dst->flags |= FLAG_SORTED;
374
375     return OK;
376 }
377
378 int get_camera_metadata_entry(camera_metadata_t *src,
379         size_t index,
380         camera_metadata_entry_t *entry) {
381     if (src == NULL || entry == NULL) return ERROR;
382     if (index >= src->entry_count) return ERROR;
383
384     camera_metadata_buffer_entry_t *buffer_entry = src->entries + index;
385
386     entry->index = index;
387     entry->tag = buffer_entry->tag;
388     entry->type = buffer_entry->type;
389     entry->count = buffer_entry->count;
390     if (buffer_entry->count *
391             camera_metadata_type_size[buffer_entry->type] > 4) {
392         entry->data.u8 = src->data + buffer_entry->data.offset;
393     } else {
394         entry->data.u8 = buffer_entry->data.value;
395     }
396     return OK;
397 }
398
399 int find_camera_metadata_entry(camera_metadata_t *src,
400         uint32_t tag,
401         camera_metadata_entry_t *entry) {
402     if (src == NULL) return ERROR;
403
404     uint32_t index;
405     if (src->flags & FLAG_SORTED) {
406         // Sorted entries, do a binary search
407         camera_metadata_buffer_entry_t *search_entry = NULL;
408         camera_metadata_buffer_entry_t key;
409         key.tag = tag;
410         search_entry = bsearch(&key,
411                 src->entries,
412                 src->entry_count,
413                 sizeof(camera_metadata_buffer_entry_t),
414                 compare_entry_tags);
415         if (search_entry == NULL) return NOT_FOUND;
416         index = search_entry - src->entries;
417     } else {
418         // Not sorted, linear search
419         for (index = 0; index < src->entry_count; index++) {
420             if (src->entries[index].tag == tag) {
421                 break;
422             }
423         }
424         if (index == src->entry_count) return NOT_FOUND;
425     }
426
427     return get_camera_metadata_entry(src, index,
428             entry);
429 }
430
431 int find_camera_metadata_ro_entry(const camera_metadata_t *src,
432         uint32_t tag,
433         camera_metadata_ro_entry_t *entry) {
434     return find_camera_metadata_entry((camera_metadata_t*)src, tag,
435             (camera_metadata_entry_t*)entry);
436 }
437
438
439 int delete_camera_metadata_entry(camera_metadata_t *dst,
440         size_t index) {
441     if (dst == NULL) return ERROR;
442     if (index >= dst->entry_count) return ERROR;
443
444     camera_metadata_buffer_entry_t *entry = dst->entries + index;
445     size_t data_bytes = calculate_camera_metadata_entry_data_size(entry->type,
446             entry->count);
447
448     if (data_bytes > 0) {
449         // Shift data buffer to overwrite deleted data
450         uint8_t *start = dst->data + entry->data.offset;
451         uint8_t *end = start + data_bytes;
452         size_t length = dst->data_count - entry->data.offset - data_bytes;
453         memmove(start, end, length);
454
455         // Update all entry indices to account for shift
456         camera_metadata_buffer_entry_t *e = dst->entries;
457         size_t i;
458         for (i = 0; i < dst->entry_count; i++) {
459             if (calculate_camera_metadata_entry_data_size(
460                     e->type, e->count) > 0 &&
461                     e->data.offset > entry->data.offset) {
462                 e->data.offset -= data_bytes;
463             }
464             ++e;
465         }
466         dst->data_count -= data_bytes;
467     }
468     // Shift entry array
469     memmove(entry, entry + 1,
470             sizeof(camera_metadata_buffer_entry_t) *
471             (dst->entry_count - index - 1) );
472     dst->entry_count -= 1;
473
474     return OK;
475 }
476
477 int update_camera_metadata_entry(camera_metadata_t *dst,
478         size_t index,
479         const void *data,
480         size_t data_count,
481         camera_metadata_entry_t *updated_entry) {
482     if (dst == NULL) return ERROR;
483     if (index >= dst->entry_count) return ERROR;
484
485     camera_metadata_buffer_entry_t *entry = dst->entries + index;
486
487     size_t data_bytes =
488             calculate_camera_metadata_entry_data_size(entry->type,
489                     data_count);
490     size_t entry_bytes =
491             calculate_camera_metadata_entry_data_size(entry->type,
492                     entry->count);
493     if (data_bytes != entry_bytes) {
494         // May need to shift/add to data array
495         if (dst->data_capacity < dst->data_count + data_bytes - entry_bytes) {
496             // No room
497             return ERROR;
498         }
499         if (entry_bytes != 0) {
500             // Remove old data
501             uint8_t *start = dst->data + entry->data.offset;
502             uint8_t *end = start + entry_bytes;
503             size_t length = dst->data_count - entry->data.offset - entry_bytes;
504             memmove(start, end, length);
505             dst->data_count -= entry_bytes;
506
507             // Update all entry indices to account for shift
508             camera_metadata_buffer_entry_t *e = dst->entries;
509             size_t i;
510             for (i = 0; i < dst->entry_count; i++) {
511                 if (calculate_camera_metadata_entry_data_size(
512                         e->type, e->count) > 0 &&
513                         e->data.offset > entry->data.offset) {
514                     e->data.offset -= entry_bytes;
515                 }
516                 ++e;
517             }
518         }
519
520         if (data_bytes != 0) {
521             // Append new data
522             entry->data.offset = dst->data_count;
523
524             memcpy(dst->data + entry->data.offset, data, data_bytes);
525             dst->data_count += data_bytes;
526         }
527     } else if (data_bytes != 0) {
528         // data size unchanged, reuse same data location
529         memcpy(dst->data + entry->data.offset, data, data_bytes);
530     }
531
532     if (data_bytes == 0) {
533         // Data fits into entry
534         memcpy(entry->data.value, data,
535                 data_count * camera_metadata_type_size[entry->type]);
536     }
537
538     entry->count = data_count;
539
540     if (updated_entry != NULL) {
541         get_camera_metadata_entry(dst,
542                 index,
543                 updated_entry);
544     }
545
546     return OK;
547 }
548
549 int set_camera_metadata_user_pointer(camera_metadata_t *dst, void* user) {
550     if (dst == NULL) return ERROR;
551     dst->user = user;
552     return OK;
553 }
554
555 int get_camera_metadata_user_pointer(camera_metadata_t *dst, void** user) {
556     if (dst == NULL) return ERROR;
557     *user = dst->user;
558     return OK;
559 }
560
561 static const vendor_tag_query_ops_t *vendor_tag_ops = NULL;
562
563 const char *get_camera_metadata_section_name(uint32_t tag) {
564     uint32_t tag_section = tag >> 16;
565     if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
566         return vendor_tag_ops->get_camera_vendor_section_name(
567             vendor_tag_ops,
568             tag);
569     }
570     if (tag_section >= ANDROID_SECTION_COUNT) {
571         return NULL;
572     }
573     return camera_metadata_section_names[tag_section];
574 }
575
576 const char *get_camera_metadata_tag_name(uint32_t tag) {
577     uint32_t tag_section = tag >> 16;
578     if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
579         return vendor_tag_ops->get_camera_vendor_tag_name(
580             vendor_tag_ops,
581             tag);
582     }
583     if (tag_section >= ANDROID_SECTION_COUNT ||
584         tag >= camera_metadata_section_bounds[tag_section][1] ) {
585         return NULL;
586     }
587     uint32_t tag_index = tag & 0xFFFF;
588     return tag_info[tag_section][tag_index].tag_name;
589 }
590
591 int get_camera_metadata_tag_type(uint32_t tag) {
592     uint32_t tag_section = tag >> 16;
593     if (tag_section >= VENDOR_SECTION && vendor_tag_ops != NULL) {
594         return vendor_tag_ops->get_camera_vendor_tag_type(
595             vendor_tag_ops,
596             tag);
597     }
598     if (tag_section >= ANDROID_SECTION_COUNT ||
599             tag >= camera_metadata_section_bounds[tag_section][1] ) {
600         return -1;
601     }
602     uint32_t tag_index = tag & 0xFFFF;
603     return tag_info[tag_section][tag_index].tag_type;
604 }
605
606 int set_camera_metadata_vendor_tag_ops(const vendor_tag_query_ops_t *query_ops) {
607     vendor_tag_ops = query_ops;
608     return OK;
609 }
610
611 static void print_data(int fd, const uint8_t *data_ptr, int type, int count,
612         int indentation);
613
614 void dump_camera_metadata(const camera_metadata_t *metadata,
615         int fd,
616         int verbosity) {
617     dump_indented_camera_metadata(metadata, fd, verbosity, 0);
618 }
619
620 void dump_indented_camera_metadata(const camera_metadata_t *metadata,
621         int fd,
622         int verbosity,
623         int indentation) {
624     if (metadata == NULL) {
625         fdprintf(fd, "%*sDumping camera metadata array: Not allocated",
626                 indentation, "");
627         return;
628     }
629     unsigned int i;
630     fdprintf(fd,
631             "%*sDumping camera metadata array: %d / %d entries, "
632             "%d / %d bytes of extra data.\n", indentation, "",
633             metadata->entry_count, metadata->entry_capacity,
634             metadata->data_count, metadata->data_capacity);
635     fdprintf(fd, "%*sVersion: %d, Flags: %08x\n",
636             indentation + 2, "",
637             metadata->version, metadata->flags);
638     for (i=0; i < metadata->entry_count; i++) {
639         camera_metadata_buffer_entry_t *entry = metadata->entries + i;
640
641         const char *tag_name, *tag_section;
642         tag_section = get_camera_metadata_section_name(entry->tag);
643         if (tag_section == NULL) {
644             tag_section = "unknownSection";
645         }
646         tag_name = get_camera_metadata_tag_name(entry->tag);
647         if (tag_name == NULL) {
648             tag_name = "unknownTag";
649         }
650         const char *type_name;
651         if (entry->type >= NUM_TYPES) {
652             type_name = "unknown";
653         } else {
654             type_name = camera_metadata_type_names[entry->type];
655         }
656         fdprintf(fd, "%*s%s.%s (%05x): %s[%d]\n",
657              indentation + 2, "",
658              tag_section,
659              tag_name,
660              entry->tag,
661              type_name,
662              entry->count);
663
664         if (verbosity < 1) continue;
665
666         if (entry->type >= NUM_TYPES) continue;
667
668         size_t type_size = camera_metadata_type_size[entry->type];
669         uint8_t *data_ptr;
670         if ( type_size * entry->count > 4 ) {
671             if (entry->data.offset >= metadata->data_count) {
672                 ALOGE("%s: Malformed entry data offset: %d (max %d)",
673                         __FUNCTION__,
674                         entry->data.offset,
675                         metadata->data_count);
676                 continue;
677             }
678             data_ptr = metadata->data + entry->data.offset;
679         } else {
680             data_ptr = entry->data.value;
681         }
682         int count = entry->count;
683         if (verbosity < 2 && count > 16) count = 16;
684
685         print_data(fd, data_ptr, entry->type, count, indentation);
686     }
687 }
688
689 static void print_data(int fd, const uint8_t *data_ptr,
690         int type, int count, int indentation) {
691     static int values_per_line[NUM_TYPES] = {
692         [TYPE_BYTE]     = 16,
693         [TYPE_INT32]    = 4,
694         [TYPE_FLOAT]    = 8,
695         [TYPE_INT64]    = 2,
696         [TYPE_DOUBLE]   = 4,
697         [TYPE_RATIONAL] = 2,
698     };
699     size_t type_size = camera_metadata_type_size[type];
700
701     int lines = count / values_per_line[type];
702     if (count % values_per_line[type] != 0) lines++;
703
704     int index = 0;
705     int j, k;
706     for (j = 0; j < lines; j++) {
707         fdprintf(fd, "%*s[", indentation + 4, "");
708         for (k = 0;
709              k < values_per_line[type] && count > 0;
710              k++, count--, index += type_size) {
711
712             switch (type) {
713                 case TYPE_BYTE:
714                     fdprintf(fd, "%hhu ",
715                             *(data_ptr + index));
716                     break;
717                 case TYPE_INT32:
718                     fdprintf(fd, "%d ",
719                             *(int32_t*)(data_ptr + index));
720                     break;
721                 case TYPE_FLOAT:
722                     fdprintf(fd, "%0.2f ",
723                             *(float*)(data_ptr + index));
724                     break;
725                 case TYPE_INT64:
726                     fdprintf(fd, "%lld ",
727                             *(int64_t*)(data_ptr + index));
728                     break;
729                 case TYPE_DOUBLE:
730                     fdprintf(fd, "%0.2f ",
731                             *(float*)(data_ptr + index));
732                     break;
733                 case TYPE_RATIONAL: {
734                     int32_t numerator = *(int32_t*)(data_ptr + index);
735                     int32_t denominator = *(int32_t*)(data_ptr + index + 4);
736                     fdprintf(fd, "(%d / %d) ",
737                             numerator, denominator);
738                     break;
739                 }
740                 default:
741                     fdprintf(fd, "??? ");
742             }
743         }
744         fdprintf(fd, "]\n");
745     }
746 }