diff options
-rw-r--r-- | src/android/camera_device.cpp | 47 | ||||
-rw-r--r-- | src/android/camera_device.h | 1 | ||||
-rw-r--r-- | src/android/camera_metadata.cpp | 84 | ||||
-rw-r--r-- | src/android/camera_metadata.h | 52 |
4 files changed, 127 insertions, 57 deletions
diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 7d4d0feb..74f6915c 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -773,43 +773,6 @@ void CameraDevice::setCallbacks(const camera3_callback_ops_t *callbacks) callbacks_ = callbacks; } -std::tuple<uint32_t, uint32_t> CameraDevice::calculateStaticMetadataSize() -{ - /* - * \todo Keep this in sync with the actual number of entries. - * Currently: 54 entries, 874 bytes of static metadata - */ - uint32_t numEntries = 54; - uint32_t byteSize = 874; - - /* - * Calculate space occupation in bytes for dynamically built metadata - * entries. - * - * Each stream configuration entry requires 48 bytes: - * 4 32bits integers for ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS - * 4 64bits integers for ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS - */ - byteSize += streamConfigurations_.size() * 48; - - /* - * 2 32bits integers for each HAL_PIXEL_FORMAT_BLOB for thumbnail sizes - * 2 32bits integers for the (0, 0) thumbnail size - * - * This is a worst case estimates as different configurations with the - * same aspect ratio will generate the same size. - */ - for (const auto &entry : streamConfigurations_) { - if (entry.androidFormat != HAL_PIXEL_FORMAT_BLOB) - continue; - - byteSize += 8; - } - byteSize += 8; - - return std::make_tuple(numEntries, byteSize); -} - /* * Return static information for the camera. */ @@ -818,15 +781,7 @@ const camera_metadata_t *CameraDevice::getStaticMetadata() if (staticMetadata_) return staticMetadata_->get(); - /* - * The here reported metadata are enough to implement a basic capture - * example application, but a real camera implementation will require - * more. - */ - uint32_t numEntries; - uint32_t byteSize; - std::tie(numEntries, byteSize) = calculateStaticMetadataSize(); - staticMetadata_ = std::make_unique<CameraMetadata>(numEntries, byteSize); + staticMetadata_ = std::make_unique<CameraMetadata>(64, 1024); if (!staticMetadata_->isValid()) { LOG(HAL, Error) << "Failed to allocate static metadata"; staticMetadata_.reset(); diff --git a/src/android/camera_device.h b/src/android/camera_device.h index 23457e47..ae162a45 100644 --- a/src/android/camera_device.h +++ b/src/android/camera_device.h @@ -98,7 +98,6 @@ private: std::vector<libcamera::Size> getRawResolutions(const libcamera::PixelFormat &pixelFormat); - std::tuple<uint32_t, uint32_t> calculateStaticMetadataSize(); libcamera::FrameBuffer *createFrameBuffer(const buffer_handle_t camera3buffer); void notifyShutter(uint32_t frameNumber, uint64_t timestamp); void notifyError(uint32_t frameNumber, camera3_stream_t *stream); diff --git a/src/android/camera_metadata.cpp b/src/android/camera_metadata.cpp index 6f1bcdbe..bf8d2781 100644 --- a/src/android/camera_metadata.cpp +++ b/src/android/camera_metadata.cpp @@ -63,11 +63,64 @@ bool CameraMetadata::getEntry(uint32_t tag, camera_metadata_ro_entry_t *entry) c return true; } -bool CameraMetadata::addEntry(uint32_t tag, const void *data, size_t count) +/* + * \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); + } + + return true; +} + +bool CameraMetadata::addEntry(uint32_t tag, const void *data, size_t count, + size_t sizeofT) { if (!valid_) return false; + if (!resize(1, count * sizeofT)) { + LOG(CameraMetadata, Error) << "Failed to resize"; + valid_ = false; + return false; + } + if (!add_camera_metadata_entry(metadata_, tag, data, count)) return true; @@ -99,16 +152,31 @@ 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) { - const char *name = get_camera_metadata_tag_name(tag); - LOG(CameraMetadata, Error) - << "Failed to update tag " << (name ? name : "<unknown>"); + 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; } - return true; + 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() diff --git a/src/android/camera_metadata.h b/src/android/camera_metadata.h index d653e2f0..07afd4b2 100644 --- a/src/android/camera_metadata.h +++ b/src/android/camera_metadata.h @@ -8,6 +8,7 @@ #define __ANDROID_CAMERA_METADATA_H__ #include <stdint.h> +#include <vector> #include <system/camera_metadata.h> @@ -23,9 +24,56 @@ public: CameraMetadata &operator=(const CameraMetadata &other); bool isValid() const { return valid_; } + bool resize(size_t count, size_t size); bool getEntry(uint32_t tag, camera_metadata_ro_entry_t *entry) const; - bool addEntry(uint32_t tag, const void *data, size_t data_count); - bool updateEntry(uint32_t tag, const void *data, size_t data_count); + + template<typename T, + std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr> + bool addEntry(uint32_t tag, const T &data) + { + return addEntry(tag, &data, 1, sizeof(T)); + } + + template<typename T, size_t size> + bool addEntry(uint32_t tag, const T (&data)[size]) + { + return addEntry(tag, data, size, sizeof(T)); + } + + template<typename S, + typename T = typename S::value_type> + bool addEntry(uint32_t tag, S &data) + { + return addEntry(tag, data.data(), data.size(), sizeof(T)); + } + + template<typename T> + bool addEntry(uint32_t tag, const T *data, size_t count) + { + return addEntry(tag, data, count, sizeof(T)); + } + + template<typename T> + bool updateEntry(uint32_t tag, const T &data) + { + return updateEntry(tag, &data, 1); + } + + template<typename T, size_t size> + bool updateEntry(uint32_t tag, const T (&data)[size]) + { + return updateEntry(tag, data, size, sizeof(T)); + } + + template<typename S, + typename T = typename S::value_type> + bool updateEntry(uint32_t tag, S &data) + { + return updateEntry(tag, data.data(), data.size()); + } + + bool addEntry(uint32_t tag, const void *data, size_t count, size_t sizeofT); + bool updateEntry(uint32_t tag, const void *data, size_t count); camera_metadata_t *get(); const camera_metadata_t *get() const; |