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> 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> 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> 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> 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> 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> 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 static void GetDataPointer(camera_metadata_ro_entry_t& entry, 124 const uint8_t** val) { 125 *val = entry.data.u8; 126 } 127 128 static void GetDataPointer(camera_metadata_ro_entry_t& entry, 129 const int32_t** val) { 130 *val = entry.data.i32; 131 } 132 133 static void GetDataPointer(camera_metadata_ro_entry_t& entry, 134 const float** val) { 135 *val = entry.data.f; 136 } 137 138 static void GetDataPointer(camera_metadata_ro_entry_t& entry, 139 const int64_t** val) { 140 *val = entry.data.i64; 141 } 142 143 static void GetDataPointer(camera_metadata_ro_entry_t& entry, 144 const double** val) { 145 *val = entry.data.d; 146 } 147 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> 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> 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> 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> 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