[libcamera-devel] [PATCH 28/38] libcamera: pipeline, ipa: raspberrypi: Use new data definition

Han-lin Chen hanlinchen at google.com
Mon Oct 5 10:33:59 CEST 2020


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



-- 
Cheers.
Hanlin Chen


More information about the libcamera-devel mailing list