diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/libcamera/pipeline/ipu3/ipu3.cpp | 62 |
1 files changed, 60 insertions, 2 deletions
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp index e7cfc66a..31322062 100644 --- a/src/libcamera/pipeline/ipu3/ipu3.cpp +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp @@ -60,6 +60,7 @@ public: void statBufferReady(FrameBuffer *buffer); void queuePendingRequests(); void cancelPendingRequests(); + void frameStart(uint32_t sequence); CIO2Device cio2_; ImgUDevice *imgu_; @@ -77,7 +78,10 @@ public: std::unique_ptr<ipa::ipu3::IPAProxyIPU3> ipa_; + /* Requests for which no buffer has been queued to the CIO2 device yet. */ std::queue<Request *> pendingRequests_; + /* Requests queued to the CIO2 device but not yet processed by the ImgU. */ + std::queue<Request *> processingRequests_; ControlInfoMap ipaControls_; @@ -758,6 +762,12 @@ int PipelineHandlerIPU3::start(Camera *camera, [[maybe_unused]] const ControlLis ImgUDevice *imgu = data->imgu_; int ret; + /* Disable test pattern mode on the sensor, if any. */ + ret = cio2->sensor()->setTestPatternMode( + controls::draft::TestPatternModeEnum::TestPatternModeOff); + if (ret) + return ret; + /* Allocate buffers for internal pipeline usage. */ ret = allocateBuffers(camera); if (ret) @@ -812,6 +822,8 @@ void PipelineHandlerIPU3::stop(Camera *camera) void IPU3CameraData::cancelPendingRequests() { + processingRequests_ = {}; + while (!pendingRequests_.empty()) { Request *request = pendingRequests_.front(); @@ -861,6 +873,7 @@ void IPU3CameraData::queuePendingRequests() ipa_->processEvent(ev); pendingRequests_.pop(); + processingRequests_.push(request); } } @@ -1122,8 +1135,8 @@ int PipelineHandlerIPU3::registerCameras() data->delayedCtrls_ = std::make_unique<DelayedControls>(cio2->sensor()->device(), params); - data->cio2_.frameStart().connect(data->delayedCtrls_.get(), - &DelayedControls::applyControls); + data->cio2_.frameStart().connect(data.get(), + &IPU3CameraData::frameStart); /* Convert the sensor rotation to a transformation */ int32_t rotation = 0; @@ -1429,6 +1442,51 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer) ipa_->processEvent(ev); } +/* + * \brief Handle the start of frame exposure signal + * \param[in] sequence The sequence number of frame + * + * Inspect the list of pending requests waiting for a RAW frame to be + * produced and apply controls for the 'next' one. + * + * Some controls need to be applied immediately, such as the + * TestPatternMode one. Other controls are handled through the delayed + * controls class. + */ +void IPU3CameraData::frameStart(uint32_t sequence) +{ + delayedCtrls_->applyControls(sequence); + + if (processingRequests_.empty()) + return; + + /* + * Handle controls to be set immediately on the next frame. + * This currently only handle the TestPatternMode control. + * + * \todo Synchronize with the sequence number + */ + Request *request = processingRequests_.front(); + processingRequests_.pop(); + + if (!request->controls().contains(controls::draft::TestPatternMode)) + return; + + const int32_t testPatternMode = request->controls().get( + controls::draft::TestPatternMode); + + int ret = cio2_.sensor()->setTestPatternMode( + static_cast<controls::draft::TestPatternModeEnum>(testPatternMode)); + if (ret) { + LOG(IPU3, Error) << "Failed to set test pattern mode: " + << ret; + return; + } + + request->metadata().set(controls::draft::TestPatternMode, + testPatternMode); +} + REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3) } /* namespace libcamera */ |