From patchwork Wed Aug 26 11:09:11 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Elder X-Patchwork-Id: 9386 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 ADC45BD87E for ; Wed, 26 Aug 2020 11:09:54 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 7A3A6628FB; Wed, 26 Aug 2020 13:09:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ivwyO3IG"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 595FB628F3 for ; Wed, 26 Aug 2020 13:09:53 +0200 (CEST) Received: from pyrite.rasen.tech (unknown [IPv6:2400:4051:61:600:2c71:1b79:d06d:5032]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 989DAB1A; Wed, 26 Aug 2020 13:09:51 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1598440193; bh=/0ZrAwhrufuHQsETJWT0Htdeae5oD1X0A00R0YVDKoE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ivwyO3IG2qzUSLINhYC8pBXFZHI45XeMeIKYULMeEHwSioe2nExbeCfPMZf1F4bav 6HRd/sLf5eL9aNQPyUlDHTOm3wpeOTbIBBc4CE29Bb1JwR10/JI3oWKsZO9LmP2Zny rSpf2LDhp0Sfa1kykrdNNxTTUzvw7XaJa31DVDdE= From: Paul Elder To: libcamera-devel@lists.libcamera.org Date: Wed, 26 Aug 2020 20:09:11 +0900 Message-Id: <20200826110926.67192-3-paul.elder@ideasonboard.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20200826110926.67192-1-paul.elder@ideasonboard.com> References: <20200826110926.67192-1-paul.elder@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [RFC PATCH 02/17] libcamera: pipeline: raspberrypi: Use generated IPARPiInterface 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" This patch shows how the pipeline would use the generated IPA interface. raspberrypi_wrapper.h is included, since that contains the definitions of all the custom data structures. ipa_proxy_raspberrypi.h is also included, so that the pipeline handler can create the IPAProxyRPi. Due to the custom IPA interface, the generic IPAProxy can no longer be used. This will be elaborated on in a few patches. Other than that, the rest of the patch should be straightforward. The only changes are just fiddling the code to use the new structures. Most noteworthy is that the pipeline handler does not know nor care if it is communicating with the IPA isolated or direct. This is one of our main goals. Signed-off-by: Paul Elder --- .../pipeline/raspberrypi/raspberrypi.cpp | 125 ++++++++++-------- 1 file changed, 69 insertions(+), 56 deletions(-) diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp index 42c9caa0..214dba8f 100644 --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ #include "dma_heaps.h" #include "staggered_ctrl.h" +#include "libcamera/internal/ipa_proxy_raspberrypi.h" + namespace libcamera { LOG_DEFINE_CATEGORY(RPI) @@ -296,7 +299,7 @@ public: int loadIPA(); int configureIPA(); - void queueFrameAction(unsigned int frame, const IPAOperationData &action); + void queueFrameAction(unsigned int frame, const RPiActionParams &action); /* bufferComplete signal handlers. */ void unicamBufferDequeue(FrameBuffer *buffer); @@ -307,6 +310,8 @@ public: void handleStreamBuffer(FrameBuffer *buffer, const RPiStream *stream); void handleState(); + std::unique_ptr ipa_; + CameraSensor *sensor_; /* Array of Unicam and ISP device streams and associated buffers/streams. */ RPiDevice unicam_; @@ -1094,7 +1099,9 @@ void RPiCameraData::frameStarted(uint32_t sequence) int RPiCameraData::loadIPA() { - ipa_ = IPAManager::createIPA(pipe_, 1, 1); + std::unique_ptr ptr = IPAManager::createIPA(pipe_, 1, 1); + ipa_ = std::unique_ptr{static_cast(std::move(ptr).release())}; + if (!ipa_) return -ENOENT; @@ -1110,8 +1117,8 @@ int RPiCameraData::loadIPA() int RPiCameraData::configureIPA() { std::map streamConfig; - std::map entityControls; - IPAOperationData ipaConfig = {}; + std::map entityControls; + RPiConfigureParams ipaConfig; /* Get the device format to pass to the IPA. */ V4L2DeviceFormat sensorFormat; @@ -1136,8 +1143,11 @@ int RPiCameraData::configureIPA() return -ENOMEM; /* Allow the IPA to mmap the LS table via the file descriptor. */ - ipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE; - ipaConfig.data = { static_cast(lsTable_.fd()) }; + RPiConfigurePayload payload; + payload.op_ = RPI_IPA_CONFIG_LS_TABLE; + payload.lsTableHandle_ = lsTable_; + payload.lsTableHandleStatic_ = lsTable_.fd(); + ipaConfig.payload_.push_back(payload); } CameraSensorInfo sensorInfo = {}; @@ -1148,60 +1158,66 @@ int RPiCameraData::configureIPA() } /* Ready the IPA - it must know about the sensor resolution. */ - IPAOperationData result; + RPiConfigureParams results; ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig, - &result); + &results); - if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) { - /* - * Setup our staggered control writer with the sensor default - * gain and exposure delays. - */ - if (!staggeredCtrl_) { - staggeredCtrl_.init(unicam_[Unicam::Image].dev(), - { { V4L2_CID_ANALOGUE_GAIN, result.data[0] }, - { V4L2_CID_EXPOSURE, result.data[1] } }); - sensorMetadata_ = result.data[2]; - } + for (RPiConfigurePayload &result : results.payload_) { + if (result.op_ == RPI_IPA_CONFIG_STAGGERED_WRITE) { - /* Configure the H/V flip controls based on the sensor rotation. */ - ControlList ctrls(unicam_[Unicam::Image].dev()->controls()); - int32_t rotation = sensor_->properties().get(properties::Rotation); - ctrls.set(V4L2_CID_HFLIP, static_cast(!!rotation)); - ctrls.set(V4L2_CID_VFLIP, static_cast(!!rotation)); - unicam_[Unicam::Image].dev()->setControls(&ctrls); - } + /* + * Setup our staggered control writer with the sensor default + * gain and exposure delays. + */ + if (!staggeredCtrl_) { + staggeredCtrl_.init(unicam_[Unicam::Image].dev(), + { { V4L2_CID_ANALOGUE_GAIN, result.staggeredWriteResult_.gainDelay_ }, + { V4L2_CID_EXPOSURE, result.staggeredWriteResult_.exposureDelay_ } }); + sensorMetadata_ = result.staggeredWriteResult_.sensorMetadata_; + } - if (result.operation & RPI_IPA_CONFIG_SENSOR) { - const ControlList &ctrls = result.controls[0]; - if (!staggeredCtrl_.set(ctrls)) - LOG(RPI, Error) << "V4L2 staggered set failed"; + /* Configure the H/V flip controls based on the sensor rotation. */ + ControlList ctrls(unicam_[Unicam::Image].dev()->controls()); + int32_t rotation = sensor_->properties().get(properties::Rotation); + ctrls.set(V4L2_CID_HFLIP, static_cast(!!rotation)); + ctrls.set(V4L2_CID_VFLIP, static_cast(!!rotation)); + unicam_[Unicam::Image].dev()->setControls(&ctrls); + } + + if (result.op_ == RPI_IPA_CONFIG_SENSOR) { + const ControlList &ctrls = result.controls_; + if (!staggeredCtrl_.set(ctrls)) + LOG(RPI, Error) << "V4L2 staggered set failed"; + } } return 0; } void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, - const IPAOperationData &action) + const RPiActionParams &action) { /* * The following actions can be handled when the pipeline handler is in * a stopped state. */ - switch (action.operation) { + switch (action.op_) { case RPI_IPA_ACTION_V4L2_SET_STAGGERED: { - const ControlList &controls = action.controls[0]; + const ControlList &controls = action.controls_; if (!staggeredCtrl_.set(controls)) LOG(RPI, Error) << "V4L2 staggered set failed"; goto done; } case RPI_IPA_ACTION_V4L2_SET_ISP: { - ControlList controls = action.controls[0]; + ControlList controls = action.controls_; isp_[Isp::Input].dev()->setControls(&controls); goto done; } + + default: + break; } if (state_ == State::Stopped) @@ -1211,20 +1227,20 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, * The following actions must not be handled when the pipeline handler * is in a stopped state. */ - switch (action.operation) { + switch (action.op_) { case RPI_IPA_ACTION_STATS_METADATA_COMPLETE: { - unsigned int bufferId = action.data[0]; + unsigned int bufferId = action.statsComplete_.bufferId_; FrameBuffer *buffer = isp_[Isp::Stats].getBuffers()->at(bufferId).get(); handleStreamBuffer(buffer, &isp_[Isp::Stats]); /* Fill the Request metadata buffer with what the IPA has provided */ - requestQueue_.front()->metadata() = std::move(action.controls[0]); + requestQueue_.front()->metadata() = std::move(action.statsComplete_.controls_); state_ = State::IpaComplete; break; } case RPI_IPA_ACTION_EMBEDDED_COMPLETE: { - unsigned int bufferId = action.data[0]; + unsigned int bufferId = action.bufferId_; FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers()->at(bufferId).get(); handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]); break; @@ -1232,20 +1248,17 @@ void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame, case RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME: case RPI_IPA_ACTION_RUN_ISP: { - unsigned int bufferId = action.data[0]; + unsigned int bufferId = action.bufferId_; FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers()->at(bufferId).get(); - LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << buffer->cookie() - << ", timestamp: " << buffer->metadata().timestamp; - isp_[Isp::Input].dev()->queueBuffer(buffer); - dropFrame_ = (action.operation == RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME) ? true : false; + dropFrame_ = (action.op_ == RPI_IPA_ACTION_RUN_ISP_AND_DROP_FRAME) ? true : false; ispOutputCount_ = 0; break; } default: - LOG(RPI, Error) << "Unknown action " << action.operation; + LOG(RPI, Error) << "Unknown action " << action.op_; break; } @@ -1345,10 +1358,10 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer) /* If this is a stats output, hand it to the IPA now. */ if (stream == &isp_[Isp::Stats]) { - IPAOperationData op; - op.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY; - op.data = { RPiIpaMask::STATS | buffer->cookie() }; - ipa_->processEvent(op); + RPiEventParams ev; + ev.ev_ = RPI_IPA_EVENT_SIGNAL_STAT_READY; + ev.bufferId_ = { RPiIpaMask::STATS | buffer->cookie() }; + ipa_->processEvent(ev); } handleState(); @@ -1491,7 +1504,7 @@ void RPiCameraData::checkRequestCompleted() void RPiCameraData::tryRunPipeline() { FrameBuffer *bayerBuffer, *embeddedBuffer; - IPAOperationData op; + RPiEventParams ev; /* If any of our request or buffer queues are empty, we cannot proceed. */ if (state_ != State::Idle || requestQueue_.empty() || @@ -1546,9 +1559,9 @@ void RPiCameraData::tryRunPipeline() * queue the ISP output buffer listed in the request to start the HW * pipeline. */ - op.operation = RPI_IPA_EVENT_QUEUE_REQUEST; - op.controls = { request->controls() }; - ipa_->processEvent(op); + ev.ev_ = RPI_IPA_EVENT_QUEUE_REQUEST; + ev.controls_ = { request->controls() }; + ipa_->processEvent(ev); /* Queue up any ISP buffers passed into the request. */ for (auto &stream : isp_) { @@ -1567,10 +1580,10 @@ void RPiCameraData::tryRunPipeline() << " Bayer buffer id: " << bayerBuffer->cookie() << " Embedded buffer id: " << embeddedBuffer->cookie(); - op.operation = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE; - op.data = { RPiIpaMask::EMBEDDED_DATA | embeddedBuffer->cookie(), - RPiIpaMask::BAYER_DATA | bayerBuffer->cookie() }; - ipa_->processEvent(op); + ev.ev_ = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE; + ev.ispPrepare_.embeddedbufferId_ = RPiIpaMask::EMBEDDED_DATA | embeddedBuffer->cookie(); + ev.ispPrepare_.bayerbufferId_ = RPiIpaMask::BAYER_DATA | bayerBuffer->cookie(); + ipa_->processEvent(ev); } void RPiCameraData::tryFlushQueues()