diff options
Diffstat (limited to 'src/android/camera_metadata.cpp')
-rw-r--r-- | src/android/camera_metadata.cpp | 147 |
1 files changed, 137 insertions, 10 deletions
diff --git a/src/android/camera_metadata.cpp b/src/android/camera_metadata.cpp index f0da9ea9..3fc7cf27 100644 --- a/src/android/camera_metadata.cpp +++ b/src/android/camera_metadata.cpp @@ -7,29 +7,132 @@ #include "camera_metadata.h" -#include "libcamera/internal/log.h" +#include <libcamera/base/log.h> using namespace libcamera; -LOG_DEFINE_CATEGORY(CameraMetadata); +LOG_DEFINE_CATEGORY(CameraMetadata) + +CameraMetadata::CameraMetadata() + : metadata_(nullptr), valid_(false), resized_(false) +{ +} CameraMetadata::CameraMetadata(size_t entryCapacity, size_t dataCapacity) + : resized_(false) { metadata_ = allocate_camera_metadata(entryCapacity, dataCapacity); valid_ = metadata_ != nullptr; } +CameraMetadata::CameraMetadata(const camera_metadata_t *metadata) + : resized_(false) +{ + metadata_ = clone_camera_metadata(metadata); + valid_ = metadata_ != nullptr; +} + +CameraMetadata::CameraMetadata(const CameraMetadata &other) + : CameraMetadata(other.get()) +{ +} + CameraMetadata::~CameraMetadata() { if (metadata_) free_camera_metadata(metadata_); } -bool CameraMetadata::addEntry(uint32_t tag, const void *data, size_t count) +CameraMetadata &CameraMetadata::operator=(const CameraMetadata &other) +{ + if (this == &other) + return *this; + + if (metadata_) + free_camera_metadata(metadata_); + + metadata_ = clone_camera_metadata(other.get()); + valid_ = metadata_ != nullptr; + + return *this; +} + +std::tuple<size_t, size_t> CameraMetadata::usage() const +{ + size_t currentEntryCount = get_camera_metadata_entry_count(metadata_); + size_t currentDataCount = get_camera_metadata_data_count(metadata_); + + return { currentEntryCount, currentDataCount }; +} + +bool CameraMetadata::getEntry(uint32_t tag, camera_metadata_ro_entry_t *entry) const +{ + if (find_camera_metadata_ro_entry(metadata_, tag, entry)) + return false; + + return true; +} + +/* + * \brief Resize the metadata container, if necessary + * \param[in] count Number of entries to add to the container + * \param[in] size Total size of entries to add, in bytes + * \return True if resize was successful or unnecessary, false otherwise + */ +bool CameraMetadata::resize(size_t count, size_t size) +{ + if (!valid_) + return false; + + if (!count && !size) + return true; + + size_t currentEntryCount = get_camera_metadata_entry_count(metadata_); + size_t currentEntryCapacity = get_camera_metadata_entry_capacity(metadata_); + size_t newEntryCapacity = currentEntryCapacity < currentEntryCount + count ? + currentEntryCapacity * 2 : currentEntryCapacity; + + size_t currentDataCount = get_camera_metadata_data_count(metadata_); + size_t currentDataCapacity = get_camera_metadata_data_capacity(metadata_); + size_t newDataCapacity = currentDataCapacity < currentDataCount + size ? + currentDataCapacity * 2 : currentDataCapacity; + + if (newEntryCapacity > currentEntryCapacity || + newDataCapacity > currentDataCapacity) { + camera_metadata_t *oldMetadata = metadata_; + metadata_ = allocate_camera_metadata(newEntryCapacity, newDataCapacity); + if (!metadata_) { + metadata_ = oldMetadata; + return false; + } + + LOG(CameraMetadata, Info) + << "Resized: old entry capacity " << currentEntryCapacity + << ", old data capacity " << currentDataCapacity + << ", new entry capacity " << newEntryCapacity + << ", new data capacity " << newDataCapacity; + + append_camera_metadata(metadata_, oldMetadata); + free_camera_metadata(oldMetadata); + + resized_ = true; + } + + return true; +} + +bool CameraMetadata::addEntry(uint32_t tag, const void *data, size_t count, + size_t elementSize) { if (!valid_) return false; + if (!resize(1, count * elementSize)) { + LOG(CameraMetadata, Error) << "Failed to resize"; + valid_ = false; + return false; + } + if (!add_camera_metadata_entry(metadata_, tag, data, count)) return true; @@ -46,7 +149,8 @@ bool CameraMetadata::addEntry(uint32_t tag, const void *data, size_t count) return false; } -bool CameraMetadata::updateEntry(uint32_t tag, const void *data, size_t count) +bool CameraMetadata::updateEntry(uint32_t tag, const void *data, size_t count, + size_t elementSize) { if (!valid_) return false; @@ -61,16 +165,39 @@ bool CameraMetadata::updateEntry(uint32_t tag, const void *data, size_t count) return false; } - ret = update_camera_metadata_entry(metadata_, entry.index, data, - count, nullptr); - if (ret) { + if (camera_metadata_type_size[entry.type] != elementSize) { const char *name = get_camera_metadata_tag_name(tag); - LOG(CameraMetadata, Error) - << "Failed to update tag " << (name ? name : "<unknown>"); + LOG(CameraMetadata, Fatal) + << "Invalid element size for tag " + << (name ? name : "<unknown>"); return false; } - return true; + size_t oldSize = + calculate_camera_metadata_entry_data_size(entry.type, + entry.count); + size_t newSize = + calculate_camera_metadata_entry_data_size(entry.type, + count); + size_t sizeIncrement = newSize - oldSize > 0 ? newSize - oldSize : 0; + if (!resize(0, sizeIncrement)) { + LOG(CameraMetadata, Error) << "Failed to resize"; + valid_ = false; + return false; + } + + ret = update_camera_metadata_entry(metadata_, entry.index, data, + count, nullptr); + if (!ret) + return true; + + const char *name = get_camera_metadata_tag_name(tag); + LOG(CameraMetadata, Error) + << "Failed to update tag " << (name ? name : "<unknown>"); + + valid_ = false; + + return false; } camera_metadata_t *CameraMetadata::get() |