1*e01b6f76SAndroid Build Coastguard Worker /*
2*e01b6f76SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project
3*e01b6f76SAndroid Build Coastguard Worker *
4*e01b6f76SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*e01b6f76SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*e01b6f76SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*e01b6f76SAndroid Build Coastguard Worker *
8*e01b6f76SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*e01b6f76SAndroid Build Coastguard Worker *
10*e01b6f76SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*e01b6f76SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*e01b6f76SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e01b6f76SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*e01b6f76SAndroid Build Coastguard Worker * limitations under the License.
15*e01b6f76SAndroid Build Coastguard Worker */
16*e01b6f76SAndroid Build Coastguard Worker
17*e01b6f76SAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*e01b6f76SAndroid Build Coastguard Worker #define LOG_TAG "Metadata"
19*e01b6f76SAndroid Build Coastguard Worker
20*e01b6f76SAndroid Build Coastguard Worker #include <errno.h>
21*e01b6f76SAndroid Build Coastguard Worker
22*e01b6f76SAndroid Build Coastguard Worker #include <log/log.h>
23*e01b6f76SAndroid Build Coastguard Worker
24*e01b6f76SAndroid Build Coastguard Worker #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
25*e01b6f76SAndroid Build Coastguard Worker #include <utils/Trace.h>
26*e01b6f76SAndroid Build Coastguard Worker
27*e01b6f76SAndroid Build Coastguard Worker #include <system/camera_metadata.h>
28*e01b6f76SAndroid Build Coastguard Worker
29*e01b6f76SAndroid Build Coastguard Worker #include "Metadata.h"
30*e01b6f76SAndroid Build Coastguard Worker
31*e01b6f76SAndroid Build Coastguard Worker namespace usb_camera_hal {
32*e01b6f76SAndroid Build Coastguard Worker
Metadata()33*e01b6f76SAndroid Build Coastguard Worker Metadata::Metadata():
34*e01b6f76SAndroid Build Coastguard Worker mData(NULL) {
35*e01b6f76SAndroid Build Coastguard Worker }
36*e01b6f76SAndroid Build Coastguard Worker
~Metadata()37*e01b6f76SAndroid Build Coastguard Worker Metadata::~Metadata() {
38*e01b6f76SAndroid Build Coastguard Worker replace(NULL);
39*e01b6f76SAndroid Build Coastguard Worker }
40*e01b6f76SAndroid Build Coastguard Worker
replace(camera_metadata_t * m)41*e01b6f76SAndroid Build Coastguard Worker void Metadata::replace(camera_metadata_t *m) {
42*e01b6f76SAndroid Build Coastguard Worker if (m == mData) {
43*e01b6f76SAndroid Build Coastguard Worker return;
44*e01b6f76SAndroid Build Coastguard Worker }
45*e01b6f76SAndroid Build Coastguard Worker if (mData)
46*e01b6f76SAndroid Build Coastguard Worker free_camera_metadata(mData);
47*e01b6f76SAndroid Build Coastguard Worker mData = m;
48*e01b6f76SAndroid Build Coastguard Worker }
49*e01b6f76SAndroid Build Coastguard Worker
init(const camera_metadata_t * metadata)50*e01b6f76SAndroid Build Coastguard Worker int Metadata::init(const camera_metadata_t *metadata) {
51*e01b6f76SAndroid Build Coastguard Worker camera_metadata_t* tmp;
52*e01b6f76SAndroid Build Coastguard Worker
53*e01b6f76SAndroid Build Coastguard Worker if (!validate_camera_metadata_structure(metadata, NULL))
54*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
55*e01b6f76SAndroid Build Coastguard Worker
56*e01b6f76SAndroid Build Coastguard Worker tmp = clone_camera_metadata(metadata);
57*e01b6f76SAndroid Build Coastguard Worker if (tmp == NULL)
58*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
59*e01b6f76SAndroid Build Coastguard Worker
60*e01b6f76SAndroid Build Coastguard Worker replace(tmp);
61*e01b6f76SAndroid Build Coastguard Worker return 0;
62*e01b6f76SAndroid Build Coastguard Worker }
63*e01b6f76SAndroid Build Coastguard Worker
addUInt8(uint32_t tag,int count,const uint8_t * data)64*e01b6f76SAndroid Build Coastguard Worker int Metadata::addUInt8(uint32_t tag, int count, const uint8_t *data) {
65*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_BYTE, count)) return -EINVAL;
66*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
67*e01b6f76SAndroid Build Coastguard Worker }
68*e01b6f76SAndroid Build Coastguard Worker
add1UInt8(uint32_t tag,const uint8_t data)69*e01b6f76SAndroid Build Coastguard Worker int Metadata::add1UInt8(uint32_t tag, const uint8_t data) {
70*e01b6f76SAndroid Build Coastguard Worker return addUInt8(tag, 1, &data);
71*e01b6f76SAndroid Build Coastguard Worker }
72*e01b6f76SAndroid Build Coastguard Worker
addInt32(uint32_t tag,int count,const int32_t * data)73*e01b6f76SAndroid Build Coastguard Worker int Metadata::addInt32(uint32_t tag, int count, const int32_t *data) {
74*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_INT32, count)) return -EINVAL;
75*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
76*e01b6f76SAndroid Build Coastguard Worker }
77*e01b6f76SAndroid Build Coastguard Worker
addFloat(uint32_t tag,int count,const float * data)78*e01b6f76SAndroid Build Coastguard Worker int Metadata::addFloat(uint32_t tag, int count, const float *data) {
79*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL;
80*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
81*e01b6f76SAndroid Build Coastguard Worker }
82*e01b6f76SAndroid Build Coastguard Worker
addInt64(uint32_t tag,int count,const int64_t * data)83*e01b6f76SAndroid Build Coastguard Worker int Metadata::addInt64(uint32_t tag, int count, const int64_t *data) {
84*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_INT64, count)) return -EINVAL;
85*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
86*e01b6f76SAndroid Build Coastguard Worker }
87*e01b6f76SAndroid Build Coastguard Worker
addDouble(uint32_t tag,int count,const double * data)88*e01b6f76SAndroid Build Coastguard Worker int Metadata::addDouble(uint32_t tag, int count, const double *data) {
89*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL;
90*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
91*e01b6f76SAndroid Build Coastguard Worker }
92*e01b6f76SAndroid Build Coastguard Worker
addRational(uint32_t tag,int count,const camera_metadata_rational_t * data)93*e01b6f76SAndroid Build Coastguard Worker int Metadata::addRational(uint32_t tag, int count,
94*e01b6f76SAndroid Build Coastguard Worker const camera_metadata_rational_t *data) {
95*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL;
96*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
97*e01b6f76SAndroid Build Coastguard Worker }
98*e01b6f76SAndroid Build Coastguard Worker
validate(uint32_t tag,int tag_type,int count)99*e01b6f76SAndroid Build Coastguard Worker bool Metadata::validate(uint32_t tag, int tag_type, int count) {
100*e01b6f76SAndroid Build Coastguard Worker if (get_camera_metadata_tag_type(tag) < 0) {
101*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag);
102*e01b6f76SAndroid Build Coastguard Worker return false;
103*e01b6f76SAndroid Build Coastguard Worker }
104*e01b6f76SAndroid Build Coastguard Worker if (tag_type < 0 || tag_type >= NUM_TYPES) {
105*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type);
106*e01b6f76SAndroid Build Coastguard Worker return false;
107*e01b6f76SAndroid Build Coastguard Worker }
108*e01b6f76SAndroid Build Coastguard Worker if (tag_type != get_camera_metadata_tag_type(tag)) {
109*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag,
110*e01b6f76SAndroid Build Coastguard Worker camera_metadata_type_names[tag_type], tag_type);
111*e01b6f76SAndroid Build Coastguard Worker return false;
112*e01b6f76SAndroid Build Coastguard Worker }
113*e01b6f76SAndroid Build Coastguard Worker if (count < 1) {
114*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Invalid metadata entry count: %d", __func__, count);
115*e01b6f76SAndroid Build Coastguard Worker return false;
116*e01b6f76SAndroid Build Coastguard Worker }
117*e01b6f76SAndroid Build Coastguard Worker return true;
118*e01b6f76SAndroid Build Coastguard Worker }
119*e01b6f76SAndroid Build Coastguard Worker
add(uint32_t tag,int count,const void * tag_data)120*e01b6f76SAndroid Build Coastguard Worker int Metadata::add(uint32_t tag, int count, const void *tag_data) {
121*e01b6f76SAndroid Build Coastguard Worker // Opportunistically attempt to add if metadata has room for it
122*e01b6f76SAndroid Build Coastguard Worker if (!add_camera_metadata_entry(mData, tag, tag_data, count)) {
123*e01b6f76SAndroid Build Coastguard Worker return 0;
124*e01b6f76SAndroid Build Coastguard Worker }
125*e01b6f76SAndroid Build Coastguard Worker
126*e01b6f76SAndroid Build Coastguard Worker int res;
127*e01b6f76SAndroid Build Coastguard Worker camera_metadata_t* tmp;
128*e01b6f76SAndroid Build Coastguard Worker int tag_type = get_camera_metadata_tag_type(tag);
129*e01b6f76SAndroid Build Coastguard Worker size_t size = calculate_camera_metadata_entry_data_size(tag_type, count);
130*e01b6f76SAndroid Build Coastguard Worker size_t entry_capacity = get_camera_metadata_entry_count(mData) + 1;
131*e01b6f76SAndroid Build Coastguard Worker size_t data_capacity = get_camera_metadata_data_count(mData) + size;
132*e01b6f76SAndroid Build Coastguard Worker
133*e01b6f76SAndroid Build Coastguard Worker // Double new dimensions to minimize future reallocations
134*e01b6f76SAndroid Build Coastguard Worker tmp = allocate_camera_metadata(entry_capacity * 2, data_capacity * 2);
135*e01b6f76SAndroid Build Coastguard Worker if (tmp == NULL) {
136*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Failed to allocate new metadata with %zu entries, %zu data",
137*e01b6f76SAndroid Build Coastguard Worker __func__, entry_capacity, data_capacity);
138*e01b6f76SAndroid Build Coastguard Worker return -ENOMEM;
139*e01b6f76SAndroid Build Coastguard Worker }
140*e01b6f76SAndroid Build Coastguard Worker // Append the current metadata to the new (empty) metadata
141*e01b6f76SAndroid Build Coastguard Worker res = append_camera_metadata(tmp, mData);
142*e01b6f76SAndroid Build Coastguard Worker if (res) {
143*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Failed to append old metadata %p to new %p",
144*e01b6f76SAndroid Build Coastguard Worker __func__, mData, tmp);
145*e01b6f76SAndroid Build Coastguard Worker return res;
146*e01b6f76SAndroid Build Coastguard Worker }
147*e01b6f76SAndroid Build Coastguard Worker // Add the remaining new item
148*e01b6f76SAndroid Build Coastguard Worker res = add_camera_metadata_entry(tmp, tag, tag_data, count);
149*e01b6f76SAndroid Build Coastguard Worker if (res) {
150*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Failed to add new entry (%d, %p, %d) to metadata %p",
151*e01b6f76SAndroid Build Coastguard Worker __func__, tag, tag_data, count, tmp);
152*e01b6f76SAndroid Build Coastguard Worker return res;
153*e01b6f76SAndroid Build Coastguard Worker }
154*e01b6f76SAndroid Build Coastguard Worker
155*e01b6f76SAndroid Build Coastguard Worker replace(tmp);
156*e01b6f76SAndroid Build Coastguard Worker return 0;
157*e01b6f76SAndroid Build Coastguard Worker }
158*e01b6f76SAndroid Build Coastguard Worker
get()159*e01b6f76SAndroid Build Coastguard Worker camera_metadata_t* Metadata::get() {
160*e01b6f76SAndroid Build Coastguard Worker return mData;
161*e01b6f76SAndroid Build Coastguard Worker }
162*e01b6f76SAndroid Build Coastguard Worker
163*e01b6f76SAndroid Build Coastguard Worker } // namespace usb_camera_hal
164