summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/android/camera_device.cpp47
-rw-r--r--src/android/camera_device.h1
-rw-r--r--src/android/camera_metadata.cpp84
-rw-r--r--src/android/camera_metadata.h52
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;