From patchwork Mon Sep 14 14:02:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 28277 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 9C0CFC3364 for ; Mon, 14 Sep 2026 14:04:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E2BCE686FF; Mon, 14 Sep 2026 16:04:55 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="uvcpC0PK"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 5E40F686ED for ; Mon, 14 Sep 2026 16:04:54 +0200 (CEST) Received: from ideasonboard.com (unknown [IPv6:2a00:6020:448c:6c00:a279:75fa:1f6c:7f40]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 5861C9A4; Mon, 14 Sep 2026 16:03:14 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1789394594; bh=KpGq7koja11lrM6y4eK2Uc1CDwGAMeTHmIbVEYMH/XY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uvcpC0PKPLaeZJ4Sb+5qwI1BZhv3Qat52cTg8A5Gd41TdneWDt7uDlXyZoVLpdMdl n3y29zijkTKq0/DMf/jtESutEcLVjT+rWRAO1kRSsyeg16mrh4HwPQNlwESwJpf1J+ xvvO+wImP0uw0MZ1FpLiI5nD4gF1jGwSLpzZMZ+0= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH v3 33/41] pipeline: rkisp1: Use BufferQueue for buffer handling Date: Mon, 14 Sep 2026 16:02:46 +0200 Message-ID: <20260914140309.3354666-34-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260914140309.3354666-1-stefan.klug@ideasonboard.com> References: <20260914140309.3354666-1-stefan.klug@ideasonboard.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" Migrate the pipeline handler to use the BufferQueue helper. This simplifies the code and makes it easier to understand. As a nice side effect, we can get rid of the statsBuffer member in SensorFrameInfo Signed-off-by: Stefan Klug --- Changes in v3: - Added assert in statsBufferReady - Dropped SensorFrameInfo::statsBuffer - Don't call postprocessedBuffers() on cancelled buffers if no request is queued in Changes in v2: - Added this patch --- src/libcamera/pipeline/rkisp1/rkisp1.cpp | 240 ++++++++--------------- 1 file changed, 84 insertions(+), 156 deletions(-) diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp index e3d188526ca5..fa530769bb04 100644 --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -35,6 +34,7 @@ #include #include +#include "libcamera/internal/buffer_queue.h" #include "libcamera/internal/camera.h" #include "libcamera/internal/camera_sensor.h" #include "libcamera/internal/camera_sensor_properties.h" @@ -88,6 +88,7 @@ public: */ unsigned int frame_; std::vector ipaBuffers_; + std::vector ipaFrameBuffers_; RkISP1MainPath *mainPath_; RkISP1SelfPath *selfPath_; @@ -140,7 +141,6 @@ private: struct SensorFrameInfo { Request *request = nullptr; - FrameBuffer *statsBuffer = nullptr; ControlList metadata; bool metadataProcessed = false; bool statsLost = false; @@ -156,11 +156,6 @@ struct RequestInfo { bool sequenceValid = false; }; -struct ParamBufferInfo { - FrameBuffer *buffer = nullptr; - size_t expectedSequence = 0; -}; - struct DewarpBufferInfo { FrameBuffer *inputBuffer; struct { @@ -247,6 +242,9 @@ private: std::unique_ptr param_; std::unique_ptr stat_; + std::unique_ptr paramQueue_; + std::unique_ptr statQueue_; + bool hasSelfPath_; bool isRaw_; @@ -256,28 +254,18 @@ private: std::unique_ptr dewarper_; /* Internal buffers used when dewarper is being used */ - std::vector> mainPathBuffers_; - std::queue availableMainPathBuffers_; + std::unique_ptr mainPathQueue_; bool running_ = false; - std::vector> paramBuffers_; - std::vector> statBuffers_; - std::queue availableParamBuffers_; - std::queue availableStatBuffers_; - std::deque queuedRequests_; std::map sensorFrameInfos_; std::deque queuedDewarpBuffers_; - SequenceSyncHelper paramsSyncHelper_; + SequenceSyncHelper imageSyncHelper_; - std::queue computingParamBuffers_; - std::queue queuedParamBuffers_; - - uint32_t nextParamsSequence_; uint32_t nextStatsToProcess_; Camera *activeCamera_; @@ -376,29 +364,23 @@ int RkISP1CameraData::loadTuningFile(const std::string &path) return 0; } -void RkISP1CameraData::paramsComputed(unsigned int frame, - [[maybe_unused]] unsigned int bufferId, +void RkISP1CameraData::paramsComputed(unsigned int frame, unsigned int bufferId, unsigned int bytesused) { PipelineHandlerRkISP1 *pipe = RkISP1CameraData::pipe(); - ParamBufferInfo &pInfo = pipe->computingParamBuffers_.front(); - pipe->computingParamBuffers_.pop(); - ASSERT(pInfo.expectedSequence == frame); - FrameBuffer *buffer = pInfo.buffer; + FrameBuffer *buffer = pipe->paramQueue_->front(BufferQueue::Preparing); + + ASSERT(buffer->cookie() == bufferId); LOG(RkISP1Schedule, Debug) << "Queue params for " << frame << " " << buffer; buffer->_d()->metadata().planes()[0].bytesused = bytesused; - int ret = pipe->param_->queueBuffer(buffer); - if (ret < 0) { + + int ret = pipe->paramQueue_->preparedBuffer(); + if (ret < 0) LOG(RkISP1, Error) << "Failed to queue parameter buffer: " << strerror(-ret); - pipe->availableParamBuffers_.push(buffer); - return; - } - - pipe->queuedParamBuffers_.push({ buffer, frame }); } void RkISP1CameraData::setSensorControls(unsigned int frame, @@ -413,7 +395,7 @@ void RkISP1CameraData::setSensorControls(unsigned int frame, } void RkISP1CameraData::metadataReady(unsigned int frame, - [[maybe_unused]] unsigned int bufferId, + unsigned int bufferId, const ControlList &metadata) { PipelineHandlerRkISP1 *pipe = RkISP1CameraData::pipe(); @@ -445,7 +427,6 @@ void RkISP1CameraData::metadataReady(unsigned int frame, << " got lost"; auto &info2 = pipe->sensorFrameInfos_[reqInfo.sequence]; info2.metadataProcessed = true; - ASSERT(info2.statsBuffer == nullptr); continue; } @@ -463,13 +444,11 @@ void RkISP1CameraData::metadataReady(unsigned int frame, info.metadataProcessed = true; /* - * info.statsBuffer can be null, if ipa->processStats() was called + * bufferId can be 0, if ipa->processStats() was called * without a buffer to just fill the metadata. */ - if (info.statsBuffer) - pipe->availableStatBuffers_.push(info.statsBuffer); - - info.statsBuffer = nullptr; + if (bufferId) + pipe->statQueue_->postprocessedBuffer(); pipe->tryCompleteRequests(); pipe->queueInternalBuffers(); @@ -884,6 +863,15 @@ int PipelineHandlerRkISP1::configure(Camera *camera, CameraConfiguration *c) isRaw_ = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW; data->usesDewarper_ = data->canUseDewarper_ && !isRaw_; + auto delegate = std::make_unique>(&mainPath_); + if (data->usesDewarper_) { + mainPathQueue_ = std::make_unique(std::move(delegate), BufferQueue::PostprocessStage, "MainPath"); + } else { + mainPathQueue_ = std::make_unique(std::move(delegate), 0, "MainPath"); + } + + mainPathQueue_->bufferReady.connect(this, &PipelineHandlerRkISP1::imageBufferReady); + Transform transform = config->combinedTransform(); bool transposeAfterIsp = false; if (data->usesDewarper_) { @@ -1090,9 +1078,9 @@ int PipelineHandlerRkISP1::exportFrameBuffers([[maybe_unused]] Camera *camera, S if (data->usesDewarper_) return dewarper_->exportBuffers(&data->mainPathStream_, count, buffers); else - return mainPath_.exportBuffers(count, buffers); + return data->mainPath_->exportBuffers(count, buffers); } else if (hasSelfPath_ && stream == &data->selfPathStream_) { - return selfPath_.exportBuffers(count, buffers); + return data->selfPath_->exportBuffers(count, buffers); } return -EINVAL; @@ -1104,39 +1092,35 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera) utils::ScopeExitActions actions; unsigned int ipaBufferId = 1; int ret; + /* Start at index 1 */ + data->ipaFrameBuffers_.resize(1); actions += [&]() { - paramBuffers_.clear(); - statBuffers_.clear(); - mainPathBuffers_.clear(); + paramQueue_->releaseBuffers(); + statQueue_->releaseBuffers(); + mainPathQueue_->releaseBuffers(); }; if (!isRaw_) { - ret = param_->allocateBuffers(kRkISP1InternalBufferCount, ¶mBuffers_); + ret = paramQueue_->allocateBuffers(kRkISP1InternalBufferCount); if (ret < 0) return ret; - ret = stat_->allocateBuffers(kRkISP1InternalBufferCount, &statBuffers_); + ret = statQueue_->allocateBuffers(kRkISP1InternalBufferCount); if (ret < 0) return ret; } /* If the dewarper is being used, allocate internal buffers for ISP. */ if (data->usesDewarper_) { - ret = mainPath_.exportBuffers(kRkISP1DewarpImageBufferCount, - &mainPathBuffers_); + ret = mainPathQueue_->allocateBuffers(kRkISP1DewarpImageBufferCount); if (ret < 0) return ret; - - for (std::unique_ptr &buffer : mainPathBuffers_) - availableMainPathBuffers_.push(buffer.get()); } else if (data->mainPath_->isEnabled()) { - ret = mainPath_.importBuffers(data->mainPathStream_.configuration().bufferCount); + ret = mainPathQueue_->importBuffers(data->mainPathStream_.configuration().bufferCount); if (ret < 0) return ret; - - actions += [&]() { mainPath_.releaseBuffers(); }; } if (hasSelfPath_ && data->selfPath_->isEnabled()) { @@ -1148,8 +1132,7 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera) actions += [&]() { selfPath_.releaseBuffers(); }; } - auto pushBuffers = [&](const std::vector> &buffers, - std::queue &queue) { + auto pushBuffers = [&](const std::vector> &buffers) { for (const std::unique_ptr &buffer : buffers) { std::span planes = buffer->planes(); @@ -1157,12 +1140,12 @@ int PipelineHandlerRkISP1::allocateBuffers(Camera *camera) data->ipaBuffers_.emplace_back(buffer->cookie(), std::vector{ planes.begin(), planes.end() }); - queue.push(buffer.get()); + data->ipaFrameBuffers_.push_back(buffer.get()); } }; - pushBuffers(paramBuffers_, availableParamBuffers_); - pushBuffers(statBuffers_, availableStatBuffers_); + pushBuffers(paramQueue_->buffers()); + pushBuffers(statQueue_->buffers()); data->ipa_->mapBuffers(data->ipaBuffers_); @@ -1174,19 +1157,6 @@ int PipelineHandlerRkISP1::freeBuffers(Camera *camera) { RkISP1CameraData *data = cameraData(camera); - while (!availableStatBuffers_.empty()) - availableStatBuffers_.pop(); - - while (!availableParamBuffers_.empty()) - availableParamBuffers_.pop(); - - while (!availableMainPathBuffers_.empty()) - availableMainPathBuffers_.pop(); - - paramBuffers_.clear(); - statBuffers_.clear(); - mainPathBuffers_.clear(); - std::vector ids; for (IPABuffer &ipabuf : data->ipaBuffers_) ids.push_back(ipabuf.id); @@ -1194,14 +1164,9 @@ int PipelineHandlerRkISP1::freeBuffers(Camera *camera) data->ipa_->unmapBuffers(ids); data->ipaBuffers_.clear(); - if (param_->releaseBuffers()) - LOG(RkISP1, Error) << "Failed to release parameters buffers"; - - if (stat_->releaseBuffers()) - LOG(RkISP1, Error) << "Failed to release stat buffers"; - - if (mainPath_.releaseBuffers()) - LOG(RkISP1, Error) << "Failed to release main path buffers"; + paramQueue_->releaseBuffers(); + statQueue_->releaseBuffers(); + mainPathQueue_->releaseBuffers(); if (hasSelfPath_ && selfPath_.releaseBuffers()) LOG(RkISP1, Error) << "Failed to release self path buffers"; @@ -1221,16 +1186,14 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL return ret; actions += [&]() { freeBuffers(camera); }; - paramsSyncHelper_.reset(); imageSyncHelper_.reset(); - nextParamsSequence_ = 0; nextStatsToProcess_ = 0; data->frame_ = 0; uint32_t paramBufferId = 0; FrameBuffer *paramBuffer = nullptr; if (!isRaw_) { - paramBuffer = availableParamBuffers_.front(); + paramBuffer = paramQueue_->front(BufferQueue::Idle); paramBufferId = paramBuffer->cookie(); } @@ -1245,10 +1208,9 @@ int PipelineHandlerRkISP1::start(Camera *camera, [[maybe_unused]] const ControlL } if (paramBuffer) { - availableParamBuffers_.pop(); - computingParamBuffers_.push({ paramBuffer, nextParamsSequence_++ }); - paramsSyncHelper_.pushCorrection(0); - data->paramsComputed(0, paramBufferId, res.paramBufferBytesUsed); + uint32_t seq; + paramQueue_->prepareBuffer(&seq); + data->paramsComputed(seq, paramBufferId, res.paramBufferBytesUsed); } actions += [&]() { data->ipa_->stop(); }; @@ -1337,12 +1299,6 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera) LOG(RkISP1, Warning) << "Failed to stop parameters for " << camera->id(); - /* - * The param buffers are not returned in order, so the queue - * becomes useless. - */ - queuedParamBuffers_ = {}; - if (data->usesDewarper_) dewarper_->stop(); } @@ -1361,8 +1317,6 @@ void PipelineHandlerRkISP1::stopDevice(Camera *camera) sensorFrameInfos_.clear(); ASSERT(queuedDewarpBuffers_.empty()); - ASSERT(queuedParamBuffers_.empty()); - ASSERT(computingParamBuffers_.empty()); freeBuffers(camera); @@ -1376,29 +1330,30 @@ void PipelineHandlerRkISP1::queueInternalBuffers() RkISP1CameraData *data = cameraData(activeCamera_); - while (!availableStatBuffers_.empty()) { - FrameBuffer *buf = availableStatBuffers_.front(); - availableStatBuffers_.pop(); - data->pipe()->stat_->queueBuffer(buf); + while (!statQueue_->empty(BufferQueue::Idle)) { + int ret = statQueue_->queueBuffer(); + if (ret) + break; } /* * In case of the dewarper, there is a seperate buffer loop for the main * path */ - while (!availableMainPathBuffers_.empty()) { - FrameBuffer *buf = availableMainPathBuffers_.front(); - availableMainPathBuffers_.pop(); + if (!data->usesDewarper_) + return; - LOG(RkISP1Schedule, Debug) << "Queue mainPath " << buf; - data->mainPath_->queueBuffer(buf); + while (!mainPathQueue_->empty(BufferQueue::Idle)) { + LOG(RkISP1Schedule, Debug) << "Queue mainPath " << mainPathQueue_->front(BufferQueue::Idle); + int ret = mainPathQueue_->queueBuffer(); + if (ret) + break; } } void PipelineHandlerRkISP1::computeParamBuffers(uint32_t maxSequence) { RkISP1CameraData *data = cameraData(activeCamera_); - if (isRaw_) { /* * Call computeParams with an empty param buffer to trigger the @@ -1408,38 +1363,24 @@ void PipelineHandlerRkISP1::computeParamBuffers(uint32_t maxSequence) return; } - while (nextParamsSequence_ <= maxSequence) { - if (availableParamBuffers_.empty()) { + while (paramQueue_->nextSequence() <= maxSequence) { + if (paramQueue_->empty(BufferQueue::Idle)) { LOG(RkISP1Schedule, Warning) << "Ran out of parameter buffers"; return; } - int correction = paramsSyncHelper_.correction(); + int correction = paramQueue_->sequenceCorrection(); if (correction != 0) LOG(RkISP1Schedule, Warning) << "Correcting params sequence " << correction; uint32_t paramsSequence; - if (correction >= 0) { - nextParamsSequence_ += correction; - paramsSyncHelper_.pushCorrection(correction); - paramsSequence = nextParamsSequence_++; - } else { - /* - * Inject the same sequence multiple times, to correct - * for the offset. - */ - paramsSyncHelper_.pushCorrection(-1); - paramsSequence = nextParamsSequence_; - } - - FrameBuffer *buf = availableParamBuffers_.front(); - availableParamBuffers_.pop(); - computingParamBuffers_.push({ buf, paramsSequence }); + FrameBuffer *buffer = paramQueue_->front(BufferQueue::Idle); + paramQueue_->prepareBuffer(¶msSequence); LOG(RkISP1Schedule, Debug) << "Request params for " << paramsSequence; - data->ipa_->computeParams(paramsSequence, buf->cookie()); + data->ipa_->computeParams(paramsSequence, buffer->cookie()); } } @@ -1475,7 +1416,7 @@ int PipelineHandlerRkISP1::queueRequestDevice(Camera *camera, Request *request) FrameBuffer *mainPathBuffer = request->findBuffer(&data->mainPathStream_); FrameBuffer *selfPathBuffer = request->findBuffer(&data->selfPathStream_); if (mainPathBuffer) - data->mainPath_->queueBuffer(mainPathBuffer); + mainPathQueue_->queueBuffer(mainPathBuffer); if (data->selfPath_ && selfPathBuffer) data->selfPath_->queueBuffer(selfPathBuffer); @@ -1678,10 +1619,18 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) if (stat_->open() < 0) return false; + statQueue_ = std::make_unique(std::make_unique>(stat_.get()), + BufferQueue::PostprocessStage, + "Stat"); + param_ = V4L2VideoDevice::fromEntityName(media_.get(), "rkisp1_params"); if (param_->open() < 0) return false; + paramQueue_ = std::make_unique(std::make_unique>(param_.get()), + BufferQueue::PrepareStage, + "Params"); + /* Locate and open the ISP main and self paths. */ if (!mainPath_.init(media_)) return false; @@ -1690,7 +1639,6 @@ bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator) return false; isp_->frameStart.connect(this, &PipelineHandlerRkISP1::frameStart); - mainPath_.bufferReady.connect(this, &PipelineHandlerRkISP1::imageBufferReady); if (hasSelfPath_) selfPath_.bufferReady.connect(this, &PipelineHandlerRkISP1::imageBufferReady); stat_->bufferReady.connect(this, &PipelineHandlerRkISP1::statBufferReady); @@ -1759,7 +1707,6 @@ void PipelineHandlerRkISP1::tryCompleteRequests() break; ASSERT(iter->second.request == nullptr); - ASSERT(iter->second.statsBuffer == nullptr); sensorFrameInfos_.erase(iter); } @@ -1819,7 +1766,8 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer) if (!reqInfo && data->usesDewarper_) { LOG(RkISP1Schedule, Info) << "Image buffer ready, but no corresponding request"; - availableMainPathBuffers_.push(buffer); + if (metadata.status != FrameMetadata::FrameCancelled) + mainPathQueue_->postprocessedBuffer(); return; } @@ -1896,7 +1844,6 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer) /* Do not queue cancelled frames to the dewarper. */ if (metadata.status == FrameMetadata::FrameCancelled) { cancelDewarpRequest(reqInfo->request); - availableMainPathBuffers_.push(buffer); return; } @@ -1921,7 +1868,7 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer) << strerror(-ret); cancelDewarpRequest(reqInfo->request); - availableMainPathBuffers_.push(buffer); + mainPathQueue_->postprocessedBuffer(); return; } queuedDewarpBuffers_.push_back(dewarpInfo); @@ -1950,7 +1897,7 @@ void PipelineHandlerRkISP1::dewarpBufferReady(FrameBuffer *buffer) outputMeta.sequence = dwInfo.inputMeta.sequence; - availableMainPathBuffers_.push(dwInfo.inputBuffer); + mainPathQueue_->postprocessedBuffer(); dwInfo.inputBuffer = nullptr; dwInfo.outputBuffer = nullptr; @@ -1969,26 +1916,10 @@ void PipelineHandlerRkISP1::paramBufferReady(FrameBuffer *buffer) { LOG(RkISP1Schedule, Debug) << "Param buffer ready " << buffer; - /* - * After stream off, the buffers are returned out of order, so we don't - * care about the rest. - */ - if (!running_) { - availableParamBuffers_.push(buffer); - return; - } - - ParamBufferInfo pInfo = queuedParamBuffers_.front(); - queuedParamBuffers_.pop(); - - ASSERT(pInfo.buffer == buffer); - size_t metaSequence = buffer->metadata().sequence; LOG(RkISP1Schedule, Debug) << "Params buffer ready " - << " Expected: " << pInfo.expectedSequence + << " Expected: " << paramQueue_->expectedSequence(buffer) << " got: " << metaSequence; - paramsSyncHelper_.receivedFrame(pInfo.expectedSequence, metaSequence); - availableParamBuffers_.push(buffer); } void PipelineHandlerRkISP1::statBufferReady(FrameBuffer *buffer) @@ -1999,12 +1930,11 @@ void PipelineHandlerRkISP1::statBufferReady(FrameBuffer *buffer) size_t sequence = buffer->metadata().sequence; if (buffer->metadata().status == FrameMetadata::FrameCancelled) { - LOG(RkISP1Schedule, Warning) << "Stats cancelled " << sequence; /* - * We can't assume that the sequence of the stat buffer is valid, - * so there is nothing left to do. + * Frame cancelled only happens after the ipa was stopped, so + * there must be no more buffers in postprocessing stage */ - availableStatBuffers_.push(buffer); + ASSERT(statQueue_->empty(BufferQueue::Postprocessing)); return; } @@ -2017,15 +1947,13 @@ void PipelineHandlerRkISP1::statBufferReady(FrameBuffer *buffer) if (nextStatsToProcess_ > sequence) { LOG(RkISP1Schedule, Warning) << "Stats were too late. Ignored"; - availableStatBuffers_.push(buffer); + statQueue_->postprocessedBuffer(); return; } while (nextStatsToProcess_ < sequence) sensorFrameInfos_[nextStatsToProcess_++].statsLost = true; - sensorFrameInfos_[sequence].statsBuffer = buffer; - LOG(RkISP1Schedule, Debug) << "Process stats " << sequence; data->ipa_->processStats(sequence, buffer->cookie(), data->delayedCtrls_->get(sequence));