<div dir="ltr"><div>Thanks for the implementation.</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Sep 22, 2020 at 9:39 PM Paul Elder <<a href="mailto:paul.elder@ideasonboard.com">paul.elder@ideasonboard.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Now that we can generate custom functions and data structures with mojo,<br>
switch the raspberrypi pipeline handler and IPA to use the custom data<br>
structures as defined in the mojom data definition file.<br>
<br>
Signed-off-by: Paul Elder <<a href="mailto:paul.elder@ideasonboard.com" target="_blank">paul.elder@ideasonboard.com</a>><br>
<br>
---<br>
Changes in v2:<br>
- rebased on "libcamera: pipeline: ipa: raspberrypi: Rework drop frame<br>
  signalling"<br>
- use newly customized RPi IPA interface<br>
---<br>
 include/libcamera/ipa/raspberrypi.h           |  37 ++--<br>
 src/ipa/raspberrypi/raspberrypi.cpp           | 152 +++++++---------<br>
 .../pipeline/raspberrypi/raspberrypi.cpp      | 171 +++++++++---------<br>
 3 files changed, 170 insertions(+), 190 deletions(-)<br>
<br>
diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h<br>
index 4e38d009..3357bf61 100644<br>
--- a/include/libcamera/ipa/raspberrypi.h<br>
+++ b/include/libcamera/ipa/raspberrypi.h<br>
@@ -24,22 +24,27 @@ enum RPiBufferMask {<br>
 namespace libcamera {<br>
<br>
 /* List of controls handled by the Raspberry Pi IPA */<br>
-static const ControlInfoMap RPiControls = {<br>
-       { &controls::AeEnable, ControlInfo(false, true) },<br>
-       { &controls::ExposureTime, ControlInfo(0, 999999) },<br>
-       { &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },<br>
-       { &controls::AeMeteringMode, ControlInfo(0, static_cast<int32_t>(controls::MeteringModeMax)) },<br>
-       { &controls::AeConstraintMode, ControlInfo(0, static_cast<int32_t>(controls::ConstraintModeMax)) },<br>
-       { &controls::AeExposureMode, ControlInfo(0, static_cast<int32_t>(controls::ExposureModeMax)) },<br>
-       { &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },<br>
-       { &controls::AwbEnable, ControlInfo(false, true) },<br>
-       { &controls::ColourGains, ControlInfo(0.0f, 32.0f) },<br>
-       { &controls::AwbMode, ControlInfo(0, static_cast<int32_t>(controls::AwbModeMax)) },<br>
-       { &controls::Brightness, ControlInfo(-1.0f, 1.0f) },<br>
-       { &controls::Contrast, ControlInfo(0.0f, 32.0f) },<br>
-       { &controls::Saturation, ControlInfo(0.0f, 32.0f) },<br>
-       { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },<br>
-       { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },<br>
+static ControlInfoMap RPiControls;<br>
+<br>
+inline void initializeRPiControls()<br>
+{<br>
+       RPiControls = {<br>
+               { &controls::AeEnable, ControlInfo(false, true) },<br>
+               { &controls::ExposureTime, ControlInfo(0, 999999) },<br>
+               { &controls::AnalogueGain, ControlInfo(1.0f, 32.0f) },<br>
+               { &controls::AeMeteringMode, ControlInfo(0, static_cast<int32_t>(controls::MeteringModeMax)) },<br>
+               { &controls::AeConstraintMode, ControlInfo(0, static_cast<int32_t>(controls::ConstraintModeMax)) },<br>
+               { &controls::AeExposureMode, ControlInfo(0, static_cast<int32_t>(controls::ExposureModeMax)) },<br>
+               { &controls::ExposureValue, ControlInfo(0.0f, 16.0f) },<br>
+               { &controls::AwbEnable, ControlInfo(false, true) },<br>
+               { &controls::ColourGains, ControlInfo(0.0f, 32.0f) },<br>
+               { &controls::AwbMode, ControlInfo(0, static_cast<int32_t>(controls::AwbModeMax)) },<br>
+               { &controls::Brightness, ControlInfo(-1.0f, 1.0f) },<br>
+               { &controls::Contrast, ControlInfo(0.0f, 32.0f) },<br>
+               { &controls::Saturation, ControlInfo(0.0f, 32.0f) },<br>
+               { &controls::Sharpness, ControlInfo(0.0f, 16.0f, 1.0f) },<br>
+               { &controls::ColourCorrectionMatrix, ControlInfo(-16.0f, 16.0f) },<br>
+       };<br>
 };<br></blockquote><div>Just out of curiosity.</div><div>Since the RPiControls is not const anymore, and each translation unit has a copy, the content used in generated ipa_proxy_raspberrypi.cpp would be empty.</div><div>Is it an intended behavior?</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
 } /* namespace libcamera */<br>
diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp<br>
index 0555cc4e..805ced33 100644<br>
--- a/src/ipa/raspberrypi/raspberrypi.cpp<br>
+++ b/src/ipa/raspberrypi/raspberrypi.cpp<br>
@@ -19,6 +19,7 @@<br>
 #include <libcamera/ipa/ipa_interface.h><br>
 #include <libcamera/ipa/ipa_module_info.h><br>
 #include <libcamera/ipa/raspberrypi.h><br>
+#include <libcamera/ipa/raspberrypi_generated.h><br>
 #include <libcamera/request.h><br>
 #include <libcamera/span.h><br>
<br>
@@ -60,7 +61,7 @@ namespace libcamera {<br>
<br>
 LOG_DEFINE_CATEGORY(IPARPI)<br>
<br>
-class IPARPi : public IPAInterface<br>
+class IPARPi : public IPARPiInterface<br>
 {<br>
 public:<br>
        IPARPi()<br>
@@ -68,6 +69,7 @@ public:<br>
                  frame_count_(0), check_count_(0), mistrust_count_(0),<br>
                  lsTable_(nullptr)<br>
        {<br>
+               initializeRPiControls();<br>
        }<br>
<br>
        ~IPARPi()<br>
@@ -82,12 +84,14 @@ public:<br>
<br>
        void configure(const CameraSensorInfo &sensorInfo,<br>
                       const std::map<unsigned int, IPAStream> &streamConfig,<br>
-                      const std::map<unsigned int, const ControlInfoMap &> &entityControls,<br>
-                      const IPAOperationData &data,<br>
-                      IPAOperationData *response) override;<br>
+                      const std::map<unsigned int, ControlInfoMap> &entityControls,<br>
+                      const RPiConfigInput &data,<br>
+                      RPiConfigOutput *response) override;<br>
        void mapBuffers(const std::vector<IPABuffer> &buffers) override;<br>
        void unmapBuffers(const std::vector<unsigned int> &ids) override;<br>
-       void processEvent(const IPAOperationData &event) override;<br>
+       void signalStatReady(const uint32_t bufferId) override;<br>
+       void signalQueueRequest(const ControlList &controls) override;<br>
+       void signalIspPrepare(const RPiIspPreparePayload &data) override;<br>
<br>
 private:<br>
        void setMode(const CameraSensorInfo &sensorInfo);<br>
@@ -141,6 +145,11 @@ private:<br>
        unsigned int mistrust_count_;<br>
        /* LS table allocation passed in from the pipeline handler. */<br>
        FileDescriptor lsTableHandle_;<br>
+       /*<br>
+        * LS table allocation passed in from the pipeline handler,<br>
+        * in the context of the pipeline handler.<br>
+        */<br>
+       int32_t lsTableHandlePH_;<br>
        void *lsTable_;<br>
 };<br>
<br>
@@ -190,15 +199,13 @@ void IPARPi::setMode(const CameraSensorInfo &sensorInfo)<br>
<br>
 void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
                       [[maybe_unused]] const std::map<unsigned int, IPAStream> &streamConfig,<br>
-                      const std::map<unsigned int, const ControlInfoMap &> &entityControls,<br>
-                      const IPAOperationData &ipaConfig,<br>
-                      IPAOperationData *result)<br>
+                      const std::map<unsigned int, ControlInfoMap> &entityControls,<br>
+                      const RPiConfigInput &ipaConfig,<br>
+                      RPiConfigOutput *result)<br>
 {<br>
        if (entityControls.empty())<br>
                return;<br>
<br>
-       result->operation = 0;<br>
-<br>
        unicam_ctrls_ = entityControls.at(0);<br>
        isp_ctrls_ = entityControls.at(1);<br>
        /* Setup a metadata ControlList to output metadata. */<br>
@@ -220,11 +227,10 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
                helper_->GetDelays(exposureDelay, gainDelay);<br>
                sensorMetadata = helper_->SensorEmbeddedDataPresent();<br>
<br>
-               result->data.push_back(gainDelay);<br>
-               result->data.push_back(exposureDelay);<br>
-               result->data.push_back(sensorMetadata);<br>
-<br>
-               result->operation |= RPI_IPA_CONFIG_STAGGERED_WRITE;<br>
+               result->op_ |= RPI_IPA_CONFIG_STAGGERED_WRITE;<br>
+               result->staggeredWriteResult_.gainDelay_ = gainDelay;<br>
+               result->staggeredWriteResult_.exposureDelay_ = exposureDelay;<br>
+               result->staggeredWriteResult_.sensorMetadata_ = sensorMetadata;<br>
        }<br>
<br>
        /* Re-assemble camera mode using the sensor info. */<br>
@@ -240,18 +246,15 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
         */<br>
        frame_count_ = 0;<br>
        check_count_ = 0;<br>
-       unsigned int drop_frame = 0;<br>
+       result->op_ |= RPI_IPA_CONFIG_DROP_FRAMES;<br>
        if (controllerInit_) {<br>
-               drop_frame = helper_->HideFramesModeSwitch();<br>
+               result->dropFrameCount_ = helper_->HideFramesModeSwitch();<br>
                mistrust_count_ = helper_->MistrustFramesModeSwitch();<br>
        } else {<br>
-               drop_frame = helper_->HideFramesStartup();<br>
+               result->dropFrameCount_ = helper_->HideFramesStartup();<br>
                mistrust_count_ = helper_->MistrustFramesStartup();<br>
        }<br>
<br>
-       result->data.push_back(drop_frame);<br>
-       result->operation |= RPI_IPA_CONFIG_DROP_FRAMES;<br>
-<br>
        struct AgcStatus agcStatus;<br>
        /* These zero values mean not program anything (unless overwritten). */<br>
        agcStatus.shutter_time = 0.0;<br>
@@ -276,15 +279,15 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
        if (agcStatus.shutter_time != 0.0 && agcStatus.analogue_gain != 0.0) {<br>
                ControlList ctrls(unicam_ctrls_);<br>
                applyAGC(&agcStatus, ctrls);<br>
-               result->controls.push_back(ctrls);<br>
<br>
-               result->operation |= RPI_IPA_CONFIG_SENSOR;<br>
+               result->op_ |= RPI_IPA_CONFIG_SENSOR;<br>
+               result->controls_ = ctrls;<br>
        }<br>
<br>
        lastMode_ = mode_;<br>
<br>
        /* Store the lens shading table pointer and handle if available. */<br>
-       if (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {<br>
+       if (ipaConfig.op_ & RPI_IPA_CONFIG_LS_TABLE) {<br>
                /* Remove any previous table, if there was one. */<br>
                if (lsTable_) {<br>
                        munmap(lsTable_, MAX_LS_GRID_SIZE);<br>
@@ -292,7 +295,8 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,<br>
                }<br>
<br>
                /* Map the LS table buffer into user space. */<br>
-               lsTableHandle_ = FileDescriptor(ipaConfig.data[0]);<br>
+               lsTableHandle_ = FileDescriptor(ipaConfig.lsTableHandle_);<br>
+               lsTableHandlePH_ = ipaConfig.lsTableHandleStatic_;<br>
                if (lsTableHandle_.isValid()) {<br>
                        lsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,<br>
                                        MAP_SHARED, lsTableHandle_.fd(), 0);<br>
@@ -337,56 +341,38 @@ void IPARPi::unmapBuffers(const std::vector<unsigned int> &ids)<br>
        }<br>
 }<br>
<br>
-void IPARPi::processEvent(const IPAOperationData &event)<br>
+void IPARPi::signalStatReady(const uint32_t bufferId)<br>
 {<br>
-       switch (event.operation) {<br>
-       case RPI_IPA_EVENT_SIGNAL_STAT_READY: {<br>
-               unsigned int bufferId = event.data[0];<br>
-<br>
-               if (++check_count_ != frame_count_) /* assert here? */<br>
-                       LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";<br>
-               if (frame_count_ > mistrust_count_)<br>
-                       processStats(bufferId);<br>
-<br>
-               reportMetadata();<br>
-<br>
-               IPAOperationData op;<br>
-               op.operation = RPI_IPA_ACTION_STATS_METADATA_COMPLETE;<br>
-               op.data = { bufferId & RPiBufferMask::ID };<br>
-               op.controls = { libcameraMetadata_ };<br>
-               queueFrameAction.emit(0, op);<br>
-               break;<br>
-       }<br>
+       if (++check_count_ != frame_count_) /* assert here? */<br>
+               LOG(IPARPI, Error) << "WARNING: Prepare/Process mismatch!!!";<br>
+       if (frame_count_ > mistrust_count_)<br>
+               processStats(bufferId);<br>
<br>
-       case RPI_IPA_EVENT_SIGNAL_ISP_PREPARE: {<br>
-               unsigned int embeddedbufferId = event.data[0];<br>
-               unsigned int bayerbufferId = event.data[1];<br>
+       reportMetadata();<br>
<br>
-               /*<br>
-                * At start-up, or after a mode-switch, we may want to<br>
-                * avoid running the control algos for a few frames in case<br>
-                * they are "unreliable".<br>
-                */<br>
-               prepareISP(embeddedbufferId);<br>
-               frame_count_++;<br>
-<br>
-               /* Ready to push the input buffer into the ISP. */<br>
-               IPAOperationData op;<br>
-               op.operation = RPI_IPA_ACTION_RUN_ISP;<br>
-               op.data = { bayerbufferId & RPiBufferMask::ID };<br>
-               queueFrameAction.emit(0, op);<br>
-               break;<br>
-       }<br>
+       statsMetadataComplete.emit(bufferId & RPiBufferMask::ID, libcameraMetadata_);<br>
+}<br>
<br>
-       case RPI_IPA_EVENT_QUEUE_REQUEST: {<br>
-               queueRequest(event.controls[0]);<br>
-               break;<br>
-       }<br>
+void IPARPi::signalQueueRequest(const ControlList &controls)<br>
+{<br>
+       queueRequest(controls);<br>
+}<br>
<br>
-       default:<br>
-               LOG(IPARPI, Error) << "Unknown event " << event.operation;<br>
-               break;<br>
-       }<br>
+void IPARPi::signalIspPrepare(const RPiIspPreparePayload &data)<br>
+{<br>
+       unsigned int embeddedbufferId = data.embeddedbufferId_;<br>
+       unsigned int bayerbufferId = data.bayerbufferId_;<br>
+<br>
+       /*<br>
+        * At start-up, or after a mode-switch, we may want to<br>
+        * avoid running the control algos for a few frames in case<br>
+        * they are "unreliable".<br>
+        */<br>
+       prepareISP(embeddedbufferId);<br>
+       frame_count_++;<br>
+<br>
+       /* Ready to push the input buffer into the ISP. */<br>
+       runIsp.emit(bayerbufferId & RPiBufferMask::ID);<br>
 }<br>
<br>
 void IPARPi::reportMetadata()<br>
@@ -489,6 +475,8 @@ void IPARPi::queueRequest(const ControlList &controls)<br>
        /* Clear the return metadata buffer. */<br>
        libcameraMetadata_.clear();<br>
<br>
+       LOG(IPARPI, Info) << "Request ctrl length: " << controls.size();<br>
+<br>
        for (auto const &ctrl : controls) {<br>
                LOG(IPARPI, Info) << "Request ctrl: "<br>
                                  << controls::<a href="http://controls.at" rel="noreferrer" target="_blank">controls.at</a>(ctrl.first)->name()<br>
@@ -698,10 +686,7 @@ void IPARPi::queueRequest(const ControlList &controls)<br>
<br>
 void IPARPi::returnEmbeddedBuffer(unsigned int bufferId)<br>
 {<br>
-       IPAOperationData op;<br>
-       op.operation = RPI_IPA_ACTION_EMBEDDED_COMPLETE;<br>
-       op.data = { bufferId & RPiBufferMask::ID };<br>
-       queueFrameAction.emit(0, op);<br>
+       embeddedComplete.emit(bufferId & RPiBufferMask::ID);<br>
 }<br>
<br>
 void IPARPi::prepareISP(unsigned int bufferId)<br>
@@ -762,12 +747,8 @@ void IPARPi::prepareISP(unsigned int bufferId)<br>
                if (dpcStatus)<br>
                        applyDPC(dpcStatus, ctrls);<br>
<br>
-               if (!ctrls.empty()) {<br>
-                       IPAOperationData op;<br>
-                       op.operation = RPI_IPA_ACTION_V4L2_SET_ISP;<br>
-                       op.controls.push_back(ctrls);<br>
-                       queueFrameAction.emit(0, op);<br>
-               }<br>
+               if (!ctrls.empty())<br>
+                       setIsp.emit(ctrls);<br>
        }<br>
 }<br>
<br>
@@ -823,10 +804,7 @@ void IPARPi::processStats(unsigned int bufferId)<br>
                ControlList ctrls(unicam_ctrls_);<br>
                applyAGC(&agcStatus, ctrls);<br>
<br>
-               IPAOperationData op;<br>
-               op.operation = RPI_IPA_ACTION_V4L2_SET_STAGGERED;<br>
-               op.controls.push_back(ctrls);<br>
-               queueFrameAction.emit(0, op);<br>
+               setStaggered.emit(ctrls);<br>
        }<br>
 }<br>
<br>
@@ -1056,7 +1034,7 @@ void IPARPi::applyLS(const struct AlscStatus *lsStatus, ControlList &ctrls)<br>
                .grid_width = w,<br>
                .grid_stride = w,<br>
                .grid_height = h,<br>
-               .dmabuf = lsTableHandle_.fd(),<br>
+               .dmabuf = lsTableHandlePH_,<br>
                .ref_transform = 0,<br>
                .corner_sampled = 1,<br>
                .gain_format = GAIN_FORMAT_U4P10<br>
@@ -1136,9 +1114,9 @@ const struct IPAModuleInfo ipaModuleInfo = {<br>
        "raspberrypi",<br>
 };<br>
<br>
-struct ipa_context *ipaCreate()<br>
+IPAInterface *ipaCreate()<br>
 {<br>
-       return new IPAInterfaceWrapper(std::make_unique<IPARPi>());<br>
+       return new IPARPi();<br>
 }<br>
<br>
 }; /* extern "C" */<br>
diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
index 50f07182..49e28e0c 100644<br>
--- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
+++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp<br>
@@ -16,7 +16,9 @@<br>
 #include <libcamera/control_ids.h><br>
 #include <libcamera/file_descriptor.h><br>
 #include <libcamera/formats.h><br>
+#include <libcamera/ipa/ipa_proxy_raspberrypi.h><br>
 #include <libcamera/ipa/raspberrypi.h><br>
+#include <libcamera/ipa/raspberrypi_generated.h><br>
 #include <libcamera/logging.h><br>
 #include <libcamera/property_ids.h><br>
 #include <libcamera/request.h><br>
@@ -142,7 +144,11 @@ public:<br>
        int loadIPA();<br>
        int configureIPA();<br>
<br>
-       void queueFrameAction(unsigned int frame, const IPAOperationData &action);<br>
+       void statsMetadataComplete(uint32_t bufferId, const ControlList &controls);<br>
+       void runIsp(uint32_t bufferId);<br>
+       void embeddedComplete(uint32_t bufferId);<br>
+       void setIsp(const ControlList &controls);<br>
+       void setStaggered(const ControlList &controls);<br>
<br>
        /* bufferComplete signal handlers. */<br>
        void unicamBufferDequeue(FrameBuffer *buffer);<br>
@@ -154,6 +160,8 @@ public:<br>
        void handleExternalBuffer(FrameBuffer *buffer, RPi::RPiStream *stream);<br>
        void handleState();<br>
<br>
+       std::unique_ptr<IPAProxyRPi> ipa_;<br>
+<br>
        CameraSensor *sensor_;<br>
        /* Array of Unicam and ISP device streams and associated buffers/streams. */<br>
        RPi::RPiDevice<Unicam, 2> unicam_;<br>
@@ -356,6 +364,7 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()<br>
 PipelineHandlerRPi::PipelineHandlerRPi(CameraManager *manager)<br>
        : PipelineHandler(manager), unicam_(nullptr), isp_(nullptr)<br>
 {<br>
+       initializeRPiControls();<br>
 }<br>
<br>
 CameraConfiguration *PipelineHandlerRPi::generateConfiguration(Camera *camera,<br>
@@ -974,11 +983,17 @@ void RPiCameraData::frameStarted(uint32_t sequence)<br>
<br>
 int RPiCameraData::loadIPA()<br>
 {<br>
-       ipa_ = IPAManager::createIPA(pipe_, 1, 1);<br>
+       std::unique_ptr<IPAProxy> ptr = IPAManager::createIPA(pipe_, 1, 1);<br>
+       ipa_ = std::unique_ptr<IPAProxyRPi>{static_cast<IPAProxyRPi*>(std::move(ptr).release())};<br>
+<br>
        if (!ipa_)<br>
                return -ENOENT;<br>
<br>
-       ipa_->queueFrameAction.connect(this, &RPiCameraData::queueFrameAction);<br>
+       ipa_->statsMetadataComplete.connect(this, &RPiCameraData::statsMetadataComplete);<br>
+       ipa_->runIsp.connect(this, &RPiCameraData::runIsp);<br>
+       ipa_->embeddedComplete.connect(this, &RPiCameraData::embeddedComplete);<br>
+       ipa_->setIsp.connect(this, &RPiCameraData::setIsp);<br>
+       ipa_->setStaggered.connect(this, &RPiCameraData::setStaggered);<br>
<br>
        IPASettings settings{<br>
                .configurationFile = ipa_->configurationFile(sensor_->model() + ".json")<br>
@@ -990,8 +1005,8 @@ int RPiCameraData::loadIPA()<br>
 int RPiCameraData::configureIPA()<br>
 {<br>
        std::map<unsigned int, IPAStream> streamConfig;<br>
-       std::map<unsigned int, const ControlInfoMap &> entityControls;<br>
-       IPAOperationData ipaConfig = {};<br>
+       std::map<unsigned int, ControlInfoMap> entityControls;<br>
+       RPiConfigInput ipaConfig;<br>
<br>
        /* Get the device format to pass to the IPA. */<br>
        V4L2DeviceFormat sensorFormat;<br>
@@ -1017,8 +1032,9 @@ int RPiCameraData::configureIPA()<br>
                        return -ENOMEM;<br>
<br>
                /* Allow the IPA to mmap the LS table via the file descriptor. */<br>
-               ipaConfig.operation = RPI_IPA_CONFIG_LS_TABLE;<br>
-               ipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };<br>
+               ipaConfig.op_ = RPI_IPA_CONFIG_LS_TABLE;<br>
+               ipaConfig.lsTableHandle_ = lsTable_;<br>
+               ipaConfig.lsTableHandleStatic_ = lsTable_.fd();<br>
        }<br>
<br>
        CameraSensorInfo sensorInfo = {};<br>
@@ -1029,105 +1045,92 @@ int RPiCameraData::configureIPA()<br>
        }<br>
<br>
        /* Ready the IPA - it must know about the sensor resolution. */<br>
-       IPAOperationData result;<br>
+       RPiConfigOutput result;<br>
<br>
        ipa_->configure(sensorInfo, streamConfig, entityControls, ipaConfig,<br>
                        &result);<br>
<br>
-       unsigned int resultIdx = 0;<br>
-       if (result.operation & RPI_IPA_CONFIG_STAGGERED_WRITE) {<br>
+       if (result.op_ & RPI_IPA_CONFIG_STAGGERED_WRITE) {<br>
+<br>
                /*<br>
                 * Setup our staggered control writer with the sensor default<br>
                 * gain and exposure delays.<br>
                 */<br>
                if (!staggeredCtrl_) {<br>
                        staggeredCtrl_.init(unicam_[Unicam::Image].dev(),<br>
-                                           { { V4L2_CID_ANALOGUE_GAIN, result.data[resultIdx++] },<br>
-                                             { V4L2_CID_EXPOSURE, result.data[resultIdx++] } });<br>
-                       sensorMetadata_ = result.data[resultIdx++];<br>
+                                       { { V4L2_CID_ANALOGUE_GAIN,<br>
+                                       result.staggeredWriteResult_.gainDelay_ },<br>
+                                       { V4L2_CID_EXPOSURE,<br>
+                                       result.staggeredWriteResult_.exposureDelay_ } });<br>
+                       sensorMetadata_ = result.staggeredWriteResult_.sensorMetadata_;<br>
+               }<br>
+<br>
+               if (result.op_ & RPI_IPA_CONFIG_SENSOR) {<br>
+                       const ControlList &ctrls = result.controls_;<br>
+                       if (!staggeredCtrl_.set(ctrls))<br>
+                               LOG(RPI, Error) << "V4L2 staggered set failed";<br>
                }<br>
-       }<br>
<br>
-       if (result.operation & RPI_IPA_CONFIG_SENSOR) {<br>
-               const ControlList &ctrls = result.controls[0];<br>
-               if (!staggeredCtrl_.set(ctrls))<br>
-                       LOG(RPI, Error) << "V4L2 staggered set failed";<br>
        }<br>
<br>
-       if (result.operation & RPI_IPA_CONFIG_DROP_FRAMES) {<br>
+       if (result.op_ & RPI_IPA_CONFIG_DROP_FRAMES) {<br>
                /* Configure the number of dropped frames required on startup. */<br>
-               dropFrameCount_ = result.data[resultIdx++];<br>
+               dropFrameCount_ = result.dropFrameCount_;<br>
        }<br>
<br>
        return 0;<br>
 }<br>
<br>
-void RPiCameraData::queueFrameAction([[maybe_unused]] unsigned int frame,<br>
-                                    const IPAOperationData &action)<br>
+void RPiCameraData::statsMetadataComplete(uint32_t bufferId, const ControlList &controls)<br>
 {<br>
-       /*<br>
-        * The following actions can be handled when the pipeline handler is in<br>
-        * a stopped state.<br>
-        */<br>
-       switch (action.operation) {<br>
-       case RPI_IPA_ACTION_V4L2_SET_STAGGERED: {<br>
-               const ControlList &controls = action.controls[0];<br>
-               if (!staggeredCtrl_.set(controls))<br>
-                       LOG(RPI, Error) << "V4L2 staggered set failed";<br>
-               goto done;<br>
-       }<br>
+       if (state_ == State::Stopped)<br>
+               handleState();<br>
<br>
-       case RPI_IPA_ACTION_V4L2_SET_ISP: {<br>
-               ControlList controls = action.controls[0];<br>
-               isp_[Isp::Input].dev()->setControls(&controls);<br>
-               goto done;<br>
-       }<br>
-       }<br>
+       FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);<br>
+<br>
+       handleStreamBuffer(buffer, &isp_[Isp::Stats]);<br>
+       /* Fill the Request metadata buffer with what the IPA has provided */<br>
+       requestQueue_.front()->metadata() = std::move(controls);<br>
+       state_ = State::IpaComplete;<br>
+       handleState();<br>
+}<br>
<br>
+void RPiCameraData::runIsp(uint32_t bufferId)<br>
+{<br>
        if (state_ == State::Stopped)<br>
-               goto done;<br>
+               handleState();<br>
<br>
-       /*<br>
-        * The following actions must not be handled when the pipeline handler<br>
-        * is in a stopped state.<br>
-        */<br>
-       switch (action.operation) {<br>
-       case RPI_IPA_ACTION_STATS_METADATA_COMPLETE: {<br>
-               unsigned int bufferId = action.data[0];<br>
-               FrameBuffer *buffer = isp_[Isp::Stats].getBuffers().at(bufferId);<br>
-<br>
-               handleStreamBuffer(buffer, &isp_[Isp::Stats]);<br>
-               /* Fill the Request metadata buffer with what the IPA has provided */<br>
-               requestQueue_.front()->metadata() = std::move(action.controls[0]);<br>
-               state_ = State::IpaComplete;<br>
-               break;<br>
-       }<br>
+       FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);<br>
<br>
-       case RPI_IPA_ACTION_EMBEDDED_COMPLETE: {<br>
-               unsigned int bufferId = action.data[0];<br>
-               FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);<br>
-               handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);<br>
-               break;<br>
-       }<br>
+       LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId<br>
+                       << ", timestamp: " << buffer->metadata().timestamp;<br>
<br>
-       case RPI_IPA_ACTION_RUN_ISP: {<br>
-               unsigned int bufferId = action.data[0];<br>
-               FrameBuffer *buffer = unicam_[Unicam::Image].getBuffers().at(bufferId);<br>
+       isp_[Isp::Input].queueBuffer(buffer);<br>
+       ispOutputCount_ = 0;<br>
+       handleState();<br>
+}<br>
<br>
-               LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId<br>
-                               << ", timestamp: " << buffer->metadata().timestamp;<br>
+void RPiCameraData::embeddedComplete(uint32_t bufferId)<br>
+{<br>
+       if (state_ == State::Stopped)<br>
+               handleState();<br>
<br>
-               isp_[Isp::Input].queueBuffer(buffer);<br>
-               ispOutputCount_ = 0;<br>
-               break;<br>
-       }<br>
+       FrameBuffer *buffer = unicam_[Unicam::Embedded].getBuffers().at(bufferId);<br>
+       handleStreamBuffer(buffer, &unicam_[Unicam::Embedded]);<br>
+       handleState();<br>
+}<br>
<br>
-       default:<br>
-               LOG(RPI, Error) << "Unknown action " << action.operation;<br>
-               break;<br>
-       }<br>
+void RPiCameraData::setIsp(const ControlList &controls)<br>
+{<br>
+       ControlList ctrls = controls;<br>
+       isp_[Isp::Input].dev()->setControls(&ctrls);<br>
+       handleState();<br>
+}<br>
<br>
-done:<br>
+void RPiCameraData::setStaggered(const ControlList &controls)<br>
+{<br>
+       if (!staggeredCtrl_.set(controls))<br>
+               LOG(RPI, Error) << "V4L2 staggered set failed";<br>
        handleState();<br>
 }<br>
<br>
@@ -1227,10 +1230,7 @@ void RPiCameraData::ispOutputDequeue(FrameBuffer *buffer)<br>
         * application until after the IPA signals so.<br>
         */<br>
        if (stream == &isp_[Isp::Stats]) {<br>
-               IPAOperationData op;<br>
-               op.operation = RPI_IPA_EVENT_SIGNAL_STAT_READY;<br>
-               op.data = { RPiBufferMask::STATS | static_cast<unsigned int>(index) };<br>
-               ipa_->processEvent(op);<br>
+               ipa_->signalStatReady(RPiBufferMask::STATS | static_cast<unsigned int>(index));<br>
        } else {<br>
                /* Any other ISP output can be handed back to the application now. */<br>
                handleStreamBuffer(buffer, stream);<br>
@@ -1403,7 +1403,6 @@ void RPiCameraData::checkRequestCompleted()<br>
 void RPiCameraData::tryRunPipeline()<br>
 {<br>
        FrameBuffer *bayerBuffer, *embeddedBuffer;<br>
-       IPAOperationData op;<br>
<br>
        /* If any of our request or buffer queues are empty, we cannot proceed. */<br>
        if (state_ != State::Idle || requestQueue_.empty() ||<br>
@@ -1454,9 +1453,7 @@ void RPiCameraData::tryRunPipeline()<br>
         * queue the ISP output buffer listed in the request to start the HW<br>
         * pipeline.<br>
         */<br>
-       op.operation = RPI_IPA_EVENT_QUEUE_REQUEST;<br>
-       op.controls = { request->controls() };<br>
-       ipa_->processEvent(op);<br>
+       ipa_->signalQueueRequest(request->controls());<br>
<br>
        /* Ready to use the buffers, pop them off the queue. */<br>
        bayerQueue_.pop();<br>
@@ -1472,10 +1469,10 @@ void RPiCameraData::tryRunPipeline()<br>
                        << " Bayer buffer id: " << bayerId<br>
                        << " Embedded buffer id: " << embeddedId;<br>
<br>
-       op.operation = RPI_IPA_EVENT_SIGNAL_ISP_PREPARE;<br>
-       op.data = { RPiBufferMask::EMBEDDED_DATA | embeddedId,<br>
-                   RPiBufferMask::BAYER_DATA | bayerId };<br>
-       ipa_->processEvent(op);<br>
+       RPiIspPreparePayload ispPrepare;<br>
+       ispPrepare.embeddedbufferId_ = RPiBufferMask::EMBEDDED_DATA | embeddedId;<br>
+       ispPrepare.bayerbufferId_ = RPiBufferMask::BAYER_DATA | bayerId;<br>
+       ipa_->signalIspPrepare(ispPrepare);<br>
 }<br>
<br>
 void RPiCameraData::tryFlushQueues()<br>
-- <br>
2.27.0<br>
<br>
_______________________________________________<br>
libcamera-devel mailing list<br>
<a href="mailto:libcamera-devel@lists.libcamera.org" target="_blank">libcamera-devel@lists.libcamera.org</a><br>
<a href="https://lists.libcamera.org/listinfo/libcamera-devel" rel="noreferrer" target="_blank">https://lists.libcamera.org/listinfo/libcamera-devel</a><br>
</blockquote></div><br clear="all"><div><br></div>-- <br><div dir="ltr" class="gmail_signature"><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr"><div><div dir="ltr">Cheers.<div>Hanlin Chen</div></div></div></div></div></div></div></div></div></div>