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 
27 #include "array_vector.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 
GetDataPointer(camera_metadata_ro_entry_t & entry,const uint8_t ** val)123 static void GetDataPointer(camera_metadata_ro_entry_t& entry,
124                            const uint8_t** val) {
125   *val = entry.data.u8;
126 }
127 
GetDataPointer(camera_metadata_ro_entry_t & entry,const int32_t ** val)128 static void GetDataPointer(camera_metadata_ro_entry_t& entry,
129                            const int32_t** val) {
130   *val = entry.data.i32;
131 }
132 
GetDataPointer(camera_metadata_ro_entry_t & entry,const float ** val)133 static void GetDataPointer(camera_metadata_ro_entry_t& entry,
134                            const float** val) {
135   *val = entry.data.f;
136 }
137 
GetDataPointer(camera_metadata_ro_entry_t & entry,const int64_t ** val)138 static void GetDataPointer(camera_metadata_ro_entry_t& entry,
139                            const int64_t** val) {
140   *val = entry.data.i64;
141 }
142 
GetDataPointer(camera_metadata_ro_entry_t & entry,const double ** val)143 static void GetDataPointer(camera_metadata_ro_entry_t& entry,
144                            const double** val) {
145   *val = entry.data.d;
146 }
147 
GetDataPointer(camera_metadata_ro_entry_t & entry,const camera_metadata_rational_t ** val)148 static void GetDataPointer(camera_metadata_ro_entry_t& entry,
149                            const camera_metadata_rational_t** val) {
150   *val = entry.data.r;
151 }
152 
153 // SingleTagValue(metadata, tag, val)
154 //
155 // Get the value of the |tag| entry in |metadata|.
156 // |tag| is expected to refer to an entry with a single item
157 // of the templated type (a "single item" is exactly N values
158 // if the templated type is an array of size N). An error will be
159 // returned if it the wrong number of items are present.
160 //
161 // Returns:
162 //   -ENOENT: The tag couldn't be found or was empty.
163 //   -EINVAL: The tag contained more than one item, or |val| is null.
164 //   -ENODEV: The tag claims to be non-empty, but the data pointer is null.
165 //   0: Success. |*val| will contain the value for |tag|.
166 
167 // Singleton.
168 template <typename T>
SingleTagValue(const android::CameraMetadata & metadata,int32_t tag,T * val)169 static int SingleTagValue(const android::CameraMetadata& metadata,
170                           int32_t tag,
171                           T* val) {
172   if (!val) {
173     HAL_LOGE("Null pointer passed to SingleTagValue.");
174     return -EINVAL;
175   }
176   camera_metadata_ro_entry_t entry = metadata.find(tag);
177   if (entry.count == 0) {
178     HAL_LOGE("Metadata tag %d is empty.", tag);
179     return -ENOENT;
180   } else if (entry.count != 1) {
181     HAL_LOGE(
182         "Error: expected metadata tag %d to contain exactly 1 value "
183         "(had %d).",
184         tag,
185         entry.count);
186     return -EINVAL;
187   }
188   const T* data = nullptr;
189   GetDataPointer(entry, &data);
190   if (data == nullptr) {
191     HAL_LOGE("Metadata tag %d is empty.", tag);
192     return -ENODEV;
193   }
194   *val = *data;
195   return 0;
196 }
197 
198 // Specialization for std::array.
199 template <typename T, size_t N>
SingleTagValue(const android::CameraMetadata & metadata,int32_t tag,std::array<T,N> * val)200 static int SingleTagValue(const android::CameraMetadata& metadata,
201                           int32_t tag,
202                           std::array<T, N>* val) {
203   if (!val) {
204     HAL_LOGE("Null pointer passed to SingleTagValue.");
205     return -EINVAL;
206   }
207   camera_metadata_ro_entry_t entry = metadata.find(tag);
208   if (entry.count == 0) {
209     HAL_LOGE("Metadata tag %d is empty.", tag);
210     return -ENOENT;
211   } else if (entry.count != N) {
212     HAL_LOGE(
213         "Error: expected metadata tag %d to contain a single array of "
214         "exactly %d values (had %d).",
215         tag,
216         N,
217         entry.count);
218     return -EINVAL;
219   }
220   const T* data = nullptr;
221   GetDataPointer(entry, &data);
222   if (data == nullptr) {
223     HAL_LOGE("Metadata tag %d is empty.", tag);
224     return -ENODEV;
225   }
226   // Fill in the array.
227   for (size_t i = 0; i < N; ++i) {
228     (*val)[i] = data[i];
229   }
230   return 0;
231 }
232 
233 // VectorTagValue(metadata, tag, val)
234 //
235 // Get the value of the |tag| entry in |metadata|.
236 // |tag| is expected to refer to an entry with a vector
237 // of the templated type. For arrays, an error will be
238 // returned if it the wrong number of items are present.
239 //
240 // Returns:
241 //   -ENOENT: The tag couldn't be found or was empty. While technically an
242 //            empty vector may be valid, this error is returned for consistency
243 //            with SingleTagValue.
244 //   -EINVAL: The tag contained an invalid number of entries (e.g. 6 entries for
245 //            a vector of length 4 arrays), or |val| is null.
246 //   -ENODEV: The tag claims to be non-empty, but the data pointer is null.
247 //   0: Success. |*val| will contain the values for |tag|.
248 template <typename T>
VectorTagValue(const android::CameraMetadata & metadata,int32_t tag,std::vector<T> * val)249 static int VectorTagValue(const android::CameraMetadata& metadata,
250                           int32_t tag,
251                           std::vector<T>* val) {
252   if (!val) {
253     HAL_LOGE("Null pointer passed to VectorTagValue.");
254     return -EINVAL;
255   }
256   camera_metadata_ro_entry_t entry = metadata.find(tag);
257   if (entry.count == 0) {
258     return -ENOENT;
259   }
260   const T* data = nullptr;
261   GetDataPointer(entry, &data);
262   if (data == nullptr) {
263     HAL_LOGE("Metadata tag %d claims to have elements but is empty.", tag);
264     return -ENODEV;
265   }
266   // Copy the data for |tag| into the output vector.
267   *val = std::vector<T>(data, data + entry.count);
268   return 0;
269 }
270 
271 // Specialization for std::array.
272 template <typename T, size_t N>
VectorTagValue(const android::CameraMetadata & metadata,int32_t tag,std::vector<std::array<T,N>> * val)273 static int VectorTagValue(const android::CameraMetadata& metadata,
274                           int32_t tag,
275                           std::vector<std::array<T, N>>* val) {
276   if (!val) {
277     HAL_LOGE("Null pointer passed to VectorTagValue.");
278     return -EINVAL;
279   }
280   camera_metadata_ro_entry_t entry = metadata.find(tag);
281   if (entry.count == 0) {
282     return -ENOENT;
283   }
284   if (entry.count % N != 0) {
285     HAL_LOGE(
286         "Error: expected metadata tag %d to contain a vector of arrays of "
287         "length %d (had %d entries, which is not divisible by %d).",
288         tag,
289         N,
290         entry.count,
291         N);
292     return -EINVAL;
293   }
294   const T* data = nullptr;
295   GetDataPointer(entry, &data);
296   if (data == nullptr) {
297     HAL_LOGE("Metadata tag %d claims to have elements but is empty.", tag);
298     return -ENODEV;
299   }
300   // Copy the data for |tag| into separate arrays for the output vector.
301   size_t num_arrays = entry.count / N;
302   *val = std::vector<std::array<T, N>>(num_arrays);
303   for (size_t i = 0; i < num_arrays; ++i) {
304     for (size_t j = 0; j < N; ++j) {
305       val->at(i)[j] = data[i * N + j];
306     }
307   }
308   return 0;
309 }
310 
311 }  // namespace v4l2_camera_hal
312 
313 #endif  // V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
314