You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
313 lines
9.9 KiB
313 lines
9.9 KiB
/* |
|
* Copyright (C) 2016 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#ifndef V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_ |
|
#define V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_ |
|
|
|
#include <array> |
|
#include <memory> |
|
#include <set> |
|
#include <vector> |
|
|
|
#include <camera/CameraMetadata.h> |
|
|
|
#include "array_vector.h" |
|
#include "partial_metadata_interface.h" |
|
|
|
namespace v4l2_camera_hal { |
|
|
|
typedef std::set<std::unique_ptr<PartialMetadataInterface>> PartialMetadataSet; |
|
|
|
// Templated helper functions effectively extending android::CameraMetadata. |
|
// Will cause a compile-time errors if CameraMetadata doesn't support |
|
// using the templated type. Templates are provided to extend this support |
|
// to std::arrays, std::vectors, and ArrayVectors of supported types as |
|
// appropriate. |
|
|
|
// UpdateMetadata(metadata, tag, data): |
|
// |
|
// Updates the entry for |tag| in |metadata| (functionally similar to |
|
// android::CameraMetadata::update). |
|
// |
|
// Args: |
|
// metadata: the android::CameraMetadata to update. |
|
// tag: the tag within |metadata| to update. |
|
// data: A reference to the data to update |tag| with. |
|
// |
|
// Returns: |
|
// 0: Success. |
|
// -ENODEV: The type of |data| does not match the expected type for |tag|, |
|
// or another error occured. Note: no errors are given for updating a |
|
// metadata entry with an incorrect amount of data (e.g. filling a tag |
|
// that expects to have only one value with multiple values), as this |
|
// information is not encoded in the type associated with the tag by |
|
// get_camera_metadata_tag_type (from <system/camera_metadata.h>). |
|
|
|
// Generic (pointer & size). |
|
template <typename T> |
|
static int UpdateMetadata(android::CameraMetadata* metadata, |
|
int32_t tag, |
|
const T* data, |
|
size_t count) { |
|
int res = metadata->update(tag, data, count); |
|
if (res) { |
|
HAL_LOGE("Failed to update metadata tag %d", tag); |
|
return -ENODEV; |
|
} |
|
return 0; |
|
} |
|
|
|
// Generic (single item reference). |
|
template <typename T> |
|
static int UpdateMetadata(android::CameraMetadata* metadata, |
|
int32_t tag, |
|
const T& val) { |
|
return UpdateMetadata(metadata, tag, &val, 1); |
|
} |
|
|
|
// Specialization for vectors. |
|
template <typename T> |
|
static int UpdateMetadata(android::CameraMetadata* metadata, |
|
int32_t tag, |
|
const std::vector<T>& val) { |
|
return UpdateMetadata(metadata, tag, val.data(), val.size()); |
|
} |
|
|
|
// Specialization for arrays. |
|
template <typename T, size_t N> |
|
static int UpdateMetadata(android::CameraMetadata* metadata, |
|
int32_t tag, |
|
const std::array<T, N>& val) { |
|
return UpdateMetadata(metadata, tag, val.data(), N); |
|
} |
|
|
|
// Specialization for ArrayVectors. |
|
template <typename T, size_t N> |
|
static int UpdateMetadata(android::CameraMetadata* metadata, |
|
int32_t tag, |
|
const ArrayVector<T, N>& val) { |
|
return UpdateMetadata(metadata, tag, val.data(), val.total_num_elements()); |
|
} |
|
|
|
// Specialization for vectors of arrays. |
|
template <typename T, size_t N> |
|
static int UpdateMetadata(android::CameraMetadata* metadata, |
|
int32_t tag, |
|
const std::vector<std::array<T, N>>& val) { |
|
// Convert to array vector so we know all the elements are contiguous. |
|
ArrayVector<T, N> array_vector; |
|
for (const auto& array : val) { |
|
array_vector.push_back(array); |
|
} |
|
return UpdateMetadata(metadata, tag, array_vector); |
|
} |
|
|
|
// GetDataPointer(entry, val) |
|
// |
|
// A helper for other methods in this file. |
|
// Gets the data pointer of a given metadata entry into |*val|. |
|
|
|
static void GetDataPointer(camera_metadata_ro_entry_t& entry, |
|
const uint8_t** val) { |
|
*val = entry.data.u8; |
|
} |
|
|
|
static void GetDataPointer(camera_metadata_ro_entry_t& entry, |
|
const int32_t** val) { |
|
*val = entry.data.i32; |
|
} |
|
|
|
static void GetDataPointer(camera_metadata_ro_entry_t& entry, |
|
const float** val) { |
|
*val = entry.data.f; |
|
} |
|
|
|
static void GetDataPointer(camera_metadata_ro_entry_t& entry, |
|
const int64_t** val) { |
|
*val = entry.data.i64; |
|
} |
|
|
|
static void GetDataPointer(camera_metadata_ro_entry_t& entry, |
|
const double** val) { |
|
*val = entry.data.d; |
|
} |
|
|
|
static void GetDataPointer(camera_metadata_ro_entry_t& entry, |
|
const camera_metadata_rational_t** val) { |
|
*val = entry.data.r; |
|
} |
|
|
|
// SingleTagValue(metadata, tag, val) |
|
// |
|
// Get the value of the |tag| entry in |metadata|. |
|
// |tag| is expected to refer to an entry with a single item |
|
// of the templated type (a "single item" is exactly N values |
|
// if the templated type is an array of size N). An error will be |
|
// returned if it the wrong number of items are present. |
|
// |
|
// Returns: |
|
// -ENOENT: The tag couldn't be found or was empty. |
|
// -EINVAL: The tag contained more than one item, or |val| is null. |
|
// -ENODEV: The tag claims to be non-empty, but the data pointer is null. |
|
// 0: Success. |*val| will contain the value for |tag|. |
|
|
|
// Singleton. |
|
template <typename T> |
|
static int SingleTagValue(const android::CameraMetadata& metadata, |
|
int32_t tag, |
|
T* val) { |
|
if (!val) { |
|
HAL_LOGE("Null pointer passed to SingleTagValue."); |
|
return -EINVAL; |
|
} |
|
camera_metadata_ro_entry_t entry = metadata.find(tag); |
|
if (entry.count == 0) { |
|
HAL_LOGE("Metadata tag %d is empty.", tag); |
|
return -ENOENT; |
|
} else if (entry.count != 1) { |
|
HAL_LOGE( |
|
"Error: expected metadata tag %d to contain exactly 1 value " |
|
"(had %d).", |
|
tag, |
|
entry.count); |
|
return -EINVAL; |
|
} |
|
const T* data = nullptr; |
|
GetDataPointer(entry, &data); |
|
if (data == nullptr) { |
|
HAL_LOGE("Metadata tag %d is empty.", tag); |
|
return -ENODEV; |
|
} |
|
*val = *data; |
|
return 0; |
|
} |
|
|
|
// Specialization for std::array. |
|
template <typename T, size_t N> |
|
static int SingleTagValue(const android::CameraMetadata& metadata, |
|
int32_t tag, |
|
std::array<T, N>* val) { |
|
if (!val) { |
|
HAL_LOGE("Null pointer passed to SingleTagValue."); |
|
return -EINVAL; |
|
} |
|
camera_metadata_ro_entry_t entry = metadata.find(tag); |
|
if (entry.count == 0) { |
|
HAL_LOGE("Metadata tag %d is empty.", tag); |
|
return -ENOENT; |
|
} else if (entry.count != N) { |
|
HAL_LOGE( |
|
"Error: expected metadata tag %d to contain a single array of " |
|
"exactly %d values (had %d).", |
|
tag, |
|
N, |
|
entry.count); |
|
return -EINVAL; |
|
} |
|
const T* data = nullptr; |
|
GetDataPointer(entry, &data); |
|
if (data == nullptr) { |
|
HAL_LOGE("Metadata tag %d is empty.", tag); |
|
return -ENODEV; |
|
} |
|
// Fill in the array. |
|
for (size_t i = 0; i < N; ++i) { |
|
(*val)[i] = data[i]; |
|
} |
|
return 0; |
|
} |
|
|
|
// VectorTagValue(metadata, tag, val) |
|
// |
|
// Get the value of the |tag| entry in |metadata|. |
|
// |tag| is expected to refer to an entry with a vector |
|
// of the templated type. For arrays, an error will be |
|
// returned if it the wrong number of items are present. |
|
// |
|
// Returns: |
|
// -ENOENT: The tag couldn't be found or was empty. While technically an |
|
// empty vector may be valid, this error is returned for consistency |
|
// with SingleTagValue. |
|
// -EINVAL: The tag contained an invalid number of entries (e.g. 6 entries for |
|
// a vector of length 4 arrays), or |val| is null. |
|
// -ENODEV: The tag claims to be non-empty, but the data pointer is null. |
|
// 0: Success. |*val| will contain the values for |tag|. |
|
template <typename T> |
|
static int VectorTagValue(const android::CameraMetadata& metadata, |
|
int32_t tag, |
|
std::vector<T>* val) { |
|
if (!val) { |
|
HAL_LOGE("Null pointer passed to VectorTagValue."); |
|
return -EINVAL; |
|
} |
|
camera_metadata_ro_entry_t entry = metadata.find(tag); |
|
if (entry.count == 0) { |
|
return -ENOENT; |
|
} |
|
const T* data = nullptr; |
|
GetDataPointer(entry, &data); |
|
if (data == nullptr) { |
|
HAL_LOGE("Metadata tag %d claims to have elements but is empty.", tag); |
|
return -ENODEV; |
|
} |
|
// Copy the data for |tag| into the output vector. |
|
*val = std::vector<T>(data, data + entry.count); |
|
return 0; |
|
} |
|
|
|
// Specialization for std::array. |
|
template <typename T, size_t N> |
|
static int VectorTagValue(const android::CameraMetadata& metadata, |
|
int32_t tag, |
|
std::vector<std::array<T, N>>* val) { |
|
if (!val) { |
|
HAL_LOGE("Null pointer passed to VectorTagValue."); |
|
return -EINVAL; |
|
} |
|
camera_metadata_ro_entry_t entry = metadata.find(tag); |
|
if (entry.count == 0) { |
|
return -ENOENT; |
|
} |
|
if (entry.count % N != 0) { |
|
HAL_LOGE( |
|
"Error: expected metadata tag %d to contain a vector of arrays of " |
|
"length %d (had %d entries, which is not divisible by %d).", |
|
tag, |
|
N, |
|
entry.count, |
|
N); |
|
return -EINVAL; |
|
} |
|
const T* data = nullptr; |
|
GetDataPointer(entry, &data); |
|
if (data == nullptr) { |
|
HAL_LOGE("Metadata tag %d claims to have elements but is empty.", tag); |
|
return -ENODEV; |
|
} |
|
// Copy the data for |tag| into separate arrays for the output vector. |
|
size_t num_arrays = entry.count / N; |
|
*val = std::vector<std::array<T, N>>(num_arrays); |
|
for (size_t i = 0; i < num_arrays; ++i) { |
|
for (size_t j = 0; j < N; ++j) { |
|
val->at(i)[j] = data[i * N + j]; |
|
} |
|
} |
|
return 0; |
|
} |
|
|
|
} // namespace v4l2_camera_hal |
|
|
|
#endif // V4L2_CAMERA_HAL_METADATA_METADATA_COMMON_H_
|
|
|