[{"id":34579,"web_url":"https://patchwork.libcamera.org/comment/34579/","msgid":"<2eodsaljfjnurqtq2gmflhxhfasxsz47iovpmyk7vjpsgkiqqi@gdazvfeqcsbu>","date":"2025-06-19T14:04:13","subject":"Re: [RFC PATCH v1 23/23] treewide: Use `Request::metadata2()`","submitter":{"id":143,"url":"https://patchwork.libcamera.org/api/people/143/","name":"Jacopo Mondi","email":"jacopo.mondi@ideasonboard.com"},"content":"Hi Barnabás\n\nOn Fri, Jun 06, 2025 at 06:41:56PM +0200, Barnabás Pőcze wrote:\n> Apart from a few exceptions, make everything use the new metadata list\n> of a request to access metadata items. After this change the only\n> thing remaining is to remove the exceptional uses, remove `Request::metadata()`\n> altogether, and finally rename `Request::metadata2()`.\n\nThis is the most intersting part indeed.. replacing\n\nControlList Request::metadata()\nwith\nMetadataList Request::metadata()\n\nThen we will remove all usages of \"ControlList Request::metadata()\" in\nthe library code base and only operate on a MetadataList.\n\nit's an ABI breaking change, so let me cc kieran to make sure he's\naware of this. I wonder if we need a plan to handle an interim period\nmaybe by keeping \"ControlList metadata()\" around for one more release\nafter this series will be merged and notifying to applications that\nthey should use \"MetadataList metadata2()\" instead ?\n\nIf I'm not mistaken, even after this series, once a Request completes\nboth metadata() and metadata2() will contain the same metadata list,\nright ?\n\n>\n> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n> ---\n>  src/android/camera_device.cpp              | 4 ++--\n>  src/apps/cam/file_sink.cpp                 | 4 ++--\n>  src/apps/cam/file_sink.h                   | 4 ++--\n>  src/apps/common/dng_writer.cpp             | 2 +-\n>  src/apps/common/dng_writer.h               | 4 ++--\n>  src/apps/qcam/main_window.cpp              | 4 ++--\n>  src/apps/qcam/main_window.h                | 4 ++--\n>  src/gstreamer/gstlibcamera-controls.cpp.in | 4 ++--\n>  src/gstreamer/gstlibcamerasrc.cpp          | 2 +-\n>  src/libcamera/pipeline/ipu3/ipu3.cpp       | 2 +-\n>  10 files changed, 17 insertions(+), 17 deletions(-)\n>\n> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n> index 80ff248c2..b8c6ddf84 100644\n> --- a/src/android/camera_device.cpp\n> +++ b/src/android/camera_device.cpp\n> @@ -1187,7 +1187,7 @@ void CameraDevice::requestComplete(Request *request)\n>  \t * \\todo The shutter event notification should be sent to the framework\n>  \t * as soon as possible, earlier than request completion time.\n>  \t */\n> -\tuint64_t sensorTimestamp = static_cast<uint64_t>(request->metadata()\n> +\tuint64_t sensorTimestamp = static_cast<uint64_t>(request->metadata2()\n>  \t\t\t\t\t\t\t\t .get(controls::SensorTimestamp)\n>  \t\t\t\t\t\t\t\t .value_or(0));\n>  \tnotifyShutter(descriptor->frameNumber_, sensorTimestamp);\n> @@ -1423,7 +1423,7 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream,\n>  std::unique_ptr<CameraMetadata>\n>  CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) const\n>  {\n> -\tconst ControlList &metadata = descriptor.request_->metadata();\n> +\tconst MetadataList &metadata = descriptor.request_->metadata2();\n>  \tconst CameraMetadata &settings = descriptor.settings_;\n>  \tcamera_metadata_ro_entry_t entry;\n>  \tbool found;\n> diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp\n> index 65794a2f9..1cc1b2b12 100644\n> --- a/src/apps/cam/file_sink.cpp\n> +++ b/src/apps/cam/file_sink.cpp\n> @@ -96,13 +96,13 @@ void FileSink::mapBuffer(FrameBuffer *buffer)\n>  bool FileSink::processRequest(Request *request)\n>  {\n>  \tfor (auto [stream, buffer] : request->buffers())\n> -\t\twriteBuffer(stream, buffer, request->metadata());\n> +\t\twriteBuffer(stream, buffer, request->metadata2());\n>\n>  \treturn true;\n>  }\n>\n>  void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer,\n> -\t\t\t   [[maybe_unused]] const ControlList &metadata)\n> +\t\t\t   [[maybe_unused]] const MetadataList &metadata)\n>  {\n>  \tstd::string filename = pattern_;\n>  \tsize_t pos;\n> diff --git a/src/apps/cam/file_sink.h b/src/apps/cam/file_sink.h\n> index 26cd61b36..1f973f2e6 100644\n> --- a/src/apps/cam/file_sink.h\n> +++ b/src/apps/cam/file_sink.h\n> @@ -11,7 +11,7 @@\n>  #include <memory>\n>  #include <string>\n>\n> -#include <libcamera/controls.h>\n> +#include <libcamera/metadata_list.h>\n>  #include <libcamera/stream.h>\n>\n>  #include \"frame_sink.h\"\n> @@ -44,7 +44,7 @@ private:\n>\n>  \tvoid writeBuffer(const libcamera::Stream *stream,\n>  \t\t\t libcamera::FrameBuffer *buffer,\n> -\t\t\t const libcamera::ControlList &metadata);\n> +\t\t\t const libcamera::MetadataList &metadata);\n>\n>  #ifdef HAVE_TIFF\n>  \tconst libcamera::Camera *camera_;\n> diff --git a/src/apps/common/dng_writer.cpp b/src/apps/common/dng_writer.cpp\n> index ac4619511..d8884548c 100644\n> --- a/src/apps/common/dng_writer.cpp\n> +++ b/src/apps/common/dng_writer.cpp\n> @@ -521,7 +521,7 @@ const std::map<PixelFormat, FormatInfo> formatInfo = {\n>\n>  int DNGWriter::write(const char *filename, const Camera *camera,\n>  \t\t     const StreamConfiguration &config,\n> -\t\t     const ControlList &metadata,\n> +\t\t     const MetadataList &metadata,\n>  \t\t     [[maybe_unused]] const FrameBuffer *buffer,\n>  \t\t     const void *data)\n>  {\n> diff --git a/src/apps/common/dng_writer.h b/src/apps/common/dng_writer.h\n> index aaa8a852b..741f78a75 100644\n> --- a/src/apps/common/dng_writer.h\n> +++ b/src/apps/common/dng_writer.h\n> @@ -10,8 +10,8 @@\n>  #ifdef HAVE_TIFF\n>\n>  #include <libcamera/camera.h>\n> -#include <libcamera/controls.h>\n>  #include <libcamera/framebuffer.h>\n> +#include <libcamera/metadata_list.h>\n>  #include <libcamera/stream.h>\n>\n>  class DNGWriter\n> @@ -19,7 +19,7 @@ class DNGWriter\n>  public:\n>  \tstatic int write(const char *filename, const libcamera::Camera *camera,\n>  \t\t\t const libcamera::StreamConfiguration &config,\n> -\t\t\t const libcamera::ControlList &metadata,\n> +\t\t\t const libcamera::MetadataList &metadata,\n>  \t\t\t const libcamera::FrameBuffer *buffer, const void *data);\n>  };\n>\n> diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\n> index 7e3f3da60..46dfbb198 100644\n> --- a/src/apps/qcam/main_window.cpp\n> +++ b/src/apps/qcam/main_window.cpp\n> @@ -643,7 +643,7 @@ void MainWindow::captureRaw()\n>  }\n>\n>  void MainWindow::processRaw(FrameBuffer *buffer,\n> -\t\t\t    [[maybe_unused]] const ControlList &metadata)\n> +\t\t\t    [[maybe_unused]] const MetadataList &metadata)\n>  {\n>  #ifdef HAVE_TIFF\n>  \tQString defaultPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);\n> @@ -707,7 +707,7 @@ void MainWindow::processCapture()\n>  \t\tprocessViewfinder(request->buffers().at(vfStream_));\n>\n>  \tif (request->buffers().count(rawStream_))\n> -\t\tprocessRaw(request->buffers().at(rawStream_), request->metadata());\n> +\t\tprocessRaw(request->buffers().at(rawStream_), request->metadata2());\n>\n>  \trequest->reuse();\n>  \tQMutexLocker locker(&mutex_);\n> diff --git a/src/apps/qcam/main_window.h b/src/apps/qcam/main_window.h\n> index 81fcf915a..eb1e4ce58 100644\n> --- a/src/apps/qcam/main_window.h\n> +++ b/src/apps/qcam/main_window.h\n> @@ -12,9 +12,9 @@\n>\n>  #include <libcamera/camera.h>\n>  #include <libcamera/camera_manager.h>\n> -#include <libcamera/controls.h>\n>  #include <libcamera/framebuffer.h>\n>  #include <libcamera/framebuffer_allocator.h>\n> +#include <libcamera/metadata_list.h>\n>  #include <libcamera/request.h>\n>  #include <libcamera/stream.h>\n>\n> @@ -66,7 +66,7 @@ private Q_SLOTS:\n>  \tvoid saveImageAs();\n>  \tvoid captureRaw();\n>  \tvoid processRaw(libcamera::FrameBuffer *buffer,\n> -\t\t\tconst libcamera::ControlList &metadata);\n> +\t\t\tconst libcamera::MetadataList &metadata);\n>\n>  \tvoid renderComplete(libcamera::FrameBuffer *buffer);\n>\n> diff --git a/src/gstreamer/gstlibcamera-controls.cpp.in b/src/gstreamer/gstlibcamera-controls.cpp.in\n> index 89c530da0..f5bd2885c 100644\n> --- a/src/gstreamer/gstlibcamera-controls.cpp.in\n> +++ b/src/gstreamer/gstlibcamera-controls.cpp.in\n> @@ -322,6 +322,6 @@ void GstCameraControls::applyControls(std::unique_ptr<libcamera::Request> &reque\n>\n>  void GstCameraControls::readMetadata(libcamera::Request *request)\n>  {\n> -\tcontrols_acc_.merge(request->metadata(),\n> -\t\t\t    ControlList::MergePolicy::OverwriteExisting);\n> +\tfor (const auto &[k, v] : request->metadata2())\n> +\t\tcontrols_acc_.set(k, ControlValue(v));\n>  }\n> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> index b34f08977..5b570e86f 100644\n> --- a/src/gstreamer/gstlibcamerasrc.cpp\n> +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> @@ -247,7 +247,7 @@ GstLibcameraSrcState::requestCompleted(Request *request)\n>  \t}\n>\n>  \tif (GST_ELEMENT_CLOCK(src_)) {\n> -\t\tint64_t timestamp = request->metadata().get(controls::SensorTimestamp).value_or(0);\n> +\t\tint64_t timestamp = request->metadata2().get(controls::SensorTimestamp).value_or(0);\n>\n>  \t\tGstClockTime gst_base_time = GST_ELEMENT(src_)->base_time;\n>  \t\tGstClockTime gst_now = gst_clock_get_time(GST_ELEMENT_CLOCK(src_));\n> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> index 0f59d0727..5bc8b5ed8 100644\n> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n> @@ -1375,7 +1375,7 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer)\n>  \t\treturn;\n>  \t}\n>\n> -\tipa_->processStats(info->id, request->metadata().get(controls::SensorTimestamp).value_or(0),\n> +\tipa_->processStats(info->id, request->metadata2().get(controls::SensorTimestamp).value_or(0),\n>  \t\t\t   info->statBuffer->cookie(), info->effectiveSensorControls);\n>  }\n>\n> --\n> 2.49.0\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 3C256BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 19 Jun 2025 14:04:19 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2C37C68DE3;\n\tThu, 19 Jun 2025 16:04:18 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id BDE5E68DDB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 19 Jun 2025 16:04:16 +0200 (CEST)","from ideasonboard.com (93-61-96-190.ip145.fastwebnet.it\n\t[93.61.96.190])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id B134699F;\n\tThu, 19 Jun 2025 16:04:02 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"IsEe2ZDz\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1750341842;\n\tbh=KHJpY2mletodPTtI3VrN6zVs+pcYUmdAdgMmNt280lA=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=IsEe2ZDzk6ClW+tNtQGci8XvXhyj+jwp3TqL/LRBvHxOBreObnnWLIOaKnWTjp+vd\n\tN8xZ8ays1BYgmyy0te1D8JdOhH/itwpg3wbqj/c10UA96QCmhNFQx0V7lyw6GedcJv\n\tYtoJaQmI+FEJoqSXQFD3VEe+18M75X75MMAfaYCA=","Date":"Thu, 19 Jun 2025 16:04:13 +0200","From":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","To":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org, \n\tkieran bingham <kieran.bingham@ideasonboard.com>","Subject":"Re: [RFC PATCH v1 23/23] treewide: Use `Request::metadata2()`","Message-ID":"<2eodsaljfjnurqtq2gmflhxhfasxsz47iovpmyk7vjpsgkiqqi@gdazvfeqcsbu>","References":"<20250606164156.1442682-1-barnabas.pocze@ideasonboard.com>\n\t<20250606164156.1442682-24-barnabas.pocze@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20250606164156.1442682-24-barnabas.pocze@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":34582,"web_url":"https://patchwork.libcamera.org/comment/34582/","msgid":"<27c2a444-1082-46d1-8d8a-9c55212ae66d@ideasonboard.com>","date":"2025-06-19T14:17:58","subject":"Re: [RFC PATCH v1 23/23] treewide: Use `Request::metadata2()`","submitter":{"id":216,"url":"https://patchwork.libcamera.org/api/people/216/","name":"Barnabás Pőcze","email":"barnabas.pocze@ideasonboard.com"},"content":"2025. 06. 19. 16:04 keltezéssel, Jacopo Mondi írta:\n> Hi Barnabás\n> \n> On Fri, Jun 06, 2025 at 06:41:56PM +0200, Barnabás Pőcze wrote:\n>> Apart from a few exceptions, make everything use the new metadata list\n>> of a request to access metadata items. After this change the only\n>> thing remaining is to remove the exceptional uses, remove `Request::metadata()`\n>> altogether, and finally rename `Request::metadata2()`.\n> \n> This is the most intersting part indeed.. replacing\n> \n> ControlList Request::metadata()\n> with\n> MetadataList Request::metadata()\n> \n> Then we will remove all usages of \"ControlList Request::metadata()\" in\n> the library code base and only operate on a MetadataList.\n> \n> it's an ABI breaking change, so let me cc kieran to make sure he's\n> aware of this. I wonder if we need a plan to handle an interim period\n> maybe by keeping \"ControlList metadata()\" around for one more release\n> after this series will be merged and notifying to applications that\n> they should use \"MetadataList metadata2()\" instead ?\n> \n> If I'm not mistaken, even after this series, once a Request completes\n> both metadata() and metadata2() will contain the same metadata list,\n> right ?\n\nYes.\n\n\n> \n>>\n>> Signed-off-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n>> ---\n>>   src/android/camera_device.cpp              | 4 ++--\n>>   src/apps/cam/file_sink.cpp                 | 4 ++--\n>>   src/apps/cam/file_sink.h                   | 4 ++--\n>>   src/apps/common/dng_writer.cpp             | 2 +-\n>>   src/apps/common/dng_writer.h               | 4 ++--\n>>   src/apps/qcam/main_window.cpp              | 4 ++--\n>>   src/apps/qcam/main_window.h                | 4 ++--\n>>   src/gstreamer/gstlibcamera-controls.cpp.in | 4 ++--\n>>   src/gstreamer/gstlibcamerasrc.cpp          | 2 +-\n>>   src/libcamera/pipeline/ipu3/ipu3.cpp       | 2 +-\n>>   10 files changed, 17 insertions(+), 17 deletions(-)\n>>\n>> diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp\n>> index 80ff248c2..b8c6ddf84 100644\n>> --- a/src/android/camera_device.cpp\n>> +++ b/src/android/camera_device.cpp\n>> @@ -1187,7 +1187,7 @@ void CameraDevice::requestComplete(Request *request)\n>>   \t * \\todo The shutter event notification should be sent to the framework\n>>   \t * as soon as possible, earlier than request completion time.\n>>   \t */\n>> -\tuint64_t sensorTimestamp = static_cast<uint64_t>(request->metadata()\n>> +\tuint64_t sensorTimestamp = static_cast<uint64_t>(request->metadata2()\n>>   \t\t\t\t\t\t\t\t .get(controls::SensorTimestamp)\n>>   \t\t\t\t\t\t\t\t .value_or(0));\n>>   \tnotifyShutter(descriptor->frameNumber_, sensorTimestamp);\n>> @@ -1423,7 +1423,7 @@ void CameraDevice::notifyError(uint32_t frameNumber, camera3_stream_t *stream,\n>>   std::unique_ptr<CameraMetadata>\n>>   CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) const\n>>   {\n>> -\tconst ControlList &metadata = descriptor.request_->metadata();\n>> +\tconst MetadataList &metadata = descriptor.request_->metadata2();\n>>   \tconst CameraMetadata &settings = descriptor.settings_;\n>>   \tcamera_metadata_ro_entry_t entry;\n>>   \tbool found;\n>> diff --git a/src/apps/cam/file_sink.cpp b/src/apps/cam/file_sink.cpp\n>> index 65794a2f9..1cc1b2b12 100644\n>> --- a/src/apps/cam/file_sink.cpp\n>> +++ b/src/apps/cam/file_sink.cpp\n>> @@ -96,13 +96,13 @@ void FileSink::mapBuffer(FrameBuffer *buffer)\n>>   bool FileSink::processRequest(Request *request)\n>>   {\n>>   \tfor (auto [stream, buffer] : request->buffers())\n>> -\t\twriteBuffer(stream, buffer, request->metadata());\n>> +\t\twriteBuffer(stream, buffer, request->metadata2());\n>>\n>>   \treturn true;\n>>   }\n>>\n>>   void FileSink::writeBuffer(const Stream *stream, FrameBuffer *buffer,\n>> -\t\t\t   [[maybe_unused]] const ControlList &metadata)\n>> +\t\t\t   [[maybe_unused]] const MetadataList &metadata)\n>>   {\n>>   \tstd::string filename = pattern_;\n>>   \tsize_t pos;\n>> diff --git a/src/apps/cam/file_sink.h b/src/apps/cam/file_sink.h\n>> index 26cd61b36..1f973f2e6 100644\n>> --- a/src/apps/cam/file_sink.h\n>> +++ b/src/apps/cam/file_sink.h\n>> @@ -11,7 +11,7 @@\n>>   #include <memory>\n>>   #include <string>\n>>\n>> -#include <libcamera/controls.h>\n>> +#include <libcamera/metadata_list.h>\n>>   #include <libcamera/stream.h>\n>>\n>>   #include \"frame_sink.h\"\n>> @@ -44,7 +44,7 @@ private:\n>>\n>>   \tvoid writeBuffer(const libcamera::Stream *stream,\n>>   \t\t\t libcamera::FrameBuffer *buffer,\n>> -\t\t\t const libcamera::ControlList &metadata);\n>> +\t\t\t const libcamera::MetadataList &metadata);\n>>\n>>   #ifdef HAVE_TIFF\n>>   \tconst libcamera::Camera *camera_;\n>> diff --git a/src/apps/common/dng_writer.cpp b/src/apps/common/dng_writer.cpp\n>> index ac4619511..d8884548c 100644\n>> --- a/src/apps/common/dng_writer.cpp\n>> +++ b/src/apps/common/dng_writer.cpp\n>> @@ -521,7 +521,7 @@ const std::map<PixelFormat, FormatInfo> formatInfo = {\n>>\n>>   int DNGWriter::write(const char *filename, const Camera *camera,\n>>   \t\t     const StreamConfiguration &config,\n>> -\t\t     const ControlList &metadata,\n>> +\t\t     const MetadataList &metadata,\n>>   \t\t     [[maybe_unused]] const FrameBuffer *buffer,\n>>   \t\t     const void *data)\n>>   {\n>> diff --git a/src/apps/common/dng_writer.h b/src/apps/common/dng_writer.h\n>> index aaa8a852b..741f78a75 100644\n>> --- a/src/apps/common/dng_writer.h\n>> +++ b/src/apps/common/dng_writer.h\n>> @@ -10,8 +10,8 @@\n>>   #ifdef HAVE_TIFF\n>>\n>>   #include <libcamera/camera.h>\n>> -#include <libcamera/controls.h>\n>>   #include <libcamera/framebuffer.h>\n>> +#include <libcamera/metadata_list.h>\n>>   #include <libcamera/stream.h>\n>>\n>>   class DNGWriter\n>> @@ -19,7 +19,7 @@ class DNGWriter\n>>   public:\n>>   \tstatic int write(const char *filename, const libcamera::Camera *camera,\n>>   \t\t\t const libcamera::StreamConfiguration &config,\n>> -\t\t\t const libcamera::ControlList &metadata,\n>> +\t\t\t const libcamera::MetadataList &metadata,\n>>   \t\t\t const libcamera::FrameBuffer *buffer, const void *data);\n>>   };\n>>\n>> diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\n>> index 7e3f3da60..46dfbb198 100644\n>> --- a/src/apps/qcam/main_window.cpp\n>> +++ b/src/apps/qcam/main_window.cpp\n>> @@ -643,7 +643,7 @@ void MainWindow::captureRaw()\n>>   }\n>>\n>>   void MainWindow::processRaw(FrameBuffer *buffer,\n>> -\t\t\t    [[maybe_unused]] const ControlList &metadata)\n>> +\t\t\t    [[maybe_unused]] const MetadataList &metadata)\n>>   {\n>>   #ifdef HAVE_TIFF\n>>   \tQString defaultPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation);\n>> @@ -707,7 +707,7 @@ void MainWindow::processCapture()\n>>   \t\tprocessViewfinder(request->buffers().at(vfStream_));\n>>\n>>   \tif (request->buffers().count(rawStream_))\n>> -\t\tprocessRaw(request->buffers().at(rawStream_), request->metadata());\n>> +\t\tprocessRaw(request->buffers().at(rawStream_), request->metadata2());\n>>\n>>   \trequest->reuse();\n>>   \tQMutexLocker locker(&mutex_);\n>> diff --git a/src/apps/qcam/main_window.h b/src/apps/qcam/main_window.h\n>> index 81fcf915a..eb1e4ce58 100644\n>> --- a/src/apps/qcam/main_window.h\n>> +++ b/src/apps/qcam/main_window.h\n>> @@ -12,9 +12,9 @@\n>>\n>>   #include <libcamera/camera.h>\n>>   #include <libcamera/camera_manager.h>\n>> -#include <libcamera/controls.h>\n>>   #include <libcamera/framebuffer.h>\n>>   #include <libcamera/framebuffer_allocator.h>\n>> +#include <libcamera/metadata_list.h>\n>>   #include <libcamera/request.h>\n>>   #include <libcamera/stream.h>\n>>\n>> @@ -66,7 +66,7 @@ private Q_SLOTS:\n>>   \tvoid saveImageAs();\n>>   \tvoid captureRaw();\n>>   \tvoid processRaw(libcamera::FrameBuffer *buffer,\n>> -\t\t\tconst libcamera::ControlList &metadata);\n>> +\t\t\tconst libcamera::MetadataList &metadata);\n>>\n>>   \tvoid renderComplete(libcamera::FrameBuffer *buffer);\n>>\n>> diff --git a/src/gstreamer/gstlibcamera-controls.cpp.in b/src/gstreamer/gstlibcamera-controls.cpp.in\n>> index 89c530da0..f5bd2885c 100644\n>> --- a/src/gstreamer/gstlibcamera-controls.cpp.in\n>> +++ b/src/gstreamer/gstlibcamera-controls.cpp.in\n>> @@ -322,6 +322,6 @@ void GstCameraControls::applyControls(std::unique_ptr<libcamera::Request> &reque\n>>\n>>   void GstCameraControls::readMetadata(libcamera::Request *request)\n>>   {\n>> -\tcontrols_acc_.merge(request->metadata(),\n>> -\t\t\t    ControlList::MergePolicy::OverwriteExisting);\n>> +\tfor (const auto &[k, v] : request->metadata2())\n>> +\t\tcontrols_acc_.set(k, ControlValue(v));\n>>   }\n>> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n>> index b34f08977..5b570e86f 100644\n>> --- a/src/gstreamer/gstlibcamerasrc.cpp\n>> +++ b/src/gstreamer/gstlibcamerasrc.cpp\n>> @@ -247,7 +247,7 @@ GstLibcameraSrcState::requestCompleted(Request *request)\n>>   \t}\n>>\n>>   \tif (GST_ELEMENT_CLOCK(src_)) {\n>> -\t\tint64_t timestamp = request->metadata().get(controls::SensorTimestamp).value_or(0);\n>> +\t\tint64_t timestamp = request->metadata2().get(controls::SensorTimestamp).value_or(0);\n>>\n>>   \t\tGstClockTime gst_base_time = GST_ELEMENT(src_)->base_time;\n>>   \t\tGstClockTime gst_now = gst_clock_get_time(GST_ELEMENT_CLOCK(src_));\n>> diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp\n>> index 0f59d0727..5bc8b5ed8 100644\n>> --- a/src/libcamera/pipeline/ipu3/ipu3.cpp\n>> +++ b/src/libcamera/pipeline/ipu3/ipu3.cpp\n>> @@ -1375,7 +1375,7 @@ void IPU3CameraData::statBufferReady(FrameBuffer *buffer)\n>>   \t\treturn;\n>>   \t}\n>>\n>> -\tipa_->processStats(info->id, request->metadata().get(controls::SensorTimestamp).value_or(0),\n>> +\tipa_->processStats(info->id, request->metadata2().get(controls::SensorTimestamp).value_or(0),\n>>   \t\t\t   info->statBuffer->cookie(), info->effectiveSensorControls);\n>>   }\n>>\n>> --\n>> 2.49.0\n>>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 34486BDE6B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 19 Jun 2025 14:18:05 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 508AB68DE3;\n\tThu, 19 Jun 2025 16:18:04 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id F15BE68DDB\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 19 Jun 2025 16:18:01 +0200 (CEST)","from [192.168.33.22] (185.221.143.107.nat.pool.zt.hu\n\t[185.221.143.107])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id F17F9107;\n\tThu, 19 Jun 2025 16:17:47 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"XkQxgNvk\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1750342668;\n\tbh=8U0kkcjNF5K/NnUa6HQ87j4EnA2TRAHJKBBzS3Il0vQ=;\n\th=Date:Subject:To:Cc:References:From:In-Reply-To:From;\n\tb=XkQxgNvkL5qYTB+WY7CRPa4mOCMcr9IGXayi4MamsdDEGbiRaJCUZQEA/qNTH1Jzs\n\tGZiRQSbhKe6uqPsc84FcQoVDOzlBL2Ze0+VqAZvRtrvC3mepQhd9UYEOAxlaEIM8AM\n\tRQh6ETIM0c6i3vaFAPcT1YXhn1ebA2ThDJOrWqco=","Message-ID":"<27c2a444-1082-46d1-8d8a-9c55212ae66d@ideasonboard.com>","Date":"Thu, 19 Jun 2025 16:17:58 +0200","MIME-Version":"1.0","User-Agent":"Mozilla Thunderbird","Subject":"Re: [RFC PATCH v1 23/23] treewide: Use `Request::metadata2()`","To":"Jacopo Mondi <jacopo.mondi@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org,\n\tkieran bingham <kieran.bingham@ideasonboard.com>","References":"<20250606164156.1442682-1-barnabas.pocze@ideasonboard.com>\n\t<20250606164156.1442682-24-barnabas.pocze@ideasonboard.com>\n\t<2eodsaljfjnurqtq2gmflhxhfasxsz47iovpmyk7vjpsgkiqqi@gdazvfeqcsbu>","From":"=?utf-8?q?Barnab=C3=A1s_P=C5=91cze?= <barnabas.pocze@ideasonboard.com>","Content-Language":"en-US, hu-HU","In-Reply-To":"<2eodsaljfjnurqtq2gmflhxhfasxsz47iovpmyk7vjpsgkiqqi@gdazvfeqcsbu>","Content-Type":"text/plain; charset=UTF-8; format=flowed","Content-Transfer-Encoding":"8bit","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]