[RFC,v3,21/22] libcamera: pipeline: Use `metadataAvailable()`
diff mbox series

Message ID 20251030165816.1095180-22-barnabas.pocze@ideasonboard.com
State New
Headers show
Series
  • libcamera: Add `MetadataList`
Related show

Commit Message

Barnabás Pőcze Oct. 30, 2025, 4:58 p.m. UTC
From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>

Use the newly introduced `metadataAvailable()` function to send metadata
items to the application.

Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
[Adjust commit message, adjust rpi changes.]
Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
---
changes in v2:
  * include rpi changes as well
---
 src/libcamera/pipeline/imx8-isi/imx8-isi.cpp  |  5 +---
 src/libcamera/pipeline/ipu3/ipu3.cpp          | 14 ++++-----
 src/libcamera/pipeline/mali-c55/mali-c55.cpp  |  2 +-
 src/libcamera/pipeline/rkisp1/rkisp1.cpp      |  7 ++---
 .../pipeline/rpi/common/pipeline_base.cpp     | 29 ++++++++++---------
 src/libcamera/pipeline/simple/simple.cpp      |  4 +--
 src/libcamera/pipeline/uvcvideo/uvcvideo.cpp  |  3 +-
 src/libcamera/pipeline/vimc/vimc.cpp          |  3 +-
 src/libcamera/pipeline/virtual/virtual.cpp    |  2 +-
 9 files changed, 32 insertions(+), 37 deletions(-)

Comments

Kieran Bingham Nov. 2, 2025, 3:49 p.m. UTC | #1
Quoting Barnabás Pőcze (2025-10-30 16:58:15)
> From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> 
> Use the newly introduced `metadataAvailable()` function to send metadata
> items to the application.
> 
> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
> [Adjust commit message, adjust rpi changes.]
> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
> ---
> changes in v2:
>   * include rpi changes as well
> ---
>  src/libcamera/pipeline/imx8-isi/imx8-isi.cpp  |  5 +---
>  src/libcamera/pipeline/ipu3/ipu3.cpp          | 14 ++++-----
>  src/libcamera/pipeline/mali-c55/mali-c55.cpp  |  2 +-
>  src/libcamera/pipeline/rkisp1/rkisp1.cpp      |  7 ++---
>  .../pipeline/rpi/common/pipeline_base.cpp     | 29 ++++++++++---------

Ack will be needed from RPi for this series.

Do you still see this series as RFC ? or is now a good time for RPi to
consider these? 

It seems like the sort of thing we could look to merge, but the series
itself is a lot to digest so a summary of implicications for RPi would
be helpful to make it easy for them to consider how it impacts the RPi
ecosystem.


Aside from that,


Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>


I see where the metadata setter is used here to batch things, I'll be
interested to see how well this is used - I almost wonder if setting
into a ControlList and then merging that would be easier to comprehend
than a lambda - but perhaps that's just because I've only looked at a
diff so far, not actual usage.


>  src/libcamera/pipeline/simple/simple.cpp      |  4 +--
>  src/libcamera/pipeline/uvcvideo/uvcvideo.cpp  |  3 +-
>  src/libcamera/pipeline/vimc/vimc.cpp          |  3 +-
>  src/libcamera/pipeline/virtual/virtual.cpp    |  2 +-
>  9 files changed, 32 insertions(+), 37 deletions(-)
> 
> diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> index fbad880b23..4353a2e7cf 100644
> --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
> @@ -1141,10 +1141,7 @@ void PipelineHandlerISI::bufferReady(FrameBuffer *buffer)
>         Request *request = buffer->request();
>  
>         /* Record the sensor's timestamp in the request metadata. */
> -       ControlList &metadata = request->metadata();
> -       if (!metadata.contains(controls::SensorTimestamp.id()))
> -               metadata.set(controls::SensorTimestamp,
> -                            buffer->metadata().timestamp);
> +       metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>  
>         completeBuffer(request, buffer);
>         if (request->hasPendingBuffers())
> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
> index 13dbdb6268..9238f4400e 100644
> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
> @@ -1254,7 +1254,7 @@ void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)
>                 return;
>  
>         Request *request = info->request;
> -       request->metadata().merge(metadata);
> +       pipe()->metadataAvailable(request, metadata);
>  
>         info->metadataProcessed = true;
>         if (frameInfos_.tryComplete(info))
> @@ -1281,12 +1281,14 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
>  
>         pipe()->completeBuffer(request, buffer);
>  
> -       request->metadata().set(controls::draft::PipelineDepth, 3);
> +       pipe()->metadataAvailable(request, controls::draft::PipelineDepth, 3);
> +
>         /* \todo Actually apply the scaler crop region to the ImgU. */
>         const auto &scalerCrop = request->controls().get(controls::ScalerCrop);
>         if (scalerCrop)
>                 cropRegion_ = *scalerCrop;
> -       request->metadata().set(controls::ScalerCrop, cropRegion_);
> +
> +       pipe()->metadataAvailable(request, controls::ScalerCrop, cropRegion_);
>  
>         if (frameInfos_.tryComplete(info))
>                 pipe()->completeRequest(request);
> @@ -1326,8 +1328,7 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
>          * \todo The sensor timestamp should be better estimated by connecting
>          * to the V4L2Device::frameStart signal.
>          */
> -       request->metadata().set(controls::SensorTimestamp,
> -                               buffer->metadata().timestamp);
> +       pipe()->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>  
>         info->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence);
>  
> @@ -1421,8 +1422,7 @@ void IPU3CameraData::frameStart(uint32_t sequence)
>                 return;
>         }
>  
> -       request->metadata().set(controls::draft::TestPatternMode,
> -                               *testPatternMode);
> +       pipe()->metadataAvailable(request, controls::draft::TestPatternMode, *testPatternMode);
>  }
>  
>  REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3, "ipu3")
> diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> index 938c5b2890..96eb9ab07f 100644
> --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
> @@ -1528,7 +1528,7 @@ void PipelineHandlerMaliC55::statsProcessed(unsigned int requestId,
>         MaliC55FrameInfo &frameInfo = frameInfoMap_[requestId];
>  
>         frameInfo.statsDone = true;
> -       frameInfo.request->metadata().merge(metadata);
> +       metadataAvailable(frameInfo.request, metadata);
>  
>         tryComplete(&frameInfo);
>  }
> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> index 002a44f304..a7d56f1a3e 100644
> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
> @@ -452,7 +452,7 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta
>         if (!info)
>                 return;
>  
> -       info->request->metadata().merge(metadata);
> +       pipe()->metadataAvailable(info->request, metadata);
>         info->metadataProcessed = true;
>  
>         pipe()->tryCompleteRequest(info);
> @@ -1520,8 +1520,7 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)
>                  * \todo The sensor timestamp should be better estimated by connecting
>                  * to the V4L2Device::frameStart signal.
>                  */
> -               request->metadata().set(controls::SensorTimestamp,
> -                                       metadata.timestamp);
> +               metadataAvailable(request, controls::SensorTimestamp, metadata.timestamp);
>  
>                 if (isRaw_) {
>                         const ControlList &ctrls =
> @@ -1604,7 +1603,7 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)
>                 LOG(RkISP1, Error) << "Cannot queue buffers to dewarper: "
>                                    << strerror(-ret);
>  
> -       request->metadata().set(controls::ScalerCrop, activeCrop_.value());
> +       metadataAvailable(request, controls::ScalerCrop, activeCrop_.value());
>  }
>  
>  void PipelineHandlerRkISP1::dewarpBufferReady(FrameBuffer *buffer)
> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> index 87ce290225..bf9404db92 100644
> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
> @@ -1227,7 +1227,7 @@ void CameraData::metadataReady(const ControlList &metadata)
>         /* Add to the Request metadata buffer what the IPA has provided. */
>         /* Last thing to do is to fill up the request metadata. */
>         Request *request = requestQueue_.front();
> -       request->metadata().merge(metadata);
> +       pipe()->metadataAvailable(request, metadata);
>  
>         /*
>          * Inform the sensor of the latest colour gains if it has the
> @@ -1497,23 +1497,24 @@ void CameraData::checkRequestCompleted()
>  
>  void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request *request)
>  {
> -       if (auto x = bufferControls.get(controls::SensorTimestamp))
> -               request->metadata().set(controls::SensorTimestamp, *x);
> -       if (auto x = bufferControls.get(controls::FrameWallClock))
> -               request->metadata().set(controls::FrameWallClock, *x);
> +       pipe()->metadataAvailable(request, [&](auto set) {
> +               if (auto x = bufferControls.get(controls::SensorTimestamp))
> +                       set(controls::SensorTimestamp, *x);
> +               if (auto x = bufferControls.get(controls::FrameWallClock))
> +                       set(controls::FrameWallClock, *x);
>  
> -       if (cropParams_.size()) {
> -               std::vector<Rectangle> crops;
> +               if (cropParams_.size()) {
> +                       std::vector<Rectangle> crops;
>  
> -               for (auto const &[k, v] : cropParams_)
> -                       crops.push_back(scaleIspCrop(v.ispCrop));
> +                       for (auto const &[k, v] : cropParams_)
> +                               crops.push_back(scaleIspCrop(v.ispCrop));
>  
> -               request->metadata().set(controls::ScalerCrop, crops[0]);
> -               if (crops.size() > 1) {
> -                       request->metadata().set(controls::rpi::ScalerCrops,
> -                                               Span<const Rectangle>(crops.data(), crops.size()));
> +                       set(controls::ScalerCrop, crops[0]);
> +
> +                       if (crops.size() > 1)
> +                               set(controls::rpi::ScalerCrops, { crops.data(), crops.size() });
>                 }
> -       }
> +       });
>  }
>  
>  } /* namespace libcamera */
> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
> index 312f35ad15..5959d94d43 100644
> --- a/src/libcamera/pipeline/simple/simple.cpp
> +++ b/src/libcamera/pipeline/simple/simple.cpp
> @@ -919,7 +919,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
>         }
>  
>         if (request)
> -               request->metadata().set(controls::SensorTimestamp,
> +               pipe->metadataAvailable(request, controls::SensorTimestamp,
>                                         buffer->metadata().timestamp);
>  
>         /*
> @@ -1007,7 +1007,7 @@ void SimpleCameraData::metadataReady(uint32_t frame, const ControlList &metadata
>         if (!info)
>                 return;
>  
> -       info->request->metadata().merge(metadata);
> +       pipe()->metadataAvailable(info->request, metadata);
>         info->metadataProcessed = true;
>         tryCompleteRequest(info->request);
>  }
> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> index 59fb4bd5c9..8cea94721d 100644
> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
> @@ -894,8 +894,7 @@ void UVCCameraData::imageBufferReady(FrameBuffer *buffer)
>         Request *request = buffer->request();
>  
>         /* \todo Use the UVC metadata to calculate a more precise timestamp */
> -       request->metadata().set(controls::SensorTimestamp,
> -                               buffer->metadata().timestamp);
> +       pipe()->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>  
>         pipe()->completeBuffer(request, buffer);
>         pipe()->completeRequest(request);
> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
> index 1b6880a5dc..8a3a63e656 100644
> --- a/src/libcamera/pipeline/vimc/vimc.cpp
> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
> @@ -620,8 +620,7 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
>         }
>  
>         /* Record the sensor's timestamp in the request metadata. */
> -       request->metadata().set(controls::SensorTimestamp,
> -                               buffer->metadata().timestamp);
> +       pipe->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>  
>         pipe->completeBuffer(request, buffer);
>         pipe->completeRequest(request);
> diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
> index 23eae852f7..c578560854 100644
> --- a/src/libcamera/pipeline/virtual/virtual.cpp
> +++ b/src/libcamera/pipeline/virtual/virtual.cpp
> @@ -354,7 +354,7 @@ int PipelineHandlerVirtual::queueRequestDevice([[maybe_unused]] Camera *camera,
>         VirtualCameraData *data = cameraData(camera);
>         const auto timestamp = currentTimestamp();
>  
> -       request->metadata().set(controls::SensorTimestamp, timestamp);
> +       metadataAvailable(request, controls::SensorTimestamp, timestamp);
>         data->invokeMethod(&VirtualCameraData::processRequest,
>                            ConnectionTypeQueued, request);
>  
> -- 
> 2.51.1
>
Barnabás Pőcze Nov. 3, 2025, 9:28 a.m. UTC | #2
Hi

2025. 11. 02. 16:49 keltezéssel, Kieran Bingham írta:
> Quoting Barnabás Pőcze (2025-10-30 16:58:15)
>> From: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>>
>> Use the newly introduced `metadataAvailable()` function to send metadata
>> items to the application.
>>
>> Signed-off-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
>> [Adjust commit message, adjust rpi changes.]
>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
>> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
>> ---
>> changes in v2:
>>    * include rpi changes as well
>> ---
>>   src/libcamera/pipeline/imx8-isi/imx8-isi.cpp  |  5 +---
>>   src/libcamera/pipeline/ipu3/ipu3.cpp          | 14 ++++-----
>>   src/libcamera/pipeline/mali-c55/mali-c55.cpp  |  2 +-
>>   src/libcamera/pipeline/rkisp1/rkisp1.cpp      |  7 ++---
>>   .../pipeline/rpi/common/pipeline_base.cpp     | 29 ++++++++++---------
> 
> Ack will be needed from RPi for this series.
> 
> Do you still see this series as RFC ? or is now a good time for RPi to
> consider these?
> 
> It seems like the sort of thing we could look to merge, but the series
> itself is a lot to digest so a summary of implicications for RPi would
> be helpful to make it easy for them to consider how it impacts the RPi
> ecosystem.
> 
> 
> Aside from that,
> 
> 
> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
> 
> 
> I see where the metadata setter is used here to batch things, I'll be
> interested to see how well this is used - I almost wonder if setting
> into a ControlList and then merging that would be easier to comprehend
> than a lambda - but perhaps that's just because I've only looked at a
> diff so far, not actual usage.

The other two overloads both have problems when reporting multiple items
in quick succession: the ControlList one naturally needs a ControlList to
be constructed, an the singleton one will notify the application after every
single one. So the lambda approach is an optimization to allow arbitrary
logic to determine which controls to report, while only emitting a single
notification at the end.



> 
> 
>>   src/libcamera/pipeline/simple/simple.cpp      |  4 +--
>>   src/libcamera/pipeline/uvcvideo/uvcvideo.cpp  |  3 +-
>>   src/libcamera/pipeline/vimc/vimc.cpp          |  3 +-
>>   src/libcamera/pipeline/virtual/virtual.cpp    |  2 +-
>>   9 files changed, 32 insertions(+), 37 deletions(-)
>>
>> diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
>> index fbad880b23..4353a2e7cf 100644
>> --- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
>> +++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
>> @@ -1141,10 +1141,7 @@ void PipelineHandlerISI::bufferReady(FrameBuffer *buffer)
>>          Request *request = buffer->request();
>>   
>>          /* Record the sensor's timestamp in the request metadata. */
>> -       ControlList &metadata = request->metadata();
>> -       if (!metadata.contains(controls::SensorTimestamp.id()))
>> -               metadata.set(controls::SensorTimestamp,
>> -                            buffer->metadata().timestamp);
>> +       metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>>   
>>          completeBuffer(request, buffer);
>>          if (request->hasPendingBuffers())
>> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> index 13dbdb6268..9238f4400e 100644
>> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp
>> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
>> @@ -1254,7 +1254,7 @@ void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)
>>                  return;
>>   
>>          Request *request = info->request;
>> -       request->metadata().merge(metadata);
>> +       pipe()->metadataAvailable(request, metadata);
>>   
>>          info->metadataProcessed = true;
>>          if (frameInfos_.tryComplete(info))
>> @@ -1281,12 +1281,14 @@ void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
>>   
>>          pipe()->completeBuffer(request, buffer);
>>   
>> -       request->metadata().set(controls::draft::PipelineDepth, 3);
>> +       pipe()->metadataAvailable(request, controls::draft::PipelineDepth, 3);
>> +
>>          /* \todo Actually apply the scaler crop region to the ImgU. */
>>          const auto &scalerCrop = request->controls().get(controls::ScalerCrop);
>>          if (scalerCrop)
>>                  cropRegion_ = *scalerCrop;
>> -       request->metadata().set(controls::ScalerCrop, cropRegion_);
>> +
>> +       pipe()->metadataAvailable(request, controls::ScalerCrop, cropRegion_);
>>   
>>          if (frameInfos_.tryComplete(info))
>>                  pipe()->completeRequest(request);
>> @@ -1326,8 +1328,7 @@ void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
>>           * \todo The sensor timestamp should be better estimated by connecting
>>           * to the V4L2Device::frameStart signal.
>>           */
>> -       request->metadata().set(controls::SensorTimestamp,
>> -                               buffer->metadata().timestamp);
>> +       pipe()->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>>   
>>          info->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence);
>>   
>> @@ -1421,8 +1422,7 @@ void IPU3CameraData::frameStart(uint32_t sequence)
>>                  return;
>>          }
>>   
>> -       request->metadata().set(controls::draft::TestPatternMode,
>> -                               *testPatternMode);
>> +       pipe()->metadataAvailable(request, controls::draft::TestPatternMode, *testPatternMode);
>>   }
>>   
>>   REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3, "ipu3")
>> diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
>> index 938c5b2890..96eb9ab07f 100644
>> --- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
>> +++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
>> @@ -1528,7 +1528,7 @@ void PipelineHandlerMaliC55::statsProcessed(unsigned int requestId,
>>          MaliC55FrameInfo &frameInfo = frameInfoMap_[requestId];
>>   
>>          frameInfo.statsDone = true;
>> -       frameInfo.request->metadata().merge(metadata);
>> +       metadataAvailable(frameInfo.request, metadata);
>>   
>>          tryComplete(&frameInfo);
>>   }
>> diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
>> index 002a44f304..a7d56f1a3e 100644
>> --- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
>> +++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
>> @@ -452,7 +452,7 @@ void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta
>>          if (!info)
>>                  return;
>>   
>> -       info->request->metadata().merge(metadata);
>> +       pipe()->metadataAvailable(info->request, metadata);
>>          info->metadataProcessed = true;
>>   
>>          pipe()->tryCompleteRequest(info);
>> @@ -1520,8 +1520,7 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)
>>                   * \todo The sensor timestamp should be better estimated by connecting
>>                   * to the V4L2Device::frameStart signal.
>>                   */
>> -               request->metadata().set(controls::SensorTimestamp,
>> -                                       metadata.timestamp);
>> +               metadataAvailable(request, controls::SensorTimestamp, metadata.timestamp);
>>   
>>                  if (isRaw_) {
>>                          const ControlList &ctrls =
>> @@ -1604,7 +1603,7 @@ void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)
>>                  LOG(RkISP1, Error) << "Cannot queue buffers to dewarper: "
>>                                     << strerror(-ret);
>>   
>> -       request->metadata().set(controls::ScalerCrop, activeCrop_.value());
>> +       metadataAvailable(request, controls::ScalerCrop, activeCrop_.value());
>>   }
>>   
>>   void PipelineHandlerRkISP1::dewarpBufferReady(FrameBuffer *buffer)
>> diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>> index 87ce290225..bf9404db92 100644
>> --- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>> +++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
>> @@ -1227,7 +1227,7 @@ void CameraData::metadataReady(const ControlList &metadata)
>>          /* Add to the Request metadata buffer what the IPA has provided. */
>>          /* Last thing to do is to fill up the request metadata. */
>>          Request *request = requestQueue_.front();
>> -       request->metadata().merge(metadata);
>> +       pipe()->metadataAvailable(request, metadata);
>>   
>>          /*
>>           * Inform the sensor of the latest colour gains if it has the
>> @@ -1497,23 +1497,24 @@ void CameraData::checkRequestCompleted()
>>   
>>   void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request *request)
>>   {
>> -       if (auto x = bufferControls.get(controls::SensorTimestamp))
>> -               request->metadata().set(controls::SensorTimestamp, *x);
>> -       if (auto x = bufferControls.get(controls::FrameWallClock))
>> -               request->metadata().set(controls::FrameWallClock, *x);
>> +       pipe()->metadataAvailable(request, [&](auto set) {
>> +               if (auto x = bufferControls.get(controls::SensorTimestamp))
>> +                       set(controls::SensorTimestamp, *x);
>> +               if (auto x = bufferControls.get(controls::FrameWallClock))
>> +                       set(controls::FrameWallClock, *x);
>>   
>> -       if (cropParams_.size()) {
>> -               std::vector<Rectangle> crops;
>> +               if (cropParams_.size()) {
>> +                       std::vector<Rectangle> crops;
>>   
>> -               for (auto const &[k, v] : cropParams_)
>> -                       crops.push_back(scaleIspCrop(v.ispCrop));
>> +                       for (auto const &[k, v] : cropParams_)
>> +                               crops.push_back(scaleIspCrop(v.ispCrop));
>>   
>> -               request->metadata().set(controls::ScalerCrop, crops[0]);
>> -               if (crops.size() > 1) {
>> -                       request->metadata().set(controls::rpi::ScalerCrops,
>> -                                               Span<const Rectangle>(crops.data(), crops.size()));
>> +                       set(controls::ScalerCrop, crops[0]);
>> +
>> +                       if (crops.size() > 1)
>> +                               set(controls::rpi::ScalerCrops, { crops.data(), crops.size() });
>>                  }
>> -       }
>> +       });
>>   }
>>   
>>   } /* namespace libcamera */
>> diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
>> index 312f35ad15..5959d94d43 100644
>> --- a/src/libcamera/pipeline/simple/simple.cpp
>> +++ b/src/libcamera/pipeline/simple/simple.cpp
>> @@ -919,7 +919,7 @@ void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
>>          }
>>   
>>          if (request)
>> -               request->metadata().set(controls::SensorTimestamp,
>> +               pipe->metadataAvailable(request, controls::SensorTimestamp,
>>                                          buffer->metadata().timestamp);
>>   
>>          /*
>> @@ -1007,7 +1007,7 @@ void SimpleCameraData::metadataReady(uint32_t frame, const ControlList &metadata
>>          if (!info)
>>                  return;
>>   
>> -       info->request->metadata().merge(metadata);
>> +       pipe()->metadataAvailable(info->request, metadata);
>>          info->metadataProcessed = true;
>>          tryCompleteRequest(info->request);
>>   }
>> diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> index 59fb4bd5c9..8cea94721d 100644
>> --- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> +++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
>> @@ -894,8 +894,7 @@ void UVCCameraData::imageBufferReady(FrameBuffer *buffer)
>>          Request *request = buffer->request();
>>   
>>          /* \todo Use the UVC metadata to calculate a more precise timestamp */
>> -       request->metadata().set(controls::SensorTimestamp,
>> -                               buffer->metadata().timestamp);
>> +       pipe()->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>>   
>>          pipe()->completeBuffer(request, buffer);
>>          pipe()->completeRequest(request);
>> diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
>> index 1b6880a5dc..8a3a63e656 100644
>> --- a/src/libcamera/pipeline/vimc/vimc.cpp
>> +++ b/src/libcamera/pipeline/vimc/vimc.cpp
>> @@ -620,8 +620,7 @@ void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
>>          }
>>   
>>          /* Record the sensor's timestamp in the request metadata. */
>> -       request->metadata().set(controls::SensorTimestamp,
>> -                               buffer->metadata().timestamp);
>> +       pipe->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
>>   
>>          pipe->completeBuffer(request, buffer);
>>          pipe->completeRequest(request);
>> diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
>> index 23eae852f7..c578560854 100644
>> --- a/src/libcamera/pipeline/virtual/virtual.cpp
>> +++ b/src/libcamera/pipeline/virtual/virtual.cpp
>> @@ -354,7 +354,7 @@ int PipelineHandlerVirtual::queueRequestDevice([[maybe_unused]] Camera *camera,
>>          VirtualCameraData *data = cameraData(camera);
>>          const auto timestamp = currentTimestamp();
>>   
>> -       request->metadata().set(controls::SensorTimestamp, timestamp);
>> +       metadataAvailable(request, controls::SensorTimestamp, timestamp);
>>          data->invokeMethod(&VirtualCameraData::processRequest,
>>                             ConnectionTypeQueued, request);
>>   
>> -- 
>> 2.51.1
>>

Patch
diff mbox series

diff --git a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
index fbad880b23..4353a2e7cf 100644
--- a/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
+++ b/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
@@ -1141,10 +1141,7 @@  void PipelineHandlerISI::bufferReady(FrameBuffer *buffer)
 	Request *request = buffer->request();
 
 	/* Record the sensor's timestamp in the request metadata. */
-	ControlList &metadata = request->metadata();
-	if (!metadata.contains(controls::SensorTimestamp.id()))
-		metadata.set(controls::SensorTimestamp,
-			     buffer->metadata().timestamp);
+	metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
 
 	completeBuffer(request, buffer);
 	if (request->hasPendingBuffers())
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 13dbdb6268..9238f4400e 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -1254,7 +1254,7 @@  void IPU3CameraData::metadataReady(unsigned int id, const ControlList &metadata)
 		return;
 
 	Request *request = info->request;
-	request->metadata().merge(metadata);
+	pipe()->metadataAvailable(request, metadata);
 
 	info->metadataProcessed = true;
 	if (frameInfos_.tryComplete(info))
@@ -1281,12 +1281,14 @@  void IPU3CameraData::imguOutputBufferReady(FrameBuffer *buffer)
 
 	pipe()->completeBuffer(request, buffer);
 
-	request->metadata().set(controls::draft::PipelineDepth, 3);
+	pipe()->metadataAvailable(request, controls::draft::PipelineDepth, 3);
+
 	/* \todo Actually apply the scaler crop region to the ImgU. */
 	const auto &scalerCrop = request->controls().get(controls::ScalerCrop);
 	if (scalerCrop)
 		cropRegion_ = *scalerCrop;
-	request->metadata().set(controls::ScalerCrop, cropRegion_);
+
+	pipe()->metadataAvailable(request, controls::ScalerCrop, cropRegion_);
 
 	if (frameInfos_.tryComplete(info))
 		pipe()->completeRequest(request);
@@ -1326,8 +1328,7 @@  void IPU3CameraData::cio2BufferReady(FrameBuffer *buffer)
 	 * \todo The sensor timestamp should be better estimated by connecting
 	 * to the V4L2Device::frameStart signal.
 	 */
-	request->metadata().set(controls::SensorTimestamp,
-				buffer->metadata().timestamp);
+	pipe()->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
 
 	info->effectiveSensorControls = delayedCtrls_->get(buffer->metadata().sequence);
 
@@ -1421,8 +1422,7 @@  void IPU3CameraData::frameStart(uint32_t sequence)
 		return;
 	}
 
-	request->metadata().set(controls::draft::TestPatternMode,
-				*testPatternMode);
+	pipe()->metadataAvailable(request, controls::draft::TestPatternMode, *testPatternMode);
 }
 
 REGISTER_PIPELINE_HANDLER(PipelineHandlerIPU3, "ipu3")
diff --git a/src/libcamera/pipeline/mali-c55/mali-c55.cpp b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
index 938c5b2890..96eb9ab07f 100644
--- a/src/libcamera/pipeline/mali-c55/mali-c55.cpp
+++ b/src/libcamera/pipeline/mali-c55/mali-c55.cpp
@@ -1528,7 +1528,7 @@  void PipelineHandlerMaliC55::statsProcessed(unsigned int requestId,
 	MaliC55FrameInfo &frameInfo = frameInfoMap_[requestId];
 
 	frameInfo.statsDone = true;
-	frameInfo.request->metadata().merge(metadata);
+	metadataAvailable(frameInfo.request, metadata);
 
 	tryComplete(&frameInfo);
 }
diff --git a/src/libcamera/pipeline/rkisp1/rkisp1.cpp b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
index 002a44f304..a7d56f1a3e 100644
--- a/src/libcamera/pipeline/rkisp1/rkisp1.cpp
+++ b/src/libcamera/pipeline/rkisp1/rkisp1.cpp
@@ -452,7 +452,7 @@  void RkISP1CameraData::metadataReady(unsigned int frame, const ControlList &meta
 	if (!info)
 		return;
 
-	info->request->metadata().merge(metadata);
+	pipe()->metadataAvailable(info->request, metadata);
 	info->metadataProcessed = true;
 
 	pipe()->tryCompleteRequest(info);
@@ -1520,8 +1520,7 @@  void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)
 		 * \todo The sensor timestamp should be better estimated by connecting
 		 * to the V4L2Device::frameStart signal.
 		 */
-		request->metadata().set(controls::SensorTimestamp,
-					metadata.timestamp);
+		metadataAvailable(request, controls::SensorTimestamp, metadata.timestamp);
 
 		if (isRaw_) {
 			const ControlList &ctrls =
@@ -1604,7 +1603,7 @@  void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)
 		LOG(RkISP1, Error) << "Cannot queue buffers to dewarper: "
 				   << strerror(-ret);
 
-	request->metadata().set(controls::ScalerCrop, activeCrop_.value());
+	metadataAvailable(request, controls::ScalerCrop, activeCrop_.value());
 }
 
 void PipelineHandlerRkISP1::dewarpBufferReady(FrameBuffer *buffer)
diff --git a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
index 87ce290225..bf9404db92 100644
--- a/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
+++ b/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
@@ -1227,7 +1227,7 @@  void CameraData::metadataReady(const ControlList &metadata)
 	/* Add to the Request metadata buffer what the IPA has provided. */
 	/* Last thing to do is to fill up the request metadata. */
 	Request *request = requestQueue_.front();
-	request->metadata().merge(metadata);
+	pipe()->metadataAvailable(request, metadata);
 
 	/*
 	 * Inform the sensor of the latest colour gains if it has the
@@ -1497,23 +1497,24 @@  void CameraData::checkRequestCompleted()
 
 void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request *request)
 {
-	if (auto x = bufferControls.get(controls::SensorTimestamp))
-		request->metadata().set(controls::SensorTimestamp, *x);
-	if (auto x = bufferControls.get(controls::FrameWallClock))
-		request->metadata().set(controls::FrameWallClock, *x);
+	pipe()->metadataAvailable(request, [&](auto set) {
+		if (auto x = bufferControls.get(controls::SensorTimestamp))
+			set(controls::SensorTimestamp, *x);
+		if (auto x = bufferControls.get(controls::FrameWallClock))
+			set(controls::FrameWallClock, *x);
 
-	if (cropParams_.size()) {
-		std::vector<Rectangle> crops;
+		if (cropParams_.size()) {
+			std::vector<Rectangle> crops;
 
-		for (auto const &[k, v] : cropParams_)
-			crops.push_back(scaleIspCrop(v.ispCrop));
+			for (auto const &[k, v] : cropParams_)
+				crops.push_back(scaleIspCrop(v.ispCrop));
 
-		request->metadata().set(controls::ScalerCrop, crops[0]);
-		if (crops.size() > 1) {
-			request->metadata().set(controls::rpi::ScalerCrops,
-						Span<const Rectangle>(crops.data(), crops.size()));
+			set(controls::ScalerCrop, crops[0]);
+
+			if (crops.size() > 1)
+				set(controls::rpi::ScalerCrops, { crops.data(), crops.size() });
 		}
-	}
+	});
 }
 
 } /* namespace libcamera */
diff --git a/src/libcamera/pipeline/simple/simple.cpp b/src/libcamera/pipeline/simple/simple.cpp
index 312f35ad15..5959d94d43 100644
--- a/src/libcamera/pipeline/simple/simple.cpp
+++ b/src/libcamera/pipeline/simple/simple.cpp
@@ -919,7 +919,7 @@  void SimpleCameraData::imageBufferReady(FrameBuffer *buffer)
 	}
 
 	if (request)
-		request->metadata().set(controls::SensorTimestamp,
+		pipe->metadataAvailable(request, controls::SensorTimestamp,
 					buffer->metadata().timestamp);
 
 	/*
@@ -1007,7 +1007,7 @@  void SimpleCameraData::metadataReady(uint32_t frame, const ControlList &metadata
 	if (!info)
 		return;
 
-	info->request->metadata().merge(metadata);
+	pipe()->metadataAvailable(info->request, metadata);
 	info->metadataProcessed = true;
 	tryCompleteRequest(info->request);
 }
diff --git a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
index 59fb4bd5c9..8cea94721d 100644
--- a/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
@@ -894,8 +894,7 @@  void UVCCameraData::imageBufferReady(FrameBuffer *buffer)
 	Request *request = buffer->request();
 
 	/* \todo Use the UVC metadata to calculate a more precise timestamp */
-	request->metadata().set(controls::SensorTimestamp,
-				buffer->metadata().timestamp);
+	pipe()->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
 
 	pipe()->completeBuffer(request, buffer);
 	pipe()->completeRequest(request);
diff --git a/src/libcamera/pipeline/vimc/vimc.cpp b/src/libcamera/pipeline/vimc/vimc.cpp
index 1b6880a5dc..8a3a63e656 100644
--- a/src/libcamera/pipeline/vimc/vimc.cpp
+++ b/src/libcamera/pipeline/vimc/vimc.cpp
@@ -620,8 +620,7 @@  void VimcCameraData::imageBufferReady(FrameBuffer *buffer)
 	}
 
 	/* Record the sensor's timestamp in the request metadata. */
-	request->metadata().set(controls::SensorTimestamp,
-				buffer->metadata().timestamp);
+	pipe->metadataAvailable(request, controls::SensorTimestamp, buffer->metadata().timestamp);
 
 	pipe->completeBuffer(request, buffer);
 	pipe->completeRequest(request);
diff --git a/src/libcamera/pipeline/virtual/virtual.cpp b/src/libcamera/pipeline/virtual/virtual.cpp
index 23eae852f7..c578560854 100644
--- a/src/libcamera/pipeline/virtual/virtual.cpp
+++ b/src/libcamera/pipeline/virtual/virtual.cpp
@@ -354,7 +354,7 @@  int PipelineHandlerVirtual::queueRequestDevice([[maybe_unused]] Camera *camera,
 	VirtualCameraData *data = cameraData(camera);
 	const auto timestamp = currentTimestamp();
 
-	request->metadata().set(controls::SensorTimestamp, timestamp);
+	metadataAvailable(request, controls::SensorTimestamp, timestamp);
 	data->invokeMethod(&VirtualCameraData::processRequest,
 			   ConnectionTypeQueued, request);