[PATCH 1/1] libcamera: mtkisp7: v4l2: Add a requestBufferReady signal

Harvey Yang chenghaoyang at chromium.org
Wed Oct 9 11:26:39 CEST 2024


From: Yunke Cao <yunkec at chromium.org>

We will be adding a large number buffers for a single media request.
Matching each single FrameBuffer against all the buffers will be an unnecessary
huge effort.

Add a new signal that emits both the frameBuffer and the mediaRequest,
match the mediaRequest instead in IMGSYS.

Signed-off-by: Han-Lin Chen <hanlinchen at chromium.com>
Co-developed-by: Yunke Cao <yunkec at chromium.org>
Signed-off-by: Yunke Cao <yunkec at chromium.org>
Co-developed-by: Harvey Yang <chenghaoyang at chromium.org>
Signed-off-by: Harvey Yang <chenghaoyang at chromium.org>
---
 include/libcamera/internal/v4l2_videodevice.h |  3 +-
 src/libcamera/v4l2_videodevice.cpp            | 33 ++++++++++++++-----
 2 files changed, 26 insertions(+), 10 deletions(-)

diff --git a/include/libcamera/internal/v4l2_videodevice.h b/include/libcamera/internal/v4l2_videodevice.h
index f021c2a01..c44e9e9c7 100644
--- a/include/libcamera/internal/v4l2_videodevice.h
+++ b/include/libcamera/internal/v4l2_videodevice.h
@@ -220,6 +220,7 @@ public:
 
 	int queueBuffer(FrameBuffer *buffer);
 	Signal<FrameBuffer *> bufferReady;
+	Signal<std::pair<FrameBuffer *, int>> requestBufferReady;
 
 	int streamOn();
 	int streamOff();
@@ -265,7 +266,7 @@ private:
 	UniqueFD exportDmabufFd(unsigned int index, unsigned int plane);
 
 	void bufferAvailable();
-	FrameBuffer *dequeueBuffer();
+	std::pair<FrameBuffer *, int> dequeueBuffer();
 
 	void watchdogExpired();
 
diff --git a/src/libcamera/v4l2_videodevice.cpp b/src/libcamera/v4l2_videodevice.cpp
index 14eba0561..5a1648602 100644
--- a/src/libcamera/v4l2_videodevice.cpp
+++ b/src/libcamera/v4l2_videodevice.cpp
@@ -1773,18 +1773,23 @@ int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer)
  *
  * When this slot is called, a Buffer has become available from the device, and
  * will be emitted through the bufferReady Signal.
+ * If the buffer is queued with a media Request, emit a requestBufferReady
+ * signal.
  *
  * For Capture video devices the FrameBuffer will contain valid data.
  * For Output video devices the FrameBuffer can be considered empty.
  */
 void V4L2VideoDevice::bufferAvailable()
 {
-	FrameBuffer *buffer = dequeueBuffer();
+	auto [buffer, mediaRequest] = dequeueBuffer();
 	if (!buffer)
 		return;
 
 	/* Notify anyone listening to the device. */
 	bufferReady.emit(buffer);
+
+	if (mediaRequest > 0)
+		requestBufferReady.emit({ buffer, mediaRequest });
 }
 
 /**
@@ -1793,9 +1798,12 @@ void V4L2VideoDevice::bufferAvailable()
  * This function dequeues the next available buffer from the device. If no
  * buffer is available to be dequeued it will return nullptr immediately.
  *
- * \return A pointer to the dequeued buffer on success, or nullptr otherwise
+ * \return A pair where the first element is a pointer to the dequeued buffer
+ * on success, or nullptr otherwise. The second is the media request fd if
+ * applicable
+ *
  */
-FrameBuffer *V4L2VideoDevice::dequeueBuffer()
+std::pair<FrameBuffer *, int> V4L2VideoDevice::dequeueBuffer()
 {
 	struct v4l2_buffer buf = {};
 	struct v4l2_plane planes[VIDEO_MAX_PLANES] = {};
@@ -1815,7 +1823,7 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
 	if (ret < 0) {
 		LOG(V4L2, Error)
 			<< "Failed to dequeue buffer: " << strerror(-ret);
-		return nullptr;
+		return { nullptr, -1 };
 	}
 
 	LOG(V4L2, Debug) << "Dequeuing buffer " << buf.index;
@@ -1837,7 +1845,7 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
 		LOG(V4L2, Error)
 			<< "Dequeued unexpected buffer index " << buf.index;
 
-		return nullptr;
+		return { nullptr, -1 };
 	}
 
 	cache_->put(buf.index);
@@ -1866,7 +1874,7 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
 			   + buf.timestamp.tv_usec * 1000ULL;
 
 	if (V4L2_TYPE_IS_OUTPUT(buf.type))
-		return buffer;
+		return { buffer, buf.request_fd };
 
 	/*
 	 * Detect kernel drivers which do not reset the sequence number to zero
@@ -1896,7 +1904,7 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
 				<< " != " << buffer->planes().size() << ")";
 
 			metadata.status = FrameMetadata::FrameError;
-			return buffer;
+			return { buffer, buf.request_fd };
 		}
 
 		/*
@@ -1921,7 +1929,7 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
 						       });
 
 				metadata.status = FrameMetadata::FrameError;
-				return buffer;
+				return { buffer, buf.request_fd };
 			}
 
 			metadata.planes()[i].bytesused =
@@ -1940,7 +1948,7 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
 		metadata.planes()[0].bytesused = buf.bytesused;
 	}
 
-	return buffer;
+	return { buffer, buf.request_fd };
 }
 
 /**
@@ -1948,6 +1956,12 @@ FrameBuffer *V4L2VideoDevice::dequeueBuffer()
  * \brief A Signal emitted when a framebuffer completes
  */
 
+/**
+ * \var V4L2VideoDevice::requestBufferReady
+ * \brief A Signal emitted when a framebuffer completes, which includes both the
+ * frameBuffer and the media request fd.
+ */
+
 /**
  * \brief Start the video stream
  * \return 0 on success or a negative error code otherwise
@@ -2012,6 +2026,7 @@ int V4L2VideoDevice::streamOff()
 		cache_->put(it.first);
 		metadata.status = FrameMetadata::FrameCancelled;
 		bufferReady.emit(buffer);
+		requestBufferReady.emit({ buffer, -1 });
 	}
 
 	ASSERT(cache_->isEmpty());
-- 
2.47.0.rc0.187.ge670bccf7e-goog



More information about the libcamera-devel mailing list