summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-03-16 02:40:37 +0100
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-03-27 16:27:28 +0100
commit417e3143a99493d89fbb5a3f3ccd82a716f5d53a (patch)
tree24f34538f4f4251ef4c876933c571bb2de75a62d /src
parent38f2efb05cef01af711a3caa2d2456d905164ba5 (diff)
libcamera: FrameBuffer: Add a method to copy buffer content
This method may be used to memory copy a whole FrameBuffer content 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@ragnatech.se> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src')
-rw-r--r--src/libcamera/buffer.cpp68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/libcamera/buffer.cpp b/src/libcamera/buffer.cpp
index 673a63d3..93057568 100644
--- a/src/libcamera/buffer.cpp
+++ b/src/libcamera/buffer.cpp
@@ -211,4 +211,72 @@ FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)
* core never modifies the buffer cookie.
*/
+/**
+ * \brief Copy the contents from another buffer
+ * \param[in] src Buffer to copy
+ *
+ * Copy the buffer contents and metadata from \a src to this buffer. The
+ * destination FrameBuffer shall have the same number of planes as the source
+ * buffer, and each destination plane shall be larger than or equal to the
+ * corresponding source plane.
+ *
+ * The complete metadata of the source buffer is copied to the destination
+ * buffer. If an error occurs during the copy, the destination buffer's metadata
+ * status is set to FrameMetadata::FrameError, and other metadata fields are not
+ * modified.
+ *
+ * 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(nullptr, 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(nullptr, 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 */