Home | History | Annotate | Download | only in metadata
      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