[libcamera-devel,04/11] libcamera: v4l2_device: Support exporting buffers

Message ID 20190203110102.5663-5-kieran.bingham@ideasonboard.com
State Superseded
Headers show
Series
  • libcamera: V4L2 Streams
Related show

Commit Message

Kieran Bingham Feb. 3, 2019, 11 a.m. UTC
Implement the VIDIOC_EXPBUF functionality allowing our buffers to be exported
to other V4L2Device objects.

Export buffers when they are allocated during a call to requestBuffers()

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
---
 src/libcamera/include/v4l2_device.h |  2 +
 src/libcamera/v4l2_device.cpp       | 59 +++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+)

Patch

diff --git a/src/libcamera/include/v4l2_device.h b/src/libcamera/include/v4l2_device.h
index 6599ce2d761c..f445f98f97a4 100644
--- a/src/libcamera/include/v4l2_device.h
+++ b/src/libcamera/include/v4l2_device.h
@@ -109,6 +109,8 @@  private:
 	int setFormatMultiplane(V4L2DeviceFormat *fmt);
 
 	int requestBuffers(unsigned int qty, std::vector<Buffer *> &buffers);
+	int exportBuffer(Buffer *buffer);
+	int exportBuffers(BufferPool *pool);
 
 	std::string deviceNode_;
 	int fd_;
diff --git a/src/libcamera/v4l2_device.cpp b/src/libcamera/v4l2_device.cpp
index 8bcd8bbc34f6..728478a1ae8f 100644
--- a/src/libcamera/v4l2_device.cpp
+++ b/src/libcamera/v4l2_device.cpp
@@ -340,6 +340,13 @@  BufferPool *V4L2Device::requestBuffers(unsigned int qty)
 		return nullptr;
 	}
 
+	ret = exportBuffers(bufferPool_);
+	if (ret) {
+		delete bufferPool_;
+		bufferPool_ = nullptr;
+		return nullptr;
+	}
+
 	return bufferPool_;
 }
 
@@ -414,6 +421,58 @@  int V4L2Device::requestBuffers(unsigned int qty, std::vector<Buffer *> &buffers)
 	return 0;
 }
 
+int V4L2Device::exportBuffer(Buffer *buffer)
+{
+	unsigned int i = 0;
+	for (Plane *plane : buffer->planes()) {
+		struct v4l2_exportbuffer expbuf = {};
+		int ret;
+
+		expbuf.type = bufferType_;
+		expbuf.index = buffer->index();
+		expbuf.plane = i++;
+
+		ret = ioctl(fd_, VIDIOC_EXPBUF, &expbuf);
+		if (ret < 0) {
+			ret = -errno;
+			LOG(V4L2, Error)
+				<< "Failed to export buffer: " << strerror(-ret);
+			return ret;
+		}
+
+		plane->setDmabuf(expbuf.fd);
+	}
+
+	return 0;
+}
+
+int V4L2Device::exportBuffers(BufferPool *pool)
+{
+	for (Buffer *buffer : pool->buffers()) {
+		int ret = exportBuffer(buffer);
+		if (ret)
+			return ret;
+
+		/**
+		 * \todo: Remove this mmap
+		 * It is a temporary work around to have all internal buffers
+		 * mapped for early development.
+		 *
+		 * Applications will be expected to map buffers if necessary.
+		 */
+		ret = buffer->mmap();
+		if (ret) {
+			ret = -errno;
+			LOG(V4L2, Error)
+				<< "Failed to mmap a buffer instance: "
+				<< strerror(-ret);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 /**
  * \brief Retrieve the image format set on the V4L2 device
  * \return 0 for success, a negative error code otherwise