1 /*
2 * Copyright (C) 2016 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
17 #ifndef V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
18 #define V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
19
20 #include <array>
21 #include <memory>
22 #include <set>
23 #include <vector>
24
25 #include <camera/CameraMetadata.h>
26 #include "array_vector.h"
27 #include "common.h"
28 #include "partial_metadata_interface.h"
29
30 namespace v4l2_camera_hal {
31
32 typedef std::set<std::unique_ptr<PartialMetadataInterface>> PartialMetadataSet;
33
34 // Templated helper functions effectively extending android::CameraMetadata.
35 // Will cause a compile-time errors if CameraMetadata doesn't support
36 // using the templated type. Templates are provided to extend this support
37 // to std::arrays, std::vectors, and ArrayVectors of supported types as
38 // appropriate.
39
40 // UpdateMetadata(metadata, tag, data):
41 //
42 // Updates the entry for |tag| in |metadata| (functionally similar to
43 // android::CameraMetadata::update).
44 //
45 // Args:
46 // metadata: the android::CameraMetadata to update.
47 // tag: the tag within |metadata| to update.
48 // data: A reference to the data to update |tag| with.
49 //
50 // Returns:
51 // 0: Success.
52 // -ENODEV: The type of |data| does not match the expected type for |tag|,
53 // or another error occured. Note: no errors are given for updating a
54 // metadata entry with an incorrect amount of data (e.g. filling a tag
55 // that expects to have only one value with multiple values), as this
56 // information is not encoded in the type associated with the tag by
57 // get_camera_metadata_tag_type (from <system/camera_metadata.h>).
58
59 // Generic (pointer & size).
60 template <typename T>
UpdateMetadata(android::CameraMetadata * metadata,int32_t tag,const T * data,size_t count)61 static int UpdateMetadata(android::CameraMetadata* metadata,
62 int32_t tag,
63 const T* data,
64 size_t count) {
65 int res = metadata->update(tag, data, count);
66 if (res) {
67 HAL_LOGE("Failed to update metadata tag %d", tag);
68 return -ENODEV;
69 }
70 return 0;
71 }
72
73 // Generic (single item reference).
74 template <typename T>
UpdateMetadata(android::CameraMetadata * metadata,int32_t tag,const T & val)75 static int UpdateMetadata(android::CameraMetadata* metadata,
76 int32_t tag,
77 const T& val) {
78 return UpdateMetadata(metadata, tag, &val, 1);
79 }
80
81 // Specialization for vectors.
82 template <typename T>
UpdateMetadata(android::CameraMetadata * metadata,int32_t tag,const std::vector<T> & val)83 static int UpdateMetadata(android::CameraMetadata* metadata,
84 int32_t tag,
85 const std::vector<T>& val) {
86 return UpdateMetadata(metadata, tag, val.data(), val.size());
87 }
88
89 // Specialization for arrays.
90 template <typename T, size_t N>
UpdateMetadata(android::CameraMetadata * metadata,int32_t tag,const std::array<T,N> & val)91 static int UpdateMetadata(android::CameraMetadata* metadata,
92 int32_t tag,
93 const std::array<T, N>& val) {
94 return UpdateMetadata(metadata, tag, val.data(), N);
95 }
96
97 // Specialization for ArrayVectors.
98 template <typename T, size_t N>
UpdateMetadata(android::CameraMetadata * metadata,int32_t tag,const ArrayVector<T,N> & val)99 static int UpdateMetadata(android::CameraMetadata* metadata,
100 int32_t tag,
101 const ArrayVector<T, N>& val) {
102 return UpdateMetadata(metadata, tag, val.data(), val.total_num_elements());
103 }
104
105 // Specialization for vectors of arrays.
106 template <typename T, size_t N>
UpdateMetadata(android::CameraMetadata * metadata,int32_t tag,const std::vector<std::array<T,N>> & val)107 static int UpdateMetadata(android::CameraMetadata* metadata,
108 int32_t tag,
109 const std::vector<std::array<T, N>>& val) {
110 // Convert to array vector so we know all the elements are contiguous.
111 ArrayVector<T, N> array_vector;
112 for (const auto& array : val) {
113 array_vector.push_back(array);
114 }
115 return UpdateMetadata(metadata, tag, array_vector);
116 }
117
118 // GetDataPointer(entry, val)
119 //
120 // A helper for other methods in this file.
121 // Gets the data pointer of a given metadata entry into |*val|.
122
123 template <typename T>
124 inline void GetDataPointer(camera_metadata_ro_entry_t&, const T**);
125
126 template <>
127 inline void GetDataPointer<uint8_t>(camera_metadata_ro_entry_t& entry,
128 const uint8_t** val) {
129 *val = entry.data.u8;
130 }
131
132 template <>
133 inline void GetDataPointer<int32_t>(camera_metadata_ro_entry_t& entry,
134 const int32_t** val) {
135 *val = entry.data.i32;
136 }
137
138 template <>
139 inline void GetDataPointer<float>(camera_metadata_ro_entry_t& entry,
140 const float** val) {
141 *val = entry.data.f;
142 }
143
144 template <>
145 inline void GetDataPointer<int64_t>(camera_metadata_ro_entry_t& entry,
146 const int64_t** val) {
147 *val = entry.data.i64;
148 }
149
150 template <>
151 inline void GetDataPointer<double>(camera_metadata_ro_entry_t& entry,
152 const double** val) {
153 *val = entry.data.d;
154 }
155
156 template <>
157 inline void GetDataPointer<camera_metadata_rational_t>(camera_metadata_ro_entry_t& entry,
158 const camera_metadata_rational_t** val) {
159 *val = entry.data.r;
160 }
161
162 // SingleTagValue(metadata, tag, val)
163 //
164 // Get the value of the |tag| entry in |metadata|.
165 // |tag| is expected to refer to an entry with a single item
166 // of the templated type (a "single item" is exactly N values
167 // if the templated type is an array of size N). An error will be
168 // returned if it the wrong number of items are present.
169 //
170 // Returns:
171 // -ENOENT: The tag couldn't be found or was empty.
172 // -EINVAL: The tag contained more than one item, or |val| is null.
173 // -ENODEV: The tag claims to be non-empty, but the data pointer is null.
174 // 0: Success. |*val| will contain the value for |tag|.
175
176 // Singleton.
177 template <typename T>
SingleTagValue(const android::CameraMetadata & metadata,int32_t tag,T * val)178 static int SingleTagValue(const android::CameraMetadata& metadata,
179 int32_t tag,
180 T* val) {
181 if (!val) {
182 HAL_LOGE("Null pointer passed to SingleTagValue.");
183 return -EINVAL;
184 }
185 camera_metadata_ro_entry_t entry = metadata.find(tag);
186 if (entry.count == 0) {
187 HAL_LOGE("Metadata tag %d is empty.", tag);
188 return -ENOENT;
189 } else if (entry.count != 1) {
190 HAL_LOGE(
191 "Error: expected metadata tag %d to contain exactly 1 value "
192 "(had %zu).",
193 tag,
194 entry.count);
195 return -EINVAL;
196 }
197 const T* data = nullptr;
198 GetDataPointer(entry, &data);
199 if (data == nullptr) {
200 HAL_LOGE("Metadata tag %d is empty.", tag);
201 return -ENODEV;
202 }
203 *val = *data;
204 return 0;
205 }
206
207 // Specialization for std::array.
208 template <typename T, size_t N>
SingleTagValue(const android::CameraMetadata & metadata,int32_t tag,std::array<T,N> * val)209 static int SingleTagValue(const android::CameraMetadata& metadata,
210 int32_t tag,
211 std::array<T, N>* val) {
212 if (!val) {
213 HAL_LOGE("Null pointer passed to SingleTagValue.");
214 return -EINVAL;
215 }
216 camera_metadata_ro_entry_t entry = metadata.find(tag);
217 if (entry.count == 0) {
218 HAL_LOGE("Metadata tag %d is empty.", tag);
219 return -ENOENT;
220 } else if (entry.count != N) {
221 HAL_LOGE(
222 "Error: expected metadata tag %d to contain a single array of "
223 "exactly %zu values (had %zu).",
224 tag,
225 N,
226 entry.count);
227 return -EINVAL;
228 }
229 const T* data = nullptr;
230 GetDataPointer(entry, &data);
231 if (data == nullptr) {
232 HAL_LOGE("Metadata tag %d is empty.", tag);
233 return -ENODEV;
234 }
235 // Fill in the array.
236 for (size_t i = 0; i < N; ++i) {
237 (*val)[i] = data[i];
238 }
239 return 0;
240 }
241
242 // VectorTagValue(metadata, tag, val)
243 //
244 // Get the value of the |tag| entry in |metadata|.
245 // |tag| is expected to refer to an entry with a vector
246 // of the templated type. For arrays, an error will be
247 // returned if it the wrong number of items are present.
248 //
249 // Returns:
250 // -ENOENT: The tag couldn't be found or was empty. While technically an
251 // empty vector may be valid, this error is returned for consistency
252 // with SingleTagValue.
253 // -EINVAL: The tag contained an invalid number of entries (e.g. 6 entries for
254 // a vector of length 4 arrays), or |val| is null.
255 // -ENODEV: The tag claims to be non-empty, but the data pointer is null.
256 // 0: Success. |*val| will contain the values for |tag|.
257 template <typename T>
VectorTagValue(const android::CameraMetadata & metadata,int32_t tag,std::vector<T> * val)258 static int VectorTagValue(const android::CameraMetadata& metadata,
259 int32_t tag,
260 std::vector<T>* val) {
261 if (!val) {
262 HAL_LOGE("Null pointer passed to VectorTagValue.");
263 return -EINVAL;
264 }
265 camera_metadata_ro_entry_t entry = metadata.find(tag);
266 if (entry.count == 0) {
267 return -ENOENT;
268 }
269 const T* data = nullptr;
270 GetDataPointer(entry, &data);
271 if (data == nullptr) {
272 HAL_LOGE("Metadata tag %d claims to have elements but is empty.", tag);
273 return -ENODEV;
274 }
275 // Copy the data for |tag| into the output vector.
276 *val = std::vector<T>(data, data + entry.count);
277 return 0;
278 }
279
280 // Specialization for std::array.
281 template <typename T, size_t N>
VectorTagValue(const android::CameraMetadata & metadata,int32_t tag,std::vector<std::array<T,N>> * val)282 static int VectorTagValue(const android::CameraMetadata& metadata,
283 int32_t tag,
284 std::vector<std::array<T, N>>* val) {
285 if (!val) {
286 HAL_LOGE("Null pointer passed to VectorTagValue.");
287 return -EINVAL;
288 }
289 camera_metadata_ro_entry_t entry = metadata.find(tag);
290 if (entry.count == 0) {
291 return -ENOENT;
292 }
293 if (entry.count % N != 0) {
294 HAL_LOGE(
295 "Error: expected metadata tag %d to contain a vector of arrays of "
296 "length %zu (had %zu entries, which is not divisible by %zu).",
297 tag,
298 N,
299 entry.count,
300 N);
301 return -EINVAL;
302 }
303 const T* data = nullptr;
304 GetDataPointer(entry, &data);
305 if (data == nullptr) {
306 HAL_LOGE("Metadata tag %d claims to have elements but is empty.", tag);
307 return -ENODEV;
308 }
309 // Copy the data for |tag| into separate arrays for the output vector.
310 size_t num_arrays = entry.count / N;
311 *val = std::vector<std::array<T, N>>(num_arrays);
312 for (size_t i = 0; i < num_arrays; ++i) {
313 for (size_t j = 0; j < N; ++j) {
314 val->at(i)[j] = data[i * N + j];
315 }
316 }
317 return 0;
318 }
319
320 } // namespace v4l2_camera_hal
321
322 #endif // V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
323