From c89cfa534ba1d35e35de7d33c57a6c2906a5b11f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Niklas=20S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>
Date: Fri, 10 Jan 2020 18:41:30 +0100
Subject: cam: Cache buffer memory mapping
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

With the buffer allocator in use it's possible to cache the dmabuf
memory mappings when starting the camera instead of mapping and
unmapping them each time.

Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
---
 src/cam/buffer_writer.cpp | 27 ++++++++++++++++++++++-----
 src/cam/buffer_writer.h   |  5 +++++
 src/cam/capture.cpp       |  3 +++
 3 files changed, 30 insertions(+), 5 deletions(-)

(limited to 'src/cam')

diff --git a/src/cam/buffer_writer.cpp b/src/cam/buffer_writer.cpp
index 1d7366c8..c5a5eb46 100644
--- a/src/cam/buffer_writer.cpp
+++ b/src/cam/buffer_writer.cpp
@@ -22,6 +22,27 @@ BufferWriter::BufferWriter(const std::string &pattern)
 {
 }
 
+BufferWriter::~BufferWriter()
+{
+	for (auto &iter : mappedBuffers_) {
+		void *memory = iter.second.first;
+		unsigned int length = iter.second.second;
+		munmap(memory, length);
+	}
+	mappedBuffers_.clear();
+}
+
+void BufferWriter::mapBuffer(FrameBuffer *buffer)
+{
+	for (const FrameBuffer::Plane &plane : buffer->planes()) {
+		void *memory = mmap(NULL, plane.length, PROT_READ, MAP_SHARED,
+				    plane.fd.fd(), 0);
+
+		mappedBuffers_[plane.fd.fd()] =
+			std::make_pair(memory, plane.length);
+	}
+}
+
 int BufferWriter::write(FrameBuffer *buffer, const std::string &streamName)
 {
 	std::string filename;
@@ -44,9 +65,7 @@ int BufferWriter::write(FrameBuffer *buffer, const std::string &streamName)
 		return -errno;
 
 	for (const FrameBuffer::Plane &plane : buffer->planes()) {
-		/* \todo Once the FrameBuffer is done cache mapped memory. */
-		void *data = mmap(NULL, plane.length, PROT_READ, MAP_SHARED,
-				  plane.fd.fd(), 0);
+		void *data = mappedBuffers_[plane.fd.fd()].first;
 		unsigned int length = plane.length;
 
 		ret = ::write(fd, data, length);
@@ -61,8 +80,6 @@ int BufferWriter::write(FrameBuffer *buffer, const std::string &streamName)
 				  << length << std::endl;
 			break;
 		}
-
-		munmap(data, length);
 	}
 
 	close(fd);
diff --git a/src/cam/buffer_writer.h b/src/cam/buffer_writer.h
index 5917a7df..8c9b2436 100644
--- a/src/cam/buffer_writer.h
+++ b/src/cam/buffer_writer.h
@@ -7,6 +7,7 @@
 #ifndef __LIBCAMERA_BUFFER_WRITER_H__
 #define __LIBCAMERA_BUFFER_WRITER_H__
 
+#include <map>
 #include <string>
 
 #include <libcamera/buffer.h>
@@ -15,12 +16,16 @@ class BufferWriter
 {
 public:
 	BufferWriter(const std::string &pattern = "frame-#.bin");
+	~BufferWriter();
+
+	void mapBuffer(libcamera::FrameBuffer *buffer);
 
 	int write(libcamera::FrameBuffer *buffer,
 		  const std::string &streamName);
 
 private:
 	std::string pattern_;
+	std::map<int, std::pair<void *, unsigned int>> mappedBuffers_;
 };
 
 #endif /* __LIBCAMERA_BUFFER_WRITER_H__ */
diff --git a/src/cam/capture.cpp b/src/cam/capture.cpp
index dd078eb0..738fa1c2 100644
--- a/src/cam/capture.cpp
+++ b/src/cam/capture.cpp
@@ -116,6 +116,9 @@ int Capture::capture(EventLoop *loop, FrameBufferAllocator *allocator)
 					  << std::endl;
 				return ret;
 			}
+
+			if (writer_)
+				writer_->mapBuffer(buffer.get());
 		}
 
 		requests.push_back(request);
-- 
cgit v1.2.1