From 1e1367badaf5f1b09ce97600da56e3195cb16c4c Mon Sep 17 00:00:00 2001 From: David Plowman Date: Fri, 26 Jun 2026 13:37:51 +0100 Subject: [PATCH] pipeline: rpi: Handle buffers with offsets This allows camera images to be written to offset locations within buffers (which must have be allocated with sufficient space available). Firstly, the RPi::Stream class tracks associated "ispOutputIndex" for output streams, that is, whether it corresponds to ISP output branch 0 or branch 1. Secondly, we pass buffer offsets on to libpisp for each request. Signed-off-by: David Plowman --- .../pipeline/rpi/common/rpi_stream.h | 10 ++++++++-- src/libcamera/pipeline/rpi/pisp/pisp.cpp | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/libcamera/pipeline/rpi/common/rpi_stream.h b/src/libcamera/pipeline/rpi/common/rpi_stream.h index 300a352a7..519318670 100644 --- a/src/libcamera/pipeline/rpi/common/rpi_stream.h +++ b/src/libcamera/pipeline/rpi/common/rpi_stream.h @@ -97,14 +97,14 @@ class Stream : public libcamera::Stream using StreamFlags = Flags; Stream() - : flags_(StreamFlag::None), id_(0), swDownscale_(0) + : flags_(StreamFlag::None), id_(0), swDownscale_(0), ispOutputIndex_(-1) { } Stream(const char *name, MediaEntity *dev, StreamFlags flags = StreamFlag::None) : flags_(flags), name_(name), dev_(std::make_unique(dev)), id_(0), - swDownscale_(0) + swDownscale_(0), ispOutputIndex_(-1) { } @@ -125,6 +125,9 @@ class Stream : public libcamera::Stream void setExportedBuffer(FrameBuffer *buffer); + void setIspIndex(int ispIndex) { ispOutputIndex_ = ispIndex; } + int getIspIndex() const { return ispOutputIndex_; } + int allocateBuffers(unsigned int count); int queueBuffer(FrameBuffer *buffer); void returnBuffer(FrameBuffer *buffer); @@ -181,6 +184,9 @@ class Stream : public libcamera::Stream * as the stream needs to maintain ownership of these buffers. */ std::vector> internalBuffers_; + + /* For output streams, the ISP branch for this stream (otherwise -1). */ + int ispOutputIndex_; }; /* diff --git a/src/libcamera/pipeline/rpi/pisp/pisp.cpp b/src/libcamera/pipeline/rpi/pisp/pisp.cpp index c9d89d58b..23f4c14d1 100644 --- a/src/libcamera/pipeline/rpi/pisp/pisp.cpp +++ b/src/libcamera/pipeline/rpi/pisp/pisp.cpp @@ -1524,6 +1524,7 @@ int PiSPCameraData::platformConfigure(const RPi::RPiCameraConfiguration *rpiConf beEnables |= PISP_BE_RGB_ENABLE_OUTPUT0; ispIndex = 0; } + stream->setIspIndex(ispIndex); format = outStreams[i].format; bool needs32BitConversion = adjustDeviceFormat(format); @@ -2306,6 +2307,24 @@ void PiSPCameraData::tryRunPipeline() Request *request = requestQueue_.front(); ASSERT(request->metadata().empty()); + /* Pass the plane offsets of any output buffers to the Back End ISP. */ + for (auto const &[stream, buffer] : request->buffers()) { + int ispIndex = static_cast(stream)->getIspIndex(); + if (ispIndex >= 0) { + /* + * PiSP takes only 2 offsets; offset 3 (where required) is assumed + * to be the same as offset 2. + */ + unsigned int offset = buffer->planes()[0].offset; + unsigned int offset2 = 0; + if (buffer->planes().size() > 1) + offset2 = buffer->planes()[1].offset; + + pisp_be_output_format_extra extra{ 0, 0, { offset, offset2 } }; + be_->SetOutputFormatExtra(ispIndex, extra); + } + } + /* See if a new ScalerCrop value needs to be applied. */ applyScalerCrop(request->controls());