1*e01b6f76SAndroid Build Coastguard Worker /*
2*e01b6f76SAndroid Build Coastguard Worker * Copyright (C) 2013 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 //#define LOG_NDEBUG 0
17*e01b6f76SAndroid Build Coastguard Worker #define LOG_TAG "Metadata"
18*e01b6f76SAndroid Build Coastguard Worker
19*e01b6f76SAndroid Build Coastguard Worker #include <errno.h>
20*e01b6f76SAndroid Build Coastguard Worker
21*e01b6f76SAndroid Build Coastguard Worker #include <system/camera_metadata.h>
22*e01b6f76SAndroid Build Coastguard Worker
23*e01b6f76SAndroid Build Coastguard Worker #include <log/log.h>
24*e01b6f76SAndroid Build Coastguard Worker
25*e01b6f76SAndroid Build Coastguard Worker #define ATRACE_TAG (ATRACE_TAG_CAMERA | ATRACE_TAG_HAL)
26*e01b6f76SAndroid Build Coastguard Worker #include <utils/Trace.h>
27*e01b6f76SAndroid Build Coastguard Worker
28*e01b6f76SAndroid Build Coastguard Worker #include "Metadata.h"
29*e01b6f76SAndroid Build Coastguard Worker
30*e01b6f76SAndroid Build Coastguard Worker namespace default_camera_hal {
31*e01b6f76SAndroid Build Coastguard Worker
Metadata()32*e01b6f76SAndroid Build Coastguard Worker Metadata::Metadata():
33*e01b6f76SAndroid Build Coastguard Worker mData(NULL)
34*e01b6f76SAndroid Build Coastguard Worker {
35*e01b6f76SAndroid Build Coastguard Worker }
36*e01b6f76SAndroid Build Coastguard Worker
~Metadata()37*e01b6f76SAndroid Build Coastguard Worker Metadata::~Metadata()
38*e01b6f76SAndroid Build Coastguard Worker {
39*e01b6f76SAndroid Build Coastguard Worker replace(NULL);
40*e01b6f76SAndroid Build Coastguard Worker }
41*e01b6f76SAndroid Build Coastguard Worker
replace(camera_metadata_t * m)42*e01b6f76SAndroid Build Coastguard Worker void Metadata::replace(camera_metadata_t *m)
43*e01b6f76SAndroid Build Coastguard Worker {
44*e01b6f76SAndroid Build Coastguard Worker if (m == mData) {
45*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Replacing metadata with itself?!", __func__);
46*e01b6f76SAndroid Build Coastguard Worker return;
47*e01b6f76SAndroid Build Coastguard Worker }
48*e01b6f76SAndroid Build Coastguard Worker if (mData)
49*e01b6f76SAndroid Build Coastguard Worker free_camera_metadata(mData);
50*e01b6f76SAndroid Build Coastguard Worker mData = m;
51*e01b6f76SAndroid Build Coastguard Worker }
52*e01b6f76SAndroid Build Coastguard Worker
init(const camera_metadata_t * metadata)53*e01b6f76SAndroid Build Coastguard Worker int Metadata::init(const camera_metadata_t *metadata)
54*e01b6f76SAndroid Build Coastguard Worker {
55*e01b6f76SAndroid Build Coastguard Worker camera_metadata_t* tmp;
56*e01b6f76SAndroid Build Coastguard Worker
57*e01b6f76SAndroid Build Coastguard Worker if (validate_camera_metadata_structure(metadata, NULL))
58*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
59*e01b6f76SAndroid Build Coastguard Worker
60*e01b6f76SAndroid Build Coastguard Worker tmp = clone_camera_metadata(metadata);
61*e01b6f76SAndroid Build Coastguard Worker if (tmp == NULL)
62*e01b6f76SAndroid Build Coastguard Worker return -EINVAL;
63*e01b6f76SAndroid Build Coastguard Worker
64*e01b6f76SAndroid Build Coastguard Worker replace(tmp);
65*e01b6f76SAndroid Build Coastguard Worker return 0;
66*e01b6f76SAndroid Build Coastguard Worker }
67*e01b6f76SAndroid Build Coastguard Worker
addUInt8(uint32_t tag,int count,const uint8_t * data)68*e01b6f76SAndroid Build Coastguard Worker int Metadata::addUInt8(uint32_t tag, int count, const uint8_t *data)
69*e01b6f76SAndroid Build Coastguard Worker {
70*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_BYTE, count)) return -EINVAL;
71*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
72*e01b6f76SAndroid Build Coastguard Worker }
73*e01b6f76SAndroid Build Coastguard Worker
add1UInt8(uint32_t tag,const uint8_t data)74*e01b6f76SAndroid Build Coastguard Worker int Metadata::add1UInt8(uint32_t tag, const uint8_t data)
75*e01b6f76SAndroid Build Coastguard Worker {
76*e01b6f76SAndroid Build Coastguard Worker return addUInt8(tag, 1, &data);
77*e01b6f76SAndroid Build Coastguard Worker }
78*e01b6f76SAndroid Build Coastguard Worker
addInt32(uint32_t tag,int count,const int32_t * data)79*e01b6f76SAndroid Build Coastguard Worker int Metadata::addInt32(uint32_t tag, int count, const int32_t *data)
80*e01b6f76SAndroid Build Coastguard Worker {
81*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_INT32, count)) return -EINVAL;
82*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
83*e01b6f76SAndroid Build Coastguard Worker }
84*e01b6f76SAndroid Build Coastguard Worker
addFloat(uint32_t tag,int count,const float * data)85*e01b6f76SAndroid Build Coastguard Worker int Metadata::addFloat(uint32_t tag, int count, const float *data)
86*e01b6f76SAndroid Build Coastguard Worker {
87*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_FLOAT, count)) return -EINVAL;
88*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
89*e01b6f76SAndroid Build Coastguard Worker }
90*e01b6f76SAndroid Build Coastguard Worker
addInt64(uint32_t tag,int count,const int64_t * data)91*e01b6f76SAndroid Build Coastguard Worker int Metadata::addInt64(uint32_t tag, int count, const int64_t *data)
92*e01b6f76SAndroid Build Coastguard Worker {
93*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_INT64, count)) return -EINVAL;
94*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
95*e01b6f76SAndroid Build Coastguard Worker }
96*e01b6f76SAndroid Build Coastguard Worker
addDouble(uint32_t tag,int count,const double * data)97*e01b6f76SAndroid Build Coastguard Worker int Metadata::addDouble(uint32_t tag, int count, const double *data)
98*e01b6f76SAndroid Build Coastguard Worker {
99*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_DOUBLE, count)) return -EINVAL;
100*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
101*e01b6f76SAndroid Build Coastguard Worker }
102*e01b6f76SAndroid Build Coastguard Worker
addRational(uint32_t tag,int count,const camera_metadata_rational_t * data)103*e01b6f76SAndroid Build Coastguard Worker int Metadata::addRational(uint32_t tag, int count,
104*e01b6f76SAndroid Build Coastguard Worker const camera_metadata_rational_t *data)
105*e01b6f76SAndroid Build Coastguard Worker {
106*e01b6f76SAndroid Build Coastguard Worker if (!validate(tag, TYPE_RATIONAL, count)) return -EINVAL;
107*e01b6f76SAndroid Build Coastguard Worker return add(tag, count, data);
108*e01b6f76SAndroid Build Coastguard Worker }
109*e01b6f76SAndroid Build Coastguard Worker
validate(uint32_t tag,int tag_type,int count)110*e01b6f76SAndroid Build Coastguard Worker bool Metadata::validate(uint32_t tag, int tag_type, int count)
111*e01b6f76SAndroid Build Coastguard Worker {
112*e01b6f76SAndroid Build Coastguard Worker if (get_camera_metadata_tag_type(tag) < 0) {
113*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Invalid metadata entry tag: %d", __func__, tag);
114*e01b6f76SAndroid Build Coastguard Worker return false;
115*e01b6f76SAndroid Build Coastguard Worker }
116*e01b6f76SAndroid Build Coastguard Worker if (tag_type < 0 || tag_type >= NUM_TYPES) {
117*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Invalid metadata entry tag type: %d", __func__, tag_type);
118*e01b6f76SAndroid Build Coastguard Worker return false;
119*e01b6f76SAndroid Build Coastguard Worker }
120*e01b6f76SAndroid Build Coastguard Worker if (tag_type != get_camera_metadata_tag_type(tag)) {
121*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Tag %d called with incorrect type: %s(%d)", __func__, tag,
122*e01b6f76SAndroid Build Coastguard Worker camera_metadata_type_names[tag_type], tag_type);
123*e01b6f76SAndroid Build Coastguard Worker return false;
124*e01b6f76SAndroid Build Coastguard Worker }
125*e01b6f76SAndroid Build Coastguard Worker if (count < 1) {
126*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Invalid metadata entry count: %d", __func__, count);
127*e01b6f76SAndroid Build Coastguard Worker return false;
128*e01b6f76SAndroid Build Coastguard Worker }
129*e01b6f76SAndroid Build Coastguard Worker return true;
130*e01b6f76SAndroid Build Coastguard Worker }
131*e01b6f76SAndroid Build Coastguard Worker
add(uint32_t tag,int count,const void * tag_data)132*e01b6f76SAndroid Build Coastguard Worker int Metadata::add(uint32_t tag, int count, const void *tag_data)
133*e01b6f76SAndroid Build Coastguard Worker {
134*e01b6f76SAndroid Build Coastguard Worker int res;
135*e01b6f76SAndroid Build Coastguard Worker size_t entry_capacity = 0;
136*e01b6f76SAndroid Build Coastguard Worker size_t data_capacity = 0;
137*e01b6f76SAndroid Build Coastguard Worker camera_metadata_t* tmp;
138*e01b6f76SAndroid Build Coastguard Worker int tag_type = get_camera_metadata_tag_type(tag);
139*e01b6f76SAndroid Build Coastguard Worker size_t size = calculate_camera_metadata_entry_data_size(tag_type, count);
140*e01b6f76SAndroid Build Coastguard Worker
141*e01b6f76SAndroid Build Coastguard Worker if (NULL == mData) {
142*e01b6f76SAndroid Build Coastguard Worker entry_capacity = 1;
143*e01b6f76SAndroid Build Coastguard Worker data_capacity = size;
144*e01b6f76SAndroid Build Coastguard Worker } else {
145*e01b6f76SAndroid Build Coastguard Worker entry_capacity = get_camera_metadata_entry_count(mData) + 1;
146*e01b6f76SAndroid Build Coastguard Worker data_capacity = get_camera_metadata_data_count(mData) + size;
147*e01b6f76SAndroid Build Coastguard Worker }
148*e01b6f76SAndroid Build Coastguard Worker
149*e01b6f76SAndroid Build Coastguard Worker // Opportunistically attempt to add if metadata exists and has room for it
150*e01b6f76SAndroid Build Coastguard Worker if (mData && !add_camera_metadata_entry(mData, tag, tag_data, count))
151*e01b6f76SAndroid Build Coastguard Worker return 0;
152*e01b6f76SAndroid Build Coastguard Worker // Double new dimensions to minimize future reallocations
153*e01b6f76SAndroid Build Coastguard Worker tmp = allocate_camera_metadata(entry_capacity * 2, data_capacity * 2);
154*e01b6f76SAndroid Build Coastguard Worker if (tmp == NULL) {
155*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Failed to allocate new metadata with %zu entries, %zu data",
156*e01b6f76SAndroid Build Coastguard Worker __func__, entry_capacity, data_capacity);
157*e01b6f76SAndroid Build Coastguard Worker return -ENOMEM;
158*e01b6f76SAndroid Build Coastguard Worker }
159*e01b6f76SAndroid Build Coastguard Worker // Append the current metadata to the new (empty) metadata, if any
160*e01b6f76SAndroid Build Coastguard Worker if (NULL != mData) {
161*e01b6f76SAndroid Build Coastguard Worker res = append_camera_metadata(tmp, mData);
162*e01b6f76SAndroid Build Coastguard Worker if (res) {
163*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Failed to append old metadata %p to new %p",
164*e01b6f76SAndroid Build Coastguard Worker __func__, mData, tmp);
165*e01b6f76SAndroid Build Coastguard Worker return res;
166*e01b6f76SAndroid Build Coastguard Worker }
167*e01b6f76SAndroid Build Coastguard Worker }
168*e01b6f76SAndroid Build Coastguard Worker // Add the remaining new item to tmp and replace mData
169*e01b6f76SAndroid Build Coastguard Worker res = add_camera_metadata_entry(tmp, tag, tag_data, count);
170*e01b6f76SAndroid Build Coastguard Worker if (res) {
171*e01b6f76SAndroid Build Coastguard Worker ALOGE("%s: Failed to add new entry (%d, %p, %d) to metadata %p",
172*e01b6f76SAndroid Build Coastguard Worker __func__, tag, tag_data, count, tmp);
173*e01b6f76SAndroid Build Coastguard Worker return res;
174*e01b6f76SAndroid Build Coastguard Worker }
175*e01b6f76SAndroid Build Coastguard Worker replace(tmp);
176*e01b6f76SAndroid Build Coastguard Worker
177*e01b6f76SAndroid Build Coastguard Worker return 0;
178*e01b6f76SAndroid Build Coastguard Worker }
179*e01b6f76SAndroid Build Coastguard Worker
get()180*e01b6f76SAndroid Build Coastguard Worker camera_metadata_t* Metadata::get()
181*e01b6f76SAndroid Build Coastguard Worker {
182*e01b6f76SAndroid Build Coastguard Worker return mData;
183*e01b6f76SAndroid Build Coastguard Worker }
184*e01b6f76SAndroid Build Coastguard Worker
185*e01b6f76SAndroid Build Coastguard Worker } // namespace default_camera_hal
186