summaryrefslogtreecommitdiff
path: root/src/libcamera/pipeline/ipu3/cio2.cpp
diff options
context:
space:
mode:
authorNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-06-02 00:28:33 +0200
committerNiklas Söderlund <niklas.soderlund@ragnatech.se>2020-06-26 13:32:29 +0200
commit40148cfcafbac274232acd07f41a4ee16bfd1f45 (patch)
tree800fb17fbe85c763611c761bc173785a75d5dfa4 /src/libcamera/pipeline/ipu3/cio2.cpp
parenta96eb0cc8fd2bd45064bf2cd1ca9e43f80627bb3 (diff)
libcamera: ipu3: Allow zero-copy RAW stream capture
With the refactored CIO2 interface it's now easy to add zero-copy for buffers in the RAW stream. Use the internally allocated buffers inside the CIO2Device if no buffer for the RAW stream is provided by the application, or use the application-provided buffer if any. Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se> Reviewed-by: Jacopo Mondi <jacopo@jmondi.org> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'src/libcamera/pipeline/ipu3/cio2.cpp')
-rw-r--r--src/libcamera/pipeline/ipu3/cio2.cpp58
1 files changed, 37 insertions, 21 deletions
diff --git a/src/libcamera/pipeline/ipu3/cio2.cpp b/src/libcamera/pipeline/ipu3/cio2.cpp
index d698cd80..885e2ca0 100644
--- a/src/libcamera/pipeline/ipu3/cio2.cpp
+++ b/src/libcamera/pipeline/ipu3/cio2.cpp
@@ -213,31 +213,16 @@ int CIO2Device::exportBuffers(unsigned int count,
return output_->exportBuffers(count, buffers);
}
-FrameBuffer *CIO2Device::getBuffer()
-{
- if (availableBuffers_.empty()) {
- LOG(IPU3, Error) << "CIO2 buffer underrun";
- return nullptr;
- }
-
- FrameBuffer *buffer = availableBuffers_.front();
-
- availableBuffers_.pop();
-
- return buffer;
-}
-
-void CIO2Device::putBuffer(FrameBuffer *buffer)
-{
- availableBuffers_.push(buffer);
-}
-
int CIO2Device::start()
{
- int ret = output_->allocateBuffers(CIO2_BUFFER_COUNT, &buffers_);
+ int ret = output_->exportBuffers(CIO2_BUFFER_COUNT, &buffers_);
if (ret < 0)
return ret;
+ ret = output_->importBuffers(CIO2_BUFFER_COUNT);
+ if (ret)
+ LOG(IPU3, Error) << "Failed to import CIO2 buffers";
+
for (std::unique_ptr<FrameBuffer> &buffer : buffers_)
availableBuffers_.push(buffer.get());
@@ -257,11 +242,42 @@ int CIO2Device::stop()
return ret;
}
-int CIO2Device::queueBuffer(FrameBuffer *buffer)
+int CIO2Device::queueBuffer(Request *request, FrameBuffer *rawBuffer)
{
+ FrameBuffer *buffer = rawBuffer;
+
+ /* If no buffer is provided in the request, use an internal one. */
+ if (!buffer) {
+ if (availableBuffers_.empty()) {
+ LOG(IPU3, Error) << "CIO2 buffer underrun";
+ return -EINVAL;
+ }
+
+ buffer = availableBuffers_.front();
+ availableBuffers_.pop();
+ }
+
+ buffer->setRequest(request);
+
return output_->queueBuffer(buffer);
}
+void CIO2Device::tryReturnBuffer(FrameBuffer *buffer)
+{
+ /*
+ * \todo Once more pipelines deal with buffers that may be allocated
+ * internally or externally this pattern might become a common need. At
+ * that point this check should be moved to something clever in
+ * FrameBuffer.
+ */
+ for (const std::unique_ptr<FrameBuffer> &buf : buffers_) {
+ if (buf.get() == buffer) {
+ availableBuffers_.push(buffer);
+ break;
+ }
+ }
+}
+
void CIO2Device::freeBuffers()
{
/* The default std::queue constructor is explicit with gcc 5 and 6. */