[libcamera-devel] [PATCH 4/7] libcamera: FrameBuffer: Add a method to copy buffer content
Niklas Söderlund
niklas.soderlund at ragnatech.se
Tue Mar 24 16:51:42 CET 2020
This method may be used to memory copy a whole FrameBuffer content to
from another buffer. The operation is not fast and should not be used
without great care by pipelines.
The intended use-case is to have an option to copy out RAW buffers from
the middle of a pipeline.
Signed-off-by: Niklas Söderlund <niklas.soderlund at ragnatech.se>
---
* Changes since RFC
- Make method member of FrameBuffer
- Add documentation
- s/out/dstmem/ and s/in/src/mem/
---
include/libcamera/buffer.h | 1 +
src/libcamera/buffer.cpp | 61 ++++++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+)
diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h
index 8e5ec699e3925eee..ef3a3b36cd4e4e17 100644
--- a/include/libcamera/buffer.h
+++ b/include/libcamera/buffer.h
@@ -57,6 +57,7 @@ public:
unsigned int cookie() const { return cookie_; }
void setCookie(unsigned int cookie) { cookie_ = cookie; }
+ int copyFrom(const FrameBuffer *src);
private:
friend class Request; /* Needed to update request_. */
friend class V4L2VideoDevice; /* Needed to update metadata_. */
diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
index 673a63d3d1658190..0352917e9f2a3202 100644
--- a/src/libcamera/buffer.cpp
+++ b/src/libcamera/buffer.cpp
@@ -211,4 +211,65 @@ FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)
* core never modifies the buffer cookie.
*/
+/**
+ * \brief Copy the content from another buffer
+ * \param[in] src Buffer to copy
+ *
+ * Copy the buffer content and metadata form \a src. The receiving FrameBuffer
+ * needs to have at least as many planes of equal or grater size then the source.
+ *
+ * The operation is performed using memcpy() so is very slow, users needs to
+ * consider this before copying buffers.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int FrameBuffer::copyFrom(const FrameBuffer *src)
+{
+ if (planes_.size() != src->planes_.size()) {
+ LOG(Buffer, Error) << "Different number of planes";
+ metadata_.status = FrameMetadata::FrameError;
+ return -EINVAL;
+ }
+
+ for (unsigned int i = 0; i < planes_.size(); i++) {
+ if (planes_[i].length < src->planes_[i].length) {
+ LOG(Buffer, Error) << "Plane " << i << " is too small";
+ metadata_.status = FrameMetadata::FrameError;
+ return -EINVAL;
+ }
+ }
+
+ for (unsigned int i = 0; i < planes_.size(); i++) {
+ void *dstmem = mmap(NULL, planes_[i].length, PROT_WRITE,
+ MAP_SHARED, planes_[i].fd.fd(), 0);
+
+ if (dstmem == MAP_FAILED) {
+ LOG(Buffer, Error)
+ << "Failed to map destination plane " << i;
+ metadata_.status = FrameMetadata::FrameError;
+ return -EINVAL;
+ }
+
+ void *srcmem = mmap(NULL, src->planes_[i].length, PROT_READ,
+ MAP_SHARED, src->planes_[i].fd.fd(), 0);
+
+ if (srcmem == MAP_FAILED) {
+ munmap(dstmem, planes_[i].length);
+ LOG(Buffer, Error)
+ << "Failed to map source plane " << i;
+ metadata_.status = FrameMetadata::FrameError;
+ return -EINVAL;
+ }
+
+ memcpy(dstmem, srcmem, src->planes_[i].length);
+
+ munmap(srcmem, src->planes_[i].length);
+ munmap(dstmem, planes_[i].length);
+ }
+
+ metadata_ = src->metadata_;
+
+ return 0;
+}
+
} /* namespace libcamera */
--
2.25.1
More information about the libcamera-devel
mailing list