diff -pruN 0.5.0-1/.b4-config 0.6.0-2/.b4-config
--- 0.5.0-1/.b4-config	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/.b4-config	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,2 @@
+[b4]
+  send-series-to = libcamera-devel@lists.libcamera.org
diff -pruN 0.5.0-1/.reuse/dep5 0.6.0-2/.reuse/dep5
--- 0.5.0-1/.reuse/dep5	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/.reuse/dep5	2025-11-27 11:55:28.000000000 +0000
@@ -6,13 +6,10 @@ Source: https://git.libcamera.org/libcam
 Files: Documentation/binning.svg
        Documentation/camera-sensor-model.rst
        Documentation/sensor_model.svg
+       Documentation/theme/static/libcamera-logo-text.svg
 Copyright: Copyright 2023 Ideas On Board Oy
 License: CC-BY-SA-4.0
 
-Files: Documentation/theme/static/search.png
-Copyright: 2022 Fonticons, Inc.
-License: CC-BY-4.0
-
 Files: src/ipa/rpi/vc4/data/*.json
        utils/raspberrypi/ctt/ctt_config_example.json
        utils/raspberrypi/ctt/ctt_ref.pgm
diff -pruN 0.5.0-1/Documentation/Doxyfile-common.in 0.6.0-2/Documentation/Doxyfile-common.in
--- 0.5.0-1/Documentation/Doxyfile-common.in	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/Doxyfile-common.in	2025-11-27 11:55:28.000000000 +0000
@@ -29,6 +29,8 @@ FILE_PATTERNS          = *.c \
 
 RECURSIVE              = YES
 
+EXCLUDE_SYMLINKS       = YES
+
 EXCLUDE_PATTERNS       = @TOP_BUILDDIR@/include/libcamera/ipa/*_serializer.h \
                          @TOP_BUILDDIR@/include/libcamera/ipa/*_proxy.h \
                          @TOP_BUILDDIR@/include/libcamera/ipa/ipu3_*.h \
@@ -50,18 +52,20 @@ EXCLUDE_SYMBOLS        = libcamera::Boun
                          *::details \
                          std::*
 
-EXCLUDE_SYMLINKS       = YES
+IMAGE_PATH             = "@TOP_SRCDIR@/Documentation/images"
+
+HTML_EXTRA_STYLESHEET  = "@TOP_SRCDIR@/Documentation/doxygen-awesome-css/doxygen-awesome.css" \
+                         "@TOP_SRCDIR@/Documentation/doxygen-awesome-css/doxygen-awesome-sidebar-only.css"
 
 GENERATE_LATEX         = NO
 
 MACRO_EXPANSION        = YES
 EXPAND_ONLY_PREDEF     = YES
 
-INCLUDE_PATH           = "@TOP_SRCDIR@/include/libcamera"
+INCLUDE_PATH           = "@TOP_BUILDDIR@/include" \
+                         "@TOP_SRCDIR@/include"
 INCLUDE_FILE_PATTERNS  = *.h
 
-IMAGE_PATH             = "@TOP_SRCDIR@/Documentation/images"
-
 PREDEFINED             = __DOXYGEN__ \
                          __cplusplus \
                          __attribute__(x)= \
diff -pruN 0.5.0-1/Documentation/Doxyfile-internal.in 0.6.0-2/Documentation/Doxyfile-internal.in
--- 0.5.0-1/Documentation/Doxyfile-internal.in	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/Doxyfile-internal.in	2025-11-27 11:55:28.000000000 +0000
@@ -3,9 +3,8 @@
 @INCLUDE_PATH          = @TOP_BUILDDIR@/Documentation
 @INCLUDE               = Doxyfile-common
 
-HIDE_UNDOC_CLASSES     = NO
 HIDE_UNDOC_MEMBERS     = NO
-HTML_OUTPUT            = internal-api-html
+HIDE_UNDOC_CLASSES     = NO
 INTERNAL_DOCS          = YES
 ENABLED_SECTIONS       = internal
 
@@ -31,3 +30,7 @@ EXCLUDE                = @TOP_SRCDIR@/in
                          @TOP_BUILDDIR@/include/libcamera/internal/tracepoints.h \
                          @TOP_BUILDDIR@/include/libcamera/ipa/soft_ipa_interface.h \
                          @TOP_BUILDDIR@/src/libcamera/proxy/
+
+HTML_OUTPUT            = internal-api
+
+GENERATE_TAGFILE       = @TOP_BUILDDIR@/Documentation/internal-api/tagfile.xml
diff -pruN 0.5.0-1/Documentation/Doxyfile-public.in 0.6.0-2/Documentation/Doxyfile-public.in
--- 0.5.0-1/Documentation/Doxyfile-public.in	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/Doxyfile-public.in	2025-11-27 11:55:28.000000000 +0000
@@ -3,9 +3,8 @@
 @INCLUDE_PATH          = @TOP_BUILDDIR@/Documentation
 @INCLUDE               = Doxyfile-common
 
-HIDE_UNDOC_CLASSES     = YES
 HIDE_UNDOC_MEMBERS     = YES
-HTML_OUTPUT            = api-html
+HIDE_UNDOC_CLASSES     = YES
 INTERNAL_DOCS          = NO
 
 INPUT                  = "@TOP_SRCDIR@/Documentation" \
@@ -17,4 +16,8 @@ EXCLUDE                = @TOP_SRCDIR@/in
                          @TOP_SRCDIR@/src/libcamera/base/class.cpp \
                          @TOP_SRCDIR@/src/libcamera/base/object.cpp
 
+HTML_OUTPUT            = public-api
+
 PREDEFINED            += __DOXYGEN_PUBLIC__
+
+GENERATE_TAGFILE       = @TOP_BUILDDIR@/Documentation/public-api/tagfile.xml
diff -pruN 0.5.0-1/Documentation/api-html/index.rst 0.6.0-2/Documentation/api-html/index.rst
--- 0.5.0-1/Documentation/api-html/index.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/api-html/index.rst	1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-.. SPDX-License-Identifier: CC-BY-SA-4.0
-
-.. _api:
-
-API Reference
-=============
-
-:: Placeholder for Doxygen documentation
diff -pruN 0.5.0-1/Documentation/camera-sensor-model.rst 0.6.0-2/Documentation/camera-sensor-model.rst
--- 0.5.0-1/Documentation/camera-sensor-model.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/camera-sensor-model.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 .. _camera-sensor-model:
 
 .. todo: Move to Doxygen-generated documentation
diff -pruN 0.5.0-1/Documentation/code-of-conduct.rst 0.6.0-2/Documentation/code-of-conduct.rst
--- 0.5.0-1/Documentation/code-of-conduct.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/code-of-conduct.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-4.0
 
-.. include:: documentation-contents.rst
-
 .. _code-of-conduct:
 
 Contributor Covenant Code of Conduct
diff -pruN 0.5.0-1/Documentation/coding-style.rst 0.6.0-2/Documentation/coding-style.rst
--- 0.5.0-1/Documentation/coding-style.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/coding-style.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 .. _coding-style-guidelines:
 
 Coding Style Guidelines
diff -pruN 0.5.0-1/Documentation/conf.py 0.6.0-2/Documentation/conf.py
--- 0.5.0-1/Documentation/conf.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/conf.py	1970-01-01 00:00:00.000000000 +0000
@@ -1,180 +0,0 @@
-# SPDX-License-Identifier: CC-BY-SA-4.0
-# -*- coding: utf-8 -*-
-#
-# Configuration file for the Sphinx documentation builder.
-#
-# This file does only contain a selection of the most common options. For a
-# full list see the documentation:
-# http://www.sphinx-doc.org/en/master/config
-
-# -- Path setup --------------------------------------------------------------
-
-# If extensions (or modules to document with autodoc) are in another directory,
-# add these directories to sys.path here. If the directory is relative to the
-# documentation root, use os.path.abspath to make it absolute, like shown here.
-#
-# import os
-# import sys
-# sys.path.insert(0, os.path.abspath('.'))
-
-
-# -- Project information -----------------------------------------------------
-
-project = 'libcamera'
-copyright = '2018-2019, The libcamera documentation authors'
-author = u'Kieran Bingham, Jacopo Mondi, Laurent Pinchart, Niklas Söderlund'
-
-# Version information is provided by the build environment, through the
-# sphinx command line.
-
-# -- General configuration ---------------------------------------------------
-
-# If your documentation needs a minimal Sphinx version, state it here.
-#
-# needs_sphinx = '1.0'
-
-# Add any Sphinx extension module names here, as strings. They can be
-# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-# ones.
-extensions = [
-    'sphinx.ext.graphviz'
-]
-
-graphviz_output_format = 'svg'
-
-# Add any paths that contain templates here, relative to this directory.
-templates_path = []
-
-# The suffix(es) of source filenames.
-# You can specify multiple suffix as a list of string:
-#
-# source_suffix = ['.rst', '.md']
-source_suffix = '.rst'
-
-# The master toctree document.
-master_doc = 'index'
-
-# The language for content autogenerated by Sphinx. Refer to documentation
-# for a list of supported languages.
-#
-# This is also used if you do content translation via gettext catalogs.
-# Usually you set "language" from the command line for these cases.
-language = 'en'
-
-# List of patterns, relative to source directory, that match files and
-# directories to ignore when looking for source files.
-# This pattern also affects html_static_path and html_extra_path.
-exclude_patterns = [
-    '_build',
-    'Thumbs.db',
-    '.DS_Store',
-    'documentation-contents.rst',
-]
-
-# The name of the Pygments (syntax highlighting) style to use.
-pygments_style = None
-
-
-# -- Options for HTML output -------------------------------------------------
-
-# The theme to use for HTML and HTML Help pages.  See the documentation for
-# a list of builtin themes.
-#
-html_theme = 'theme'
-html_theme_path = ['.']
-
-# Theme options are theme-specific and customize the look and feel of a theme
-# further.  For a list of options available for each theme, see the
-# documentation.
-#
-# html_theme_options = {}
-
-# Add any paths that contain custom static files (such as style sheets) here,
-# relative to this directory. They are copied after the builtin static files,
-# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = []
-
-# Custom sidebar templates, must be a dictionary that maps document names
-# to template names.
-#
-# The default sidebars (for documents that don't match any pattern) are
-# defined by theme itself.  Builtin themes are using these templates by
-# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
-# 'searchbox.html']``.
-#
-# html_sidebars = {}
-
-
-# -- Options for HTMLHelp output ---------------------------------------------
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'libcameradoc'
-
-
-# -- Options for LaTeX output ------------------------------------------------
-
-latex_elements = {
-    # The paper size ('letterpaper' or 'a4paper').
-    #
-    # 'papersize': 'letterpaper',
-
-    # The font size ('10pt', '11pt' or '12pt').
-    #
-    # 'pointsize': '10pt',
-
-    # Additional stuff for the LaTeX preamble.
-    #
-    # 'preamble': '',
-
-    # Latex figure (float) alignment
-    #
-    # 'figure_align': 'htbp',
-}
-
-# Grouping the document tree into LaTeX files. List of tuples
-# (source start file, target name, title,
-#  author, documentclass [howto, manual, or own class]).
-latex_documents = [
-    (master_doc, 'libcamera.tex', 'libcamera Documentation',
-     author, 'manual'),
-]
-
-
-# -- Options for manual page output ------------------------------------------
-
-# One entry per manual page. List of tuples
-# (source start file, name, description, authors, manual section).
-man_pages = [
-    (master_doc, 'libcamera', 'libcamera Documentation',
-     [author], 1)
-]
-
-
-# -- Options for Texinfo output ----------------------------------------------
-
-# Grouping the document tree into Texinfo files. List of tuples
-# (source start file, target name, title, author,
-#  dir menu entry, description, category)
-texinfo_documents = [
-    (master_doc, 'libcamera', 'libcamera Documentation',
-     author, 'libcamera', 'One line description of project.',
-     'Miscellaneous'),
-]
-
-
-# -- Options for Epub output -------------------------------------------------
-
-# Bibliographic Dublin Core info.
-epub_title = project
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#
-# epub_identifier = ''
-
-# A unique identification for the text.
-#
-# epub_uid = ''
-
-# A list of files that should not be packed into the epub file.
-epub_exclude_files = ['search.html']
diff -pruN 0.5.0-1/Documentation/conf.py.in 0.6.0-2/Documentation/conf.py.in
--- 0.5.0-1/Documentation/conf.py.in	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/conf.py.in	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,120 @@
+# SPDX-License-Identifier: CC-BY-SA-4.0
+# -*- coding: utf-8 -*-
+#
+# Configuration file for the Sphinx documentation builder.
+#
+# This file does only contain a selection of the most common options. For a
+# full list see the documentation:
+# http://www.sphinx-doc.org/en/master/config
+
+# -- Path setup --------------------------------------------------------------
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#
+# import os
+# import sys
+# sys.path.insert(0, os.path.abspath('.'))
+
+
+# -- Project information -----------------------------------------------------
+
+project = 'libcamera'
+copyright = '2018-2025, The libcamera documentation authors'
+author = 'The libcamera documentation authors'
+
+# Version information is provided by the build environment, through the
+# sphinx command line.
+
+# -- General configuration ---------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#
+# needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be
+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
+# ones.
+extensions = [
+    'sphinx.ext.graphviz',
+    'sphinxcontrib.doxylink',
+]
+
+graphviz_output_format = 'svg'
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = []
+
+# The suffix(es) of source filenames.
+# You can specify multiple suffix as a list of string:
+#
+# source_suffix = ['.rst', '.md']
+source_suffix = '.rst'
+
+# The master toctree document.
+master_doc = 'index'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#
+# This is also used if you do content translation via gettext catalogs.
+# Usually you set "language" from the command line for these cases.
+language = 'en'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+# This pattern also affects html_static_path and html_extra_path.
+exclude_patterns = [
+]
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = None
+
+doxylink = {
+    'doxy-pub': (
+        '@TOP_BUILDDIR@/Documentation/public-api/tagfile.xml',
+        'public-api/',
+    ),
+    'doxy-int': (
+        '@TOP_BUILDDIR@/Documentation/internal-api/tagfile.xml',
+        'internal-api/',
+    ),
+}
+
+# -- Options for HTML output -------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  See the documentation for
+# a list of builtin themes.
+#
+html_theme = 'sphinx_book_theme'
+html_theme_path = []
+
+html_logo = '@CURRENT_SRCDIR@/theme/static/libcamera-logo-text.svg'
+
+html_context = {
+    # Set the default mode, so that syntax highlighting works without
+    # javascript.
+    'default_mode': 'light'
+}
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#
+# html_theme_options = {}
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = []
+
+# Custom sidebar templates, must be a dictionary that maps document names
+# to template names.
+#
+# The default sidebars (for documents that don't match any pattern) are
+# defined by theme itself.  Builtin themes are using these templates by
+# default: ``['localtoc.html', 'relations.html', 'sourcelink.html',
+# 'searchbox.html']``.
+#
+# html_sidebars = {}
diff -pruN 0.5.0-1/Documentation/contributing.rst 0.6.0-2/Documentation/contributing.rst
--- 0.5.0-1/Documentation/contributing.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/contributing.rst	2025-11-27 11:55:28.000000000 +0000
@@ -30,10 +30,34 @@ to the public. Point your IRC client to
 
 .. _WebChat: https://webchat.oftc.net/?channels=libcamera
 
+The IRC channel is also bridged and accessible via `Matrix`_ in the #libcamera
+room:
+
+.. _Matrix: https://matrix.to/#/#libcamera:matrix.org
+
 Source Code
 -----------
 
-libcamera is in early stages of development, and no releases are available yet.
+libcamera is in active development, including investigations into what a 'good'
+API is for the implementation. We can't guarantee we have all features
+implemented, or designed correctly yet, and we have plans to make considerable
+changes to the API and ABI in our roadmap.
+
+Even so, we provide periodic 'releases' to support distributions and packaging
+teams. To support this we are currently making releases of the 0.y.z version
+scheme, loosely following semver.
+
+In the foreseeable future, the following applies:
+
+  0.y.z : Active development, but with ABI breakage detection. The 0.y
+          version will bump on an ABI/API breakage. Ongoing development will
+          increment the .z version component. Therefore, pre 1.0 'y' is a
+          close equivalent to a major release.
+
+  1.y.z : Stable API and ABI guarantees on the Major version number.
+          Following semantic versioning as documented at https://semver.org/
+
+
 The source code is available from the project's `git tree`_.
 
 .. code-block:: shell
@@ -42,17 +66,21 @@ The source code is available from the pr
 
 .. _git tree: https://git.libcamera.org/libcamera/libcamera.git/
 
-A mirror is also hosted on `LinuxTV`_.
+A development mirror is also hosted on `Freedesktop`_.
+
+.. _Freedesktop: https://gitlab.freedesktop.org/camera/libcamera
+
+Freedesktop also provides our CI and `testing pipeline`_.
 
-.. _LinuxTV: https://git.linuxtv.org/libcamera.git/
+.. _testing pipeline: https://gitlab.freedesktop.org/camera/libcamera/-/pipelines
 
 Issue Tracker
 -------------
 
-Our `issue tracker`_ tracks all bugs, issues and feature requests. All issues
-are publicly visible, and you can register for an account to create new issues.
+Our `issue tracker`_ also hosted at Freedesktop tracks all bugs, issues and
+feature requests.
 
-.. _issue tracker: https://bugs.libcamera.org/
+.. _issue tracker: https://gitlab.freedesktop.org/camera/libcamera/-/issues
 
 Documentation
 -------------
diff -pruN 0.5.0-1/Documentation/documentation-contents.rst 0.6.0-2/Documentation/documentation-contents.rst
--- 0.5.0-1/Documentation/documentation-contents.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/documentation-contents.rst	1970-01-01 00:00:00.000000000 +0000
@@ -1,35 +0,0 @@
-.. SPDX-License-Identifier: CC-BY-SA-4.0
-
-.. container:: documentation-nav
-
-   * **Documentation for Users**
-   * :doc:`Introduction </introduction>`
-   * :doc:`/feature_requirements`
-   * :doc:`/guides/application-developer`
-   * :doc:`/python-bindings`
-   * :doc:`/environment_variables`
-   * :doc:`/api-html/index`
-   * :doc:`/code-of-conduct`
-   * |
-   * **Documentation for Developers**
-   * :doc:`/libcamera_architecture`
-   * :doc:`/guides/pipeline-handler`
-   * :doc:`/guides/ipa`
-   * :doc:`/camera-sensor-model`
-   * :doc:`/guides/tracing`
-   * :doc:`/software-isp-benchmarking`
-   * :doc:`/coding-style`
-   * :doc:`/internal-api-html/index`
-   * |
-   * **Documentation for System Integrators**
-   * :doc:`/lens_driver_requirements`
-   * :doc:`/sensor_driver_requirements`
-
-..
-   The following directive adds the "documentation" class to all of the pages
-   generated by sphinx. This is not relevant in libcamera nor addressed in the
-   theme's CSS, since all of the pages here are documentation. It **is** used
-   to properly format the documentation pages on libcamera.org and so should not
-   be removed.
-
-.. rst-class:: documentation
diff -pruN 0.5.0-1/Documentation/doxygen-awesome-css/doxygen-awesome-sidebar-only.css 0.6.0-2/Documentation/doxygen-awesome-css/doxygen-awesome-sidebar-only.css
--- 0.5.0-1/Documentation/doxygen-awesome-css/doxygen-awesome-sidebar-only.css	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/doxygen-awesome-css/doxygen-awesome-sidebar-only.css	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,97 @@
+/* SPDX-License-Identifier: MIT */
+/**
+
+Doxygen Awesome
+https://github.com/jothepro/doxygen-awesome-css
+
+Copyright (c) 2021 - 2023 jothepro
+
+ */
+
+html {
+    /* side nav width. MUST be = `TREEVIEW_WIDTH`.
+     * Make sure it is wide enough to contain the page title (logo + title + version)
+     */
+    --side-nav-fixed-width: 335px;
+    --menu-display: none;
+
+    --top-height: 120px;
+    --toc-sticky-top: -25px;
+    --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 25px);
+}
+
+#projectname {
+    white-space: nowrap;
+}
+
+
+@media screen and (min-width: 768px) {
+    html {
+        --searchbar-background: var(--page-background-color);
+    }
+
+    #side-nav {
+        min-width: var(--side-nav-fixed-width);
+        max-width: var(--side-nav-fixed-width);
+        top: var(--top-height);
+        overflow: visible;
+    }
+
+    #nav-tree, #side-nav {
+        height: calc(100vh - var(--top-height)) !important;
+    }
+
+    #nav-tree {
+        padding: 0;
+    }
+
+    #top {
+        display: block;
+        border-bottom: none;
+        height: var(--top-height);
+        margin-bottom: calc(0px - var(--top-height));
+        max-width: var(--side-nav-fixed-width);
+        overflow: hidden;
+        background: var(--side-nav-background);
+    }
+    #main-nav {
+        float: left;
+        padding-right: 0;
+    }
+
+    .ui-resizable-handle {
+        cursor: default;
+        width: 1px !important;
+        background: var(--separator-color);
+        box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color);
+    }
+
+    #nav-path {
+        position: fixed;
+        right: 0;
+        left: var(--side-nav-fixed-width);
+        bottom: 0;
+        width: auto;
+    }
+
+    #doc-content {
+        height: calc(100vh - 31px) !important;
+        padding-bottom: calc(3 * var(--spacing-large));
+        padding-top: calc(var(--top-height) - 80px);
+        box-sizing: border-box;
+        margin-left: var(--side-nav-fixed-width) !important;
+    }
+
+    #MSearchBox {
+        width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)));
+    }
+
+    #MSearchField {
+        width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px);
+    }
+
+    #MSearchResultsWindow {
+        left: var(--spacing-medium) !important;
+        right: auto;
+    }
+}
diff -pruN 0.5.0-1/Documentation/doxygen-awesome-css/doxygen-awesome.css 0.6.0-2/Documentation/doxygen-awesome-css/doxygen-awesome.css
--- 0.5.0-1/Documentation/doxygen-awesome-css/doxygen-awesome.css	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/doxygen-awesome-css/doxygen-awesome.css	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,2664 @@
+/* SPDX-License-Identifier: MIT */
+/**
+
+Doxygen Awesome
+https://github.com/jothepro/doxygen-awesome-css
+
+Copyright (c) 2021 - 2023 jothepro
+
+*/
+
+html {
+    /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */
+    --primary-color: #1779c4;
+    --primary-dark-color: #335c80;
+    --primary-light-color: #70b1e9;
+    --on-primary-color: #ffffff;
+
+    /* page base colors */
+    --page-background-color: #ffffff;
+    --page-foreground-color: #2f4153;
+    --page-secondary-foreground-color: #6f7e8e;
+
+    /* color for all separators on the website: hr, borders, ... */
+    --separator-color: #dedede;
+
+    /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */
+    --border-radius-large: 8px;
+    --border-radius-small: 4px;
+    --border-radius-medium: 6px;
+
+    /* default spacings. Most components reference these values for spacing, to provide uniform spacing on the page. */
+    --spacing-small: 5px;
+    --spacing-medium: 10px;
+    --spacing-large: 16px;
+
+    /* default box shadow used for raising an element above the normal content. Used in dropdowns, search result, ... */
+    --box-shadow: 0 2px 8px 0 rgba(0,0,0,.075);
+
+    --odd-color: rgba(0,0,0,.028);
+
+    /* font-families. will affect all text on the website
+     * font-family: the normal font for text, headlines, menus
+     * font-family-monospace: used for preformatted text in memtitle, code, fragments
+     */
+    --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
+    --font-family-monospace: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace;
+
+    /* font sizes */
+    --page-font-size: 15.6px;
+    --navigation-font-size: 14.4px;
+    --toc-font-size: 13.4px;
+    --code-font-size: 14px; /* affects code, fragment */
+    --title-font-size: 22px;
+
+    /* content text properties. These only affect the page content, not the navigation or any other ui elements */
+    --content-line-height: 27px;
+    /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/
+    --content-maxwidth: 1050px;
+    --table-line-height: 24px;
+    --toc-sticky-top: var(--spacing-medium);
+    --toc-width: 200px;
+    --toc-max-height: calc(100vh - 2 * var(--spacing-medium) - 85px);
+
+    /* colors for various content boxes: @warning, @note, @deprecated @bug */
+    --warning-color: #faf3d8;
+    --warning-color-dark: #f3a600;
+    --warning-color-darker: #5f4204;
+    --note-color: #e4f3ff;
+    --note-color-dark: #1879C4;
+    --note-color-darker: #274a5c;
+    --todo-color: #e4dafd;
+    --todo-color-dark: #5b2bdd;
+    --todo-color-darker: #2a0d72;
+    --deprecated-color: #ecf0f3;
+    --deprecated-color-dark: #5b6269;
+    --deprecated-color-darker: #43454a;
+    --bug-color: #f8d1cc;
+    --bug-color-dark: #b61825;
+    --bug-color-darker: #75070f;
+    --invariant-color: #d8f1e3;
+    --invariant-color-dark: #44b86f;
+    --invariant-color-darker: #265532;
+
+    /* blockquote colors */
+    --blockquote-background: #f8f9fa;
+    --blockquote-foreground: #636568;
+
+    /* table colors */
+    --tablehead-background: #f1f1f1;
+    --tablehead-foreground: var(--page-foreground-color);
+
+    /* menu-display: block | none
+     * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible.
+     * `GENERATE_TREEVIEW` MUST be enabled!
+     */
+    --menu-display: block;
+
+    --menu-focus-foreground: var(--on-primary-color);
+    --menu-focus-background: var(--primary-color);
+    --menu-selected-background: rgba(0,0,0,.05);
+
+
+    --header-background: var(--page-background-color);
+    --header-foreground: var(--page-foreground-color);
+
+    /* searchbar colors */
+    --searchbar-background: var(--side-nav-background);
+    --searchbar-foreground: var(--page-foreground-color);
+
+    /* searchbar size
+     * (`searchbar-width` is only applied on screens >= 768px.
+     * on smaller screens the searchbar will always fill the entire screen width) */
+    --searchbar-height: 33px;
+    --searchbar-width: 210px;
+    --searchbar-border-radius: var(--searchbar-height);
+
+    /* code block colors */
+    --code-background: #f5f5f5;
+    --code-foreground: var(--page-foreground-color);
+
+    /* fragment colors */
+    --fragment-background: #F8F9FA;
+    --fragment-foreground: #37474F;
+    --fragment-keyword: #bb6bb2;
+    --fragment-keywordtype: #8258b3;
+    --fragment-keywordflow: #d67c3b;
+    --fragment-token: #438a59;
+    --fragment-comment: #969696;
+    --fragment-link: #5383d6;
+    --fragment-preprocessor: #46aaa5;
+    --fragment-linenumber-color: #797979;
+    --fragment-linenumber-background: #f4f4f5;
+    --fragment-linenumber-border: #e3e5e7;
+    --fragment-lineheight: 20px;
+
+    /* sidebar navigation (treeview) colors */
+    --side-nav-background: #fbfbfb;
+    --side-nav-foreground: var(--page-foreground-color);
+    --side-nav-arrow-opacity: 0;
+    --side-nav-arrow-hover-opacity: 0.9;
+
+    --toc-background: var(--side-nav-background);
+    --toc-foreground: var(--side-nav-foreground);
+
+    /* height of an item in any tree / collapsible table */
+    --tree-item-height: 30px;
+
+    --memname-font-size: var(--code-font-size);
+    --memtitle-font-size: 18px;
+
+    --webkit-scrollbar-size: 7px;
+    --webkit-scrollbar-padding: 4px;
+    --webkit-scrollbar-color: var(--separator-color);
+
+    --animation-duration: .12s
+}
+
+@media screen and (max-width: 767px) {
+    html {
+        --page-font-size: 16px;
+        --navigation-font-size: 16px;
+        --toc-font-size: 15px;
+        --code-font-size: 15px; /* affects code, fragment */
+        --title-font-size: 22px;
+    }
+}
+
+@media (prefers-color-scheme: dark) {
+    html:not(.light-mode) {
+        color-scheme: dark;
+
+        --primary-color: #1982d2;
+        --primary-dark-color: #86a9c4;
+        --primary-light-color: #4779ac;
+
+        --box-shadow: 0 2px 8px 0 rgba(0,0,0,.35);
+
+        --odd-color: rgba(100,100,100,.06);
+
+        --menu-selected-background: rgba(0,0,0,.4);
+
+        --page-background-color: #1C1D1F;
+        --page-foreground-color: #d2dbde;
+        --page-secondary-foreground-color: #859399;
+        --separator-color: #38393b;
+        --side-nav-background: #252628;
+
+        --code-background: #2a2c2f;
+
+        --tablehead-background: #2a2c2f;
+    
+        --blockquote-background: #222325;
+        --blockquote-foreground: #7e8c92;
+
+        --warning-color: #3b2e04;
+        --warning-color-dark: #f1b602;
+        --warning-color-darker: #ceb670;
+        --note-color: #163750;
+        --note-color-dark: #1982D2;
+        --note-color-darker: #dcf0fa;
+        --todo-color: #2a2536;
+        --todo-color-dark: #7661b3;
+        --todo-color-darker: #ae9ed6;
+        --deprecated-color: #2e323b;
+        --deprecated-color-dark: #738396;
+        --deprecated-color-darker: #abb0bd;
+        --bug-color: #2e1917;
+        --bug-color-dark: #ad2617;
+        --bug-color-darker: #f5b1aa;
+        --invariant-color: #303a35;
+        --invariant-color-dark: #76ce96;
+        --invariant-color-darker: #cceed5;
+
+        --fragment-background: #282c34;
+        --fragment-foreground: #dbe4eb;
+        --fragment-keyword: #cc99cd;
+        --fragment-keywordtype: #ab99cd;
+        --fragment-keywordflow: #e08000;
+        --fragment-token: #7ec699;
+        --fragment-comment: #999999;
+        --fragment-link: #98c0e3;
+        --fragment-preprocessor: #65cabe;
+        --fragment-linenumber-color: #cccccc;
+        --fragment-linenumber-background: #35393c;
+        --fragment-linenumber-border: #1f1f1f;
+    }
+}
+
+/* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */
+html.dark-mode {
+    color-scheme: dark;
+
+    --primary-color: #1982d2;
+    --primary-dark-color: #86a9c4;
+    --primary-light-color: #4779ac;
+
+    --box-shadow: 0 2px 8px 0 rgba(0,0,0,.30);
+
+    --odd-color: rgba(100,100,100,.06);
+
+    --menu-selected-background: rgba(0,0,0,.4);
+
+    --page-background-color: #1C1D1F;
+    --page-foreground-color: #d2dbde;
+    --page-secondary-foreground-color: #859399;
+    --separator-color: #38393b;
+    --side-nav-background: #252628;
+
+    --code-background: #2a2c2f;
+
+    --tablehead-background: #2a2c2f;
+
+    --blockquote-background: #222325;
+    --blockquote-foreground: #7e8c92;
+
+    --warning-color: #3b2e04;
+    --warning-color-dark: #f1b602;
+    --warning-color-darker: #ceb670;
+    --note-color: #163750;
+    --note-color-dark: #1982D2;
+    --note-color-darker: #dcf0fa;
+    --todo-color: #2a2536;
+    --todo-color-dark: #7661b3;
+    --todo-color-darker: #ae9ed6;
+    --deprecated-color: #2e323b;
+    --deprecated-color-dark: #738396;
+    --deprecated-color-darker: #abb0bd;
+    --bug-color: #2e1917;
+    --bug-color-dark: #ad2617;
+    --bug-color-darker: #f5b1aa;
+    --invariant-color: #303a35;
+    --invariant-color-dark: #76ce96;
+    --invariant-color-darker: #cceed5;
+
+    --fragment-background: #282c34;
+    --fragment-foreground: #dbe4eb;
+    --fragment-keyword: #cc99cd;
+    --fragment-keywordtype: #ab99cd;
+    --fragment-keywordflow: #e08000;
+    --fragment-token: #7ec699;
+    --fragment-comment: #999999;
+    --fragment-link: #98c0e3;
+    --fragment-preprocessor: #65cabe;
+    --fragment-linenumber-color: #cccccc;
+    --fragment-linenumber-background: #35393c;
+    --fragment-linenumber-border: #1f1f1f;
+}
+
+body {
+    color: var(--page-foreground-color);
+    background-color: var(--page-background-color);
+    font-size: var(--page-font-size);
+}
+
+body, table, div, p, dl, #nav-tree .label, .title,
+.sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname,
+.SelectItem, #MSearchField, .navpath li.navelem a,
+.navpath li.navelem a:hover, p.reference, p.definition, div.toc li, div.toc h3 {
+    font-family: var(--font-family);
+}
+
+h1, h2, h3, h4, h5 {
+    margin-top: 1em;
+    font-weight: 600;
+    line-height: initial;
+}
+
+p, div, table, dl, p.reference, p.definition {
+    font-size: var(--page-font-size);
+}
+
+p.reference, p.definition {
+    color: var(--page-secondary-foreground-color);
+}
+
+a:link, a:visited, a:hover, a:focus, a:active {
+    color: var(--primary-color) !important;
+    font-weight: 500;
+    background: none;
+}
+
+a.anchor {
+    scroll-margin-top: var(--spacing-large);
+    display: block;
+}
+
+/*
+ Title and top navigation
+ */
+
+#top {
+    background: var(--header-background);
+    border-bottom: 1px solid var(--separator-color);
+}
+
+@media screen and (min-width: 768px) {
+    #top {
+        display: flex;
+        flex-wrap: wrap;
+        justify-content: space-between;
+        align-items: center;
+    }
+}
+
+#main-nav {
+    flex-grow: 5;
+    padding: var(--spacing-small) var(--spacing-medium);
+}
+
+#titlearea {
+    width: auto;
+    padding: var(--spacing-medium) var(--spacing-large);
+    background: none;
+    color: var(--header-foreground);
+    border-bottom: none;
+}
+
+@media screen and (max-width: 767px) {
+    #titlearea {
+        padding-bottom: var(--spacing-small);
+    }
+}
+
+#titlearea table tbody tr {
+    height: auto !important;
+}
+
+#projectname {
+    font-size: var(--title-font-size);
+    font-weight: 600;
+}
+
+#projectnumber {
+    font-family: inherit;
+    font-size: 60%;
+}
+
+#projectbrief {
+    font-family: inherit;
+    font-size: 80%;
+}
+
+#projectlogo {
+    vertical-align: middle;
+}
+
+#projectlogo img {
+    max-height: calc(var(--title-font-size) * 2);
+    margin-right: var(--spacing-small);
+}
+
+.sm-dox, .tabs, .tabs2, .tabs3 {
+    background: none;
+    padding: 0;
+}
+
+.tabs, .tabs2, .tabs3 {
+    border-bottom: 1px solid var(--separator-color);
+    margin-bottom: -1px;
+}
+
+.main-menu-btn-icon, .main-menu-btn-icon:before, .main-menu-btn-icon:after {
+    background: var(--page-secondary-foreground-color);
+}
+
+@media screen and (max-width: 767px) {
+    .sm-dox a span.sub-arrow {
+        background: var(--code-background);
+    }
+
+    #main-menu a.has-submenu span.sub-arrow {
+        color: var(--page-secondary-foreground-color);
+        border-radius: var(--border-radius-medium);
+    }
+
+    #main-menu a.has-submenu:hover span.sub-arrow {
+        color: var(--page-foreground-color);
+    }
+}
+
+@media screen and (min-width: 768px) {
+    .sm-dox li, .tablist li {
+        display: var(--menu-display);
+    }
+
+    .sm-dox a span.sub-arrow {
+        border-color: var(--header-foreground) transparent transparent transparent;
+    }
+
+    .sm-dox a:hover span.sub-arrow {
+        border-color: var(--menu-focus-foreground) transparent transparent transparent;
+    }
+
+    .sm-dox ul a span.sub-arrow {
+        border-color: transparent transparent transparent var(--page-foreground-color);
+    }
+
+    .sm-dox ul a:hover span.sub-arrow {
+        border-color: transparent transparent transparent var(--menu-focus-foreground);
+    }
+}
+
+.sm-dox ul {
+    background: var(--page-background-color);
+    box-shadow: var(--box-shadow);
+    border: 1px solid var(--separator-color);
+    border-radius: var(--border-radius-medium) !important;
+    padding: var(--spacing-small);
+    animation: ease-out 150ms slideInMenu;
+}
+
+@keyframes slideInMenu {
+    from {
+        opacity: 0;
+        transform: translate(0px, -2px);
+    }
+
+    to {
+        opacity: 1;
+        transform: translate(0px, 0px);
+    }
+}
+
+.sm-dox ul a {
+    color: var(--page-foreground-color) !important;
+    background: var(--page-background-color);
+    font-size: var(--navigation-font-size);
+}
+
+.sm-dox>li>ul:after {
+    border-bottom-color: var(--page-background-color) !important;
+}
+
+.sm-dox>li>ul:before {
+    border-bottom-color: var(--separator-color) !important;
+}
+
+.sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus {
+    font-size: var(--navigation-font-size) !important;
+    color: var(--menu-focus-foreground) !important;
+    text-shadow: none;
+    background-color: var(--menu-focus-background);
+    border-radius: var(--border-radius-small) !important;
+}
+
+.sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a {
+    text-shadow: none;
+    background: transparent;
+    background-image: none !important;
+    color: var(--header-foreground) !important;
+    font-weight: normal;
+    font-size: var(--navigation-font-size);
+    border-radius: var(--border-radius-small) !important;
+}
+
+.sm-dox a:focus {
+    outline: auto;
+}
+
+.sm-dox a:hover, .sm-dox a:active, .tablist li a:hover {
+    text-shadow: none;
+    font-weight: normal;
+    background: var(--menu-focus-background);
+    color: var(--menu-focus-foreground) !important;
+    border-radius: var(--border-radius-small) !important;
+    font-size: var(--navigation-font-size);
+}
+
+.tablist li.current {
+    border-radius: var(--border-radius-small);
+    background: var(--menu-selected-background);
+}
+
+.tablist li {
+    margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small);
+}
+
+.tablist a {
+    padding: 0 var(--spacing-large);
+}
+
+
+/*
+ Search box
+ */
+
+#MSearchBox {
+    height: var(--searchbar-height);
+    background: var(--searchbar-background);
+    border-radius: var(--searchbar-border-radius);
+    border: 1px solid var(--separator-color);
+    overflow: hidden;
+    width: var(--searchbar-width);
+    position: relative;
+    box-shadow: none;
+    display: block;
+    margin-top: 0;
+}
+
+/* until Doxygen 1.9.4 */
+.left img#MSearchSelect {
+    left: 0;
+    user-select: none;
+    padding-left: 8px;
+}
+
+/* Doxygen 1.9.5 */
+.left span#MSearchSelect {
+    left: 0;
+    user-select: none;
+    margin-left: 8px;
+    padding: 0;
+}
+
+.left #MSearchSelect[src$=".png"] {
+    padding-left: 0
+}
+
+.SelectionMark {
+    user-select: none;
+}
+
+.tabs .left #MSearchSelect {
+    padding-left: 0;
+}
+
+.tabs #MSearchBox {
+    position: absolute;
+    right: var(--spacing-medium);
+}
+
+@media screen and (max-width: 767px) {
+    .tabs #MSearchBox {
+        position: relative;
+        right: 0;
+        margin-left: var(--spacing-medium);
+        margin-top: 0;
+    }
+}
+
+#MSearchSelectWindow, #MSearchResultsWindow {
+    z-index: 9999;
+}
+
+#MSearchBox.MSearchBoxActive {
+    border-color: var(--primary-color);
+    box-shadow: inset 0 0 0 1px var(--primary-color);
+}
+
+#main-menu > li:last-child {
+    margin-right: 0;
+}
+
+@media screen and (max-width: 767px) {
+    #main-menu > li:last-child {
+        height: 50px;
+    }
+}
+
+#MSearchField {
+    font-size: var(--navigation-font-size);
+    height: calc(var(--searchbar-height) - 2px);
+    background: transparent;
+    width: calc(var(--searchbar-width) - 64px);
+}
+
+.MSearchBoxActive #MSearchField {
+    color: var(--searchbar-foreground);
+}
+
+#MSearchSelect {
+    top: calc(calc(var(--searchbar-height) / 2) - 11px);
+}
+
+#MSearchBox span.left, #MSearchBox span.right {
+    background: none;
+    background-image: none;
+}
+
+#MSearchBox span.right {
+    padding-top: calc(calc(var(--searchbar-height) / 2) - 12px);
+    position: absolute;
+    right: var(--spacing-small);
+}
+
+.tabs #MSearchBox span.right {
+    top: calc(calc(var(--searchbar-height) / 2) - 12px);
+}
+
+@keyframes slideInSearchResults {
+    from {
+        opacity: 0;
+        transform: translate(0, 15px);
+    }
+
+    to {
+        opacity: 1;
+        transform: translate(0, 20px);
+    }
+}
+
+#MSearchResultsWindow {
+    left: auto !important;
+    right: var(--spacing-medium);
+    border-radius: var(--border-radius-large);
+    border: 1px solid var(--separator-color);
+    transform: translate(0, 20px);
+    box-shadow: var(--box-shadow);
+    animation: ease-out 280ms slideInSearchResults;
+    background: var(--page-background-color);
+}
+
+iframe#MSearchResults {
+    margin: 4px;
+}
+
+iframe {
+    color-scheme: normal;
+}
+
+@media (prefers-color-scheme: dark) {
+    html:not(.light-mode) iframe#MSearchResults {
+        filter: invert() hue-rotate(180deg);
+    }
+}
+
+html.dark-mode iframe#MSearchResults {
+    filter: invert() hue-rotate(180deg);
+}
+
+#MSearchResults .SRPage {
+    background-color: transparent;
+}
+
+#MSearchResults .SRPage .SREntry {
+    font-size: 10pt;
+    padding: var(--spacing-small) var(--spacing-medium);
+}
+
+#MSearchSelectWindow {
+    border: 1px solid var(--separator-color);
+    border-radius: var(--border-radius-medium);
+    box-shadow: var(--box-shadow);
+    background: var(--page-background-color);
+    padding-top: var(--spacing-small);
+    padding-bottom: var(--spacing-small);
+}
+
+#MSearchSelectWindow a.SelectItem {
+    font-size: var(--navigation-font-size);
+    line-height: var(--content-line-height);
+    margin: 0 var(--spacing-small);
+    border-radius: var(--border-radius-small);
+    color: var(--page-foreground-color) !important;
+    font-weight: normal;
+}
+
+#MSearchSelectWindow a.SelectItem:hover {
+    background: var(--menu-focus-background);
+    color: var(--menu-focus-foreground) !important;
+}
+
+@media screen and (max-width: 767px) {
+    #MSearchBox {
+        margin-top: var(--spacing-medium);
+        margin-bottom: var(--spacing-medium);
+        width: calc(100vw - 30px);
+    }
+
+    #main-menu > li:last-child {
+        float: none !important;
+    }
+
+    #MSearchField {
+        width: calc(100vw - 110px);
+    }
+
+    @keyframes slideInSearchResultsMobile {
+        from {
+            opacity: 0;
+            transform: translate(0, 15px);
+        }
+
+        to {
+            opacity: 1;
+            transform: translate(0, 20px);
+        }
+    }
+
+    #MSearchResultsWindow {
+        left: var(--spacing-medium) !important;
+        right: var(--spacing-medium);
+        overflow: auto;
+        transform: translate(0, 20px);
+        animation: ease-out 280ms slideInSearchResultsMobile;
+        width: auto !important;
+    }
+
+    /*
+     * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2
+     */
+    label.main-menu-btn ~ #searchBoxPos1 {
+        top: 3px !important;
+        right: 6px !important;
+        left: 45px;
+        display: flex;
+    }
+
+    label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox {
+        margin-top: 0;
+        margin-bottom: 0;
+        flex-grow: 2;
+        float: left;
+    }
+}
+
+/*
+ Tree view
+ */
+
+#side-nav {
+    padding: 0 !important;
+    background: var(--side-nav-background);
+    min-width: 8px;
+    max-width: 50vw;
+}
+
+@media screen and (max-width: 767px) {
+    #side-nav {
+        display: none;
+    }
+
+    #doc-content {
+        margin-left: 0 !important;
+    }
+}
+
+#nav-tree {
+    background: transparent;
+    margin-right: 1px;
+}
+
+#nav-tree .label {
+    font-size: var(--navigation-font-size);
+}
+
+#nav-tree .item {
+    height: var(--tree-item-height);
+    line-height: var(--tree-item-height);
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+#nav-tree .item > a:focus {
+    outline: none;
+}
+
+#nav-sync {
+    bottom: 12px;
+    right: 12px;
+    top: auto !important;
+    user-select: none;
+}
+
+#nav-tree .selected {
+    text-shadow: none;
+    background-image: none;
+    background-color: transparent;
+    position: relative;
+    color: var(--primary-color) !important;
+    font-weight: 500;
+}
+
+#nav-tree .selected::after {
+    content: "";
+    position: absolute;
+    top: 1px;
+    bottom: 1px;
+    left: 0;
+    width: 4px;
+    border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;
+    background: var(--primary-color);
+}
+
+
+#nav-tree a {
+    color: var(--side-nav-foreground) !important;
+    font-weight: normal;
+}
+
+#nav-tree a:focus {
+    outline-style: auto;
+}
+
+#nav-tree .arrow {
+    opacity: var(--side-nav-arrow-opacity);
+    background: none;
+}
+
+.arrow {
+    color: inherit;
+    cursor: pointer;
+    font-size: 45%;
+    vertical-align: middle;
+    margin-right: 2px;
+    font-family: serif;
+    height: auto;
+    text-align: right;
+}
+
+#nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow {
+    opacity: var(--side-nav-arrow-hover-opacity);
+}
+
+#nav-tree .selected a {
+    color: var(--primary-color) !important;
+    font-weight: bolder;
+    font-weight: 600;
+}
+
+.ui-resizable-e {
+    width: 4px;
+    background: transparent;
+    box-shadow: inset -1px 0 0 0 var(--separator-color);
+}
+
+/*
+ Contents
+ */
+
+div.header {
+    border-bottom: 1px solid var(--separator-color);
+    background-color: var(--page-background-color);
+    background-image: none;
+}
+
+@media screen and (min-width: 1000px) {
+    #doc-content > div > div.contents,
+    .PageDoc > div.contents {
+        display: flex;
+        flex-direction: row-reverse;
+        flex-wrap: nowrap;
+        align-items: flex-start;
+    }
+    
+    div.contents .textblock {
+        min-width: 200px;
+        flex-grow: 1;
+    }
+}
+
+div.contents, div.header .title, div.header .summary {
+    max-width: var(--content-maxwidth);
+}
+
+div.contents, div.header .title  {
+    line-height: initial;
+    margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto;
+}
+
+div.header .summary {
+    margin: var(--spacing-medium) auto 0 auto;
+}
+
+div.headertitle {
+    padding: 0;
+}
+
+div.header .title {
+    font-weight: 600;
+    font-size: 225%;
+    padding: var(--spacing-medium) var(--spacing-large);
+    word-break: break-word;
+}
+
+div.header .summary {
+    width: auto;
+    display: block;
+    float: none;
+    padding: 0 var(--spacing-large);
+}
+
+td.memSeparator {
+    border-color: var(--separator-color);
+}
+
+span.mlabel {
+    background: var(--primary-color);
+    color: var(--on-primary-color);
+    border: none;
+    padding: 4px 9px;
+    border-radius: 12px;
+    margin-right: var(--spacing-medium);
+}
+
+span.mlabel:last-of-type {
+    margin-right: 2px;
+}
+
+div.contents {
+    padding: 0 var(--spacing-large);
+}
+
+div.contents p, div.contents li {
+    line-height: var(--content-line-height);
+}
+
+div.contents div.dyncontent {
+    margin: var(--spacing-medium) 0;
+}
+
+@media (prefers-color-scheme: dark) {
+    html:not(.light-mode) div.contents div.dyncontent img,
+    html:not(.light-mode) div.contents center img,
+    html:not(.light-mode) div.contents > table img,
+    html:not(.light-mode) div.contents div.dyncontent iframe,
+    html:not(.light-mode) div.contents center iframe,
+    html:not(.light-mode) div.contents table iframe,
+    html:not(.light-mode) div.contents .dotgraph iframe {
+        filter: brightness(89%) hue-rotate(180deg) invert();
+    }
+}
+
+html.dark-mode div.contents div.dyncontent img,
+html.dark-mode div.contents center img,
+html.dark-mode div.contents > table img,
+html.dark-mode div.contents div.dyncontent iframe,
+html.dark-mode div.contents center iframe,
+html.dark-mode div.contents table iframe,
+html.dark-mode div.contents .dotgraph iframe
+ {
+    filter: brightness(89%) hue-rotate(180deg) invert();
+}
+
+h2.groupheader {
+    border-bottom: 0px;
+    color: var(--page-foreground-color);
+    box-shadow: 
+        100px 0 var(--page-background-color), 
+        -100px 0 var(--page-background-color),
+        100px 0.75px var(--separator-color),
+        -100px 0.75px var(--separator-color),
+        500px 0 var(--page-background-color), 
+        -500px 0 var(--page-background-color),
+        500px 0.75px var(--separator-color),
+        -500px 0.75px var(--separator-color),
+        900px 0 var(--page-background-color), 
+        -900px 0 var(--page-background-color),
+        900px 0.75px var(--separator-color),
+        -900px 0.75px var(--separator-color),
+        1400px 0 var(--page-background-color),
+        -1400px 0 var(--page-background-color), 
+        1400px 0.75px var(--separator-color),
+        -1400px 0.75px var(--separator-color),
+        1900px 0 var(--page-background-color),
+        -1900px 0 var(--page-background-color),
+        1900px 0.75px var(--separator-color),
+        -1900px 0.75px var(--separator-color);
+}
+
+blockquote {
+    margin: 0 var(--spacing-medium) 0 var(--spacing-medium);
+    padding: var(--spacing-small) var(--spacing-large);
+    background: var(--blockquote-background);
+    color: var(--blockquote-foreground);
+    border-left: 0;
+    overflow: visible;
+    border-radius: var(--border-radius-medium);
+    overflow: visible;
+    position: relative;
+}
+
+blockquote::before, blockquote::after {
+    font-weight: bold;
+    font-family: serif;
+    font-size: 360%;
+    opacity: .15;
+    position: absolute;
+}
+
+blockquote::before {
+    content: "“";
+    left: -10px;
+    top: 4px;
+}
+
+blockquote::after {
+    content: "”";
+    right: -8px;
+    bottom: -25px;
+}
+
+blockquote p {
+    margin: var(--spacing-small) 0 var(--spacing-medium) 0;
+}
+.paramname, .paramname em {
+    font-weight: 600;
+    color: var(--primary-dark-color);
+}
+
+.paramname > code {
+    border: 0;
+}
+
+table.params .paramname {
+    font-weight: 600;
+    font-family: var(--font-family-monospace);
+    font-size: var(--code-font-size);
+    padding-right: var(--spacing-small);
+    line-height: var(--table-line-height);
+}
+
+h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
+    text-shadow: 0 0 15px var(--primary-light-color);
+}
+
+.alphachar a {
+    color: var(--page-foreground-color);
+}
+
+.dotgraph {
+    max-width: 100%;
+    overflow-x: scroll;
+}
+
+.dotgraph .caption {
+    position: sticky;
+    left: 0;
+}
+
+/* Wrap Graphviz graphs with the `interactive_dotgraph` class if `INTERACTIVE_SVG = YES` */
+.interactive_dotgraph .dotgraph iframe {
+    max-width: 100%;
+}
+
+/*
+ Table of Contents
+ */
+
+div.contents .toc {
+    max-height: var(--toc-max-height);
+    min-width: var(--toc-width);
+    border: 0;
+    border-left: 1px solid var(--separator-color);
+    border-radius: 0;
+    background-color: var(--page-background-color);
+    box-shadow: none;
+    position: sticky;
+    top: var(--toc-sticky-top);
+    padding: 0 var(--spacing-large);
+    margin: var(--spacing-small) 0 var(--spacing-large) var(--spacing-large);
+}
+
+div.toc h3 {
+    color: var(--toc-foreground);
+    font-size: var(--navigation-font-size);
+    margin: var(--spacing-large) 0 var(--spacing-medium) 0;
+}
+
+div.toc li {
+    padding: 0;
+    background: none;
+    line-height: var(--toc-font-size);
+    margin: var(--toc-font-size) 0 0 0;
+}
+
+div.toc li::before {
+    display: none;
+}
+
+div.toc ul {
+    margin-top: 0
+}
+
+div.toc li a {
+    font-size: var(--toc-font-size);
+    color: var(--page-foreground-color) !important;
+    text-decoration: none;
+}
+
+div.toc li a:hover, div.toc li a.active {
+    color: var(--primary-color) !important;
+}
+
+div.toc li a.aboveActive {
+    color: var(--page-secondary-foreground-color) !important;
+}
+
+
+@media screen and (max-width: 999px) {
+    div.contents .toc {
+        max-height: 45vh;
+        float: none;
+        width: auto;
+        margin: 0 0 var(--spacing-medium) 0;
+        position: relative;
+        top: 0;
+        position: relative;
+        border: 1px solid var(--separator-color);
+        border-radius: var(--border-radius-medium);
+        background-color: var(--toc-background);
+        box-shadow: var(--box-shadow);
+    }
+
+    div.contents .toc.interactive {
+        max-height: calc(var(--navigation-font-size) + 2 * var(--spacing-large));
+        overflow: hidden;
+    }
+
+    div.contents .toc > h3 {
+        -webkit-tap-highlight-color: transparent;
+        cursor: pointer;
+        position: sticky;
+        top: 0;
+        background-color: var(--toc-background);
+        margin: 0;
+        padding: var(--spacing-large) 0;
+        display: block;
+    }
+
+    div.contents .toc.interactive > h3::before {
+        content: "";
+        width: 0; 
+        height: 0; 
+        border-left: 4px solid transparent;
+        border-right: 4px solid transparent;
+        border-top: 5px solid var(--primary-color);
+        display: inline-block;
+        margin-right: var(--spacing-small);
+        margin-bottom: calc(var(--navigation-font-size) / 4);
+        transform: rotate(-90deg);
+        transition: transform var(--animation-duration) ease-out;
+    }
+
+    div.contents .toc.interactive.open > h3::before {
+        transform: rotate(0deg);
+    }
+
+    div.contents .toc.interactive.open {
+        max-height: 45vh;
+        overflow: auto;
+        transition: max-height 0.2s ease-in-out;
+    }
+
+    div.contents .toc a, div.contents .toc a.active {
+        color: var(--primary-color) !important;
+    }
+
+    div.contents .toc a:hover {
+        text-decoration: underline;
+    }
+}
+
+/*
+ Code & Fragments
+ */
+
+code, div.fragment, pre.fragment {
+    border-radius: var(--border-radius-small);
+    border: 1px solid var(--separator-color);
+    overflow: hidden;
+}
+
+code {
+    display: inline;
+    background: var(--code-background);
+    color: var(--code-foreground);
+    padding: 2px 6px;
+}
+
+div.fragment, pre.fragment {
+    margin: var(--spacing-medium) 0;
+    padding: calc(var(--spacing-large) - (var(--spacing-large) / 6)) var(--spacing-large);
+    background: var(--fragment-background);
+    color: var(--fragment-foreground);
+    overflow-x: auto;
+}
+
+@media screen and (max-width: 767px) {
+    div.fragment, pre.fragment {
+        border-top-right-radius: 0;
+        border-bottom-right-radius: 0;
+        border-right: 0;
+    }
+
+    .contents > div.fragment,
+    .textblock > div.fragment,
+    .textblock > pre.fragment,
+    .textblock > .tabbed > ul > li > div.fragment,
+    .textblock > .tabbed > ul > li > pre.fragment,
+    .contents > .doxygen-awesome-fragment-wrapper > div.fragment,
+    .textblock > .doxygen-awesome-fragment-wrapper > div.fragment,
+    .textblock > .doxygen-awesome-fragment-wrapper > pre.fragment,
+    .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > div.fragment,
+    .textblock > .tabbed > ul > li > .doxygen-awesome-fragment-wrapper > pre.fragment {
+        margin: var(--spacing-medium) calc(0px - var(--spacing-large));
+        border-radius: 0;
+        border-left: 0;
+    }
+
+    .textblock li > .fragment,
+    .textblock li > .doxygen-awesome-fragment-wrapper > .fragment {
+        margin: var(--spacing-medium) calc(0px - var(--spacing-large));
+    }
+
+    .memdoc li > .fragment,
+    .memdoc li > .doxygen-awesome-fragment-wrapper > .fragment {
+        margin: var(--spacing-medium) calc(0px - var(--spacing-medium));
+    }
+
+    .textblock ul, .memdoc ul {
+        overflow: initial;
+    }
+
+    .memdoc > div.fragment,
+    .memdoc > pre.fragment,
+    dl dd > div.fragment,
+    dl dd pre.fragment,
+    .memdoc > .doxygen-awesome-fragment-wrapper > div.fragment,
+    .memdoc > .doxygen-awesome-fragment-wrapper > pre.fragment,
+    dl dd > .doxygen-awesome-fragment-wrapper > div.fragment,
+    dl dd .doxygen-awesome-fragment-wrapper > pre.fragment {
+        margin: var(--spacing-medium) calc(0px - var(--spacing-medium));
+        border-radius: 0;
+        border-left: 0;
+    }
+}
+
+code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span {
+    font-family: var(--font-family-monospace);
+    font-size: var(--code-font-size) !important;
+}
+
+div.line:after {
+    margin-right: var(--spacing-medium);
+}
+
+div.fragment .line, pre.fragment {
+    white-space: pre;
+    word-wrap: initial;
+    line-height: var(--fragment-lineheight);
+}
+
+div.fragment span.keyword {
+    color: var(--fragment-keyword);
+}
+
+div.fragment span.keywordtype {
+    color: var(--fragment-keywordtype);
+}
+
+div.fragment span.keywordflow {
+    color: var(--fragment-keywordflow);
+}
+
+div.fragment span.stringliteral {
+    color: var(--fragment-token)
+}
+
+div.fragment span.comment {
+    color: var(--fragment-comment);
+}
+
+div.fragment a.code {
+    color: var(--fragment-link) !important;
+}
+
+div.fragment span.preprocessor {
+    color: var(--fragment-preprocessor);
+}
+
+div.fragment span.lineno {
+    display: inline-block;
+    width: 27px;
+    border-right: none;
+    background: var(--fragment-linenumber-background);
+    color: var(--fragment-linenumber-color);
+}
+
+div.fragment span.lineno a {
+    background: none;
+    color: var(--fragment-link) !important;
+}
+
+div.fragment > .line:first-child .lineno {
+    box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border);
+    background-color: var(--fragment-linenumber-background) !important;
+}
+
+div.line {
+    border-radius: var(--border-radius-small);
+}
+
+div.line.glow {
+    background-color: var(--primary-light-color);
+    box-shadow: none;
+}
+
+/*
+ dl warning, attention, note, deprecated, bug, ...
+ */
+
+dl.bug dt a, dl.deprecated dt a, dl.todo dt a {
+    font-weight: bold !important;
+}
+
+dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre, dl.post, dl.todo, dl.remark {
+    padding: var(--spacing-medium);
+    margin: var(--spacing-medium) 0;
+    color: var(--page-background-color);
+    overflow: hidden;
+    margin-left: 0;
+    border-radius: var(--border-radius-small);
+}
+
+dl.section dd {
+    margin-bottom: 2px;
+}
+
+dl.warning, dl.attention {
+    background: var(--warning-color);
+    border-left: 8px solid var(--warning-color-dark);
+    color: var(--warning-color-darker);
+}
+
+dl.warning dt, dl.attention dt {
+    color: var(--warning-color-dark);
+}
+
+dl.note, dl.remark {
+    background: var(--note-color);
+    border-left: 8px solid var(--note-color-dark);
+    color: var(--note-color-darker);
+}
+
+dl.note dt, dl.remark dt {
+    color: var(--note-color-dark);
+}
+
+dl.todo {
+    background: var(--todo-color);
+    border-left: 8px solid var(--todo-color-dark);
+    color: var(--todo-color-darker);
+}
+
+dl.todo dt a {
+    color: var(--todo-color-dark) !important;
+}
+
+dl.bug dt a {
+    color: var(--todo-color-dark) !important;
+}
+
+dl.bug {
+    background: var(--bug-color);
+    border-left: 8px solid var(--bug-color-dark);
+    color: var(--bug-color-darker);
+}
+
+dl.bug dt a {
+    color: var(--bug-color-dark) !important;
+}
+
+dl.deprecated {
+    background: var(--deprecated-color);
+    border-left: 8px solid var(--deprecated-color-dark);
+    color: var(--deprecated-color-darker);
+}
+
+dl.deprecated dt a {
+    color: var(--deprecated-color-dark) !important;
+}
+
+dl.section dd, dl.bug dd, dl.deprecated dd, dl.todo dd {
+    margin-inline-start: 0px;
+}
+
+dl.invariant, dl.pre, dl.post {
+    background: var(--invariant-color);
+    border-left: 8px solid var(--invariant-color-dark);
+    color: var(--invariant-color-darker);
+}
+
+dl.invariant dt, dl.pre dt, dl.post dt {
+    color: var(--invariant-color-dark);
+}
+
+/*
+ memitem
+ */
+
+div.memdoc, div.memproto, h2.memtitle {
+    box-shadow: none;
+    background-image: none;
+    border: none;
+}
+
+div.memdoc {
+    padding: 0 var(--spacing-medium);
+    background: var(--page-background-color);
+}
+
+h2.memtitle, div.memitem {
+    border: 1px solid var(--separator-color);
+    box-shadow: var(--box-shadow);
+}
+
+h2.memtitle {
+    box-shadow: 0px var(--spacing-medium) 0 -1px var(--fragment-background), var(--box-shadow);
+}
+
+div.memitem {
+    transition: none;
+}
+
+div.memproto, h2.memtitle {
+    background: var(--fragment-background);
+}
+
+h2.memtitle {
+    font-weight: 500;
+    font-size: var(--memtitle-font-size);
+    font-family: var(--font-family-monospace);
+    border-bottom: none;
+    border-top-left-radius: var(--border-radius-medium);
+    border-top-right-radius: var(--border-radius-medium);
+    word-break: break-all;
+    position: relative;
+}
+
+h2.memtitle:after {
+    content: "";
+    display: block;
+    background: var(--fragment-background);
+    height: var(--spacing-medium);
+    bottom: calc(0px - var(--spacing-medium));
+    left: 0;
+    right: -14px;
+    position: absolute;
+    border-top-right-radius: var(--border-radius-medium);
+}
+
+h2.memtitle > span.permalink {
+    font-size: inherit;
+}
+
+h2.memtitle > span.permalink > a {
+    text-decoration: none;
+    padding-left: 3px;
+    margin-right: -4px;
+    user-select: none;
+    display: inline-block;
+    margin-top: -6px;
+}
+
+h2.memtitle > span.permalink > a:hover {
+    color: var(--primary-dark-color) !important;
+}
+
+a:target + h2.memtitle, a:target + h2.memtitle + div.memitem {
+    border-color: var(--primary-light-color);
+}
+
+div.memitem {
+    border-top-right-radius: var(--border-radius-medium);
+    border-bottom-right-radius: var(--border-radius-medium);
+    border-bottom-left-radius: var(--border-radius-medium);
+    overflow: hidden;
+    display: block !important;
+}
+
+div.memdoc {
+    border-radius: 0;
+}
+
+div.memproto {
+    border-radius: 0 var(--border-radius-small) 0 0;
+    overflow: auto;
+    border-bottom: 1px solid var(--separator-color);
+    padding: var(--spacing-medium);
+    margin-bottom: -1px;
+}
+
+div.memtitle {
+    border-top-right-radius: var(--border-radius-medium);
+    border-top-left-radius: var(--border-radius-medium);
+}
+
+div.memproto table.memname {
+    font-family: var(--font-family-monospace);
+    color: var(--page-foreground-color);
+    font-size: var(--memname-font-size);
+    text-shadow: none;
+}
+
+div.memproto div.memtemplate {
+    font-family: var(--font-family-monospace);
+    color: var(--primary-dark-color);
+    font-size: var(--memname-font-size);
+    margin-left: 2px;
+    text-shadow: none;
+}
+
+table.mlabels, table.mlabels > tbody {
+    display: block;
+}
+
+td.mlabels-left {
+    width: auto;
+}
+
+td.mlabels-right {
+    margin-top: 3px;
+    position: sticky;
+    left: 0;
+}
+
+table.mlabels > tbody > tr:first-child {
+    display: flex;
+    justify-content: space-between;
+    flex-wrap: wrap;
+}
+
+.memname, .memitem span.mlabels {
+    margin: 0
+}
+
+/*
+ reflist
+ */
+
+dl.reflist {
+    box-shadow: var(--box-shadow);
+    border-radius: var(--border-radius-medium);
+    border: 1px solid var(--separator-color);
+    overflow: hidden;
+    padding: 0;
+}
+
+
+dl.reflist dt, dl.reflist dd {
+    box-shadow: none;
+    text-shadow: none;
+    background-image: none;
+    border: none;
+    padding: 12px;
+}
+
+
+dl.reflist dt {
+    font-weight: 500;
+    border-radius: 0;
+    background: var(--code-background);
+    border-bottom: 1px solid var(--separator-color);
+    color: var(--page-foreground-color)
+}
+
+
+dl.reflist dd {
+    background: none;
+}
+
+/*
+ Table
+ */
+
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname),
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody {
+    display: inline-block;
+    max-width: 100%;
+}
+
+.contents > table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname):not(.classindex) {
+    margin-left: calc(0px - var(--spacing-large));
+    margin-right: calc(0px - var(--spacing-large));
+    max-width: calc(100% + 2 * var(--spacing-large));
+}
+
+table.fieldtable,
+table.markdownTable tbody,
+table.doxtable tbody {
+    border: none;
+    margin: var(--spacing-medium) 0;
+    box-shadow: 0 0 0 1px var(--separator-color);
+    border-radius: var(--border-radius-small);
+}
+
+table.markdownTable, table.doxtable, table.fieldtable {
+    padding: 1px;
+}
+
+table.doxtable caption {
+    display: block;
+}
+
+table.fieldtable {
+    border-collapse: collapse;
+    width: 100%;
+}
+
+th.markdownTableHeadLeft,
+th.markdownTableHeadRight,
+th.markdownTableHeadCenter,
+th.markdownTableHeadNone,
+table.doxtable th {
+    background: var(--tablehead-background);
+    color: var(--tablehead-foreground);
+    font-weight: 600;
+    font-size: var(--page-font-size);
+}
+
+th.markdownTableHeadLeft:first-child,
+th.markdownTableHeadRight:first-child,
+th.markdownTableHeadCenter:first-child,
+th.markdownTableHeadNone:first-child,
+table.doxtable tr th:first-child {
+    border-top-left-radius: var(--border-radius-small);
+}
+
+th.markdownTableHeadLeft:last-child,
+th.markdownTableHeadRight:last-child,
+th.markdownTableHeadCenter:last-child,
+th.markdownTableHeadNone:last-child,
+table.doxtable tr th:last-child {
+    border-top-right-radius: var(--border-radius-small);
+}
+
+table.markdownTable td,
+table.markdownTable th,
+table.fieldtable td,
+table.fieldtable th,
+table.doxtable td,
+table.doxtable th {
+    border: 1px solid var(--separator-color);
+    padding: var(--spacing-small) var(--spacing-medium);
+}
+
+table.markdownTable td:last-child,
+table.markdownTable th:last-child,
+table.fieldtable td:last-child,
+table.fieldtable th:last-child,
+table.doxtable td:last-child,
+table.doxtable th:last-child {
+    border-right: none;
+}
+
+table.markdownTable td:first-child,
+table.markdownTable th:first-child,
+table.fieldtable td:first-child,
+table.fieldtable th:first-child,
+table.doxtable td:first-child,
+table.doxtable th:first-child {
+    border-left: none;
+}
+
+table.markdownTable tr:first-child td,
+table.markdownTable tr:first-child th,
+table.fieldtable tr:first-child td,
+table.fieldtable tr:first-child th,
+table.doxtable tr:first-child td,
+table.doxtable tr:first-child th {
+    border-top: none;
+}
+
+table.markdownTable tr:last-child td,
+table.markdownTable tr:last-child th,
+table.fieldtable tr:last-child td,
+table.fieldtable tr:last-child th,
+table.doxtable tr:last-child td,
+table.doxtable tr:last-child th {
+    border-bottom: none;
+}
+
+table.markdownTable tr, table.doxtable tr {
+    border-bottom: 1px solid var(--separator-color);
+}
+
+table.markdownTable tr:last-child, table.doxtable tr:last-child {
+    border-bottom: none;
+}
+
+.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) {
+    display: block;
+}
+
+.full_width_table table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody {
+    display: table;
+    width: 100%;
+}
+
+table.fieldtable th {
+    font-size: var(--page-font-size);
+    font-weight: 600;
+    background-image: none;
+    background-color: var(--tablehead-background);
+    color: var(--tablehead-foreground);
+}
+
+table.fieldtable td.fieldtype, .fieldtable td.fieldname, .fieldtable td.fieldinit, .fieldtable td.fielddoc, .fieldtable th {
+    border-bottom: 1px solid var(--separator-color);
+    border-right: 1px solid var(--separator-color);
+}
+
+table.fieldtable tr:last-child td:first-child {
+    border-bottom-left-radius: var(--border-radius-small);
+}
+
+table.fieldtable tr:last-child td:last-child {
+    border-bottom-right-radius: var(--border-radius-small);
+}
+
+.memberdecls td.glow, .fieldtable tr.glow {
+    background-color: var(--primary-light-color);
+    box-shadow: none;
+}
+
+table.memberdecls {
+    display: block;
+    -webkit-tap-highlight-color: transparent;
+}
+
+table.memberdecls tr[class^='memitem'] {
+    font-family: var(--font-family-monospace);
+    font-size: var(--code-font-size);
+}
+
+table.memberdecls tr[class^='memitem'] .memTemplParams {
+    font-family: var(--font-family-monospace);
+    font-size: var(--code-font-size);
+    color: var(--primary-dark-color);
+    white-space: normal;
+}
+
+table.memberdecls .memItemLeft,
+table.memberdecls .memItemRight,
+table.memberdecls .memTemplItemLeft,
+table.memberdecls .memTemplItemRight,
+table.memberdecls .memTemplParams {
+    transition: none;
+    padding-top: var(--spacing-small);
+    padding-bottom: var(--spacing-small);
+    border-top: 1px solid var(--separator-color);
+    border-bottom: 1px solid var(--separator-color);
+    background-color: var(--fragment-background);
+}
+
+table.memberdecls .memTemplItemLeft,
+table.memberdecls .memTemplItemRight {
+    padding-top: 2px;
+}
+
+table.memberdecls .memTemplParams {
+    border-bottom: 0;
+    border-left: 1px solid var(--separator-color);
+    border-right: 1px solid var(--separator-color);
+    border-radius: var(--border-radius-small) var(--border-radius-small) 0 0;
+    padding-bottom: var(--spacing-small);
+}
+
+table.memberdecls .memTemplItemLeft {
+    border-radius: 0 0 0 var(--border-radius-small);
+    border-left: 1px solid var(--separator-color);
+    border-top: 0;
+}
+
+table.memberdecls .memTemplItemRight {
+    border-radius: 0 0 var(--border-radius-small) 0;
+    border-right: 1px solid var(--separator-color);
+    padding-left: 0;
+    border-top: 0;
+}
+
+table.memberdecls .memItemLeft {
+    border-radius: var(--border-radius-small) 0 0 var(--border-radius-small);
+    border-left: 1px solid var(--separator-color);
+    padding-left: var(--spacing-medium);
+    padding-right: 0;
+}
+
+table.memberdecls .memItemRight  {
+    border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;
+    border-right: 1px solid var(--separator-color);
+    padding-right: var(--spacing-medium);
+    padding-left: 0;
+
+}
+
+table.memberdecls .mdescLeft, table.memberdecls .mdescRight {
+    background: none;
+    color: var(--page-foreground-color);
+    padding: var(--spacing-small) 0;
+}
+
+table.memberdecls .memItemLeft,
+table.memberdecls .memTemplItemLeft {
+    padding-right: var(--spacing-medium);
+}
+
+table.memberdecls .memSeparator {
+    background: var(--page-background-color);
+    height: var(--spacing-large);
+    border: 0;
+    transition: none;
+}
+
+table.memberdecls .groupheader {
+    margin-bottom: var(--spacing-large);
+}
+
+table.memberdecls .inherit_header td {
+    padding: 0 0 var(--spacing-medium) 0;
+    text-indent: -12px;
+    color: var(--page-secondary-foreground-color);
+}
+
+table.memberdecls img[src="closed.png"],
+table.memberdecls img[src="open.png"],
+div.dynheader img[src="open.png"],
+div.dynheader img[src="closed.png"] {
+    width: 0; 
+    height: 0; 
+    border-left: 4px solid transparent;
+    border-right: 4px solid transparent;
+    border-top: 5px solid var(--primary-color);
+    margin-top: 8px;
+    display: block;
+    float: left;
+    margin-left: -10px;
+    transition: transform var(--animation-duration) ease-out;
+}
+
+table.memberdecls img {
+    margin-right: 10px;
+}
+
+table.memberdecls img[src="closed.png"],
+div.dynheader img[src="closed.png"] {
+    transform: rotate(-90deg);
+    
+}
+
+.compoundTemplParams {
+    font-family: var(--font-family-monospace);
+    color: var(--primary-dark-color);
+    font-size: var(--code-font-size);
+}
+
+@media screen and (max-width: 767px) {
+
+    table.memberdecls .memItemLeft,
+    table.memberdecls .memItemRight,
+    table.memberdecls .mdescLeft,
+    table.memberdecls .mdescRight,
+    table.memberdecls .memTemplItemLeft,
+    table.memberdecls .memTemplItemRight,
+    table.memberdecls .memTemplParams {
+        display: block;
+        text-align: left;
+        padding-left: var(--spacing-large);
+        margin: 0 calc(0px - var(--spacing-large)) 0 calc(0px - var(--spacing-large));
+        border-right: none;
+        border-left: none;
+        border-radius: 0;
+        white-space: normal;
+    }
+
+    table.memberdecls .memItemLeft,
+    table.memberdecls .mdescLeft,
+    table.memberdecls .memTemplItemLeft {
+        border-bottom: 0;
+        padding-bottom: 0;
+    }
+
+    table.memberdecls .memTemplItemLeft {
+        padding-top: 0;
+    }
+
+    table.memberdecls .mdescLeft {
+        margin-bottom: calc(0px - var(--page-font-size));
+    }
+
+    table.memberdecls .memItemRight, 
+    table.memberdecls .mdescRight,
+    table.memberdecls .memTemplItemRight {
+        border-top: 0;
+        padding-top: 0;
+        padding-right: var(--spacing-large);
+        overflow-x: auto;
+    }
+
+    table.memberdecls tr[class^='memitem']:not(.inherit) {
+        display: block;
+        width: calc(100vw - 2 * var(--spacing-large));
+    }
+
+    table.memberdecls .mdescRight {
+        color: var(--page-foreground-color);
+    }
+
+    table.memberdecls tr.inherit {
+        visibility: hidden;
+    }
+
+    table.memberdecls tr[style="display: table-row;"] {
+        display: block !important;
+        visibility: visible;
+        width: calc(100vw - 2 * var(--spacing-large));
+        animation: fade .5s;
+    }
+
+    @keyframes fade {
+        0% {
+            opacity: 0;
+            max-height: 0;
+        }
+
+        100% {
+            opacity: 1;
+            max-height: 200px;
+        }
+    }
+}
+
+
+/*
+ Horizontal Rule
+ */
+
+hr {
+    margin-top: var(--spacing-large);
+    margin-bottom: var(--spacing-large);
+    height: 1px;
+    background-color: var(--separator-color);
+    border: 0;
+}
+
+.contents hr {
+    box-shadow: 100px 0 var(--separator-color),
+                -100px 0 var(--separator-color),
+                500px 0 var(--separator-color),
+                -500px 0 var(--separator-color),
+                900px 0 var(--separator-color),
+                -900px 0 var(--separator-color),
+                1400px 0 var(--separator-color),
+                -1400px 0 var(--separator-color),
+                1900px 0 var(--separator-color),
+                -1900px 0 var(--separator-color);       
+}
+
+.contents img, .contents .center, .contents center, .contents div.image object {
+    max-width: 100%;
+    overflow: auto;
+}
+
+@media screen and (max-width: 767px) {
+    .contents .dyncontent > .center, .contents > center {
+        margin-left: calc(0px - var(--spacing-large));
+        margin-right: calc(0px - var(--spacing-large));
+        max-width: calc(100% + 2 * var(--spacing-large));
+    }
+}
+
+/*
+ Directories
+ */
+div.directory {
+    border-top: 1px solid var(--separator-color);
+    border-bottom: 1px solid var(--separator-color);
+    width: auto;
+}
+
+table.directory {
+    font-family: var(--font-family);
+    font-size: var(--page-font-size);
+    font-weight: normal;
+    width: 100%;
+}
+
+table.directory td.entry, table.directory td.desc {
+    padding: calc(var(--spacing-small) / 2) var(--spacing-small);
+    line-height: var(--table-line-height);
+}
+
+table.directory tr.even td:last-child {
+    border-radius: 0 var(--border-radius-small) var(--border-radius-small) 0;
+}
+
+table.directory tr.even td:first-child {
+    border-radius: var(--border-radius-small) 0 0 var(--border-radius-small);
+}
+
+table.directory tr.even:last-child td:last-child {
+    border-radius: 0 var(--border-radius-small) 0 0;
+}
+
+table.directory tr.even:last-child td:first-child {
+    border-radius: var(--border-radius-small) 0 0 0;
+}
+
+table.directory td.desc {
+    min-width: 250px;
+}
+
+table.directory tr.even {
+    background-color: var(--odd-color);
+}
+
+table.directory tr.odd {
+    background-color: transparent;
+}
+
+.icona {
+    width: auto;
+    height: auto;
+    margin: 0 var(--spacing-small);
+}
+
+.icon {
+    background: var(--primary-color);
+    border-radius: var(--border-radius-small);
+    font-size: var(--page-font-size);
+    padding: calc(var(--page-font-size) / 5);
+    line-height: var(--page-font-size);
+    transform: scale(0.8);
+    height: auto;
+    width: var(--page-font-size);
+    user-select: none;
+}
+
+.iconfopen, .icondoc, .iconfclosed {
+    background-position: center;
+    margin-bottom: 0;
+    height: var(--table-line-height);
+}
+
+.icondoc {
+    filter: saturate(0.2);
+}
+
+@media screen and (max-width: 767px) {
+    div.directory {
+        margin-left: calc(0px - var(--spacing-large));
+        margin-right: calc(0px - var(--spacing-large));
+    }
+}
+
+@media (prefers-color-scheme: dark) {
+    html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed {
+        filter: hue-rotate(180deg) invert();
+    }
+}
+
+html.dark-mode .iconfopen, html.dark-mode .iconfclosed {
+    filter: hue-rotate(180deg) invert();
+}
+
+/*
+ Class list
+ */
+
+.classindex dl.odd {
+    background: var(--odd-color);
+    border-radius: var(--border-radius-small);
+}
+
+.classindex dl.even {
+    background-color: transparent;
+}
+
+/* 
+ Class Index Doxygen 1.8 
+*/
+
+table.classindex {
+    margin-left: 0;
+    margin-right: 0;
+    width: 100%;
+}
+
+table.classindex table div.ah {
+    background-image: none;
+    background-color: initial;
+    border-color: var(--separator-color);
+    color: var(--page-foreground-color);
+    box-shadow: var(--box-shadow);
+    border-radius: var(--border-radius-large);
+    padding: var(--spacing-small);
+}
+
+div.qindex {
+    background-color: var(--odd-color);
+    border-radius: var(--border-radius-small);
+    border: 1px solid var(--separator-color);
+    padding: var(--spacing-small) 0;
+}
+
+/*
+  Footer and nav-path
+ */
+
+#nav-path {
+    width: 100%;
+}
+
+#nav-path ul {
+    background-image: none;
+    background: var(--page-background-color);
+    border: none;
+    border-top: 1px solid var(--separator-color);
+    border-bottom: 1px solid var(--separator-color);
+    border-bottom: 0;
+    box-shadow: 0 0.75px 0 var(--separator-color);
+    font-size: var(--navigation-font-size);
+}
+
+img.footer {
+    width: 60px;
+}
+
+.navpath li.footer {
+    color: var(--page-secondary-foreground-color);
+}
+
+address.footer {
+    color: var(--page-secondary-foreground-color);
+    margin-bottom: var(--spacing-large);
+}
+
+#nav-path li.navelem {
+    background-image: none;
+    display: flex;
+    align-items: center;
+}
+
+.navpath li.navelem a {
+    text-shadow: none;
+    display: inline-block;
+    color: var(--primary-color) !important;
+}
+
+.navpath li.navelem b {
+    color: var(--primary-dark-color);
+    font-weight: 500;
+}
+
+li.navelem {
+    padding: 0;
+    margin-left: -8px;
+}
+
+li.navelem:first-child {
+    margin-left: var(--spacing-large);
+}
+
+li.navelem:first-child:before {
+    display: none;
+}
+
+#nav-path li.navelem:after {
+    content: '';
+    border: 5px solid var(--page-background-color);
+    border-bottom-color: transparent;
+    border-right-color: transparent;
+    border-top-color: transparent;
+    transform: translateY(-1px) scaleY(4.2);
+    z-index: 10;
+    margin-left: 6px;
+}
+
+#nav-path li.navelem:before {
+    content: '';
+    border: 5px solid var(--separator-color);
+    border-bottom-color: transparent;
+    border-right-color: transparent;
+    border-top-color: transparent;
+    transform: translateY(-1px) scaleY(3.2);
+    margin-right: var(--spacing-small);
+}
+
+.navpath li.navelem a:hover {
+    color: var(--primary-color);
+}
+
+/*
+ Scrollbars for Webkit
+*/
+
+#nav-tree::-webkit-scrollbar,
+div.fragment::-webkit-scrollbar,
+pre.fragment::-webkit-scrollbar,
+div.memproto::-webkit-scrollbar,
+.contents center::-webkit-scrollbar,
+.contents .center::-webkit-scrollbar,
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar,
+div.contents .toc::-webkit-scrollbar,
+.contents .dotgraph::-webkit-scrollbar,
+.contents .tabs-overview-container::-webkit-scrollbar {
+    background: transparent;
+    width: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding));
+    height: calc(var(--webkit-scrollbar-size) + var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding));
+}
+
+#nav-tree::-webkit-scrollbar-thumb,
+div.fragment::-webkit-scrollbar-thumb,
+pre.fragment::-webkit-scrollbar-thumb,
+div.memproto::-webkit-scrollbar-thumb,
+.contents center::-webkit-scrollbar-thumb,
+.contents .center::-webkit-scrollbar-thumb,
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-thumb,
+div.contents .toc::-webkit-scrollbar-thumb,
+.contents .dotgraph::-webkit-scrollbar-thumb,
+.contents .tabs-overview-container::-webkit-scrollbar-thumb {
+    background-color: transparent;
+    border: var(--webkit-scrollbar-padding) solid transparent;
+    border-radius: calc(var(--webkit-scrollbar-padding) + var(--webkit-scrollbar-padding));
+    background-clip: padding-box;  
+}
+
+#nav-tree:hover::-webkit-scrollbar-thumb,
+div.fragment:hover::-webkit-scrollbar-thumb,
+pre.fragment:hover::-webkit-scrollbar-thumb,
+div.memproto:hover::-webkit-scrollbar-thumb,
+.contents center:hover::-webkit-scrollbar-thumb,
+.contents .center:hover::-webkit-scrollbar-thumb,
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody:hover::-webkit-scrollbar-thumb,
+div.contents .toc:hover::-webkit-scrollbar-thumb,
+.contents .dotgraph:hover::-webkit-scrollbar-thumb,
+.contents .tabs-overview-container:hover::-webkit-scrollbar-thumb {
+    background-color: var(--webkit-scrollbar-color);
+}
+
+#nav-tree::-webkit-scrollbar-track,
+div.fragment::-webkit-scrollbar-track,
+pre.fragment::-webkit-scrollbar-track,
+div.memproto::-webkit-scrollbar-track,
+.contents center::-webkit-scrollbar-track,
+.contents .center::-webkit-scrollbar-track,
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody::-webkit-scrollbar-track,
+div.contents .toc::-webkit-scrollbar-track,
+.contents .dotgraph::-webkit-scrollbar-track,
+.contents .tabs-overview-container::-webkit-scrollbar-track {
+    background: transparent;
+}
+
+#nav-tree::-webkit-scrollbar-corner {
+    background-color: var(--side-nav-background);
+}
+
+#nav-tree,
+div.fragment,
+pre.fragment,
+div.memproto,
+.contents center,
+.contents .center,
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody,
+div.contents .toc {
+    overflow-x: auto;
+    overflow-x: overlay;
+}
+
+#nav-tree {
+    overflow-x: auto;
+    overflow-y: auto;
+    overflow-y: overlay;
+}
+
+/*
+ Scrollbars for Firefox
+*/
+
+#nav-tree,
+div.fragment,
+pre.fragment,
+div.memproto,
+.contents center,
+.contents .center,
+.contents table:not(.memberdecls):not(.mlabels):not(.fieldtable):not(.memname) tbody,
+div.contents .toc,
+.contents .dotgraph,
+.contents .tabs-overview-container {
+    scrollbar-width: thin;
+}
+
+/*
+  Optional Dark mode toggle button
+*/
+
+doxygen-awesome-dark-mode-toggle {
+    display: inline-block;
+    margin: 0 0 0 var(--spacing-small);
+    padding: 0;
+    width: var(--searchbar-height);
+    height: var(--searchbar-height);
+    background: none;
+    border: none;
+    border-radius: var(--searchbar-height);
+    vertical-align: middle;
+    text-align: center;
+    line-height: var(--searchbar-height);
+    font-size: 22px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    user-select: none;
+    cursor: pointer;
+}
+
+doxygen-awesome-dark-mode-toggle > svg {
+    transition: transform var(--animation-duration) ease-in-out;
+}
+
+doxygen-awesome-dark-mode-toggle:active > svg {
+    transform: scale(.5);
+}
+
+doxygen-awesome-dark-mode-toggle:hover {
+    background-color: rgba(0,0,0,.03);
+}
+
+html.dark-mode doxygen-awesome-dark-mode-toggle:hover {
+    background-color: rgba(0,0,0,.18);
+}
+
+/*
+ Optional fragment copy button
+*/
+.doxygen-awesome-fragment-wrapper {
+    position: relative;
+}
+
+doxygen-awesome-fragment-copy-button {
+    opacity: 0;
+    background: var(--fragment-background);
+    width: 28px;
+    height: 28px;
+    position: absolute;
+    right: calc(var(--spacing-large) - (var(--spacing-large) / 2.5));
+    top: calc(var(--spacing-large) - (var(--spacing-large) / 2.5));
+    border: 1px solid var(--fragment-foreground);
+    cursor: pointer;
+    border-radius: var(--border-radius-small);
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+
+.doxygen-awesome-fragment-wrapper:hover doxygen-awesome-fragment-copy-button, doxygen-awesome-fragment-copy-button.success {
+    opacity: .28;
+}
+
+doxygen-awesome-fragment-copy-button:hover, doxygen-awesome-fragment-copy-button.success {
+    opacity: 1 !important;
+}
+
+doxygen-awesome-fragment-copy-button:active:not([class~=success]) svg {
+    transform: scale(.91);
+}
+
+doxygen-awesome-fragment-copy-button svg {
+    fill: var(--fragment-foreground);
+    width: 18px;
+    height: 18px;
+}
+
+doxygen-awesome-fragment-copy-button.success svg {
+    fill: rgb(14, 168, 14);
+}
+
+doxygen-awesome-fragment-copy-button.success {
+    border-color: rgb(14, 168, 14);
+}
+
+@media screen and (max-width: 767px) {
+    .textblock > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,
+    .textblock li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,
+    .memdoc li > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,
+    .memdoc > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button,
+    dl dd > .doxygen-awesome-fragment-wrapper > doxygen-awesome-fragment-copy-button {
+        right: 0;
+    }
+}
+
+/*
+ Optional paragraph link button
+*/
+
+a.anchorlink {
+    font-size: 90%;
+    margin-left: var(--spacing-small);
+    color: var(--page-foreground-color) !important;
+    text-decoration: none;
+    opacity: .15;
+    display: none;
+    transition: opacity var(--animation-duration) ease-in-out, color var(--animation-duration) ease-in-out;
+}
+
+a.anchorlink svg {
+    fill: var(--page-foreground-color);
+}
+
+h3 a.anchorlink svg, h4 a.anchorlink svg {
+    margin-bottom: -3px;
+    margin-top: -4px;
+}
+
+a.anchorlink:hover {
+    opacity: .45;
+}
+
+h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.anchorlink  {
+    display: inline-block;
+}
+
+/*
+ Optional tab feature
+*/
+
+.tabbed > ul {
+    padding-inline-start: 0px;
+    margin: 0;
+    padding: var(--spacing-small) 0;
+}
+
+.tabbed > ul > li {
+    display: none;
+}
+
+.tabbed > ul > li.selected {
+    display: block;
+}
+
+.tabs-overview-container {
+    overflow-x: auto;
+    display: block;
+    overflow-y: visible;
+}
+
+.tabs-overview {
+    border-bottom: 1px solid var(--separator-color);
+    display: flex;
+    flex-direction: row;
+}
+
+@media screen and (max-width: 767px) {
+    .tabs-overview-container {
+        margin: 0 calc(0px - var(--spacing-large));
+    }
+    .tabs-overview {
+        padding: 0 var(--spacing-large)
+    }
+}
+
+.tabs-overview button.tab-button {
+    color: var(--page-foreground-color);
+    margin: 0;
+    border: none;
+    background: transparent;
+    padding: calc(var(--spacing-large) / 2) 0;
+    display: inline-block;
+    font-size: var(--page-font-size);
+    cursor: pointer;
+    box-shadow: 0 1px 0 0 var(--separator-color);
+    position: relative;
+    
+    -webkit-tap-highlight-color: transparent;
+}
+
+.tabs-overview button.tab-button .tab-title::before {
+    display: block;
+    content: attr(title);
+    font-weight: 600;
+    height: 0;
+    overflow: hidden;
+    visibility: hidden;
+}
+
+.tabs-overview button.tab-button .tab-title {
+    float: left;
+    white-space: nowrap;
+    font-weight: normal;
+    padding: calc(var(--spacing-large) / 2) var(--spacing-large);
+    border-radius: var(--border-radius-medium);
+    transition: background-color var(--animation-duration) ease-in-out, font-weight var(--animation-duration) ease-in-out;
+}
+
+.tabs-overview button.tab-button:not(:last-child) .tab-title {
+    box-shadow: 8px 0 0 -7px var(--separator-color);
+}
+
+.tabs-overview button.tab-button:hover .tab-title {
+    background: var(--separator-color);
+    box-shadow: none;
+}
+
+.tabs-overview button.tab-button.active .tab-title {
+    font-weight: 600;
+}
+
+.tabs-overview button.tab-button::after {
+    content: '';
+    display: block;
+    position: absolute;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    height: 0;
+    width: 0%;
+    margin: 0 auto;
+    border-radius: var(--border-radius-small) var(--border-radius-small) 0 0;
+    background-color: var(--primary-color);
+    transition: width var(--animation-duration) ease-in-out, height var(--animation-duration) ease-in-out;
+}
+
+.tabs-overview button.tab-button.active::after {
+    width: 100%;
+    box-sizing: border-box;
+    height: 3px;
+}
+
+
+/*
+ Navigation Buttons
+*/
+
+.section_buttons:not(:empty) {
+    margin-top: calc(var(--spacing-large) * 3);
+}
+
+.section_buttons table.markdownTable {
+    display: block;
+    width: 100%;
+}
+
+.section_buttons table.markdownTable tbody {
+    display: table !important;
+    width: 100%;
+    box-shadow: none;
+    border-spacing: 10px;
+}
+
+.section_buttons table.markdownTable td {
+    padding: 0;
+}
+
+.section_buttons table.markdownTable th {
+    display: none;
+}
+
+.section_buttons table.markdownTable tr.markdownTableHead {
+    border: none;
+}
+
+.section_buttons tr th, .section_buttons tr td {
+    background: none;
+    border: none;
+    padding: var(--spacing-large) 0 var(--spacing-small);
+}
+
+.section_buttons a {
+    display: inline-block;
+    border: 1px solid var(--separator-color);
+    border-radius: var(--border-radius-medium);
+    color: var(--page-secondary-foreground-color) !important;
+    text-decoration: none;
+    transition: color var(--animation-duration) ease-in-out, background-color var(--animation-duration) ease-in-out;
+}
+
+.section_buttons a:hover {
+    color: var(--page-foreground-color) !important;
+    background-color: var(--odd-color);
+}
+
+.section_buttons tr td.markdownTableBodyLeft a {
+    padding: var(--spacing-medium) var(--spacing-large) var(--spacing-medium) calc(var(--spacing-large) / 2);
+}
+
+.section_buttons tr td.markdownTableBodyRight a {
+    padding: var(--spacing-medium) calc(var(--spacing-large) / 2) var(--spacing-medium) var(--spacing-large);
+}
+
+.section_buttons tr td.markdownTableBodyLeft a::before,
+.section_buttons tr td.markdownTableBodyRight a::after {
+    color: var(--page-secondary-foreground-color) !important;
+    display: inline-block;
+    transition: color .08s ease-in-out, transform .09s ease-in-out;
+}
+
+.section_buttons tr td.markdownTableBodyLeft a::before {
+    content: '〈';
+    padding-right: var(--spacing-large);
+}
+
+
+.section_buttons tr td.markdownTableBodyRight a::after {
+    content: '〉';
+    padding-left: var(--spacing-large);
+}
+
+
+.section_buttons tr td.markdownTableBodyLeft a:hover::before {
+    color: var(--page-foreground-color) !important;
+    transform: translateX(-3px);
+}
+
+.section_buttons tr td.markdownTableBodyRight a:hover::after {
+    color: var(--page-foreground-color) !important;
+    transform: translateX(3px);
+}
+
+@media screen and (max-width: 450px) {
+    .section_buttons a {
+        width: 100%;
+        box-sizing: border-box;
+    }
+
+    .section_buttons tr td:nth-of-type(1).markdownTableBodyLeft a {
+        border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium);
+        border-right: none;
+    }
+
+    .section_buttons tr td:nth-of-type(2).markdownTableBodyRight a {
+        border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0;
+    }
+}
diff -pruN 0.5.0-1/Documentation/environment_variables.rst 0.6.0-2/Documentation/environment_variables.rst
--- 0.5.0-1/Documentation/environment_variables.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/environment_variables.rst	1970-01-01 00:00:00.000000000 +0000
@@ -1,176 +0,0 @@
-.. SPDX-License-Identifier: CC-BY-SA-4.0
-
-.. include:: documentation-contents.rst
-
-Environment variables
-=====================
-
-The libcamera behaviour can be tuned through environment variables. This
-document lists all the available variables and describes their usage.
-
-List of variables
------------------
-
-LIBCAMERA_LOG_FILE
-   The custom destination for log output.
-
-   Example value: ``/home/{user}/camera_log.log``
-
-LIBCAMERA_LOG_LEVELS
-   Configure the verbosity of log messages for different categories (`more <Log levels_>`__).
-
-   Example value: ``*:DEBUG``
-
-LIBCAMERA_LOG_NO_COLOR
-   Disable coloring of log messages (`more <Notes about debugging_>`__).
-
-LIBCAMERA_IPA_CONFIG_PATH
-   Define custom search locations for IPA configurations (`more <IPA configuration_>`__).
-
-   Example value: ``${HOME}/.libcamera/share/ipa:/opt/libcamera/vendor/share/ipa``
-
-LIBCAMERA_IPA_FORCE_ISOLATION
-   When set to a non-empty string, force process isolation of all IPA modules.
-
-   Example value: ``1``
-
-LIBCAMERA_IPA_MODULE_PATH
-   Define custom search locations for IPA modules (`more <IPA module_>`__).
-
-   Example value: ``${HOME}/.libcamera/lib:/opt/libcamera/vendor/lib``
-
-LIBCAMERA_IPA_PROXY_PATH
-   Define custom full path for a proxy worker for a given executable name.
-
-   Example value: ``${HOME}/.libcamera/proxy/worker:/opt/libcamera/vendor/proxy/worker``
-
-LIBCAMERA_PIPELINES_MATCH_LIST
-   Define an ordered list of pipeline names to be used to match the media
-   devices in the system. The pipeline handler names used to populate the
-   variable are the ones passed to the REGISTER_PIPELINE_HANDLER() macro in the
-   source code.
-
-   Example value: ``rkisp1,simple``
-
-LIBCAMERA_RPI_CONFIG_FILE
-   Define a custom configuration file to use in the Raspberry Pi pipeline handler.
-
-   Example value: ``/usr/local/share/libcamera/pipeline/rpi/vc4/minimal_mem.yaml``
-
-LIBCAMERA_<NAME>_TUNING_FILE
-   Define a custom IPA tuning file to use with the pipeline handler `NAME`.
-
-   Example value: ``/usr/local/share/libcamera/ipa/rpi/vc4/custom_sensor.json``
-
-Further details
----------------
-
-Notes about debugging
-~~~~~~~~~~~~~~~~~~~~~
-
-The environment variables ``LIBCAMERA_LOG_FILE``, ``LIBCAMERA_LOG_LEVELS`` and
-``LIBCAMERA_LOG_NO_COLOR`` are used to modify the default configuration of the
-libcamera logger.
-
-By default, libcamera logs all messages to the standard error (std::cerr).
-Messages are colored by default depending on the log level. Coloring can be
-disabled by setting the ``LIBCAMERA_LOG_NO_COLOR`` environment variable.
-
-The default log destination can also be directed to a file by setting the
-``LIBCAMERA_LOG_FILE`` environment variable to the log file name. This also
-disables coloring.
-
-Log levels are controlled through the ``LIBCAMERA_LOG_LEVELS`` variable, which
-accepts a comma-separated list of 'category:level' pairs.
-
-The `level <Log levels_>`__ part is mandatory and can either be specified by
-name or by numerical index associated with each level.
-
-The optional `category <Log categories_>`__ is a string matching the categories
-defined by each file in the source base using the logging infrastructure. It
-can include a wildcard ('*') character at the end to match multiple categories.
-
-For more information refer to the `API documentation <https://libcamera.org/api-html/log_8h.html#details>`__.
-
-Examples:
-
-Enable full debug output to a separate file, for every `category <Log categories_>`__
-within a local environment:
-
-.. code:: bash
-
-   :~$ LIBCAMERA_LOG_FILE='/tmp/example_log.log' \
-       LIBCAMERA_LOG_LEVELS=0 \
-       cam --list
-
-Enable full debug output for the categories ``Camera`` and ``V4L2`` within a
-global environment:
-
-.. code:: bash
-
-   :~$ export LIBCAMERA_LOG_LEVELS='Camera:DEBUG,V4L2:DEBUG'
-   :~$ cam --list
-
-Log levels
-~~~~~~~~~~
-
-This is the list of available log levels, notice that all levels below
-the chosen one are printed, while those above are discarded.
-
--  DEBUG (0)
--  INFO (1)
--  WARN (2)
--  ERROR (3)
--  FATAL (4)
-
-Example:
-If you choose WARN (2), you will be able to see WARN (2), ERROR (3) and FATAL (4)
-but not DEBUG (0) and INFO (1).
-
-Log categories
-~~~~~~~~~~~~~~
-
-Every category represents a specific area of the libcamera codebase,
-the names can be located within the source code, for example:
-`src/libcamera/camera_manager.cpp <https://git.libcamera.org/libcamera/libcamera.git/tree/src/libcamera/camera_manager.cpp#n35>`__
-
-.. code:: cpp
-
-   LOG_DEFINE_CATEGORY(Camera)
-
-There are two available macros used to assign a category name to a part of the
-libcamera codebase:
-
-LOG_DEFINE_CATEGORY
-   This macro is required, in order to use the ``LOGC`` macro for a particular
-   category. It can only be used once for each category. If you want to create
-   log messages within multiple compilation units for the same category utilize
-   the ``LOG_DECLARE_CATEGORY`` macro, in every file except the definition file.
-LOG_DECLARE_CATEGORY
-   Used for sharing an already defined category between multiple separate
-   compilation units.
-
-Both macros have to be used within the libcamera namespace of the C++ source
-code.
-
-IPA configuration
-~~~~~~~~~~~~~~~~~
-
-IPA modules use configuration files to store parameters. The format and
-contents of the configuration files is specific to the IPA module. They usually
-contain tuning parameters for the algorithms, in JSON format.
-
-The ``LIBCAMERA_IPA_CONFIG_PATH`` variable can be used to specify custom
-storage locations to search for those configuration files.
-
-`Examples <https://git.libcamera.org/libcamera/libcamera.git/tree/src/ipa/rpi/vc4/data>`__
-
-IPA module
-~~~~~~~~~~
-
-In order to locate the correct IPA module for your hardware, libcamera gathers
-existing IPA modules from multiple locations. The default locations for this
-operation are the installed system path (for example on Debian:
-``/usr/local/x86_64-pc-linux-gnu/libcamera``) and the build directory.
-With the ``LIBCAMERA_IPA_MODULE_PATH``, you can specify a non-default location
-to search for IPA modules.
diff -pruN 0.5.0-1/Documentation/feature_requirements.rst 0.6.0-2/Documentation/feature_requirements.rst
--- 0.5.0-1/Documentation/feature_requirements.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/feature_requirements.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 Feature Requirements
 ====================
 
diff -pruN 0.5.0-1/Documentation/gen-doxyfile.py 0.6.0-2/Documentation/gen-doxyfile.py
--- 0.5.0-1/Documentation/gen-doxyfile.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/gen-doxyfile.py	2025-11-27 11:55:28.000000000 +0000
@@ -12,15 +12,6 @@ import string
 import sys
 
 
-def fill_template(template, data):
-
-    template = open(template, 'rb').read()
-    template = template.decode('utf-8')
-    template = string.Template(template)
-
-    return template.substitute(data)
-
-
 def main(argv):
 
     parser = argparse.ArgumentParser()
@@ -28,7 +19,8 @@ def main(argv):
                         type=argparse.FileType('w', encoding='utf-8'),
                         default=sys.stdout,
                         help='Output file name (default: standard output)')
-    parser.add_argument('template', metavar='doxyfile.tmpl', type=str,
+    parser.add_argument('template', metavar='doxyfile.tmpl',
+                        type=argparse.FileType('r', encoding='utf-8'),
                         help='Doxyfile template')
     parser.add_argument('inputs', type=str, nargs='*',
                         help='Input files')
@@ -36,7 +28,9 @@ def main(argv):
     args = parser.parse_args(argv[1:])
 
     inputs = [f'"{os.path.realpath(input)}"' for input in args.inputs]
-    data = fill_template(args.template, {'inputs': (' \\\n' + ' ' * 25).join(inputs)})
+    data = string.Template(args.template.read()).substitute({
+        'inputs': (' \\\n' + ' ' * 25).join(inputs),
+    })
     args.output.write(data)
 
     return 0
diff -pruN 0.5.0-1/Documentation/guides/application-developer.rst 0.6.0-2/Documentation/guides/application-developer.rst
--- 0.5.0-1/Documentation/guides/application-developer.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/guides/application-developer.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: ../documentation-contents.rst
-
 Using libcamera in a C++ application
 ====================================
 
@@ -46,15 +44,14 @@ defined names and types without the need
 Camera Manager
 --------------
 
-Every libcamera-based application needs an instance of a `CameraManager`_ that
-runs for the life of the application. When the Camera Manager starts, it
+Every libcamera-based application needs an instance of a :doxy-pub:`CameraManager`
+that runs for the life of the application. When the Camera Manager starts, it
 enumerates all the cameras detected in the system. Behind the scenes, libcamera
 abstracts and manages the complex pipelines that kernel drivers expose through
 the `Linux Media Controller`_ and `Video for Linux`_ (V4L2) APIs, meaning that
 an application doesn't need to handle device or driver specific details.
 
-.. _CameraManager: https://libcamera.org/api-html/classlibcamera_1_1CameraManager.html
-.. _Linux Media Controller: https://www.kernel.org/doc/html/latest/media/uapi/mediactl/media-controller-intro.html
+.. _Linux Media Controller: https://www.kernel.org/doc/html/latest/userspace-api/media/mediactl/media-controller.html
 .. _Video for Linux: https://www.linuxtv.org/docs.php
 
 Before the ``int main()`` function, create a global shared pointer
@@ -210,10 +207,9 @@ function. If the new values are not supp
 validation process adjusts the parameters to what it considers to be the closest
 supported values.
 
-The ``validate`` function returns a `Status`_ which applications shall check to
-see if the Pipeline Handler adjusted the configuration.
-
-.. _Status: https://libcamera.org/api-html/classlibcamera_1_1CameraConfiguration.html#a64163f21db2fe1ce0a6af5a6f6847744
+The ``validate`` function returns a :doxy-pub:`CameraConfiguration::Status`
+which applications shall check to see if the Pipeline Handler adjusted the
+configuration.
 
 For example, the code above set the width and height to 640x480, but if the
 camera cannot produce an image that large, it might adjust the configuration to
@@ -348,10 +344,10 @@ camera device, and associate a buffer fo
 Event handling and callbacks
 ----------------------------
 
-The libcamera library uses the concept of `signals and slots` (similar to `Qt
-Signals and Slots`_) to connect events with callbacks to handle them.
+The libcamera library uses the concept of :doxy-pub:`signals and slots <Signal>`
+(similar to `Qt Signals and Slots`_) to connect events with callbacks to handle
+them.
 
-.. _signals and slots: https://libcamera.org/api-html/classlibcamera_1_1Signal.html#details
 .. _Qt Signals and Slots: https://doc.qt.io/qt-6/signalsandslots.html
 
 The ``Camera`` device emits two signals that applications can connect to in
@@ -400,9 +396,7 @@ Request completion events can be emitted
 for example, by unexpected application shutdown. To avoid an application
 processing invalid image data, it's worth checking that the request has
 completed successfully. The list of request completion statuses is available in
-the `Request::Status`_ class enum documentation.
-
-.. _Request::Status: https://www.libcamera.org/api-html/classlibcamera_1_1Request.html#a2209ba8d51af8167b25f6e3e94d5c45b
+the :doxy-pub:`Request::Status` class enum documentation.
 
 .. code:: cpp
 
@@ -422,9 +416,7 @@ Iterating through the map allows applica
 in this request, and access the metadata associated to each frame.
 
 The metadata buffer contains information such the capture status, a timestamp,
-and the bytes used, as described in the `FrameMetadata`_ documentation.
-
-.. _FrameMetaData: https://libcamera.org/api-html/structlibcamera_1_1FrameMetadata.html
+and the bytes used, as described in the :doxy-pub:`FrameMetadata` documentation.
 
 .. code:: cpp
 
@@ -515,13 +507,11 @@ and queue all the previously created req
 Event processing
 ~~~~~~~~~~~~~~~~
 
-libcamera creates an internal execution thread at `CameraManager::start()`_
+libcamera creates an internal execution thread at :doxy-pub:`CameraManager::start()`
 time to decouple its own event processing from the application's main thread.
 Applications are thus free to manage their own execution opportunely, and only
 need to respond to events generated by libcamera emitted through signals.
 
-.. _CameraManager::start(): https://libcamera.org/api-html/classlibcamera_1_1CameraManager.html#a49e322880a2a26013bb0076788b298c5
-
 Real-world applications will likely either integrate with the event loop of the
 framework they use, or create their own event loop to respond to user events.
 For the simple application presented in this example, it is enough to prevent
@@ -618,7 +608,7 @@ accordingly. In this example, the applic
 
    simple_cam = executable('simple-cam',
        'simple-cam.cpp',
-       dependencies: dependency('libcamera', required : true))
+       dependencies: dependency('libcamera'))
 
 The ``dependencies`` line instructs meson to ask ``pkgconfig`` (or ``cmake``) to
 locate the ``libcamera`` library,  which the test application will be
diff -pruN 0.5.0-1/Documentation/guides/ipa.rst 0.6.0-2/Documentation/guides/ipa.rst
--- 0.5.0-1/Documentation/guides/ipa.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/guides/ipa.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: ../documentation-contents.rst
-
 IPA Writer's Guide
 ==================
 
diff -pruN 0.5.0-1/Documentation/guides/pipeline-handler.rst 0.6.0-2/Documentation/guides/pipeline-handler.rst
--- 0.5.0-1/Documentation/guides/pipeline-handler.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/guides/pipeline-handler.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: ../documentation-contents.rst
-
 Pipeline Handler Writers Guide
 ==============================
 
@@ -83,49 +81,49 @@ functionalities described above. Below i
 .. TODO: (MediaDevice) Reference to the Media Device API (possibly with versioning requirements)
 .. TODO: (IPAInterface) refer to the IPA guide
 
--  `MediaDevice <https://libcamera.org/api-html/classlibcamera_1_1MediaDevice.html>`_:
+-  :doxy-int:`MediaDevice`:
    Instances of this class are associated with a kernel media controller
    device and its connected objects.
 
--  `DeviceEnumerator <https://libcamera.org/api-html/classlibcamera_1_1DeviceEnumerator.html>`_:
+-  :doxy-int:`DeviceEnumerator`:
    Enumerates all media devices attached to the system and the media entities
    registered with it, by creating instances of the ``MediaDevice`` class and
    storing them.
 
--  `DeviceMatch <https://libcamera.org/api-html/classlibcamera_1_1DeviceMatch.html>`_:
+-  :doxy-int:`DeviceMatch`:
    Describes a media device search pattern using entity names, or other
    properties.
 
--  `V4L2VideoDevice <https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html>`_:
+-  :doxy-int:`V4L2VideoDevice`:
    Models an instance of a V4L2 video device constructed with the path to a V4L2
    video device node.
 
--  `V4L2SubDevice <https://libcamera.org/api-html/classlibcamera_1_1V4L2Subdevice.html>`_:
+-  :doxy-int:`V4L2Subdevice`:
    Provides an API to the sub-devices that model the hardware components of a
    V4L2 device.
 
--  `CameraSensor <https://libcamera.org/api-html/classlibcamera_1_1CameraSensor.html>`_:
+-  :doxy-int:`CameraSensor`:
    Abstracts camera sensor handling by hiding the details of the V4L2 subdevice
    kernel API and caching sensor information.
 
--  `Camera::Private <https://libcamera.org/api-html/classlibcamera_1_1Camera_1_1Private.html>`_:
+-  :doxy-int:`Camera::Private`:
    Represents device-specific data a pipeline handler associates to each Camera
    instance.
 
--  `StreamConfiguration <https://libcamera.org/api-html/structlibcamera_1_1StreamConfiguration.html>`_:
+-  :doxy-int:`StreamConfiguration`:
    Models the current configuration of an image stream produced by the camera by
    reporting its format and sizes.
 
--  `CameraConfiguration <https://libcamera.org/api-html/classlibcamera_1_1CameraConfiguration.html>`_:
+-  :doxy-int:`CameraConfiguration`:
    Represents the current configuration of a camera, which includes a list of
    stream configurations for each active stream in a capture session. When
    validated, it is applied to the camera.
 
--  `IPAInterface <https://libcamera.org/api-html/classlibcamera_1_1IPAInterface.html>`_:
+-  :doxy-int:`IPAInterface`:
    The interface to the Image Processing Algorithm (IPA) module which performs
    the computation of the image processing pipeline tuning parameters.
 
--  `ControlList <https://libcamera.org/api-html/classlibcamera_1_1ControlList.html>`_:
+-  :doxy-int:`ControlList`:
    A list of control items, indexed by Control<> instances or by numerical index
    which contains values used by application and IPA to change parameters of
    image streams, used to return to applications and share with IPA the metadata
@@ -191,10 +189,8 @@ to the libcamera build options in the to
 
 
 In *vivid.cpp* add the pipeline handler to the ``libcamera`` namespace, defining
-a `PipelineHandler`_ derived class named PipelineHandlerVivid, and add stub
-implementations for the overridden class members.
-
-.. _PipelineHandler: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html
+a :doxy-int:`PipelineHandler` derived class named PipelineHandlerVivid, and add
+stub implementations for the overridden class members.
 
 .. code-block:: cpp
 
@@ -213,7 +209,7 @@ implementations for the overridden class
           std::vector<std::unique_ptr<FrameBuffer>> *buffers) override;
 
           int start(Camera *camera, const ControlList *controls) override;
-          void stop(Camera *camera) override;
+          void stopDevice(Camera *camera) override;
 
           int queueRequestDevice(Camera *camera, Request *request) override;
 
@@ -247,7 +243,7 @@ implementations for the overridden class
           return -1;
    }
 
-   void PipelineHandlerVivid::stop(Camera *camera)
+   void PipelineHandlerVivid::stopDevice(Camera *camera)
    {
    }
 
@@ -266,21 +262,17 @@ implementations for the overridden class
    } /* namespace libcamera */
 
 Note that you must register the ``PipelineHandler`` subclass with the pipeline
-handler factory using the `REGISTER_PIPELINE_HANDLER`_ macro which
+handler factory using the :doxy-int:`REGISTER_PIPELINE_HANDLER` macro which
 registers it and creates a global symbol to reference the class and make it
 available to try and match devices.
 String "vivid" is the name assigned to the pipeline, matching the pipeline
 subdirectory name in the source tree.
 
-.. _REGISTER_PIPELINE_HANDLER: https://libcamera.org/api-html/pipeline__handler_8h.html
-
 For debugging and testing a pipeline handler during development, you can define
 a log message category for the pipeline handler. The ``LOG_DEFINE_CATEGORY``
 macro and ``LIBCAMERA_LOG_LEVELS`` environment variable help you use the inbuilt
-libcamera `logging infrastructure`_ that allow for the inspection of internal
-operations in a user-configurable way.
-
-.. _logging infrastructure: https://libcamera.org/api-html/log_8h.html
+libcamera :doxy-int:`logging infrastructure <log.h>` that allow for the
+inspection of internal operations in a user-configurable way.
 
 Add the following before the ``PipelineHandlerVivid`` class declaration:
 
@@ -326,21 +318,18 @@ system configuration, by matching a ``De
 have been registered in the system and allows the pipeline handler to be
 initialized.
 
-The main entry point of a pipeline handler is the `match()`_ class member
-function. When the ``CameraManager`` is started (using the `start()`_ function),
-all the registered pipeline handlers are iterated and their ``match`` function
-called with an enumerator of all devices it found on a system.
+The main entry point of a pipeline handler is the :doxy-int:`PipelineHandler::match`
+class member function. When the ``CameraManager`` is started (using the
+:doxy-int:`CameraManager::start` function), all the registered pipeline
+handlers are iterated and their ``match`` function called with an enumerator of
+all devices it found on a system.
 
 The match function should identify if there are suitable devices available in
 the ``DeviceEnumerator`` which the pipeline supports, returning ``true`` if it
 matches a device, and ``false`` if it does not. To do this, construct a
-`DeviceMatch`_ class with the name of the ``MediaController`` device to match.
-You can specify the search further by adding specific media entities to the
-search using the ``.add()`` function on the DeviceMatch.
-
-.. _match(): https://www.libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#a7cd5b652a2414b543ec20ba9dabf61b6
-.. _start(): https://libcamera.org/api-html/classlibcamera_1_1CameraManager.html#a49e322880a2a26013bb0076788b298c5
-.. _DeviceMatch: https://libcamera.org/api-html/classlibcamera_1_1DeviceMatch.html
+:doxy-int:`DeviceMatch` class with the name of the ``MediaController`` device
+to match. You can specify the search further by adding specific media entities
+to the search using the ``.add()`` function on the DeviceMatch.
 
 This example uses search patterns that match vivid, but when developing a new
 pipeline handler, you should change this value to suit your device identifier.
@@ -355,11 +344,9 @@ following:
    return false; // Prevent infinite loops for now
 
 With the device matching criteria defined, attempt to acquire exclusive access
-to the matching media controller device with the `acquireMediaDevice`_ function.
-If the function attempts to acquire a device it has already matched, it returns
-``false``.
-
-.. _acquireMediaDevice: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#a77e424fe704e7b26094164b9189e0f84
+to the matching media controller device with the :doxy-int:`PipelineHandler::acquireMediaDevice`
+function. If the function attempts to acquire a device it has already matched,
+it returns ``false``.
 
 Add the following below ``dm.add("vivid-000-vid-cap");``:
 
@@ -421,12 +408,9 @@ receivers port output.
 The Pipeline Handler is responsible for defining the set of Streams associated
 with the Camera.
 
-Each Camera has instance-specific data represented using the `Camera::Private`_
+Each Camera has instance-specific data represented using the :doxy-int:`Camera::Private`
 class, which can be extended for the specific needs of the pipeline handler.
 
-.. _Camera::Private: https://libcamera.org/api-html/classlibcamera_1_1Camera_1_1Private.html
-
-
 To support the Camera we will later register, we need to create a Camera::Private
 class that we can implement for our specific Pipeline Handler.
 
@@ -476,11 +460,9 @@ and is usually responsible for opening a
 
 We can now implement the ``init`` function for our example Pipeline Handler to
 create a new V4L2 video device from the media entity, which we can specify using
-the `MediaDevice::getEntityByName`_ function from the MediaDevice. As our
-example is based upon the simplistic Vivid test device, we only need to open a
-single capture device named 'vivid-000-vid-cap' by the device.
-
-.. _MediaDevice::getEntityByName: https://libcamera.org/api-html/classlibcamera_1_1MediaDevice.html#ad5d9279329ef4987ceece2694b33e230
+the :doxy-int:`MediaDevice::getEntityByName` function from the MediaDevice. As
+our example is based upon the simplistic Vivid test device, we only need to
+open a single capture device named 'vivid-000-vid-cap' by the device.
 
 .. code-block:: cpp
 
@@ -514,21 +496,18 @@ handler.
 Once the camera data has been initialized, the Camera device instances and the
 associated streams have to be registered. Create a set of streams for the
 camera, which for this device is only one. You create a camera using the static
-`Camera::create`_ function, passing the Camera::Private instance, the id of the
-camera, and the streams available. Then register the camera with the pipeline
-handler and camera manager using `registerCamera`_.
+:doxy-int:`Camera::create` function, passing the Camera::Private instance, the
+id of the camera, and the streams available. Then register the camera with the
+pipeline handler and camera manager using :doxy-int:`PipelineHandler::registerCamera`.
 
 Finally with a successful construction, we return 'true' indicating that the
 PipelineHandler successfully matched and constructed a device.
 
-.. _Camera::create: https://libcamera.org/api-html/classlibcamera_1_1Camera.html#a453740e0d2a2f495048ae307a85a2574
-.. _registerCamera: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#adf02a7f1bbd87aca73c0e8d8e0e6c98b
-
 .. code-block:: cpp
 
    std::set<Stream *> streams{ &data->stream_ };
-   std::shared_ptr<Camera> camera = Camera::create(this, data->video_->deviceName(), streams);
-   registerCamera(std::move(camera), std::move(data));
+   std::shared_ptr<Camera> camera = Camera::create(std::move(data), data->video_->deviceName(), streams);
+   registerCamera(std::move(camera));
 
    return true;
 
@@ -554,8 +533,7 @@ Our match function should now look like
 
    	/* Create and register the camera. */
    	std::set<Stream *> streams{ &data->stream_ };
-   	const std::string &id = data->video_->deviceName();
-   	std::shared_ptr<Camera> camera = Camera::create(data.release(), id, streams);
+   	std::shared_ptr<Camera> camera = Camera::create(std::move(data), data->video_->deviceName(), streams);
    	registerCamera(std::move(camera));
 
    	return true;
@@ -586,33 +564,26 @@ interface, and device interaction interf
 Registering controls and properties
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-The libcamera `controls framework`_ allows an application to configure the
-streams capture parameters on a per-frame basis and is also used to advertise
-immutable properties of the ``Camera`` device.
+The libcamera :doxy-int:`controls framework <controls.h>` allows an application
+to configure the streams capture parameters on a per-frame basis and is also
+used to advertise immutable properties of the ``Camera`` device.
 
 The libcamera controls and properties are defined in YAML form which is
 processed to automatically generate documentation and interfaces. Controls are
-defined by the src/libcamera/`control_ids_core.yaml`_ file and camera properties
-are defined by src/libcamera/`properties_ids_core.yaml`_.
-
-.. _controls framework: https://libcamera.org/api-html/controls_8h.html
-.. _control_ids_core.yaml: https://libcamera.org/api-html/control__ids_8h.html
-.. _properties_ids_core.yaml: https://libcamera.org/api-html/property__ids_8h.html
+defined by the :doxy-int:`src/libcamera/control_ids_core.yaml <control_ids.h>`
+file and camera properties are defined by
+:doxy-int:`src/libcamera/property_ids_core.yaml <property_ids.h>`.
 
 Pipeline handlers can optionally register the list of controls an application
 can set as well as a list of immutable camera properties. Being both
 Camera-specific values, they are represented in the ``Camera::Private`` base
 class, which provides two members for this purpose: the
-`Camera::Private::controlInfo_`_ and the `Camera::Private::properties_`_ fields.
-
-.. _Camera::Private::controlInfo_: https://libcamera.org/api-html/classlibcamera_1_1Camera_1_1Private.html#ab4e183eb4dabe929d1b2bbbb519b969f
-.. _Camera::Private::properties_: https://libcamera.org/api-html/classlibcamera_1_1Camera_1_1Private.html#ad31f12f5ed9c1fbe25750902f4791064
+:doxy-int:`Camera::Private::controlInfo_` and the
+:doxy-int:`Camera::Private::properties_` fields.
 
 The ``controlInfo_`` field represents a map of ``ControlId`` instances
 associated with the limits of valid values supported for the control. More
-information can be found in the `ControlInfoMap`_ class documentation.
-
-.. _ControlInfoMap: https://libcamera.org/api-html/classlibcamera_1_1ControlInfoMap.html
+information can be found in the :doxy-int:`ControlInfoMap` class documentation.
 
 Pipeline handlers register controls to expose the tunable device and IPA
 parameters to applications. Our example pipeline handler only exposes trivial
@@ -754,10 +725,8 @@ This configuration and validation proces
 specific class derived from a common base implementation and interface.
 
 To support validation in our example pipeline handler, Create a new class called
-``VividCameraConfiguration`` derived from the base `CameraConfiguration`_ class
-which we can implement and use within our ``PipelineHandlerVivid`` class.
-
-.. _CameraConfiguration: https://libcamera.org/api-html/classlibcamera_1_1CameraConfiguration.html
+``VividCameraConfiguration`` derived from the base :doxy-int:`CameraConfiguration`
+class which we can implement and use within our ``PipelineHandlerVivid`` class.
 
 The derived ``CameraConfiguration`` class must override the base class
 ``validate()`` function, where the stream configuration inspection and
@@ -779,20 +748,16 @@ adjustment happens.
     }
 
 Applications generate a ``CameraConfiguration`` instance by calling the
-`Camera::generateConfiguration()`_ function, which calls into the pipeline
-implementation of the overridden `PipelineHandler::generateConfiguration()`_
-function.
-
-.. _Camera::generateConfiguration(): https://libcamera.org/api-html/classlibcamera_1_1Camera.html#a25c80eb7fc9b1cf32692ce0c7f09991d
-.. _PipelineHandler::generateConfiguration(): https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#a7932e87735695500ce1f8c7ae449b65b
+:doxy-int:`Camera::generateConfiguration` function, which calls into the
+pipeline implementation of the overridden
+:doxy-int:`PipelineHandler::generateConfiguration` function.
 
 Configurations are generated by receiving a list of ``StreamRole`` instances,
 which libcamera uses as predefined ways an application intends to use a camera
-(You can read the full list in the `StreamRole API`_ documentation). These are
-optional hints on how an application intends to use a stream, and a pipeline
-handler should return an ideal configuration for each role that is requested.
-
-.. _StreamRole API: https://libcamera.org/api-html/stream_8h.html#file_a295d1f5e7828d95c0b0aabc0a8baac03
+(You can read the full list in the :doxy-int:`StreamRole` API documentation).
+These are optional hints on how an application intends to use a stream, and a
+pipeline handler should return an ideal configuration for each role that is
+requested.
 
 In the pipeline handler ``generateConfiguration`` implementation, remove the
 ``return nullptr;``, create a new instance of the ``CameraConfiguration``
@@ -800,8 +765,7 @@ derived class, and assign it to a base c
 
 .. code-block:: cpp
 
-   VividCameraData *data = cameraData(camera);
-   CameraConfiguration *config = new VividCameraConfiguration();
+   auto config = std::make_unique<VividCameraConfiguration>();
 
 A ``CameraConfiguration`` is specific to each pipeline, so you can only create
 it from the pipeline handler code path. Applications can also generate an empty
@@ -829,9 +793,7 @@ To generate a ``StreamConfiguration``, y
 frame sizes which are supported as outputs of the stream. You can fetch a map of
 the ``V4LPixelFormat`` and ``SizeRange`` supported by the underlying output
 device, but the pipeline handler needs to convert this to a
-``libcamera::PixelFormat`` type to pass to applications. We do this here using
-``std::transform`` to convert the formats and populate a new ``PixelFormat`` map
-as shown below.
+``libcamera::PixelFormat`` type to pass to applications.
 
 Continue adding the following code example to our ``generateConfiguration``
 implementation.
@@ -841,20 +803,16 @@ implementation.
    std::map<V4L2PixelFormat, std::vector<SizeRange>> v4l2Formats =
            data->video_->formats();
    std::map<PixelFormat, std::vector<SizeRange>> deviceFormats;
-   std::transform(v4l2Formats.begin(), v4l2Formats.end(),
-          std::inserter(deviceFormats, deviceFormats.begin()),
-          [&](const decltype(v4l2Formats)::value_type &format) {
-              return decltype(deviceFormats)::value_type{
-                  format.first.toPixelFormat(),
-                  format.second
-              };
-          });
-
-The `StreamFormats`_ class holds information about the pixel formats and frame
-sizes that a stream can support. The class groups size information by the pixel
-format, which can produce it.
 
-.. _StreamFormats: https://libcamera.org/api-html/classlibcamera_1_1StreamFormats.html
+   for (auto &[v4l2PixelFormat, sizes] : v4l2Formats) {
+           PixelFormat pixelFormat = v4l2PixelFormat.toPixelFormat();
+           if (pixelFormat.isValid())
+                   deviceFormats.try_emplace(pixelFormat, std::move(sizes));
+   }
+
+The :doxy-int:`StreamFormats` class holds information about the pixel formats
+and frame sizes that a stream can support. The class groups size information by
+the pixel format, which can produce it.
 
 The code below uses the ``StreamFormats`` class to represent all of the
 supported pixel formats, associated with a list of frame sizes. It then
@@ -899,16 +857,14 @@ Add the following code to complete the i
    return config;
 
 To validate a camera configuration, a pipeline handler must implement the
-`CameraConfiguration::validate()`_ function in its derived class to inspect all
-the stream configuration associated to it, make any adjustments required to make
-the configuration valid, and return the validation status.
+:doxy-int:`CameraConfiguration::validate` function in its derived class to
+inspect all the stream configuration associated to it, make any adjustments
+required to make the configuration valid, and return the validation status.
 
 If changes are made, it marks the configuration as ``Adjusted``, however if the
 requested configuration is not supported and cannot be adjusted it shall be
 refused and marked as ``Invalid``.
 
-.. _CameraConfiguration::validate(): https://libcamera.org/api-html/classlibcamera_1_1CameraConfiguration.html#a29f8f263384c6149775b6011c7397093
-
 The validation phase makes sure all the platform-specific constraints are
 respected by the requested configuration. The most trivial examples being making
 sure the requested image formats are supported and the image alignment
@@ -938,9 +894,9 @@ Add the following function implementatio
 
            StreamConfiguration &cfg = config_[0];
 
-           const std::vector<libcamera::PixelFormat> formats = cfg.formats().pixelformats();
+           const std::vector<libcamera::PixelFormat> &formats = cfg.formats().pixelformats();
            if (std::find(formats.begin(), formats.end(), cfg.pixelFormat) == formats.end()) {
-                  cfg.pixelFormat = cfg.formats().pixelformats()[0];
+                  cfg.pixelFormat = formats[0];
                   LOG(VIVID, Debug) << "Adjusting format to " << cfg.pixelFormat.toString();
                   status = Adjusted;
            }
@@ -1002,13 +958,10 @@ With the configuration generated, and op
 pipeline handler needs a function that allows an application to apply a
 configuration to the hardware devices.
 
-The `PipelineHandler::configure()`_ function receives a valid
-`CameraConfiguration`_ and applies the settings to hardware devices, using its
-parameters to prepare a device for a streaming session with the desired
-properties.
-
-.. _PipelineHandler::configure(): https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#a930f2a9cdfb51dfb4b9ca3824e84fc29
-.. _CameraConfiguration: https://libcamera.org/api-html/classlibcamera_1_1CameraConfiguration.html
+The :doxy-int:`PipelineHandler::configure` function receives a valid
+:doxy-int:`CameraConfiguration` and applies the settings to hardware devices,
+using its parameters to prepare a device for a streaming session with the
+desired properties.
 
 Replace the contents of the stubbed ``PipelineHandlerVivid::configure`` function
 with the following to obtain the camera data and stream configuration. This
@@ -1023,16 +976,14 @@ system accordingly.
    StreamConfiguration &cfg = config->at(0);
    int ret;
 
-The Vivid capture device is a V4L2 video device, so we use a `V4L2DeviceFormat`_
-with the fourcc and size attributes to apply directly to the capture device
-node. The fourcc attribute is a `V4L2PixelFormat`_ and differs from the
-``libcamera::PixelFormat``. Converting the format requires knowledge of the
-plane configuration for multiplanar formats, so you must explicitly convert it
-using the helper ``V4L2VideoDevice::toV4L2PixelFormat()`` provided by the
-V4L2VideoDevice instance that the format will be applied on.
-
-.. _V4L2DeviceFormat: https://libcamera.org/api-html/classlibcamera_1_1V4L2DeviceFormat.html
-.. _V4L2PixelFormat: https://libcamera.org/api-html/classlibcamera_1_1V4L2PixelFormat.html
+The Vivid capture device is a V4L2 video device, so we use a
+:doxy-int:`V4L2DeviceFormat` with the fourcc and size attributes to apply
+directly to the capture device node. The fourcc attribute is a
+:doxy-int:`V4L2PixelFormat` and differs from the ``libcamera::PixelFormat``.
+Converting the format requires knowledge of the plane configuration for
+multiplanar formats, so you must explicitly convert it using the helper
+``V4L2VideoDevice::toV4L2PixelFormat()`` provided by the V4L2VideoDevice
+instance that the format will be applied on.
 
 Add the following code beneath the code from above:
 
@@ -1043,12 +994,10 @@ Add the following code beneath the code
    format.size = cfg.size;
 
 Set the video device format defined above using the
-`V4L2VideoDevice::setFormat()`_ function. You should check if the kernel
-driver has adjusted the format, as this shows the pipeline handler has failed to
-handle the validation stages correctly, and the configure operation shall also
-fail.
-
-.. _V4L2VideoDevice::setFormat(): https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#ad67b47dd9327ce5df43350b80c083cca
+:doxy-int:`V4L2VideoDevice::setFormat` function. You should check if the kernel
+driver has adjusted the format, as this shows the pipeline handler has failed
+to handle the validation stages correctly, and the configure operation shall
+also fail.
 
 Continue the implementation with the following code:
 
@@ -1064,10 +1013,8 @@ Continue the implementation with the fol
 
 Finally, store and set stream-specific data reflecting the state of the stream.
 Associate the configuration with the stream by using the
-`StreamConfiguration::setStream`_ function, and set the values of individual
-stream configuration members as required.
-
-.. _StreamConfiguration::setStream: https://libcamera.org/api-html/structlibcamera_1_1StreamConfiguration.html#a74a0eb44dad1b00112c7c0443ae54a12
+:doxy-int:`StreamConfiguration::setStream` function, and set the values of
+individual stream configuration members as required.
 
 .. NOTE: the cfg.setStream() call here associates the stream to the
    StreamConfiguration however that should quite likely be done as part of
@@ -1090,9 +1037,7 @@ Initializing device controls
 Pipeline handlers can optionally initialize the video devices and camera sensor
 controls at system configuration time, to make sure they are defaulted to sane
 values. Handling of device controls is again performed using the libcamera
-`controls framework`_.
-
-.. _Controls Framework: https://libcamera.org/api-html/controls_8h.html
+:doxy-int:`controls framework <controls.h>`.
 
 This section is particularly specific to Vivid as it sets the initial values of
 controls to match `Vivid Controls`_ defined by the kernel driver. You won't need
@@ -1113,10 +1058,8 @@ come directly from the kernel sources:
    #define VIVID_CID_HOR_MOVEMENT          (VIVID_CID_VIVID_BASE  + 2)
 
 We can now use the V4L2 control IDs to prepare a list of controls with the
-`ControlList`_ class, and set them using the `ControlList::set()`_ function.
-
-.. _ControlList: https://libcamera.org/api-html/classlibcamera_1_1ControlList.html
-.. _ControlList::set(): https://libcamera.org/api-html/classlibcamera_1_1ControlList.html#a74a1a29abff5243e6e37ace8e24eb4ba
+:doxy-int:`ControlList` class, and set them using the :doxy-int:`ControlList::set`
+function.
 
 In our pipeline ``configure`` function, add the following code after the format
 has been set and checked to initialise the ControlList and apply it to the
@@ -1158,7 +1101,7 @@ available to the devices which have to b
 images. At the end of a capture session the ``Camera`` device needs to be
 stopped, to gracefully clean up any allocated memory and stop the hardware
 devices. Pipeline handlers implement two functions for these purposes, the
-``start()`` and ``stop()`` functions.
+``start()`` and ``stopDevice()`` functions.
 
 The memory initialization phase that happens at ``start()`` time serves to
 configure video devices to be able to use memory buffers exported as dma-buf
@@ -1167,28 +1110,22 @@ provide application facing streams alway
 in V4L2 terminology, buffers of V4L2_MEMORY_DMABUF memory type.
 
 libcamera also provides an API to allocate and export memory to applications
-realized through the `exportFrameBuffers`_ function and the
-`FrameBufferAllocator`_ class which will be presented later.
-
-.. _exportFrameBuffers: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#a6312a69da7129c2ed41f9d9f790adf7c
-.. _FrameBufferAllocator: https://libcamera.org/api-html/classlibcamera_1_1FrameBufferAllocator.html
+realized through the :doxy-int:`PipelineHandler::exportFrameBuffers` function
+and the :doxy-int:`FrameBufferAllocator` class which will be presented later.
 
 Please refer to the V4L2VideoDevice API documentation, specifically the
-`allocateBuffers`_, `importBuffers`_ and `exportBuffers`_ functions for a
+:doxy-int:`allocateBuffers <V4L2VideoDevice::allocateBuffers>`,
+:doxy-int:`importBuffers <V4L2VideoDevice::importBuffers>` and
+:doxy-int:`exportBuffers <V4L2VideoDevice::exportBuffers>` functions for a
 detailed description of the video device memory management.
 
-.. _allocateBuffers: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a3a1a77e5e6c220ea7878e89485864a1c
-.. _importBuffers: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a154f5283d16ebd5e15d63e212745cb64
-.. _exportBuffers: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#ae9c0b0a68f350725b63b73a6da5a2ecd
-
-Video memory buffers are represented in libcamera by the `FrameBuffer`_ class.
-A ``FrameBuffer`` instance has to be associated to each ``Stream`` which is part
-of a capture ``Request``. Pipeline handlers should prepare the capture devices
-by importing the dma-buf file descriptors it needs to operate on. This operation
-is performed by using the ``V4L2VideoDevice`` API, which provides an
-``importBuffers()`` function that prepares the video device accordingly.
-
-.. _FrameBuffer: https://libcamera.org/api-html/classlibcamera_1_1FrameBuffer.html
+Video memory buffers are represented in libcamera by the
+:doxy-int:`FrameBuffer` class.  A ``FrameBuffer`` instance has to be associated
+to each ``Stream`` which is part of a capture ``Request``. Pipeline handlers
+should prepare the capture devices by importing the dma-buf file descriptors it
+needs to operate on. This operation is performed by using the
+``V4L2VideoDevice`` API, which provides an ``importBuffers()`` function that
+prepares the video device accordingly.
 
 Implement the pipeline handler ``start()`` function by replacing the stub
 version with the following code:
@@ -1212,20 +1149,17 @@ complex pipeline handlers in the libcame
 
 Applications might want to use memory allocated in the video devices instead of
 allocating it from other parts of the system. libcamera provides an abstraction
-to assist with this task in the `FrameBufferAllocator`_ class. The
+to assist with this task in the :doxy-int:`FrameBufferAllocator` class. The
 ``FrameBufferAllocator`` reserves memory for a ``Stream`` in the video device
 and exports it as dma-buf file descriptors. From this point on, the allocated
 ``FrameBuffer`` are associated to ``Stream`` instances in a ``Request`` and then
 imported by the pipeline hander in exactly the same fashion as if they were
 allocated elsewhere.
 
-.. _FrameBufferAllocator: https://libcamera.org/api-html/classlibcamera_1_1FrameBufferAllocator.html
-
 Pipeline handlers support the ``FrameBufferAllocator`` operations by
-implementing the `exportFrameBuffers`_ function, which will allocate memory in
-the video device associated with a stream and export it.
-
-.. _exportFrameBuffers: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#a6312a69da7129c2ed41f9d9f790adf7c
+implementing the :doxy-int:`PipelineHandler::exportFrameBuffers` function,
+which will allocate memory in the video device associated with a stream and
+export it.
 
 Implement the ``exportFrameBuffers`` stub function with the following code to
 handle this:
@@ -1252,19 +1186,16 @@ with the following code:
    return 0;
 
 The function starts the video device associated with the stream with the
-`streamOn`_ function. If the call fails, the error value is propagated to the
-caller and the `releaseBuffers`_ function releases any buffers to leave the
-device in a consistent state. If your pipeline handler uses any image processing
-algorithms, or other devices you should also stop them.
-
-.. _streamOn: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a588a5dc9d6f4c54c61136ac43ff9a8cc
-.. _releaseBuffers: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a191619c152f764e03bc461611f3fcd35
+:doxy-int:`V4L2VideoDevice::streamOn` function. If the call fails, the error
+value is propagated to the caller and the
+:doxy-int:`V4L2VideoDevice::releaseBuffers` function releases any buffers to
+leave the device in a consistent state. If your pipeline handler uses any image
+processing algorithms, or other devices you should also stop them.
 
 Of course we also need to handle the corresponding actions to stop streaming on
-a device, Add the following to the ``stop`` function, to stop the stream with
-the `streamOff`_ function and release all buffers.
-
-.. _streamOff: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a61998710615bdf7aa25a046c8565ed66
+a device, Add the following to the ``stopDevice()`` function, to stop the
+stream with the :doxy-int:`V4L2VideoDevice::streamOff` function and release
+all buffers.
 
 .. code-block:: cpp
 
@@ -1283,12 +1214,11 @@ When an application sends a capture requ
 which video devices have to be provided with buffers to generate a frame from
 the enabled streams.
 
-This example pipeline handler identifies the buffer using the `findBuffer`_
-helper from the only supported stream and queues it to the capture device
-directly with the `queueBuffer`_ function provided by the V4L2VideoDevice.
-
-.. _findBuffer: https://libcamera.org/api-html/classlibcamera_1_1Request.html#ac66050aeb9b92c64218945158559c4d4
-.. _queueBuffer: https://libcamera.org/api-html/classlibcamera_1_1V4L2VideoDevice.html#a594cd594686a8c1cf9ae8dba0b2a8a75
+This example pipeline handler identifies the buffer using the
+:doxy-int:`Request::findBuffer` helper from the only supported stream and
+queues it to the capture device directly with the
+:doxy-int:`V4L2VideoDevice::queueBuffer` function provided by the
+V4L2VideoDevice.
 
 Replace the stubbed contents of ``queueRequestDevice`` with the following:
 
@@ -1383,11 +1313,9 @@ where appropriate by setting controls on
 handler is responsible for understanding the correct procedure for applying
 controls to the device they support.
 
-This example pipeline handler applies controls during the `queueRequestDevice`_
-function for each request, and applies them to the capture device through the
-capture node.
-
-.. _queueRequestDevice: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html#a106914cca210640c9da9ee1f0419e83c
+This example pipeline handler applies controls during the
+:doxy-int:`PipelineHandler::queueRequestDevice` function for each request, and
+applies them to the capture device through the capture node.
 
 In the ``queueRequestDevice`` function, replace the following:
 
@@ -1424,11 +1352,10 @@ Slots`_) to connect event sources with c
 
 As a general summary, a ``Slot`` can be connected to a ``Signal``, which when
 emitted triggers the execution of the connected slots.  A detailed description
-of the libcamera implementation is available in the `libcamera Signal and Slot`_
-classes documentation.
+of the libcamera implementation is available in the :doxy-int:`libcamera Signal
+and Slot <Signal>` classes documentation.
 
 .. _Qt Signals and Slots: https://doc.qt.io/qt-6/signalsandslots.html
-.. _libcamera Signal and Slot: https://libcamera.org/api-html/classlibcamera_1_1Signal.html#details
 
 In order to notify applications about the availability of new frames and data,
 the ``Camera`` device exposes two ``Signals`` to which applications can connect
@@ -1444,18 +1371,17 @@ The ``bufferComplete`` and ``requestComp
 ``Camera`` device upon notifications received from the pipeline handler, which
 tracks the buffers and request completion status.
 
-The single buffer completion notification is implemented by pipeline handlers by
-`connecting`_ the ``bufferReady`` signal of the capture devices they have queued
-buffers to, to a member function slot that handles processing of the completed
-frames. When a buffer is ready, the pipeline handler must propagate the
-completion of that buffer to the Camera by using the PipelineHandler base class
-``completeBuffer`` function. When all of the buffers referenced by a ``Request``
-have been completed, the pipeline handler must again notify the ``Camera`` using
-the PipelineHandler base class ``completeRequest`` function. The PipelineHandler
-class implementation makes sure the request completion notifications are
-delivered to applications in the same order as they have been submitted.
-
-.. _connecting: https://libcamera.org/api-html/classlibcamera_1_1Signal.html#aa04db72d5b3091ffbb4920565aeed382
+The single buffer completion notification is implemented by pipeline handlers
+by :doxy-int:`connecting <Signal::connect>` the ``bufferReady`` signal of the
+capture devices they have queued buffers to, to a member function slot that
+handles processing of the completed frames. When a buffer is ready, the
+pipeline handler must propagate the completion of that buffer to the Camera by
+using the PipelineHandler base class ``completeBuffer`` function. When all of
+the buffers referenced by a ``Request`` have been completed, the pipeline
+handler must again notify the ``Camera`` using the PipelineHandler base class
+``completeRequest`` function. The PipelineHandler class implementation makes
+sure the request completion notifications are delivered to applications in the
+same order as they have been submitted.
 
 Returning to the ``int VividCameraData::init()`` function, add the following
 above the closing ``return 0;`` to connect the pipeline handler ``bufferReady``
diff -pruN 0.5.0-1/Documentation/guides/tracing.rst 0.6.0-2/Documentation/guides/tracing.rst
--- 0.5.0-1/Documentation/guides/tracing.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/guides/tracing.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: ../documentation-contents.rst
-
 Tracing Guide
 =============
 
diff -pruN 0.5.0-1/Documentation/index.rst 0.6.0-2/Documentation/index.rst
--- 0.5.0-1/Documentation/index.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/index.rst	2025-11-27 11:55:28.000000000 +0000
@@ -4,28 +4,35 @@
 
 .. toctree::
    :maxdepth: 1
-   :caption: Contents:
+   :caption: For Users
+
+   Introduction <self>
+   Feature Requirements <feature_requirements>
+   Runtime configuration <runtime_configuration>
+   Application Writer's Guide <guides/application-developer>
+   Python Bindings <python-bindings>
+   Public API <public-api/index>
+
+.. toctree::
+   :maxdepth: 1
+   :caption: For Developers
 
-   Home <self>
    Contribute <contributing>
    Getting Started <getting-started>
-
-   Application Writer's Guide <guides/application-developer>
    Camera Sensor Model <camera-sensor-model>
-   Environment variables <environment_variables>
-   Feature Requirements <feature_requirements>
    IPA Writer's guide <guides/ipa>
-   Lens driver requirements <lens_driver_requirements>
    libcamera Architecture <libcamera_architecture>
    Pipeline Handler Writer's Guide <guides/pipeline-handler>
-   Python Bindings <python-bindings>
-   Sensor driver requirements <sensor_driver_requirements>
    SoftwareISP Benchmarking <software-isp-benchmarking>
    Tracing guide <guides/tracing>
-
    Design document: AE <design/ae>
+   Internal API <internal-api/index>
 
 .. toctree::
-   :hidden:
+   :maxdepth: 1
+   :caption: For System Integrators
+
+   Lens driver requirements <lens_driver_requirements>
+   Sensor driver requirements <sensor_driver_requirements>
+
 
-   introduction
diff -pruN 0.5.0-1/Documentation/install-doxygen.sh 0.6.0-2/Documentation/install-doxygen.sh
--- 0.5.0-1/Documentation/install-doxygen.sh	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/install-doxygen.sh	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,18 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Copyright (C) 2025, Ideas on Board Oy
+#
+# Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+#
+# Move Doxygen-generated API documentation to correct location
+
+doc_dir="${MESON_INSTALL_DESTDIR_PREFIX}/$1"
+shift
+dirs="$*"
+
+echo "Moving API documentation"
+
+for dir in $dirs ; do
+	rm -r "${doc_dir}/html/${dir}"
+	mv "${doc_dir}/${dir}" "${doc_dir}/html/"
+done
diff -pruN 0.5.0-1/Documentation/internal-api/index.rst 0.6.0-2/Documentation/internal-api/index.rst
--- 0.5.0-1/Documentation/internal-api/index.rst	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/internal-api/index.rst	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: CC-BY-SA-4.0
+
+.. _internal-api:
+
+Internal API Reference
+======================
+
+:: Placeholder for Doxygen documentation
diff -pruN 0.5.0-1/Documentation/internal-api-html/index.rst 0.6.0-2/Documentation/internal-api-html/index.rst
--- 0.5.0-1/Documentation/internal-api-html/index.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/internal-api-html/index.rst	1970-01-01 00:00:00.000000000 +0000
@@ -1,8 +0,0 @@
-.. SPDX-License-Identifier: CC-BY-SA-4.0
-
-.. _internal-api:
-
-Internal API Reference
-======================
-
-:: Placeholder for Doxygen documentation
diff -pruN 0.5.0-1/Documentation/introduction.rst 0.6.0-2/Documentation/introduction.rst
--- 0.5.0-1/Documentation/introduction.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/introduction.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,17 +1,9 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 ************
 Introduction
 ************
 
-.. toctree::
-   :hidden:
-
-   API <api-html/index>
-   Internal API <internal-api-html/index>
-
 What is libcamera?
 ==================
 
diff -pruN 0.5.0-1/Documentation/lens_driver_requirements.rst 0.6.0-2/Documentation/lens_driver_requirements.rst
--- 0.5.0-1/Documentation/lens_driver_requirements.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/lens_driver_requirements.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 .. _lens-driver-requirements:
 
 Lens Driver Requirements
diff -pruN 0.5.0-1/Documentation/libcamera_architecture.rst 0.6.0-2/Documentation/libcamera_architecture.rst
--- 0.5.0-1/Documentation/libcamera_architecture.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/libcamera_architecture.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 libcamera Architecture
 ======================
 
@@ -68,9 +66,7 @@ Camera Manager
   Each application's instance of the Camera Manager ensures that only a single
   application can take control of a camera device at once.
 
-  Read the `Camera Manager API`_ documentation for more details.
-
-.. _Camera Manager API: https://libcamera.org/api-html/classlibcamera_1_1CameraManager.html
+  Read the :doxy-pub:`CameraManager` API documentation for more details.
 
 Camera Device
   The Camera class represents a single item of camera hardware that is capable
@@ -85,9 +81,7 @@ Camera Device
   object that all other API operations interact with from configuration to
   capture.
 
-  Read the `Camera API`_ documentation for more details.
-
-.. _Camera API: https://libcamera.org/api-html/classlibcamera_1_1Camera.html
+  Read the :doxy-pub:`Camera` API documentation for more details.
 
 Pipeline Handler
   The Pipeline Handler manages the complex pipelines exposed by the kernel
@@ -107,11 +101,10 @@ Pipeline Handler
   they detect and support on the running system, and are responsible for
   managing the interactions with a camera device.
 
-  More details can be found in the `PipelineHandler API`_ documentation, and the
+  More details can be found in the :doxy-int:`PipelineHandler` API
+  documentation, and the
   :doc:`Pipeline Handler Writers Guide <guides/pipeline-handler>`.
 
-.. _PipelineHandler API: https://libcamera.org/api-html/classlibcamera_1_1PipelineHandler.html
-
 Image Processing Algorithms
   Together with the hardware image processing and hardware statistics
   collection, the Image Processing Algorithms (IPA) implement 3A (Auto-Exposure,
diff -pruN 0.5.0-1/Documentation/mainpage.dox 0.6.0-2/Documentation/mainpage.dox
--- 0.5.0-1/Documentation/mainpage.dox	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/mainpage.dox	2025-11-27 11:55:28.000000000 +0000
@@ -1,5 +1,9 @@
 /**
-\mainpage libcamera API reference
+\if internal
+\mainpage libcamera internal API reference
+\else
+\mainpage libcamera public API reference
+\endif
 
 Welcome to the API reference for <a href="https://libcamera.org/">libcamera</a>,
 a complex camera support library for Linux, Android and ChromeOS. These pages
@@ -16,7 +20,7 @@ your platform the [pipeline handler writ
 and the [ipa module writer's guide](../guides/ipa.html) should be helpful.
 
 The full libcamera API is documented here. If you wish to see only the public
-part of the API you can use [these pages](../api-html/index.html) instead.
+part of the API you can use [these pages](../public-api/index.html) instead.
 
 \else
 
@@ -27,7 +31,7 @@ gives an overview on how to achieve that
 Only the public part of the libcamera API is documented here; if you are a
 developer seeking to add support for your hardware to the library or make other
 improvements, you should switch to the internal API
-[reference pages](../internal-api-html/index.html) instead.
+[reference pages](../internal-api/index.html) instead.
 
 \endif
 */
diff -pruN 0.5.0-1/Documentation/meson.build 0.6.0-2/Documentation/meson.build
--- 0.5.0-1/Documentation/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -64,9 +64,9 @@ if doxygen.found() and dot.found()
                                    configuration : cdata)
 
     # The set of public input files stored in the doxygen_public_input array
-    # needs to be set in Doxyfile public. We can't pass them through cdata
-    # cdata, as some of the array members are custom_tgt instances, which
-    # configuration_data.set() doesn't support. Using a separate script invoked
+    # needs to be set in Doxyfile-public. We can't pass them through cdata, as
+    # some of the array members are custom_tgt instances, which
+    # configuration_data.set() doesn't support. Use a separate script invoked
     # through custom_target(), which supports custom_tgt instances as inputs.
 
     doxyfile = custom_target('doxyfile-public',
@@ -81,16 +81,16 @@ if doxygen.found() and dot.found()
                                  '@INPUT@',
                              ])
 
-    custom_target('doxygen-public',
-                  input : [
-                      doxyfile,
-                      doxyfile_common,
-                  ],
-                  output : 'api-html',
-                  command : [doxygen, doxyfile],
-                  install : true,
-                  install_dir : doc_install_dir,
-                  install_tag : 'doc')
+    doxygen_public = custom_target('doxygen-public',
+                                   input : [
+                                       doxyfile,
+                                       doxyfile_common,
+                                   ],
+                                   output : 'public-api',
+                                   command : [doxygen, doxyfile],
+                                   install : true,
+                                   install_dir : doc_install_dir,
+                                   install_tag : 'doc')
 
     # This is the internal documentation, which hard-codes a list of directories
     # to parse in its doxyfile.
@@ -99,49 +99,77 @@ if doxygen.found() and dot.found()
                               output : 'Doxyfile-internal',
                               configuration : cdata)
 
-    custom_target('doxygen-internal',
-                  input : [
-                      doxyfile,
-                      doxyfile_common,
-                      doxygen_internal_input,
-                  ],
-                  output : 'internal-api-html',
-                  command : [doxygen, doxyfile],
-                  install : true,
-                  install_dir : doc_install_dir,
-                  install_tag : 'doc-internal')
+    doxygen_internal = custom_target('doxygen-internal',
+                                     input : [
+                                         doxyfile,
+                                         doxyfile_common,
+                                         doxygen_public_input,
+                                         doxygen_internal_input,
+                                     ],
+                                     output : 'internal-api',
+                                     command : [doxygen, doxyfile],
+                                     install : true,
+                                     install_dir : doc_install_dir,
+                                     install_tag : 'doc-internal')
 endif
 
 #
 # Sphinx
 #
 
-sphinx = find_program('sphinx-build-3', required : false)
-if not sphinx.found()
-    sphinx = find_program('sphinx-build', required : get_option('documentation'))
-endif
+sphinx = find_program('sphinx-build-3', 'sphinx-build',
+                      required : get_option('documentation'))
 
 if sphinx.found()
+    # Many distributions do not provide a recent-enough version of the doxylink
+    # module. This results in a build error with a cryptic message. Check the
+    # version manually and print clear error messages.
+    mod = 'sphinxcontrib.doxylink'
+    min_version = '>=1.6.1'
+    version = run_command('python3', '-c',
+                          'import @0@ ; print(@0@.__version__)'.format(mod),
+                          check : false).stdout().strip()
+
+    if version == ''
+        error('@0@ module not found'.format(mod))
+    endif
+
+    if not version.version_compare(min_version)
+        error('@0@ module v@1@ is too old, @2@ is needed'
+              .format(mod, version, min_version))
+    endif
+
+    sphinx_conf = configure_file(input : 'conf.py.in',
+                                 output : 'conf.py',
+                                 configuration : {
+                                    'CURRENT_SRCDIR': meson.current_source_dir(),
+                                    'TOP_BUILDDIR': meson.project_build_root(),
+                                 })
+
+    fs = import('fs')
+    sphinx_conf_dir = fs.parent(sphinx_conf)
+
     docs_sources = [
         'camera-sensor-model.rst',
         'code-of-conduct.rst',
         'coding-style.rst',
-        'conf.py',
+        sphinx_conf,
         'contributing.rst',
         'design/ae.rst',
-        'documentation-contents.rst',
-        'environment_variables.rst',
         'feature_requirements.rst',
         'guides/application-developer.rst',
         'guides/ipa.rst',
         'guides/pipeline-handler.rst',
         'guides/tracing.rst',
         'index.rst',
+        'internal-api/index.rst',
         'introduction.rst',
         'lens_driver_requirements.rst',
         'libcamera_architecture.rst',
         'mali-c55.dot',
+        'public-api/index.rst',
         'python-bindings.rst',
+        'runtime_configuration.rst',
         'sensor_driver_requirements.rst',
         'software-isp-benchmarking.rst',
        '../README.rst',
@@ -151,16 +179,26 @@ if sphinx.found()
 
     custom_target('documentation',
                   command : [sphinx, '-D', release, '-q', '-W', '-b', 'html',
+                             '-c', sphinx_conf_dir,
                              meson.current_source_dir(), '@OUTPUT@'],
                   input : docs_sources,
                   output : 'html',
                   build_by_default : true,
+                  depends : [
+                      doxygen_public,
+                      doxygen_internal,
+                  ],
                   install : true,
                   install_dir : doc_install_dir,
                   install_tag : 'doc')
 
+    meson.add_install_script('install-doxygen.sh', doc_install_dir,
+                             'public-api', 'internal-api')
+
     custom_target('documentation-linkcheck',
-                  command : [sphinx, '-W', '-b', 'linkcheck', meson.current_source_dir(), '@OUTPUT@'],
+                  command : [sphinx, '-W', '-b', 'linkcheck',
+                             '-c', sphinx_conf_dir,
+                             meson.current_source_dir(), '@OUTPUT@'],
                   build_always_stale : true,
                   input : docs_sources,
                   output : 'linkcheck')
diff -pruN 0.5.0-1/Documentation/public-api/index.rst 0.6.0-2/Documentation/public-api/index.rst
--- 0.5.0-1/Documentation/public-api/index.rst	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/public-api/index.rst	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,8 @@
+.. SPDX-License-Identifier: CC-BY-SA-4.0
+
+.. _api:
+
+API Reference
+=============
+
+:: Placeholder for Doxygen documentation
diff -pruN 0.5.0-1/Documentation/python-bindings.rst 0.6.0-2/Documentation/python-bindings.rst
--- 0.5.0-1/Documentation/python-bindings.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/python-bindings.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 .. _python-bindings:
 
 Python Bindings for libcamera
diff -pruN 0.5.0-1/Documentation/runtime_configuration.rst 0.6.0-2/Documentation/runtime_configuration.rst
--- 0.5.0-1/Documentation/runtime_configuration.rst	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/runtime_configuration.rst	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,281 @@
+.. SPDX-License-Identifier: CC-BY-SA-4.0
+
+Runtime configuration
+=====================
+
+The libcamera behaviour can be tuned through a configuration file or
+environment variables. This document lists all the configuration options
+and describes their usage.
+
+General rules
+-------------
+
+The configuration file is looked up in the following locations, in this
+order:
+
+- $XDG_CONFIG_HOME/libcamera/configuration.yaml
+- LIBCAMERA_SYSCONF_DIR/configuration.yaml
+- LIBCAMERA_DATA_DIR/libcamera/configuration.yaml
+
+The first configuration file found wins, configuration files in other
+locations are ignored.
+
+Settings in environment variables take precedence over settings in
+configuration files. This allows overriding behaviour temporarily
+without the need to modify configuration files.
+
+Configuration options
+---------------------
+
+Here is an overview of the available configuration options, in the YAML
+file structure:
+
+::
+
+  configuration:
+    ipa:
+      force_isolation: # true/false
+      config_paths:
+        - ... # full path to a directory
+      module_paths:
+        - ... # full path to a directory
+    pipelines_match_list:
+      - ... # pipeline name
+    pipelines:
+      simple:
+        supported_devices:
+          - driver: # driver name, e.g. `mxc-isi`
+            software_isp: # true/false
+    software_isp:
+      copy_input_buffer: # true/false
+      measure:
+        skip: # non-negative integer, frames to skip initially
+        number: # non-negative integer, frames to measure
+
+Configuration file example
+--------------------------
+
+::
+
+   ---
+   version: 1
+   configuration:
+     ipa:
+       config_paths:
+         - /home/user/.libcamera/share/ipa
+         - /opt/libcamera/vendor/share/ipa
+       module_paths:
+         - /home/user/.libcamera/lib
+         - /opt/libcamera/vendor/lib
+       proxy_paths:
+         - /home/user/.libcamera/proxy/worker
+         - /opt/libcamera/vendor/proxy/worker
+       force_isolation: true
+     pipelines_match_list:
+       - rkisp1
+       - simple
+     pipelines:
+       simple:
+         supported_devices:
+           - driver: mxc-isi
+             software_isp: true
+     software_isp:
+       copy_input_buffer: false
+       measure:
+         skip: 50
+         number: 30
+
+List of variables and configuration options
+-------------------------------------------
+
+LIBCAMERA_LOG_FILE
+   The custom destination for log output.
+
+   Example value: ``/home/{user}/camera_log.log``
+
+LIBCAMERA_LOG_LEVELS
+   Configure the verbosity of log messages for different categories (`more <Log levels_>`__).
+
+   Example value: ``*:DEBUG``
+
+LIBCAMERA_LOG_NO_COLOR
+   Disable coloring of log messages (`more <Notes about debugging_>`__).
+
+LIBCAMERA_IPA_CONFIG_PATH, ipa.config_paths
+   Define custom search locations for IPA configurations (`more <IPA configuration_>`__).
+
+   Example value: ``${HOME}/.libcamera/share/ipa:/opt/libcamera/vendor/share/ipa``
+
+LIBCAMERA_IPA_FORCE_ISOLATION, ipa.force_isolation
+   When set to a non-empty string, force process isolation of all IPA modules.
+
+   Example value: ``1``
+
+LIBCAMERA_IPA_MODULE_PATH, ipa.module_paths
+   Define custom search locations for IPA modules (`more <IPA module_>`__).
+
+   Example value: ``${HOME}/.libcamera/lib:/opt/libcamera/vendor/lib``
+
+LIBCAMERA_IPA_PROXY_PATH, ipa.proxy_paths
+   Define custom full path for a proxy worker for a given executable name.
+
+   Example value: ``${HOME}/.libcamera/proxy/worker:/opt/libcamera/vendor/proxy/worker``
+
+LIBCAMERA_PIPELINES_MATCH_LIST, pipelines_match_list
+   Define an ordered list of pipeline names to be used to match the media
+   devices in the system. The pipeline handler names used to populate the
+   variable are the ones passed to the REGISTER_PIPELINE_HANDLER() macro in the
+   source code.
+
+   Example value: ``rkisp1,simple``
+
+LIBCAMERA_RPI_CONFIG_FILE
+   Define a custom configuration file to use in the Raspberry Pi pipeline handler.
+
+   Example value: ``/usr/local/share/libcamera/pipeline/rpi/vc4/minimal_mem.yaml``
+
+LIBCAMERA_<NAME>_TUNING_FILE
+   Define a custom IPA tuning file to use with the pipeline handler `NAME`.
+
+   Example value: ``/usr/local/share/libcamera/ipa/rpi/vc4/custom_sensor.json``
+
+pipelines.simple.supported_devices.driver, pipelines.simple.supported_devices.software_isp
+   Override whether software ISP is enabled for the given driver.
+
+   Example `driver` value: ``mxc-isi``
+
+   Example `software_isp` value: ``true``
+
+software_isp.copy_input_buffer
+   Define whether input buffers should be copied into standard (cached)
+   memory in software ISP. This is done by default to prevent very slow
+   processing on platforms with non-cached buffers. It can be set to
+   false on platforms with cached buffers to avoid an unnecessary
+   overhead.
+
+   Example value: ``false``
+
+software_isp.measure.skip, software_isp.measure.number
+   Define per-frame time measurement parameters in software ISP. `skip`
+   defines how many initial frames are skipped before starting the
+   measurement; `number` defines how many frames then participate in the
+   measurement.
+
+   Set `software_isp.measure.number` to 0 to disable the measurement.
+
+   Example `skip` value: ``50``
+
+   Example `number` value: ``30``
+
+Further details
+---------------
+
+Notes about debugging
+~~~~~~~~~~~~~~~~~~~~~
+
+The environment variables ``LIBCAMERA_LOG_FILE``, ``LIBCAMERA_LOG_LEVELS`` and
+``LIBCAMERA_LOG_NO_COLOR`` are used to modify the default configuration of the
+libcamera logger.
+
+By default, libcamera logs all messages to the standard error (std::cerr).
+Messages are colored by default depending on the log level. Coloring can be
+disabled by setting the ``LIBCAMERA_LOG_NO_COLOR`` environment variable.
+
+The default log destination can also be directed to a file by setting the
+``LIBCAMERA_LOG_FILE`` environment variable to the log file name. This also
+disables coloring.
+
+Log levels are controlled through the ``LIBCAMERA_LOG_LEVELS`` variable, which
+accepts a comma-separated list of 'category:level' pairs.
+
+The `level <Log levels_>`__ part is mandatory and can either be specified by
+name or by numerical index associated with each level.
+
+The optional `category <Log categories_>`__ is a string matching the categories
+defined by each file in the source base using the logging infrastructure. It
+can include a wildcard ('*') character at the end to match multiple categories.
+
+For more information refer to the :doxy-int:`API documentation <log.h>`.
+
+Examples:
+
+Enable full debug output to a separate file, for every `category <Log categories_>`__
+within a local environment:
+
+.. code:: bash
+
+   :~$ LIBCAMERA_LOG_FILE='/tmp/example_log.log' \
+       LIBCAMERA_LOG_LEVELS=0 \
+       cam --list
+
+Enable full debug output for the categories ``Camera`` and ``V4L2`` within a
+global environment:
+
+.. code:: bash
+
+   :~$ export LIBCAMERA_LOG_LEVELS='Camera:DEBUG,V4L2:DEBUG'
+   :~$ cam --list
+
+Log levels
+~~~~~~~~~~
+
+This is the list of available log levels, notice that all levels below
+the chosen one are printed, while those above are discarded.
+
+-  DEBUG (0)
+-  INFO (1)
+-  WARN (2)
+-  ERROR (3)
+-  FATAL (4)
+
+Example:
+If you choose WARN (2), you will be able to see WARN (2), ERROR (3) and FATAL (4)
+but not DEBUG (0) and INFO (1).
+
+Log categories
+~~~~~~~~~~~~~~
+
+Every category represents a specific area of the libcamera codebase,
+the names can be located within the source code, for example:
+`src/libcamera/camera_manager.cpp <https://git.libcamera.org/libcamera/libcamera.git/tree/src/libcamera/camera_manager.cpp#n35>`__
+
+.. code:: cpp
+
+   LOG_DEFINE_CATEGORY(Camera)
+
+There are two available macros used to assign a category name to a part of the
+libcamera codebase:
+
+LOG_DEFINE_CATEGORY
+   This macro is required, in order to use the ``LOGC`` macro for a particular
+   category. It can only be used once for each category. If you want to create
+   log messages within multiple compilation units for the same category utilize
+   the ``LOG_DECLARE_CATEGORY`` macro, in every file except the definition file.
+LOG_DECLARE_CATEGORY
+   Used for sharing an already defined category between multiple separate
+   compilation units.
+
+Both macros have to be used within the libcamera namespace of the C++ source
+code.
+
+IPA configuration
+~~~~~~~~~~~~~~~~~
+
+IPA modules use their own configuration files to store parameters. The format
+and contents of the configuration files is specific to the IPA module. They
+usually contain tuning parameters for the algorithms, in JSON format.
+
+The ``LIBCAMERA_IPA_CONFIG_PATH`` variable can be used to specify custom
+storage locations to search for those configuration files.
+
+`Examples <https://git.libcamera.org/libcamera/libcamera.git/tree/src/ipa/rpi/vc4/data>`__
+
+IPA module
+~~~~~~~~~~
+
+In order to locate the correct IPA module for your hardware, libcamera gathers
+existing IPA modules from multiple locations. The default locations for this
+operation are the installed system path (for example on Debian:
+``/usr/local/x86_64-pc-linux-gnu/libcamera``) and the build directory.
+With the ``LIBCAMERA_IPA_MODULE_PATH``, you can specify a non-default location
+to search for IPA modules.
diff -pruN 0.5.0-1/Documentation/sensor_driver_requirements.rst 0.6.0-2/Documentation/sensor_driver_requirements.rst
--- 0.5.0-1/Documentation/sensor_driver_requirements.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/sensor_driver_requirements.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 .. _sensor-driver-requirements:
 
 Sensor Driver Requirements
diff -pruN 0.5.0-1/Documentation/software-isp-benchmarking.rst 0.6.0-2/Documentation/software-isp-benchmarking.rst
--- 0.5.0-1/Documentation/software-isp-benchmarking.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/software-isp-benchmarking.rst	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,5 @@
 .. SPDX-License-Identifier: CC-BY-SA-4.0
 
-.. include:: documentation-contents.rst
-
 .. _software-isp-benchmarking:
 
 Software ISP benchmarking
diff -pruN 0.5.0-1/Documentation/theme/footer.html 0.6.0-2/Documentation/theme/footer.html
--- 0.5.0-1/Documentation/theme/footer.html	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/theme/footer.html	1970-01-01 00:00:00.000000000 +0000
@@ -1,14 +0,0 @@
-{#
-SPDX-License-Identifier: CC-BY-SA-4.0
-#}
-<footer>
-  <div id="signature">
-    {%- if show_copyright %}
-      {%- if hasdoc('copyright') %}
-        {% trans path=pathto('copyright'), copyright=copyright|e %}&copy; <a href="{{ path }}">Copyright</a> {{ copyright }}.{% endtrans %}
-      {%- else %}
-        {% trans copyright=copyright|e %}&copy; Copyright {{ copyright }}.{% endtrans %}
-      {%- endif %}
-    {%- endif %}
-  </div>
-</footer>
diff -pruN 0.5.0-1/Documentation/theme/layout.html 0.6.0-2/Documentation/theme/layout.html
--- 0.5.0-1/Documentation/theme/layout.html	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/theme/layout.html	1970-01-01 00:00:00.000000000 +0000
@@ -1,109 +0,0 @@
-{#
-SPDX-License-Identifier: CC-BY-SA-4.0
-#}
-{# TEMPLATE VAR SETTINGS #}
-{%- set url_root = pathto('', 1) %}
-{%- if url_root == '#' %}{% set url_root = '' %}{% endif %}
-{%- if not embedded and docstitle %}
-  {%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
-{%- else %}
-  {%- set titlesuffix = "" %}
-{%- endif %}
-<!DOCTYPE html>
-<head>
-  <meta charset="utf-8">
-  {{ metatags }}
-  <meta name="viewport" content="width=device-width, initial-scale=1.0">
-  {% block htmltitle %}
-  <title>{{ title|striptags|e }}{{ titlesuffix }}</title>
-  {% endblock %}
-
-  {# FAVICON #}
-  {% if favicon %}
-    <link rel="shortcut icon" href="{{ pathto('_static/' + favicon, 1) }}"/>
-  {% endif %}
-
-  {# CSS #}
-
-  {# OPENSEARCH #}
-  {% if not embedded %}
-    {% if use_opensearch %}
-      <link rel="search" type="application/opensearchdescription+xml" title="{% trans docstitle=docstitle|e %}Search within {{ docstitle }}{% endtrans %}" href="{{ pathto('_static/opensearch.xml', 1) }}"/>
-    {% endif %}
-
-  {% endif %}
-
-  {% for cssfile in css_files %}
-    <link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
-  {% endfor %}
-
-  {% for cssfile in extra_css_files %}
-    <link rel="stylesheet" href="{{ pathto(cssfile, 1) }}" type="text/css" />
-  {% endfor %}
-
-  {%- block linktags %}
-    {%- if hasdoc('about') %}
-        <link rel="author" title="{{ _('About these documents') }}"
-              href="{{ pathto('about') }}"/>
-    {%- endif %}
-    {%- if hasdoc('genindex') %}
-        <link rel="index" title="{{ _('Index') }}"
-              href="{{ pathto('genindex') }}"/>
-    {%- endif %}
-    {%- if hasdoc('search') %}
-        <link rel="search" title="{{ _('Search') }}" href="{{ pathto('search') }}"/>
-    {%- endif %}
-    {%- if hasdoc('copyright') %}
-        <link rel="copyright" title="{{ _('Copyright') }}" href="{{ pathto('copyright') }}"/>
-    {%- endif %}
-    <link rel="top" title="{{ docstitle|e }}" href="{{ pathto('index') }}"/>
-    {%- if parents %}
-        <link rel="up" title="{{ parents[-1].title|striptags|e }}" href="{{ parents[-1].link|e }}"/>
-    {%- endif %}
-    {%- if next %}
-        <link rel="next" title="{{ next.title|striptags|e }}" href="{{ next.link|e }}"/>
-    {%- endif %}
-    {%- if prev %}
-        <link rel="prev" title="{{ prev.title|striptags|e }}" href="{{ prev.link|e }}"/>
-    {%- endif %}
-  {%- endblock %}
-  {%- block extrahead %} {% endblock %}
-
-</head>
-
-<body role="document">
-  <header>
-    <div id="navbar">
-      <div class="navbar-brand">
-        <div class="navbar-logo">   _
-+-/ \-+
-| (o) |
-+-----+</div>
-        <div class="navbar-name"><span class="text-light">lib</span>camera</div>
-      </div>
-
-      <div class="navbar">
-        {{ toctree(maxdepth=1) }}
-        <div class="searchbox" role="search">
-          <form class="search" action="{{ pathto('search') }}" method="get">
-            <input type="text" name="q" />
-	    <input type="submit" value="Go" />
-            <input type="hidden" name="check_keywords" value="yes" />
-            <input type="hidden" name="area" value="default" />
-          </form>
-        </div>
-      </div>
-
-    </div>
-  </header>
-
-  <div id="content">
-    {# PAGE CONTENT #}
-    <div class="block">
-      {% block body %}{% endblock %}
-    </div>
-  </div>
-
-  {% include "footer.html" %}
-</body>
-</html>
diff -pruN 0.5.0-1/Documentation/theme/search.html 0.6.0-2/Documentation/theme/search.html
--- 0.5.0-1/Documentation/theme/search.html	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/theme/search.html	1970-01-01 00:00:00.000000000 +0000
@@ -1,63 +0,0 @@
-{#
-SPDX-License-Identifier: CC-BY-SA-4.0
-#}
-{#
-    basic/search.html
-    ~~~~~~~~~~~~~~~~~
-
-    Template for the search page.
-
-    :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
-    :license: BSD, see LICENSE for details.
-#}
-{%- extends "layout.html" %}
-{% block extrahead %}
-  <script type="text/javascript" id="documentation_options" data-url_root="{{ pathto('', 1) }}" src="{{ pathto('_static/documentation_options.js', 1) }}"></script>
-  {%- for scriptfile in script_files %}
-  <script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
-  {%- endfor %}
-  <script type="text/javascript" src="_static/searchtools.js"></script>
-  <script type="text/javascript">
-    jQuery(function() { Search.loadIndex("{{ pathto('searchindex.js', 1) }}"); });
-  </script>
-  {# this is used when loading the search index using $.ajax fails,
-     such as on Chrome for documents on localhost #}
-  <script type="text/javascript" id="searchindexloader"></script>
-{% endblock %}
-{% block body %}
-  <h1 id="search-documentation">{{ _('Search') }}</h1>
-  <div id="fallback" class="admonition warning">
-  <script type="text/javascript">$('#fallback').hide();</script>
-  <p>
-    Please activate JavaScript to enable the search functionality.
-  </p>
-  </div>
-  <p>
-    From here you can search these documents. Enter your search
-    words into the box below and click "search". Note that the search
-    function will automatically search for all of the words. Pages
-    containing fewer words won't appear in the result list.
-  </p>
-  <form action="" method="get">
-    <input type="text" name="q" value="" />
-    <input type="submit" value="{{ _('search') }}" />
-    <span id="search-progress" style="padding-left: 10px"></span>
-  </form>
-  {% if search_performed %}
-    <h2>{{ _('Search Results') }}</h2>
-    {% if not search_results %}
-      <p>{{ _('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.') }}</p>
-    {% endif %}
-  {% endif %}
-  <div id="search-results">
-  {% if search_results %}
-    <ul>
-    {% for href, caption, context in search_results %}
-      <li><a href="{{ pathto(item.href) }}">{{ caption }}</a>
-        <div class="context">{{ context|e }}</div>
-      </li>
-    {% endfor %}
-    </ul>
-  {% endif %}
-  </div>
-{% endblock %}
diff -pruN 0.5.0-1/Documentation/theme/static/css/theme.css 0.6.0-2/Documentation/theme/static/css/theme.css
--- 0.5.0-1/Documentation/theme/static/css/theme.css	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/theme/static/css/theme.css	1970-01-01 00:00:00.000000000 +0000
@@ -1,295 +0,0 @@
-/* SPDX-License-Identifier: CC-BY-SA-4.0 */
-
-html {
-	background-image: linear-gradient(to bottom right, #4895e1, #56c3ae);
-	background-size: cover;
-	background-repeat: no-repeat;
-	min-height: 100vh;
-}
-
-body {
-	color: rgb(0, 0, 0, 0.65);
-	font-family: Arial, sans-serif;
-	margin: 0px;
-}
-
-a {
-	color: unset;
-	font-weight: bold;
-	text-decoration: underline dotted;
-}
-
-a.headerlink {
-	color: rgba(0, 0, 0, 0.2);
-	font-size: 70%;
-	padding-left: 5px;
-	visibility: hidden;
-}
-
-a.toc-backref {
-	text-decoration: none;
-}
-
-h1:hover a.headerlink,
-h2:hover a.headerlink,
-h3:hover a.headerlink,
-h4:hover a.headerlink,
-h5:hover a.headerlink,
-h6:hover a.headerlink {
-	visibility: visible;
-}
-
-dt {
-	font-weight: bold;
-}
-
-.text-light {
-	color: rgba(255, 255, 255, 0.3);
-}
-
-div#navbar {
-	margin-top: 0px;
-}
-
-div.navbar-brand {
-	color: rgb(255, 255, 255, 1.0);
-	float: left;
-	font-size: 36px;
-	margin: 0px 24px 24px 24px;
-}
-
-div.navbar-logo {
-	float: left;
-	font-family: monospace;
-	font-size: 18px;
-	font-weight: bold;
-	white-space: pre;
-}
-
-div.navbar-name {
-	float: left;
-	color: rgb(255, 255, 255, 1.0);
-	font-size: 34px;
-	margin-top: 31px;
-	margin-left: 10px;
-	padding-top: 1px;
-}
-
-div.navbar {
-	float: right;
-}
-
-div.navbar p.caption {
-	height: 0px;
-	margin: 0px;
-	visibility: hidden;
-}
-
-div.navbar ul {
-	float: left;
-	font-size: 24px;
-	list-style: none;
-	margin-top: 42px;
-	margin-right: 20px;
-	padding-left: 0px;
-}
-
-div.navbar a {
-	font-weight: normal;
-	text-decoration: none;
-}
-
-div.navbar li {
-	float: left;
-	margin-left: 20px;
-	margin-right: 20px;
-	position: relative;
-}
-
-div.navbar li a {
-	color: rgb(255, 255, 255, 0.5);
-	position: relative;
-}
-
-div.navbar li a:before {
-	content: "";
-	position: absolute;
-	width: 100%;
-	height: 2px;
-	bottom: 0;
-	left: 0;
-	background-color: rgb(255, 255, 255, 0.5);
-	visibility: hidden;
-	transform: scaleX(0);
-	transition: all 0.3s ease-in-out 0s;
-}
-
-div.navbar li a:hover {
-	color: rgb(255, 255, 255, 1.0);
-}
-
-div.navbar li a:hover:before {
-	visibility: visible;
-	transform: scaleX(1);
-}
-
-div.navbar li.current a {
-	color: rgb(255, 255, 255, 1.0);
-}
-
-div.navbar li.current a:before {
-	visibility: visible;
-	transform: unset;
-	transition: unset;
-}
-
-div.navbar div.searchbox {
-	background-color: white;
-	float: right;
-	margin-right: 50px;
-	margin-top: 42px;
-}
-
-div.navbar input[type=text] {
-	border-width: 0;
-	height: 2em;
-	margin-left: 10px;
-	margin-right: 5px;
-}
-
-div.navbar input[type=submit] {
-	background-color: white;
-	background-image: url(../search.png);
-	background-repeat: no-repeat;
-	border-width: 0;
-	color: rgba(0, 0, 0, 0);
-	margin-right: 2px;
-	width: 20px;
-}
-
-div#frontpage {
-	clear: both;
-	padding-top: 50px;
-	margin-left: auto;
-	margin-right: auto;
-	width: 75%;
-	display: flex;
-	justify-content: space-between;
-}
-
-div#frontpage > div.block {
-	background-color: white;
-	border-radius: 5px;
-	box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.2), 0 6px 40px 0 rgba(0, 0, 0, 0.19);
-	color: rgb(0, 0, 0, 0.5);
-	font-size: 20px;
-	margin-bottom: 40px;
-	margin-right: 20px;
-	margin-left: 20px;
-	padding: 20px 60px 20px 60px;
-	text-align: center;
-	width: 50%;
-}
-
-div#frontpage > div.block h1 {
-	font-size: 64px;
-	padding-left: 20%;
-	padding-right: 20%;
-	text-align: center;
-	text-shadow: 4px 4px 5px;
-}
-
-div#content {
-	background-color: white;
-	clear: both;
-	padding-top: 50px;
-	padding-bottom: 50px;
-	margin-left: 0px;
-	margin-right: 0px;
-}
-
-div#content > div.block {
-	font-size: 16px;
-	margin-right: 0px;
-	margin-left: 0px;
-	max-width: 1280px;
-	padding: 0px 60px 0px 60px;
-	text-align: justify;
-}
-
-div#content > div.block h1 {
-	font-size: 40px;
-	margin-top: 0px;
-	text-align: left;
-}
-
-div#content > div.block > div.section {
-	max-width: 800px;
-}
-
-div.local.topic {
-	float: right;
-	background-color: #fcfcff;
-	border: 1px dotted #4896e0;
-	margin-left: 20px;
-	margin-right: 0px;
-	max-width: 15em;
-	padding: 10px 20px 10px 10px;
-	text-align: left;
-}
-
-div.local.topic ul {
-	padding-left: 20px;
-	margin-bottom: 5px;
-}
-
-div.local.topic > ul:before {
-	content: "Contents";
-	display: block;
-	font-weight: bold;
-	margin-bottom: 10px;
-}
-
-div.local.topic a {
-	font-weight: normal;
-	padding-left: 10px;
-	text-decoration: none;
-}
-
-div.highlight-shell > div.highlight > pre,
-pre.console {
-	background-color: #fcfcff;
-	border: 1px dotted #4896e0;
-	margin-left: 0em;
-	padding: 10px;
-	text-align: left;
-}
-
-div.highlight-default > div.highlight > pre,
-pre.diagram {
-	background-color: #fcfcff;
-	border: 1px dotted #4896e0;
-	font-size: 12px;
-	margin-left: 0em;
-	padding: 10px;
-	text-align: left;
-	width: 47em;
-}
-
-div#signature {
-	color: rgb(255, 255, 255, 0.5);
-	margin: 20px;
-	float: right;
-	font-size: 12px;
-}
-
-#licensing div.toctree-wrapper {
-	height: 0px;
-	margin: 0px;
-	padding: 0px;
-	visibility: hidden;
-}
-
-.documentation-nav {
-	display: none;
-}
diff -pruN 0.5.0-1/Documentation/theme/static/libcamera-logo-text.svg 0.6.0-2/Documentation/theme/static/libcamera-logo-text.svg
--- 0.5.0-1/Documentation/theme/static/libcamera-logo-text.svg	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/Documentation/theme/static/libcamera-logo-text.svg	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,223 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   width="76.987656mm"
+   height="27.246868mm"
+   viewBox="0 0 76.987653 27.246868"
+   version="1.1"
+   id="svg885"
+   inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+   sodipodi:docname="libcamera-logo-text.svg"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <defs
+     id="defs879">
+    <linearGradient
+       inkscape:collect="always"
+       id="libcamera-gradient">
+      <stop
+         style="stop-color:#4a9cd8;stop-opacity:1;"
+         offset="0"
+         id="stop837" />
+      <stop
+         style="stop-color:#4da5ce;stop-opacity:1;"
+         offset="1"
+         id="stop839" />
+    </linearGradient>
+    <linearGradient
+       inkscape:collect="always"
+       xlink:href="#libcamera-gradient"
+       id="linearGradient843"
+       x1="36.235832"
+       y1="124.7846"
+       x2="169.38322"
+       y2="124.7846"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.5782953,0,0,0.34895428,44.509503,81.842882)" />
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="2.8"
+     inkscape:cx="101.07143"
+     inkscape:cy="113.03571"
+     inkscape:document-units="mm"
+     inkscape:current-layer="layer2"
+     showgrid="false"
+     inkscape:window-width="2560"
+     inkscape:window-height="1531"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="1"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:showpageshadow="2"
+     inkscape:pagecheckerboard="0"
+     inkscape:deskcolor="#d1d1d1" />
+  <metadata
+     id="metadata882">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:groupmode="layer"
+     id="layer2"
+     inkscape:label="background"
+     transform="translate(-65.469925,-111.76357)">
+    <rect
+       style="opacity:1;fill:url(#linearGradient843);fill-opacity:1;stroke:#1a1a1a;stroke-width:0.0377345;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers"
+       id="rect824"
+       width="76.949921"
+       height="27.209133"
+       x="65.488792"
+       y="111.78244" />
+  </g>
+  <g
+     inkscape:label="LogoLayer"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-65.469925,-111.76357)">
+    <g
+       aria-label="   _ +-/ \-+ | (o) | +-----+"
+       style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;line-height:1.25;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583"
+       id="text1432">
+      <path
+         d="m 85.263307,117.54782 v 0.39275 h -2.548682 v -0.39275 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path928" />
+      <path
+         d="m 76.587868,119.76991 v 0.88884 h 0.888834 v 0.49196 h -0.888834 v 0.89296 h -0.489893 v -0.89296 h -0.892969 v -0.49196 h 0.892969 v -0.88884 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path930" />
+      <path
+         d="m 78.239446,120.71456 h 1.304313 v 0.60151 h -1.304313 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path932" />
+      <path
+         d="m 82.024228,119.14773 h 0.45682 l -1.624707,3.47885 h -0.45682 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path934" />
+      <path
+         d="m 85.953704,119.14773 1.624707,3.47885 h -0.460954 l -1.624707,-3.47885 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path936" />
+      <path
+         d="m 88.434172,120.71456 h 1.304313 v 0.60151 h -1.304313 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path938" />
+      <path
+         d="m 91.879957,119.76991 v 0.88884 h 0.888835 v 0.49196 h -0.888835 v 0.89296 h -0.489892 v -0.89296 h -0.892969 v -0.49196 h 0.892969 v -0.88884 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path940" />
+      <path
+         d="m 76.575465,124.29057 v 4.23333 h -0.469222 v -4.23333 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path942" />
+      <path
+         d="m 82.075904,124.3133 q -0.272851,0.49403 -0.405143,0.95705 -0.132291,0.46302 -0.132291,0.92604 0,0.45889 0.132291,0.92604 0.132292,0.46509 0.405143,0.96119 h -0.471289 q -0.328662,-0.4775 -0.487825,-0.94052 -0.159163,-0.46508 -0.159163,-0.94671 0,-0.47956 0.159163,-0.94464 0.16123,-0.46716 0.487825,-0.93845 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path944" />
+      <path
+         d="m 83.987933,125.64655 q -0.217041,0 -0.341065,0.19224 -0.124023,0.19017 -0.124023,0.53123 0,0.34107 0.124023,0.53331 0.124024,0.19016 0.341065,0.19016 0.219108,0 0.343131,-0.19016 0.124024,-0.19224 0.124024,-0.53331 0,-0.34106 -0.124024,-0.53123 -0.124023,-0.19224 -0.343131,-0.19224 z m -1.070736,0.72347 q 0,-0.56017 0.289388,-0.88676 0.291455,-0.32866 0.781348,-0.32866 0.491959,0 0.781347,0.32866 0.291455,0.32659 0.291455,0.88676 0,0.56018 -0.291455,0.88884 -0.289388,0.32659 -0.781347,0.32659 -0.489893,0 -0.781348,-0.32659 -0.289388,-0.32866 -0.289388,-0.88884 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path946" />
+      <path
+         d="m 85.902027,124.3133 h 0.471289 q 0.326595,0.47129 0.485759,0.93845 0.16123,0.46508 0.16123,0.94464 0,0.48163 -0.159163,0.94671 -0.159164,0.46302 -0.487826,0.94052 h -0.471289 q 0.272852,-0.4961 0.405143,-0.96119 0.132292,-0.46715 0.132292,-0.92604 0,-0.46302 -0.132292,-0.92604 -0.132291,-0.46302 -0.405143,-0.95705 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path948" />
+      <path
+         d="m 91.867555,124.29057 v 4.23333 h -0.469222 v -4.23333 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path950" />
+      <path
+         d="m 76.587868,130.35324 v 0.88884 h 0.888834 v 0.49196 h -0.888834 v 0.89297 h -0.489893 v -0.89297 h -0.892969 v -0.49196 h 0.892969 v -0.88884 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path952" />
+      <path
+         d="m 78.239446,131.29789 h 1.304313 v 0.60151 h -1.304313 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path954" />
+      <path
+         d="m 80.788128,131.29789 h 1.304313 v 0.60151 h -1.304313 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path956" />
+      <path
+         d="m 83.33681,131.29789 h 1.304313 v 0.60151 H 83.33681 Z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path958" />
+      <path
+         d="m 85.885491,131.29789 h 1.304313 v 0.60151 h -1.304313 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path960" />
+      <path
+         d="m 88.434172,131.29789 h 1.304313 v 0.60151 h -1.304313 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path962" />
+      <path
+         d="m 91.879957,130.35324 v 0.88884 h 0.888835 v 0.49196 h -0.888835 v 0.89297 h -0.489892 v -0.89297 h -0.892969 v -0.49196 h 0.892969 v -0.88884 z"
+         style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:4.23333px;font-family:monospace;-inkscape-font-specification:'monospace, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff;stroke-width:0.264583"
+         id="path964" />
+    </g>
+    <g
+       aria-label="libcamera"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;line-height:1.25;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.264583"
+       id="text1442">
+      <path
+         d="m 97.705568,129.92384 q -0.626534,0 -0.948267,-0.36407 -0.313267,-0.37253 -0.313267,-1.07526 v -4.60587 h 0.6858 v 4.55507 q 0,0.90593 0.719667,0.90593 0.211667,0 0.381,-0.0508 l -0.01693,0.57573 q -0.262467,0.0593 -0.508,0.0593 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:0.352941"
+         id="path909" />
+      <path
+         d="m 98.865497,124.70837 v -0.77046 h 0.846666 v 0.77046 z m 0.08467,5.13927 v -4.1148 h 0.685799 v 4.1148 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:0.352941"
+         id="path911" />
+      <path
+         d="m 102.99722,129.92384 q -0.49107,0 -0.8636,-0.22013 -0.36407,-0.22014 -0.55034,-0.60114 v 0.74507 h -0.66886 v -5.969 h 0.6858 v 2.5654 q 0.1778,-0.36407 0.55033,-0.57573 0.37253,-0.21167 0.84667,-0.21167 0.55033,0 0.95673,0.26247 0.41487,0.254 0.635,0.7366 0.2286,0.47413 0.2286,1.13453 0,0.65193 -0.2286,1.13453 -0.22013,0.47414 -0.635,0.7366 -0.4064,0.26247 -0.95673,0.26247 z m -0.14394,-0.55033 q 0.57574,0 0.92287,-0.4064 0.34713,-0.41487 0.34713,-1.17687 0,-0.77047 -0.34713,-1.17687 -0.34713,-0.4064 -0.92287,-0.4064 -0.57573,0 -0.92286,0.4064 -0.34714,0.4064 -0.34714,1.17687 0,0.762 0.34714,1.17687 0.34713,0.4064 0.92286,0.4064 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;opacity:1;fill:#ffffff;fill-opacity:0.352941"
+         id="path913" />
+      <path
+         d="m 107.5946,129.92384 q -0.61806,0 -1.0668,-0.26247 -0.44873,-0.27093 -0.69426,-0.75353 -0.23707,-0.49107 -0.23707,-1.143 0,-0.98213 0.5334,-1.54093 0.5334,-0.56727 1.46473,-0.56727 0.381,0 0.75354,0.13547 0.37253,0.13546 0.61806,0.381 l -0.23706,0.49953 q -0.24554,-0.23707 -0.54187,-0.34713 -0.28787,-0.11007 -0.55033,-0.11007 -0.64347,0 -0.9906,0.4064 -0.34714,0.39793 -0.34714,1.15147 0,0.7366 0.34714,1.1684 0.34713,0.42333 0.9906,0.42333 0.26246,0 0.55033,-0.11007 0.29633,-0.11006 0.54187,-0.3556 l 0.23706,0.49954 q -0.24553,0.24553 -0.62653,0.38946 -0.37253,0.13547 -0.74507,0.13547 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
+         id="path915" />
+      <path
+         d="m 111.03205,129.92384 q -0.42333,0 -0.762,-0.16087 -0.3302,-0.16933 -0.52493,-0.4572 -0.19474,-0.28786 -0.19474,-0.64346 0,-0.44874 0.2286,-0.7112 0.23707,-0.26247 0.77047,-0.37254 0.54187,-0.11853 1.4732,-0.11853 h 0.27093 v -0.26247 q 0,-0.52493 -0.22013,-0.75353 -0.21167,-0.23707 -0.6858,-0.23707 -0.37253,0 -0.71967,0.11007 -0.34713,0.1016 -0.7112,0.33867 l -0.23706,-0.49954 q 0.32173,-0.2286 0.77893,-0.36406 0.46567,-0.13547 0.889,-0.13547 0.79587,0 1.17687,0.38947 0.38946,0.38946 0.38946,1.21073 v 2.5908 h -0.64346 v -0.7112 q -0.16087,0.36407 -0.49954,0.57573 -0.3302,0.21167 -0.77893,0.21167 z m 0.11007,-0.51647 q 0.508,0 0.82973,-0.34713 0.32173,-0.3556 0.32173,-0.89747 v -0.254 h -0.26246 q -0.6858,0 -1.08374,0.0677 -0.38946,0.0593 -0.55033,0.22013 -0.1524,0.1524 -0.1524,0.42333 0,0.34714 0.23707,0.56727 0.24553,0.22013 0.6604,0.22013 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
+         id="path917" />
+      <path
+         d="m 114.24091,129.84764 v -4.1148 h 0.66886 v 0.69427 q 0.18627,-0.37254 0.51647,-0.56727 0.3302,-0.2032 0.77047,-0.2032 0.9652,0 1.23613,0.8382 0.18627,-0.38947 0.55033,-0.6096 0.36407,-0.2286 0.8382,-0.2286 1.3716,0 1.3716,1.6256 v 2.5654 h -0.6858 v -2.53153 q 0,-0.56727 -0.2032,-0.82974 -0.19473,-0.27093 -0.65193,-0.27093 -0.49953,0 -0.79587,0.3556 -0.29633,0.3556 -0.29633,0.94827 v 2.32833 h -0.6858 v -2.53153 q 0,-0.56727 -0.2032,-0.82974 -0.19473,-0.27093 -0.65193,-0.27093 -0.508,0 -0.80434,0.3556 -0.28786,0.3556 -0.28786,0.94827 v 2.32833 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
+         id="path919" />
+      <path
+         d="m 123.32563,129.92384 q -0.97367,0 -1.54093,-0.56727 -0.56727,-0.57573 -0.56727,-1.55786 0,-0.635 0.254,-1.1176 0.254,-0.49107 0.69427,-0.75354 0.44873,-0.27093 1.03293,-0.27093 0.8382,0 1.31233,0.54187 0.47414,0.5334 0.47414,1.4732 v 0.26246 h -3.0988 q 0.0339,0.70274 0.4064,1.07527 0.37253,0.36407 1.03293,0.36407 0.37253,0 0.7112,-0.11007 0.33867,-0.11853 0.64347,-0.381 l 0.23706,0.4826 q -0.2794,0.26247 -0.7112,0.41487 -0.4318,0.14393 -0.88053,0.14393 z m -0.11007,-3.7592 q -0.5842,0 -0.92286,0.36407 -0.33867,0.36406 -0.39794,0.95673 h 2.49767 q -0.0254,-0.62653 -0.3302,-0.97367 -0.29633,-0.34713 -0.84667,-0.34713 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
+         id="path921" />
+      <path
+         d="m 125.97569,129.84764 v -4.1148 h 0.66887 v 0.7366 q 0.3302,-0.74507 1.35467,-0.82127 l 0.24553,-0.0254 0.0508,0.59267 -0.4318,0.0508 q -0.5842,0.0508 -0.889,0.37253 -0.3048,0.31327 -0.3048,0.8636 v 2.34527 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
+         id="path923" />
+      <path
+         d="m 130.25982,129.92384 q -0.42334,0 -0.762,-0.16087 -0.3302,-0.16933 -0.52494,-0.4572 -0.19473,-0.28786 -0.19473,-0.64346 0,-0.44874 0.2286,-0.7112 0.23707,-0.26247 0.77047,-0.37254 0.54186,-0.11853 1.4732,-0.11853 h 0.27093 v -0.26247 q 0,-0.52493 -0.22013,-0.75353 -0.21167,-0.23707 -0.6858,-0.23707 -0.37254,0 -0.71967,0.11007 -0.34713,0.1016 -0.7112,0.33867 l -0.23707,-0.49954 q 0.32174,-0.2286 0.77894,-0.36406 0.46566,-0.13547 0.889,-0.13547 0.79586,0 1.17686,0.38947 0.38947,0.38946 0.38947,1.21073 v 2.5908 h -0.64347 v -0.7112 q -0.16086,0.36407 -0.49953,0.57573 -0.3302,0.21167 -0.77893,0.21167 z m 0.11006,-0.51647 q 0.508,0 0.82974,-0.34713 0.32173,-0.3556 0.32173,-0.89747 v -0.254 h -0.26247 q -0.6858,0 -1.08373,0.0677 -0.38947,0.0593 -0.55033,0.22013 -0.1524,0.1524 -0.1524,0.42333 0,0.34714 0.23706,0.56727 0.24554,0.22013 0.6604,0.22013 z"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:8.46667px;font-family:'Nunito Sans';-inkscape-font-specification:'Nunito Sans, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#ffffff"
+         id="path925" />
+    </g>
+  </g>
+</svg>
Binary files 0.5.0-1/Documentation/theme/static/search.png and 0.6.0-2/Documentation/theme/static/search.png differ
diff -pruN 0.5.0-1/Documentation/theme/theme.conf 0.6.0-2/Documentation/theme/theme.conf
--- 0.5.0-1/Documentation/theme/theme.conf	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/Documentation/theme/theme.conf	1970-01-01 00:00:00.000000000 +0000
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: CC-BY-SA-4.0
-
-[theme]
-inherit = basic
-stylesheet = css/theme.css
-
-[options]
diff -pruN 0.5.0-1/README.rst 0.6.0-2/README.rst
--- 0.5.0-1/README.rst	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/README.rst	2025-11-27 11:55:28.000000000 +0000
@@ -44,7 +44,7 @@ A C++ toolchain: [required]
         Either {g++, clang}
 
 Meson Build system: [required]
-        meson (>= 0.60) ninja-build pkg-config
+        meson (>= 1.0.1) ninja-build pkg-config
 
 for the libcamera core: [required]
         libyaml-dev python3-yaml python3-ply python3-jinja2
@@ -67,7 +67,8 @@ for device hotplug enumeration: [optiona
         libudev-dev
 
 for documentation: [optional]
-        python3-sphinx doxygen graphviz texlive-latex-extra
+        doxygen graphviz python3-sphinx python3-sphinx-book-theme
+        python3-sphinxcontrib.doxylink (>= 1.6.1) texlive-latex-extra
 
 for gstreamer: [optional]
         libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
@@ -83,9 +84,10 @@ for cam: [optional]
         - libdrm-dev: Enables the KMS sink
         - libjpeg-dev: Enables MJPEG on the SDL sink
         - libsdl2-dev: Enables the SDL sink
+        - libtiff-dev: Enables writing DNG
 
 for qcam: [optional]
-        libtiff-dev qt6-base-dev qt6-tools-dev-tools
+        libtiff-dev qt6-base-dev
 
 for tracing with lttng: [optional]
         liblttng-ust-dev python3-jinja2 lttng-tools
diff -pruN 0.5.0-1/debian/changelog 0.6.0-2/debian/changelog
--- 0.5.0-1/debian/changelog	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/changelog	2025-12-23 10:28:25.000000000 +0000
@@ -1,3 +1,53 @@
+libcamera (0.6.0-2) unstable; urgency=medium
+
+  * Upload to unstable.
+
+ -- Dylan Aïssi <daissi@debian.org>  Tue, 23 Dec 2025 11:28:25 +0100
+
+libcamera (0.6.0-1) experimental; urgency=medium
+
+  * New upstream version 0.6.0
+  * Bump SONAME to libcamera0.6
+  * Remove Disable_libunwind_integration.patch, merged upstream.
+  * Add python3-sphinx-book-theme in Build-Depends-Indep.
+  * Adjust python module install path.
+  * salsa-ci: disable debrebuild and reprotest jobs.
+  * Convert watch to version 5 and use Gitlab template.
+
+ -- Dylan Aïssi <daissi@debian.org>  Sat, 29 Nov 2025 15:06:30 +0100
+
+libcamera (0.5.2-3) unstable; urgency=medium
+
+  * salsa-ci: enable cross-build job
+  * Add ':native' to python packages with arch 'all'
+  * Disable signatures verification if cross-building
+
+ -- Dylan Aïssi <daissi@debian.org>  Thu, 18 Sep 2025 14:39:55 +0200
+
+libcamera (0.5.2-2) unstable; urgency=medium
+
+  * Adjust VCS fields in d/control and d/gbp.conf for unstable.
+  * Upload to unstable.
+
+ -- Dylan Aïssi <daissi@debian.org>  Sun, 17 Aug 2025 22:47:35 +0200
+
+libcamera (0.5.2-1) experimental; urgency=medium
+
+  * New upstream version 0.5.2
+  * Add python3-sphinxcontrib.doxylink in Build-Depends-Indep
+  * Refresh debian/copyright
+
+ -- Dylan Aïssi <daissi@debian.org>  Thu, 07 Aug 2025 17:16:21 +0200
+
+libcamera (0.5.1-1) experimental; urgency=medium
+
+  * New upstream version 0.5.1
+  * Refresh patches
+  * Install IPA modules in usr/lib/*/libcamera/ipa
+  * Adjust VCS field in d/control for experimental
+
+ -- Dylan Aïssi <daissi@debian.org>  Tue, 03 Jun 2025 21:16:11 +0200
+
 libcamera (0.5.0-1) experimental; urgency=medium
 
   * New upstream version 0.5.0
diff -pruN 0.5.0-1/debian/control 0.6.0-2/debian/control
--- 0.5.0-1/debian/control	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/control	2025-12-23 10:28:25.000000000 +0000
@@ -27,10 +27,10 @@ Build-Depends: debhelper-compat (= 13),
                meson (>= 0.63),
                openssl,
                pkgconf,
-               python3-jinja2,
+               python3-jinja2:native,
                python3-ply,
                python3-pybind11 <!pkg.libcamera.nopython>,
-               python3-yaml,
+               python3-yaml:native,
                qt6-base-dev [!i386] <!pkg.libcamera.noqt>
 Build-Depends-Indep: doxygen <!nodoc>,
                      doxygen-latex <!nodoc>,
@@ -38,7 +38,9 @@ Build-Depends-Indep: doxygen <!nodoc>,
                      libjs-jquery <!nodoc>,
                      libjs-sphinxdoc <!nodoc>,
                      libjs-underscore <!nodoc>,
-                     python3-sphinx <!nodoc>,
+                     python3-sphinx:native <!nodoc>,
+                     python3-sphinx-book-theme:native <!nodoc>,
+                     python3-sphinxcontrib.doxylink:native <!nodoc>
 Standards-Version: 4.7.2
 Vcs-Browser: https://salsa.debian.org/multimedia-team/libcamera
 Vcs-Git: https://salsa.debian.org/multimedia-team/libcamera.git
@@ -48,7 +50,7 @@ Rules-Requires-Root: no
 Package: libcamera-dev
 Architecture: linux-any
 Section: libdevel
-Depends: libcamera0.5 (= ${binary:Version}),
+Depends: libcamera0.6 (= ${binary:Version}),
          ${misc:Depends},
          ${shlibs:Depends}
 Description: complex camera support library (development files)
@@ -76,7 +78,7 @@ Description: complex camera support libr
  This package contains the documentation developing with libcamera.
 Build-Profiles: <!nodoc>
 
-Package: libcamera0.5
+Package: libcamera0.6
 Architecture: linux-any
 Multi-Arch: same
 Depends: ${misc:Depends},
diff -pruN 0.5.0-1/debian/copyright 0.6.0-2/debian/copyright
--- 0.5.0-1/debian/copyright	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/copyright	2025-12-23 10:28:25.000000000 +0000
@@ -5,22 +5,22 @@ Source: https://libcamera.org/
 
 Files: *
 Copyright:
- 2018—2024 Libcamera contributors
+ 2018—2025 Libcamera contributors
  2019      Giulio Benetti
  2018—2019 Jacopo Mondi
- 2018—2024 Kieran Bingham
- 2018—2024 Laurent Pinchart
+ 2018—2025 Kieran Bingham
+ 2018—2025 Laurent Pinchart
  2019      Mickael Guene
  2018—2019 Niklas Söderlund
  2019—2024 Paul Elder
  2018—2024 Google Inc.
- 2021—2024 Ideas on Board Oy
+ 2021—2025 Ideas on Board Oy
 License: GPL-2+
 
 Files:
  */*/meson.build
 Copyright:
- 2018—2024 Libcamera contributors
+ 2018—2025 Libcamera contributors
 License: CC0-1.0
 
 Files:
@@ -30,7 +30,7 @@ Files:
  src/apps/common/dng_writer.*
  include/libcamera/*
 Copyright:
- 2018—2024 Libcamera contributors
+ 2018—2025 Libcamera contributors
  2019      Giulio Benetti
  2018—2019 Jacopo Mondi
  2018—2019 Kieran Bingham
@@ -39,10 +39,10 @@ Copyright:
  2018—2019 Niklas Söderlund
  2019      Paul Elder
  2018—2022 Google Inc.
- 2019—2023 Raspberry Pi Ltd.
- 2021—2024 Ideas on Board Oy
+ 2019—2025 Raspberry Pi Ltd.
+ 2021—2025 Ideas on Board Oy
  2023 Linaro Ltd
- 2023—2024 Red Hat Inc.
+ 2023—2025 Red Hat Inc.
 License: LGPL-2.1+
 
 Files:
@@ -91,7 +91,7 @@ Copyright:
 License: Expat
 
 Files: include/linux/bcm2835-isp.h
-Copyright: 2019—2022 Raspberry Pi Ltd
+Copyright: 2019—2025 Raspberry Pi Ltd
 License: GPL-2+ with Linux-syscall-note exception or BSD-3-Clause
 
 Files:
@@ -105,7 +105,7 @@ Files:
  src/libcamera/pipeline/rpi/*
  utils/raspberrypi/ctt/*
 Copyright:
- 2019—2024 Raspberry Pi Ltd
+ 2019—2025 Raspberry Pi Ltd
 License: BSD-2-Clause
 
 Files: include/linux/rkisp1-config.h
@@ -113,7 +113,7 @@ Copyright: 2017, Rockchip Electronics Co
 License: GPL-2+
 
 Files: Documentation/*
-Copyright: 2020—2024 Libcamera contributors
+Copyright: 2020—2025 Libcamera contributors
 License: CC-BY-SA-4.0
 
 Files: Documentation/theme/static/search.png
@@ -130,7 +130,7 @@ Copyright:
  2019 Emmanuel Arias <emmanuelarias30@gmail.com>
  2019—2022 Andrej Shadura <andrewsh@debian.org>
  2020 IOhannes m zmölnig <umlaeute@debian.org>
- 2022-2024 Collabora Ltd.
+ 2022-2025 Collabora Ltd.
 License: GPL-2+
 
 License: GPL-2+
diff -pruN 0.5.0-1/debian/gbp.conf 0.6.0-2/debian/gbp.conf
--- 0.5.0-1/debian/gbp.conf	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/gbp.conf	2025-12-23 10:28:25.000000000 +0000
@@ -1,5 +1,5 @@
 [DEFAULT]
-debian-branch=debian/experimental
+debian-branch=debian/unstable
 upstream-branch=upstream/latest
 pristine-tar = True
 
diff -pruN 0.5.0-1/debian/libcamera-ipa.install 0.6.0-2/debian/libcamera-ipa.install
--- 0.5.0-1/debian/libcamera-ipa.install	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/libcamera-ipa.install	2025-12-23 10:28:25.000000000 +0000
@@ -1,4 +1,3 @@
-usr/lib/*/libcamera/ipa_*.so
-usr/lib/*/libcamera/ipa_*.so.sign
+usr/lib/*/libcamera/ipa
 usr/libexec/*/libcamera/*_ipa_proxy
 usr/share/libcamera
diff -pruN 0.5.0-1/debian/libcamera0.5.install 0.6.0-2/debian/libcamera0.5.install
--- 0.5.0-1/debian/libcamera0.5.install	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/libcamera0.5.install	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-usr/lib/*/libcamera*.so.*
diff -pruN 0.5.0-1/debian/libcamera0.6.install 0.6.0-2/debian/libcamera0.6.install
--- 0.5.0-1/debian/libcamera0.6.install	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/debian/libcamera0.6.install	2025-12-23 10:28:25.000000000 +0000
@@ -0,0 +1 @@
+usr/lib/*/libcamera*.so.*
diff -pruN 0.5.0-1/debian/patches/Disable_libunwind_integration.patch 0.6.0-2/debian/patches/Disable_libunwind_integration.patch
--- 0.5.0-1/debian/patches/Disable_libunwind_integration.patch	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/patches/Disable_libunwind_integration.patch	1970-01-01 00:00:00.000000000 +0000
@@ -1,30 +0,0 @@
-Description: Disable libunwind integration
-Bug-Debian: https://bugs.debian.org/1093688
-Forwarded: no
-Author: Dylan Aïssi <daissi@debian.org>
-
---- a/meson_options.txt
-+++ b/meson_options.txt
-@@ -41,6 +41,11 @@
-         value : 'auto',
-         description : 'Compile the lc-compliance test application')
- 
-+option('libunwind',
-+        type : 'feature',
-+        value : 'auto',
-+        description : 'Enable libunwind provide backtraces to help debugging')
-+
- option('pipelines',
-         type : 'array',
-         value : ['auto'],
---- a/src/libcamera/base/meson.build
-+++ b/src/libcamera/base/meson.build
-@@ -27,7 +27,7 @@
- ])
- 
- libdw = dependency('libdw', required : false)
--libunwind = dependency('libunwind', required : false)
-+libunwind = dependency('libunwind', required : get_option('libunwind'))
- 
- if cc.has_header_symbol('execinfo.h', 'backtrace')
-     config_h.set('HAVE_BACKTRACE', 1)
diff -pruN 0.5.0-1/debian/patches/series 0.6.0-2/debian/patches/series
--- 0.5.0-1/debian/patches/series	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/patches/series	2025-12-23 10:28:25.000000000 +0000
@@ -1,3 +1,2 @@
 ppc64el-fix-ftbfs-gcc.patch
 skip_failing_tests.patch
-Disable_libunwind_integration.patch
diff -pruN 0.5.0-1/debian/patches/skip_failing_tests.patch 0.6.0-2/debian/patches/skip_failing_tests.patch
--- 0.5.0-1/debian/patches/skip_failing_tests.patch	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/patches/skip_failing_tests.patch	2025-12-23 10:28:25.000000000 +0000
@@ -50,8 +50,8 @@ Forwarded: not-needed
 +#    {'name': 'file', 'sources': ['file.cpp']},
      {'name': 'flags', 'sources': ['flags.cpp']},
      {'name': 'hotplug-cameras', 'sources': ['hotplug-cameras.cpp']},
-     {'name': 'message', 'sources': ['message.cpp']},
-@@ -65,13 +65,13 @@
+     {'name': 'matrix', 'sources': ['matrix.cpp']},
+@@ -66,13 +66,13 @@
      {'name': 'object-delete', 'sources': ['object-delete.cpp']},
      {'name': 'object-invoke', 'sources': ['object-invoke.cpp']},
      {'name': 'pixel-format', 'sources': ['pixel-format.cpp']},
diff -pruN 0.5.0-1/debian/python3-libcamera.install 0.6.0-2/debian/python3-libcamera.install
--- 0.5.0-1/debian/python3-libcamera.install	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/python3-libcamera.install	2025-12-23 10:28:25.000000000 +0000
@@ -1 +1 @@
-usr/lib/*/python*	/usr/lib/
+usr/lib/python*
diff -pruN 0.5.0-1/debian/rules 0.6.0-2/debian/rules
--- 0.5.0-1/debian/rules	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/rules	2025-12-23 10:28:25.000000000 +0000
@@ -54,12 +54,16 @@ override_dh_strip:
 	dh_strip -a
 	MESON_INSTALL_DESTDIR_PREFIX=. ./src/ipa/ipa-sign-install.sh \
 		./obj-${DEB_HOST_GNU_TYPE}/src/ipa-priv-key.pem \
-		debian/libcamera-ipa/usr/lib/${DEB_HOST_MULTIARCH}/libcamera/ipa_*.so
-	for IPA_MOD in debian/libcamera-ipa/usr/lib/*/libcamera/ipa_*.so; \
+		debian/libcamera-ipa/usr/lib/${DEB_HOST_MULTIARCH}/libcamera/ipa/ipa_*.so
+ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
+	echo "Cross-building: signatures verification disabled!"
+else
+	for IPA_MOD in debian/libcamera-ipa/usr/lib/*/libcamera/ipa/ipa_*.so; \
 	do \
 	  echo "Verifying signature of $${IPA_MOD}"; \
 	  ./obj-${DEB_HOST_GNU_TYPE}/src/apps/ipa-verify/ipa_verify $${IPA_MOD}; \
 	done
+endif
 
 execute_after_dh_fixperms:
 	find debian/ -name 'v4l2-compat.so' -exec chmod -x '{}' \;
diff -pruN 0.5.0-1/debian/salsa-ci.yml 0.6.0-2/debian/salsa-ci.yml
--- 0.5.0-1/debian/salsa-ci.yml	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/salsa-ci.yml	2025-12-23 10:28:25.000000000 +0000
@@ -4,9 +4,13 @@ include:
 
 variables:
   SALSA_CI_DISABLE_BUILD_PACKAGE_ARM64: 0
+  SALSA_CI_DISABLE_CROSSBUILD_ARM64: 0
 
-reprotest:
-  allow_failure: true
+variables:
+  SALSA_CI_DISABLE_DEBREBUILD: 1
+  SALSA_CI_DISABLE_REPROTEST: 1
+# libcamera is known not to be reproducible, see:
+# https://gitlab.freedesktop.org/camera/libcamera/-/issues/233
 
 # See https://bugs.debian.org/1088099
 blhc:
diff -pruN 0.5.0-1/debian/tests/check-IPA-modules-signatures 0.6.0-2/debian/tests/check-IPA-modules-signatures
--- 0.5.0-1/debian/tests/check-IPA-modules-signatures	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/tests/check-IPA-modules-signatures	2025-12-23 10:28:25.000000000 +0000
@@ -1,7 +1,7 @@
 #!/bin/sh -e
 # autopkgtest check: Verify signatures of installed IPA modules.
 
-for IPA_MOD in /usr/lib/*/libcamera/ipa_*.so
+for IPA_MOD in /usr/lib/*/libcamera/ipa/ipa_*.so
 do
   echo "Verifying signature of ${IPA_MOD}"
   ipa_verify "${IPA_MOD}"
diff -pruN 0.5.0-1/debian/watch 0.6.0-2/debian/watch
--- 0.5.0-1/debian/watch	2025-04-08 11:30:03.000000000 +0000
+++ 0.6.0-2/debian/watch	2025-12-23 10:28:25.000000000 +0000
@@ -1,4 +1,4 @@
-version=4
-opts="searchmode=plain" \
- https://gitlab.freedesktop.org/camera/@PACKAGE@/tags?sort=updated_desc \
- -/archive/v?\d[\d.]+/@PACKAGE@-@ANY_VERSION@@ARCHIVE_EXT@
+Version: 5
+
+Template: Gitlab
+Dist: https://gitlab.freedesktop.org/camera/libcamera
diff -pruN 0.5.0-1/include/libcamera/base/bound_method.h 0.6.0-2/include/libcamera/base/bound_method.h
--- 0.5.0-1/include/libcamera/base/bound_method.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/base/bound_method.h	2025-11-27 11:55:28.000000000 +0000
@@ -33,16 +33,12 @@ template<typename R, typename... Args>
 class BoundMethodPack : public BoundMethodPackBase
 {
 public:
-	BoundMethodPack(const Args &... args)
-		: args_(args...)
+	template<typename... Ts>
+	BoundMethodPack(Ts &&...args)
+		: args_(std::forward<Ts>(args)...)
 	{
 	}
 
-	R returnValue()
-	{
-		return ret_;
-	}
-
 	std::tuple<typename std::remove_reference_t<Args>...> args_;
 	R ret_;
 };
@@ -51,12 +47,9 @@ template<typename... Args>
 class BoundMethodPack<void, Args...> : public BoundMethodPackBase
 {
 public:
-	BoundMethodPack(const Args &... args)
-		: args_(args...)
-	{
-	}
-
-	void returnValue()
+	template<typename... Ts>
+	BoundMethodPack(Ts &&...args)
+		: args_(std::forward<Ts>(args)...)
 	{
 	}
 
@@ -130,23 +123,25 @@ public:
 
 	BoundMethodFunctor(T *obj, Object *object, Func func,
 			   ConnectionType type = ConnectionTypeAuto)
-		: BoundMethodArgs<R, Args...>(obj, object, type), func_(func)
+		: BoundMethodArgs<R, Args...>(obj, object, type), func_(std::move(func))
 	{
 	}
 
 	R activate(Args... args, bool deleteMethod = false) override
 	{
 		if (!this->object_)
-			return func_(args...);
+			return func_(std::forward<Args>(args)...);
+
+		auto pack = std::make_shared<PackType>(std::forward<Args>(args)...);
+		[[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
 
-		auto pack = std::make_shared<PackType>(args...);
-		bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
-		return sync ? pack->returnValue() : R();
+		if constexpr (!std::is_void_v<R>)
+			return sync ? std::move(pack->ret_) : R();
 	}
 
 	R invoke(Args... args) override
 	{
-		return func_(args...);
+		return func_(std::forward<Args>(args)...);
 	}
 
 private:
@@ -171,18 +166,20 @@ public:
 	{
 		if (!this->object_) {
 			T *obj = static_cast<T *>(this->obj_);
-			return (obj->*func_)(args...);
+			return (obj->*func_)(std::forward<Args>(args)...);
 		}
 
-		auto pack = std::make_shared<PackType>(args...);
-		bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
-		return sync ? pack->returnValue() : R();
+		auto pack = std::make_shared<PackType>(std::forward<Args>(args)...);
+		[[maybe_unused]] bool sync = BoundMethodBase::activatePack(pack, deleteMethod);
+
+		if constexpr (!std::is_void_v<R>)
+			return sync ? std::move(pack->ret_) : R();
 	}
 
 	R invoke(Args... args) override
 	{
 		T *obj = static_cast<T *>(this->obj_);
-		return (obj->*func_)(args...);
+		return (obj->*func_)(std::forward<Args>(args)...);
 	}
 
 private:
@@ -203,7 +200,7 @@ public:
 
 	R activate(Args... args, [[maybe_unused]] bool deleteMethod = false) override
 	{
-		return (*func_)(args...);
+		return (*func_)(std::forward<Args>(args)...);
 	}
 
 	R invoke(Args...) override
diff -pruN 0.5.0-1/include/libcamera/base/log.h 0.6.0-2/include/libcamera/base/log.h
--- 0.5.0-1/include/libcamera/base/log.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/base/log.h	2025-11-27 11:55:28.000000000 +0000
@@ -75,7 +75,7 @@ public:
 	const LogCategory &category() const { return category_; }
 	const std::string &fileInfo() const { return fileInfo_; }
 	const std::string &prefix() const { return prefix_; }
-	const std::string msg() const { return msgStream_.str(); }
+	std::string msg() const { return msgStream_.str(); }
 
 private:
 	LIBCAMERA_DISABLE_COPY_AND_MOVE(LogMessage)
@@ -96,12 +96,12 @@ public:
 protected:
 	virtual std::string logPrefix() const = 0;
 
-	LogMessage _log(const LogCategory *category, LogSeverity severity,
+	LogMessage _log(const LogCategory &category, LogSeverity severity,
 			const char *fileName = __builtin_FILE(),
 			unsigned int line = __builtin_LINE()) const;
 };
 
-LogMessage _log(const LogCategory *category, LogSeverity severity,
+LogMessage _log(const LogCategory &category, LogSeverity severity,
 		const char *fileName = __builtin_FILE(),
 		unsigned int line = __builtin_LINE());
 
@@ -109,9 +109,9 @@ LogMessage _log(const LogCategory *categ
 #define _LOG_CATEGORY(name) logCategory##name
 
 #define _LOG1(severity) \
-	_log(nullptr, Log##severity).stream()
+	_log(LogCategory::defaultCategory(), Log##severity).stream()
 #define _LOG2(category, severity) \
-	_log(&_LOG_CATEGORY(category)(), Log##severity).stream()
+	_log(_LOG_CATEGORY(category)(), Log##severity).stream()
 
 /*
  * Expand the LOG() macro to _LOG1() or _LOG2() based on the number of
diff -pruN 0.5.0-1/include/libcamera/base/thread.h 0.6.0-2/include/libcamera/base/thread.h
--- 0.5.0-1/include/libcamera/base/thread.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/base/thread.h	2025-11-27 11:55:28.000000000 +0000
@@ -8,6 +8,7 @@
 #pragma once
 
 #include <memory>
+#include <string>
 #include <sys/types.h>
 #include <thread>
 
@@ -30,7 +31,7 @@ class ThreadMain;
 class Thread
 {
 public:
-	Thread();
+	Thread(std::string name = {});
 	virtual ~Thread();
 
 	void start();
@@ -50,6 +51,7 @@ public:
 
 	void dispatchMessages(Message::Type type = Message::Type::None,
 			      Object *receiver = nullptr);
+	void removeMessages(Object *receiver);
 
 protected:
 	int exec();
@@ -64,7 +66,6 @@ private:
 	void setThreadAffinityInternal();
 
 	void postMessage(std::unique_ptr<Message> msg, Object *receiver);
-	void removeMessages(Object *receiver);
 
 	friend class Object;
 	friend class ThreadData;
@@ -74,8 +75,9 @@ private:
 	void moveObject(Object *object, ThreadData *currentData,
 			ThreadData *targetData);
 
+	std::string name_;
 	std::thread thread_;
-	ThreadData *data_;
+	std::unique_ptr<ThreadData> data_;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/base/utils.h 0.6.0-2/include/libcamera/base/utils.h
--- 0.5.0-1/include/libcamera/base/utils.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/base/utils.h	2025-11-27 11:55:28.000000000 +0000
@@ -21,6 +21,7 @@
 #include <utility>
 #include <vector>
 
+#include <libcamera/base/class.h>
 #include <libcamera/base/private.h>
 
 #ifndef __DOXYGEN__
@@ -76,69 +77,29 @@ using time_point = std::chrono::steady_c
 struct timespec duration_to_timespec(const duration &value);
 std::string time_point_to_string(const time_point &time);
 
-#ifndef __DOXYGEN__
-struct _hex {
+namespace details {
+
+struct hex {
 	uint64_t v;
 	unsigned int w;
 };
 
-std::basic_ostream<char, std::char_traits<char>> &
-operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
-#endif
-
-template<typename T,
-	 std::enable_if_t<std::is_integral<T>::value> * = nullptr>
-_hex hex(T value, unsigned int width = 0);
-
-#ifndef __DOXYGEN__
-template<>
-inline _hex hex<int8_t>(int8_t value, unsigned int width)
-{
-	return { static_cast<uint64_t>(value), width ? width : 2 };
-}
-
-template<>
-inline _hex hex<uint8_t>(uint8_t value, unsigned int width)
-{
-	return { static_cast<uint64_t>(value), width ? width : 2 };
-}
-
-template<>
-inline _hex hex<int16_t>(int16_t value, unsigned int width)
-{
-	return { static_cast<uint64_t>(value), width ? width : 4 };
-}
-
-template<>
-inline _hex hex<uint16_t>(uint16_t value, unsigned int width)
-{
-	return { static_cast<uint64_t>(value), width ? width : 4 };
-}
-
-template<>
-inline _hex hex<int32_t>(int32_t value, unsigned int width)
+template<typename T>
+constexpr unsigned int hex_width()
 {
-	return { static_cast<uint64_t>(value), width ? width : 8 };
+	return sizeof(T) * 2;
 }
 
-template<>
-inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
-{
-	return { static_cast<uint64_t>(value), width ? width : 8 };
-}
+std::basic_ostream<char, std::char_traits<char>> &
+operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const hex &h);
 
-template<>
-inline _hex hex<int64_t>(int64_t value, unsigned int width)
-{
-	return { static_cast<uint64_t>(value), width ? width : 16 };
-}
+} /* namespace details */
 
-template<>
-inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
+template<typename T, std::enable_if_t<std::is_integral_v<T>> * = nullptr>
+details::hex hex(T value, unsigned int width = details::hex_width<T>())
 {
-	return { static_cast<uint64_t>(value), width ? width : 16 };
+	return { static_cast<std::make_unsigned_t<T>>(value), width };
 }
-#endif
 
 size_t strlcpy(char *dst, const char *src, size_t size);
 
@@ -354,19 +315,11 @@ private:
 } /* namespace details */
 
 template<typename T>
-auto enumerate(T &iterable) -> details::enumerate_adapter<decltype(iterable.begin())>
+auto enumerate(T &iterable)
 {
-	return { std::begin(iterable), std::end(iterable) };
+	return details::enumerate_adapter{ std::begin(iterable), std::end(iterable) };
 }
 
-#ifndef __DOXYGEN__
-template<typename T, size_t N>
-auto enumerate(T (&iterable)[N]) -> details::enumerate_adapter<T *>
-{
-	return { std::begin(iterable), std::end(iterable) };
-}
-#endif
-
 class Duration : public std::chrono::duration<double, std::nano>
 {
 	using BaseDuration = std::chrono::duration<double, std::nano>;
@@ -393,6 +346,11 @@ public:
 		return c.count();
 	}
 
+	constexpr Duration operator-() const
+	{
+		return BaseDuration::operator-();
+	}
+
 	explicit constexpr operator bool() const
 	{
 		return *this != BaseDuration::zero();
@@ -428,6 +386,43 @@ private:
 	std::vector<std::function<void()>> actions_;
 };
 
+#ifndef __DOXYGEN__
+template<typename EF>
+class scope_exit
+{
+public:
+	template<typename Fn,
+		 std::enable_if_t<!std::is_same_v<std::remove_cv_t<std::remove_reference_t<Fn>>, scope_exit> &&
+				  std::is_constructible_v<EF, Fn>> * = nullptr>
+	explicit scope_exit(Fn &&fn)
+		: exitFunction_(std::forward<Fn>(fn))
+	{
+		static_assert(std::is_nothrow_constructible_v<EF, Fn>);
+	}
+
+	~scope_exit()
+	{
+		if (active_)
+			exitFunction_();
+	}
+
+	void release()
+	{
+		active_ = false;
+	}
+
+private:
+	LIBCAMERA_DISABLE_COPY_AND_MOVE(scope_exit)
+
+	EF exitFunction_;
+	bool active_ = true;
+};
+
+template<typename EF>
+scope_exit(EF) -> scope_exit<EF>;
+
+#endif /* __DOXYGEN__ */
+
 } /* namespace utils */
 
 #ifndef __DOXYGEN__
diff -pruN 0.5.0-1/include/libcamera/camera.h 0.6.0-2/include/libcamera/camera.h
--- 0.5.0-1/include/libcamera/camera.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/camera.h	2025-11-27 11:55:28.000000000 +0000
@@ -165,6 +165,8 @@ private:
 	friend class FrameBufferAllocator;
 	int exportFrameBuffers(Stream *stream,
 			       std::vector<std::unique_ptr<FrameBuffer>> *buffers);
+
+	void patchControlList(ControlList &controls);
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/control_ids.h.in 0.6.0-2/include/libcamera/control_ids.h.in
--- 0.5.0-1/include/libcamera/control_ids.h.in	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/control_ids.h.in	2025-11-27 11:55:28.000000000 +0000
@@ -13,6 +13,7 @@
 #include <map>
 #include <stdint.h>
 #include <string>
+#include <string_view>
 
 #include <libcamera/controls.h>
 
@@ -49,6 +50,7 @@ extern const std::array<const ControlVal
 extern const std::map<std::string, {{ctrl.type}}> {{ctrl.name}}NameValueMap;
 {% endif -%}
 extern const Control<{{ctrl.type}}> {{ctrl.name}};
+#define LIBCAMERA_HAS_{{vendor|upper}}_VENDOR_{{mode|upper}}_{{ctrl.name|snake_case|upper}}
 {% endfor -%}
 
 {% if vendor != 'libcamera' %}
diff -pruN 0.5.0-1/include/libcamera/controls.h 0.6.0-2/include/libcamera/controls.h
--- 0.5.0-1/include/libcamera/controls.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/controls.h	2025-11-27 11:55:28.000000000 +0000
@@ -10,9 +10,9 @@
 #include <assert.h>
 #include <map>
 #include <optional>
-#include <set>
 #include <stdint.h>
 #include <string>
+#include <string_view>
 #include <unordered_map>
 #include <vector>
 
@@ -96,7 +96,7 @@ struct control_type<float> {
 };
 
 template<>
-struct control_type<std::string> {
+struct control_type<std::string_view> {
 	static constexpr ControlType value = ControlTypeString;
 	static constexpr std::size_t size = 0;
 };
@@ -120,7 +120,7 @@ struct control_type<Point> {
 };
 
 template<typename T, std::size_t N>
-struct control_type<Span<T, N>> : public control_type<std::remove_cv_t<T>> {
+struct control_type<Span<T, N>, std::enable_if_t<control_type<std::remove_cv_t<T>>::size == 0>> : public control_type<std::remove_cv_t<T>> {
 	static constexpr std::size_t size = N;
 };
 
@@ -138,7 +138,7 @@ public:
 #ifndef __DOXYGEN__
 	template<typename T, std::enable_if_t<!details::is_span<T>::value &&
 					      details::control_type<T>::value &&
-					      !std::is_same<std::string, std::remove_cv_t<T>>::value,
+					      !std::is_same<std::string_view, std::remove_cv_t<T>>::value,
 					      std::nullptr_t> = nullptr>
 	ControlValue(const T &value)
 		: type_(ControlTypeNone), numElements_(0)
@@ -148,7 +148,7 @@ public:
 	}
 
 	template<typename T, std::enable_if_t<details::is_span<T>::value ||
-					      std::is_same<std::string, std::remove_cv_t<T>>::value,
+					      std::is_same<std::string_view, std::remove_cv_t<T>>::value,
 					      std::nullptr_t> = nullptr>
 #else
 	template<typename T>
@@ -182,7 +182,7 @@ public:
 
 #ifndef __DOXYGEN__
 	template<typename T, std::enable_if_t<!details::is_span<T>::value &&
-					      !std::is_same<std::string, std::remove_cv_t<T>>::value,
+					      !std::is_same<std::string_view, std::remove_cv_t<T>>::value,
 					      std::nullptr_t> = nullptr>
 	T get() const
 	{
@@ -193,7 +193,7 @@ public:
 	}
 
 	template<typename T, std::enable_if_t<details::is_span<T>::value ||
-					      std::is_same<std::string, std::remove_cv_t<T>>::value,
+					      std::is_same<std::string_view, std::remove_cv_t<T>>::value,
 					      std::nullptr_t> = nullptr>
 #else
 	template<typename T>
@@ -210,7 +210,7 @@ public:
 
 #ifndef __DOXYGEN__
 	template<typename T, std::enable_if_t<!details::is_span<T>::value &&
-					      !std::is_same<std::string, std::remove_cv_t<T>>::value,
+					      !std::is_same<std::string_view, std::remove_cv_t<T>>::value,
 					      std::nullptr_t> = nullptr>
 	void set(const T &value)
 	{
@@ -219,7 +219,7 @@ public:
 	}
 
 	template<typename T, std::enable_if_t<details::is_span<T>::value ||
-					      std::is_same<std::string, std::remove_cv_t<T>>::value,
+					      std::is_same<std::string_view, std::remove_cv_t<T>>::value,
 					      std::nullptr_t> = nullptr>
 #else
 	template<typename T>
@@ -334,8 +334,6 @@ public:
 			     const ControlValue &def = {});
 	explicit ControlInfo(Span<const ControlValue> values,
 			     const ControlValue &def = {});
-	explicit ControlInfo(std::set<bool> values, bool def);
-	explicit ControlInfo(bool value);
 
 	const ControlValue &min() const { return min_; }
 	const ControlValue &max() const { return max_; }
diff -pruN 0.5.0-1/include/libcamera/formats.h.in 0.6.0-2/include/libcamera/formats.h.in
--- 0.5.0-1/include/libcamera/formats.h.in	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/formats.h.in	2025-11-27 11:55:28.000000000 +0000
@@ -33,9 +33,13 @@ constexpr uint64_t __mod(unsigned int ve
 	       (static_cast<uint64_t>(mod) << 0);
 }
 
+constexpr uint32_t kDrmFormatBigEndian = uint32_t(1) << 31; /* DRM_FORMAT_BIG_ENDIAN */
+
 } /* namespace */
 
-${formats}
+{% for f in formats -%}
+constexpr PixelFormat {{f.name}}(__fourcc({{f.fourcc}}){{ ' | kDrmFormatBigEndian' if f.big_endian }}, __mod({{f.mod}}));
+{% endfor %}
 
 } /* namespace formats */
 
diff -pruN 0.5.0-1/include/libcamera/framebuffer.h 0.6.0-2/include/libcamera/framebuffer.h
--- 0.5.0-1/include/libcamera/framebuffer.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/framebuffer.h	2025-11-27 11:55:28.000000000 +0000
@@ -26,6 +26,7 @@ struct FrameMetadata {
 		FrameSuccess,
 		FrameError,
 		FrameCancelled,
+		FrameStartup,
 	};
 
 	struct Plane {
@@ -57,11 +58,11 @@ public:
 		unsigned int length;
 	};
 
-	FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie = 0);
+	FrameBuffer(Span<const Plane> planes, unsigned int cookie = 0);
 	FrameBuffer(std::unique_ptr<Private> d);
 	virtual ~FrameBuffer() {}
 
-	const std::vector<Plane> &planes() const;
+	Span<const Plane> planes() const;
 	Request *request() const;
 	const FrameMetadata &metadata() const;
 
diff -pruN 0.5.0-1/include/libcamera/geometry.h 0.6.0-2/include/libcamera/geometry.h
--- 0.5.0-1/include/libcamera/geometry.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/geometry.h	2025-11-27 11:55:28.000000000 +0000
@@ -31,7 +31,7 @@ public:
 	int x;
 	int y;
 
-	const std::string toString() const;
+	std::string toString() const;
 
 	constexpr Point operator-() const
 	{
@@ -64,7 +64,7 @@ public:
 	unsigned int height;
 
 	bool isNull() const { return !width && !height; }
-	const std::string toString() const;
+	std::string toString() const;
 
 	Size &alignDownTo(unsigned int hAlignment, unsigned int vAlignment)
 	{
@@ -108,6 +108,12 @@ public:
 		return *this;
 	}
 
+	Size &transpose()
+	{
+		std::swap(width, height);
+		return *this;
+	}
+
 	[[nodiscard]] constexpr Size alignedDownTo(unsigned int hAlignment,
 						   unsigned int vAlignment) const
 	{
@@ -275,7 +281,7 @@ public:
 	unsigned int height;
 
 	bool isNull() const { return !width && !height; }
-	const std::string toString() const;
+	std::string toString() const;
 
 	Point center() const;
 
diff -pruN 0.5.0-1/include/libcamera/internal/camera.h 0.6.0-2/include/libcamera/internal/camera.h
--- 0.5.0-1/include/libcamera/internal/camera.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/camera.h	2025-11-27 11:55:28.000000000 +0000
@@ -10,6 +10,7 @@
 #include <atomic>
 #include <list>
 #include <memory>
+#include <queue>
 #include <set>
 #include <stdint.h>
 #include <string>
@@ -36,6 +37,7 @@ public:
 	const PipelineHandler *pipe() const { return pipe_.get(); }
 
 	std::list<Request *> queuedRequests_;
+	std::queue<Request *> waitingRequests_;
 	ControlInfoMap controlInfo_;
 	ControlList properties_;
 
diff -pruN 0.5.0-1/include/libcamera/internal/camera_manager.h 0.6.0-2/include/libcamera/internal/camera_manager.h
--- 0.5.0-1/include/libcamera/internal/camera_manager.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/camera_manager.h	2025-11-27 11:55:28.000000000 +0000
@@ -18,6 +18,7 @@
 #include <libcamera/base/thread.h>
 #include <libcamera/base/thread_annotations.h>
 
+#include "libcamera/internal/global_configuration.h"
 #include "libcamera/internal/process.h"
 
 namespace libcamera {
@@ -38,6 +39,11 @@ public:
 	void addCamera(std::shared_ptr<Camera> camera) LIBCAMERA_TSA_EXCLUDES(mutex_);
 	void removeCamera(std::shared_ptr<Camera> camera) LIBCAMERA_TSA_EXCLUDES(mutex_);
 
+	const GlobalConfiguration &configuration() const
+	{
+		return configuration_;
+	}
+
 	IPAManager *ipaManager() const { return ipaManager_.get(); }
 
 protected:
@@ -65,7 +71,8 @@ private:
 	std::unique_ptr<DeviceEnumerator> enumerator_;
 
 	std::unique_ptr<IPAManager> ipaManager_;
-	ProcessManager processManager_;
+
+	const GlobalConfiguration configuration_;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/camera_sensor.h 0.6.0-2/include/libcamera/internal/camera_sensor.h
--- 0.5.0-1/include/libcamera/internal/camera_sensor.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/camera_sensor.h	2025-11-27 11:55:28.000000000 +0000
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include <libcamera/base/class.h>
+#include <libcamera/base/span.h>
 
 #include <libcamera/control_ids.h>
 #include <libcamera/controls.h>
@@ -53,7 +54,7 @@ public:
 	virtual Size resolution() const = 0;
 
 	virtual V4L2SubdeviceFormat
-	getFormat(const std::vector<unsigned int> &mbusCodes,
+	getFormat(Span<const unsigned int> mbusCodes,
 		  const Size &size, const Size maxSize = Size()) const = 0;
 	virtual int setFormat(V4L2SubdeviceFormat *format,
 			      Transform transform = Transform::Identity) = 0;
@@ -72,9 +73,10 @@ public:
 	virtual int sensorInfo(IPACameraSensorInfo *info) const = 0;
 	virtual Transform computeTransform(Orientation *orientation) const = 0;
 	virtual BayerFormat::Order bayerOrder(Transform t) const = 0;
+	virtual Orientation mountingOrientation() const = 0;
 
 	virtual const ControlInfoMap &controls() const = 0;
-	virtual ControlList getControls(const std::vector<uint32_t> &ids) = 0;
+	virtual ControlList getControls(Span<const uint32_t> ids) = 0;
 	virtual int setControls(ControlList *ctrls) = 0;
 
 	virtual const std::vector<controls::draft::TestPatternModeEnum> &
diff -pruN 0.5.0-1/include/libcamera/internal/clock_recovery.h 0.6.0-2/include/libcamera/internal/clock_recovery.h
--- 0.5.0-1/include/libcamera/internal/clock_recovery.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/clock_recovery.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Raspberry Pi Ltd
+ *
+ * Camera recovery algorithm
+ */
+#pragma once
+
+#include <stdint.h>
+
+namespace libcamera {
+
+class ClockRecovery
+{
+public:
+	ClockRecovery();
+
+	void configure(unsigned int numSamples = 100, unsigned int maxJitter = 2000,
+		       unsigned int minSamples = 10, unsigned int errorThreshold = 50000);
+	void reset();
+
+	void addSample();
+	void addSample(uint64_t input, uint64_t output);
+
+	uint64_t getOutput(uint64_t input);
+
+private:
+	/* Approximate number of samples over which the model state persists. */
+	unsigned int numSamples_;
+	/* Remove any output jitter larger than this immediately. */
+	unsigned int maxJitter_;
+	/* Number of samples required before we start to use model estimates. */
+	unsigned int minSamples_;
+	/* Threshold above which we assume the wallclock has been reset. */
+	unsigned int errorThreshold_;
+
+	/* How many samples seen (up to numSamples_). */
+	unsigned int count_;
+	/* This gets subtracted from all input values, just to make the numbers easier. */
+	uint64_t inputBase_;
+	/* As above, for the output. */
+	uint64_t outputBase_;
+	/* The previous input sample. */
+	uint64_t lastInput_;
+	/* The previous output sample. */
+	uint64_t lastOutput_;
+
+	/* Average x value seen so far. */
+	double xAve_;
+	/* Average y value seen so far */
+	double yAve_;
+	/* Average x^2 value seen so far. */
+	double x2Ave_;
+	/* Average x*y value seen so far. */
+	double xyAve_;
+
+	/*
+	 * The latest estimate of linear parameters to derive the output clock
+	 * from the input.
+	 */
+	double slope_;
+	double offset_;
+
+	/* Use this cumulative error to monitor for spontaneous clock updates. */
+	double error_;
+};
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/control_serializer.h 0.6.0-2/include/libcamera/internal/control_serializer.h
--- 0.5.0-1/include/libcamera/internal/control_serializer.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/control_serializer.h	2025-11-27 11:55:28.000000000 +0000
@@ -47,9 +47,13 @@ private:
 	static void store(const ControlValue &value, ByteStreamBuffer &buffer);
 	static void store(const ControlInfo &info, ByteStreamBuffer &buffer);
 
+	void populateControlValueEntry(struct ipa_control_value_entry &entry,
+				       const ControlValue &value,
+				       uint32_t offset);
+
 	ControlValue loadControlValue(ByteStreamBuffer &buffer,
-				      bool isArray = false, unsigned int count = 1);
-	ControlInfo loadControlInfo(ByteStreamBuffer &buffer);
+				      ControlType type,
+				      bool isArray, unsigned int count);
 
 	unsigned int serial_;
 	unsigned int serialSeed_;
diff -pruN 0.5.0-1/include/libcamera/internal/converter/converter_dw100.h 0.6.0-2/include/libcamera/internal/converter/converter_dw100.h
--- 0.5.0-1/include/libcamera/internal/converter/converter_dw100.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/converter/converter_dw100.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,93 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ *
+ * DW100 Dewarp Engine integration
+ */
+
+#pragma once
+
+#include <memory>
+#include <queue>
+
+#include <libcamera/control_ids.h>
+#include <libcamera/controls.h>
+#include <libcamera/framebuffer.h>
+
+#include "libcamera/internal/converter/converter_dw100_vertexmap.h"
+#include "libcamera/internal/converter/converter_v4l2_m2m.h"
+#include "libcamera/internal/device_enumerator.h"
+
+namespace libcamera {
+
+class MediaDevice;
+class Rectangle;
+class Stream;
+
+class ConverterDW100Module
+{
+public:
+	virtual ~ConverterDW100Module() = default;
+
+	static std::unique_ptr<ConverterDW100Module> createModule(DeviceEnumerator *enumerator);
+
+	int init(const YamlObject &params);
+
+	int configure(const StreamConfiguration &inputCfg,
+		      const std::vector<std::reference_wrapper<StreamConfiguration>>
+			      &outputCfg);
+	bool isConfigured(const Stream *stream) const;
+
+	Size adjustInputSize(const PixelFormat &pixFmt, const Size &size,
+			     Converter::Alignment align = Converter::Alignment::Down);
+	Size adjustOutputSize(const PixelFormat &pixFmt, const Size &size,
+			      Converter::Alignment align = Converter::Alignment::Down);
+
+	int exportBuffers(const Stream *stream, unsigned int count,
+			  std::vector<std::unique_ptr<FrameBuffer>> *buffers);
+	int validateOutput(StreamConfiguration *cfg, bool *adjusted,
+			   Converter::Alignment align = Converter::Alignment::Down);
+	int queueBuffers(FrameBuffer *input,
+			 const std::map<const Stream *, FrameBuffer *> &outputs);
+
+	int start();
+	void stop();
+
+	void updateControlInfos(const Stream *stream, ControlInfoMap::Map &infos);
+	void setControls(const Stream *stream, const ControlList &controls);
+	void populateMetadata(const Stream *stream, ControlList &meta);
+
+	void setSensorCrop(const Rectangle &rect);
+	void setTransform(const Stream *stream, const Transform &transform);
+
+	Signal<FrameBuffer *> inputBufferReady;
+	Signal<FrameBuffer *> outputBufferReady;
+
+private:
+	ConverterDW100Module(std::shared_ptr<MediaDevice> media);
+
+	int applyControls(const Stream *stream, const V4L2Request *request);
+	void reinitRequest(V4L2Request *request);
+
+	struct DewarpParms {
+		Matrix<double, 3, 3> cm;
+		std::vector<double> coeffs;
+	};
+
+	struct VertexMapInfo {
+		Dw100VertexMap map;
+		bool update;
+	};
+
+	std::map<const Stream *, VertexMapInfo> vertexMaps_;
+	std::optional<DewarpParms> dewarpParams_;
+	unsigned int inputBufferCount_;
+	V4L2M2MConverter converter_;
+	Rectangle sensorCrop_;
+	bool running_;
+
+	std::vector<std::unique_ptr<V4L2Request>> requests_;
+	std::queue<V4L2Request *> availableRequests_;
+};
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/converter/converter_dw100_vertexmap.h 0.6.0-2/include/libcamera/internal/converter/converter_dw100_vertexmap.h
--- 0.5.0-1/include/libcamera/internal/converter/converter_dw100_vertexmap.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/converter/converter_dw100_vertexmap.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ *
+ * DW100 vertex map interface
+ */
+
+#pragma once
+
+#include <assert.h>
+#include <cmath>
+#include <stdint.h>
+#include <vector>
+
+#include <libcamera/base/span.h>
+
+#include <libcamera/geometry.h>
+#include <libcamera/transform.h>
+
+#include "libcamera/internal/matrix.h"
+#include "libcamera/internal/vector.h"
+
+namespace libcamera {
+
+class Dw100VertexMap
+{
+public:
+	enum ScaleMode {
+		Fill = 0,
+		Crop = 1,
+	};
+
+	void applyLimits();
+	void setInputSize(const Size &size)
+	{
+		inputSize_ = size;
+		scalerCrop_ = Rectangle(size);
+	}
+
+	void setSensorCrop(const Rectangle &rect) { sensorCrop_ = rect; }
+
+	void setScalerCrop(const Rectangle &rect) { scalerCrop_ = rect; }
+	const Rectangle &effectiveScalerCrop() const { return effectiveScalerCrop_; }
+
+	void setOutputSize(const Size &size) { outputSize_ = size; }
+	const Size &outputSize() const { return outputSize_; }
+
+	void setTransform(const Transform &transform) { transform_ = transform; }
+	const Transform &transform() const { return transform_; }
+
+	void setScale(const float scale) { scale_ = scale; }
+	float effectiveScale() const { return (effectiveScaleX_ + effectiveScaleY_) * 0.5; }
+
+	void setRotation(const float rotation) { rotation_ = rotation; }
+	float rotation() const { return rotation_; }
+
+	void setOffset(const Point &offset) { offset_ = offset; }
+	const Point &effectiveOffset() const { return effectiveOffset_; }
+
+	void setMode(const ScaleMode mode) { mode_ = mode; }
+	ScaleMode mode() const { return mode_; }
+
+	int setDewarpParams(const Matrix<double, 3, 3> &cm, const Span<const double> &coeffs);
+	bool dewarpParamsValid() { return dewarpParamsValid_; }
+
+	void setLensDewarpEnable(bool enable) { lensDewarpEnable_ = enable; }
+	bool lensDewarpEnable() { return lensDewarpEnable_; }
+
+	std::vector<uint32_t> getVertexMap();
+
+private:
+	Vector<double, 2> dewarpPoint(const Vector<double, 2> &p);
+
+	Rectangle scalerCrop_;
+	Rectangle sensorCrop_;
+	Transform transform_ = Transform::Identity;
+	Size inputSize_;
+	Size outputSize_;
+	Point offset_;
+	double scale_ = 1.0;
+	double rotation_ = 0.0;
+	ScaleMode mode_ = Fill;
+	double effectiveScaleX_;
+	double effectiveScaleY_;
+	Point effectiveOffset_;
+	Rectangle effectiveScalerCrop_;
+
+	Matrix<double, 3, 3> dewarpM_ = Matrix<double, 3, 3>::identity();
+	std::array<double, 12> dewarpCoeffs_;
+	bool lensDewarpEnable_ = true;
+	bool dewarpParamsValid_ = false;
+};
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/converter/converter_v4l2_m2m.h 0.6.0-2/include/libcamera/internal/converter/converter_v4l2_m2m.h
--- 0.5.0-1/include/libcamera/internal/converter/converter_v4l2_m2m.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/converter/converter_v4l2_m2m.h	2025-11-27 11:55:28.000000000 +0000
@@ -24,6 +24,7 @@
 
 namespace libcamera {
 
+class ControlList;
 class FrameBuffer;
 class MediaDevice;
 class Size;
@@ -36,7 +37,7 @@ class V4L2M2MDevice;
 class V4L2M2MConverter : public Converter
 {
 public:
-	V4L2M2MConverter(MediaDevice *media);
+	V4L2M2MConverter(std::shared_ptr<MediaDevice> media);
 
 	int loadConfiguration([[maybe_unused]] const std::string &filename) override { return 0; }
 	bool isValid() const override { return m2m_ != nullptr; }
@@ -66,12 +67,20 @@ public:
 			   Alignment align = Alignment::Down) override;
 
 	int queueBuffers(FrameBuffer *input,
-			 const std::map<const Stream *, FrameBuffer *> &outputs) override;
+			 const std::map<const Stream *, FrameBuffer *> &outputs,
+			 const V4L2Request *request = nullptr) override;
 
 	int setInputCrop(const Stream *stream, Rectangle *rect) override;
 	std::pair<Rectangle, Rectangle> inputCropBounds() override { return inputCropBounds_; }
 	std::pair<Rectangle, Rectangle> inputCropBounds(const Stream *stream) override;
 
+	int applyControls(const Stream *stream, ControlList &ctrls, const V4L2Request *request = nullptr);
+
+	int allocateRequests(unsigned int count,
+			     std::vector<std::unique_ptr<V4L2Request>> *requests);
+
+	bool supportsRequests();
+
 private:
 	class V4L2M2MStream : protected Loggable
 	{
@@ -88,7 +97,10 @@ private:
 		int start();
 		void stop();
 
-		int queueBuffers(FrameBuffer *input, FrameBuffer *output);
+		int applyControls(ControlList &ctrls, const V4L2Request *request = nullptr);
+
+		int queueBuffers(FrameBuffer *input, FrameBuffer *output,
+				 const V4L2Request *request = nullptr);
 
 		int setInputSelection(unsigned int target, Rectangle *rect);
 		int getInputSelection(unsigned int target, Rectangle *rect);
@@ -120,6 +132,8 @@ private:
 	std::map<const Stream *, std::unique_ptr<V4L2M2MStream>> streams_;
 	std::map<FrameBuffer *, unsigned int> queue_;
 	std::pair<Rectangle, Rectangle> inputCropBounds_;
+
+	std::shared_ptr<MediaDevice> media_;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/converter/meson.build 0.6.0-2/include/libcamera/internal/converter/meson.build
--- 0.5.0-1/include/libcamera/internal/converter/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/converter/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: CC0-1.0
 
 libcamera_internal_headers += files([
+    'converter_dw100.h',
+    'converter_dw100_vertexmap.h',
     'converter_v4l2_m2m.h',
 ])
diff -pruN 0.5.0-1/include/libcamera/internal/converter.h 0.6.0-2/include/libcamera/internal/converter.h
--- 0.5.0-1/include/libcamera/internal/converter.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/converter.h	2025-11-27 11:55:28.000000000 +0000
@@ -22,6 +22,7 @@
 #include <libcamera/base/signal.h>
 
 #include <libcamera/geometry.h>
+#include "libcamera/internal/v4l2_request.h"
 
 namespace libcamera {
 
@@ -46,7 +47,7 @@ public:
 		Up,
 	};
 
-	Converter(MediaDevice *media, Features features = Feature::None);
+	Converter(std::shared_ptr<MediaDevice> media, Features features = Feature::None);
 	virtual ~Converter();
 
 	virtual int loadConfiguration(const std::string &filename) = 0;
@@ -79,7 +80,8 @@ public:
 	virtual void stop() = 0;
 
 	virtual int queueBuffers(FrameBuffer *input,
-				 const std::map<const Stream *, FrameBuffer *> &outputs) = 0;
+				 const std::map<const Stream *, FrameBuffer *> &outputs,
+				 const V4L2Request *request = nullptr) = 0;
 
 	virtual int setInputCrop(const Stream *stream, Rectangle *rect) = 0;
 	virtual std::pair<Rectangle, Rectangle> inputCropBounds() = 0;
@@ -107,7 +109,7 @@ public:
 
 	const std::vector<std::string> &compatibles() const { return compatibles_; }
 
-	static std::unique_ptr<Converter> create(MediaDevice *media);
+	static std::unique_ptr<Converter> create(std::shared_ptr<MediaDevice> media);
 	static std::vector<ConverterFactoryBase *> &factories();
 	static std::vector<std::string> names();
 
@@ -116,7 +118,8 @@ private:
 
 	static void registerType(ConverterFactoryBase *factory);
 
-	virtual std::unique_ptr<Converter> createInstance(MediaDevice *media) const = 0;
+	virtual std::unique_ptr<Converter>
+	createInstance(std::shared_ptr<MediaDevice> media) const = 0;
 
 	std::string name_;
 	std::vector<std::string> compatibles_;
@@ -131,7 +134,7 @@ public:
 	{
 	}
 
-	std::unique_ptr<Converter> createInstance(MediaDevice *media) const override
+	std::unique_ptr<Converter> createInstance(std::shared_ptr<MediaDevice> media) const override
 	{
 		return std::make_unique<_Converter>(media);
 	}
diff -pruN 0.5.0-1/include/libcamera/internal/delayed_controls.h 0.6.0-2/include/libcamera/internal/delayed_controls.h
--- 0.5.0-1/include/libcamera/internal/delayed_controls.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/delayed_controls.h	2025-11-27 11:55:28.000000000 +0000
@@ -10,13 +10,15 @@
 #include <stdint.h>
 #include <unordered_map>
 
+#include <libcamera/base/object.h>
+
 #include <libcamera/controls.h>
 
 namespace libcamera {
 
 class V4L2Device;
 
-class DelayedControls
+class DelayedControls : public Object
 {
 public:
 	struct ControlParams {
diff -pruN 0.5.0-1/include/libcamera/internal/framebuffer.h 0.6.0-2/include/libcamera/internal/framebuffer.h
--- 0.5.0-1/include/libcamera/internal/framebuffer.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/framebuffer.h	2025-11-27 11:55:28.000000000 +0000
@@ -12,6 +12,7 @@
 #include <utility>
 
 #include <libcamera/base/class.h>
+#include <libcamera/base/span.h>
 
 #include <libcamera/fence.h>
 #include <libcamera/framebuffer.h>
@@ -23,7 +24,7 @@ class FrameBuffer::Private : public Exte
 	LIBCAMERA_DECLARE_PUBLIC(FrameBuffer)
 
 public:
-	Private(const std::vector<Plane> &planes, uint64_t cookie = 0);
+	Private(Span<const Plane> planes, uint64_t cookie = 0);
 	virtual ~Private();
 
 	void setRequest(Request *request) { request_ = request; }
diff -pruN 0.5.0-1/include/libcamera/internal/global_configuration.h 0.6.0-2/include/libcamera/internal/global_configuration.h
--- 0.5.0-1/include/libcamera/internal/global_configuration.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/global_configuration.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024-2025 Red Hat, inc.
+ *
+ * Global configuration handling
+ */
+
+#pragma once
+
+#include <filesystem>
+#include <optional>
+#include <string>
+#include <string_view>
+
+#include <libcamera/base/utils.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
+namespace libcamera {
+
+class GlobalConfiguration
+{
+public:
+	using Configuration = const YamlObject &;
+
+	GlobalConfiguration();
+
+	unsigned int version() const;
+	Configuration configuration() const;
+
+	template<typename T>
+	std::optional<T> option(
+		const std::initializer_list<std::string_view> confPath) const
+	{
+		const YamlObject *c = &configuration();
+		for (auto part : confPath) {
+			c = &(*c)[part];
+			if (!*c)
+				return {};
+		}
+		return c->get<T>();
+	}
+
+	std::optional<std::vector<std::string>> listOption(
+		const std::initializer_list<std::string_view> confPath) const;
+	std::optional<std::string> envOption(
+		const char *const envVariable,
+		const std::initializer_list<std::string_view> confPath) const;
+	std::optional<std::vector<std::string>> envListOption(
+		const char *const envVariable,
+		const std::initializer_list<std::string_view> confPath,
+		const std::string delimiter = ":") const;
+
+private:
+	bool loadFile(const std::filesystem::path &fileName);
+	void load();
+
+	std::unique_ptr<YamlObject> yamlConfiguration_ =
+		std::make_unique<YamlObject>();
+};
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/ipa_data_serializer.h 0.6.0-2/include/libcamera/internal/ipa_data_serializer.h
--- 0.5.0-1/include/libcamera/internal/ipa_data_serializer.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/ipa_data_serializer.h	2025-11-27 11:55:28.000000000 +0000
@@ -61,7 +61,7 @@ T readPOD(std::vector<uint8_t> &vec, siz
 
 } /* namespace */
 
-template<typename T>
+template<typename T, typename = void>
 class IPADataSerializer
 {
 public:
@@ -309,7 +309,6 @@ public:
 	serialize(const Flags<E> &data, [[maybe_unused]] ControlSerializer *cs = nullptr)
 	{
 		std::vector<uint8_t> dataVec;
-		dataVec.reserve(sizeof(Flags<E>));
 		appendPOD<uint32_t>(dataVec, static_cast<typename Flags<E>::Type>(data));
 
 		return { dataVec, {} };
@@ -343,6 +342,52 @@ public:
 	{
 		return deserialize(dataBegin, dataEnd);
 	}
+};
+
+template<typename E>
+class IPADataSerializer<E, std::enable_if_t<std::is_enum_v<E>>>
+{
+	using U = uint32_t;
+	static_assert(sizeof(E) <= sizeof(U));
+
+public:
+	static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>>
+	serialize(const E &data, [[maybe_unused]] ControlSerializer *cs = nullptr)
+	{
+		std::vector<uint8_t> dataVec;
+		appendPOD<U>(dataVec, static_cast<U>(data));
+
+		return { dataVec, {} };
+	}
+
+	static E deserialize(std::vector<uint8_t> &data,
+			     [[maybe_unused]] ControlSerializer *cs = nullptr)
+	{
+		return deserialize(data.cbegin(), data.cend());
+	}
+
+	static E deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+			     std::vector<uint8_t>::const_iterator dataEnd,
+			     [[maybe_unused]] ControlSerializer *cs = nullptr)
+	{
+		return static_cast<E>(readPOD<U>(dataBegin, 0, dataEnd));
+	}
+
+	static E deserialize(std::vector<uint8_t> &data,
+			     [[maybe_unused]] std::vector<SharedFD> &fds,
+			     [[maybe_unused]] ControlSerializer *cs = nullptr)
+	{
+		return deserialize(data.cbegin(), data.cend());
+	}
+
+	static E deserialize(std::vector<uint8_t>::const_iterator dataBegin,
+			     std::vector<uint8_t>::const_iterator dataEnd,
+			     [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsBegin,
+			     [[maybe_unused]] std::vector<SharedFD>::const_iterator fdsEnd,
+			     [[maybe_unused]] ControlSerializer *cs = nullptr)
+	{
+		return deserialize(dataBegin, dataEnd);
+	}
 };
 
 #endif /* __DOXYGEN__ */
diff -pruN 0.5.0-1/include/libcamera/internal/ipa_manager.h 0.6.0-2/include/libcamera/internal/ipa_manager.h
--- 0.5.0-1/include/libcamera/internal/ipa_manager.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/ipa_manager.h	2025-11-27 11:55:28.000000000 +0000
@@ -17,6 +17,7 @@
 #include <libcamera/ipa/ipa_module_info.h>
 
 #include "libcamera/internal/camera_manager.h"
+#include "libcamera/internal/global_configuration.h"
 #include "libcamera/internal/ipa_module.h"
 #include "libcamera/internal/pipeline_handler.h"
 #include "libcamera/internal/pub_key.h"
@@ -28,7 +29,7 @@ LOG_DECLARE_CATEGORY(IPAManager)
 class IPAManager
 {
 public:
-	IPAManager();
+	IPAManager(const GlobalConfiguration &configuration);
 	~IPAManager();
 
 	template<typename T>
@@ -42,7 +43,15 @@ public:
 		if (!m)
 			return nullptr;
 
-		std::unique_ptr<T> proxy = std::make_unique<T>(m, !self->isSignatureValid(m));
+		const GlobalConfiguration &configuration = cm->_d()->configuration();
+
+		auto proxy = [&]() -> std::unique_ptr<T> {
+			if (self->isSignatureValid(m))
+				return std::make_unique<typename T::Threaded>(m, configuration);
+			else
+				return std::make_unique<typename T::Isolated>(m, configuration);
+		}();
+
 		if (!proxy->isValid()) {
 			LOG(IPAManager, Error) << "Failed to load proxy";
 			return nullptr;
@@ -73,6 +82,7 @@ private:
 #if HAVE_IPA_PUBKEY
 	static const uint8_t publicKeyData_[];
 	static const PubKey pubKey_;
+	bool forceIsolation_;
 #endif
 };
 
diff -pruN 0.5.0-1/include/libcamera/internal/ipa_module.h 0.6.0-2/include/libcamera/internal/ipa_module.h
--- 0.5.0-1/include/libcamera/internal/ipa_module.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/ipa_module.h	2025-11-27 11:55:28.000000000 +0000
@@ -29,7 +29,7 @@ public:
 	bool isValid() const;
 
 	const struct IPAModuleInfo &info() const;
-	const std::vector<uint8_t> signature() const;
+	const std::vector<uint8_t> &signature() const;
 	const std::string &path() const;
 
 	bool load();
diff -pruN 0.5.0-1/include/libcamera/internal/ipa_proxy.h 0.6.0-2/include/libcamera/internal/ipa_proxy.h
--- 0.5.0-1/include/libcamera/internal/ipa_proxy.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/ipa_proxy.h	2025-11-27 11:55:28.000000000 +0000
@@ -7,10 +7,14 @@
 
 #pragma once
 
+#include <optional>
 #include <string>
+#include <vector>
 
 #include <libcamera/ipa/ipa_interface.h>
 
+#include "libcamera/internal/global_configuration.h"
+
 namespace libcamera {
 
 class IPAModule;
@@ -24,7 +28,7 @@ public:
 		ProxyRunning,
 	};
 
-	IPAProxy(IPAModule *ipam);
+	IPAProxy(IPAModule *ipam, const GlobalConfiguration &configuration);
 	~IPAProxy();
 
 	bool isValid() const { return valid_; }
@@ -40,6 +44,8 @@ protected:
 
 private:
 	IPAModule *ipam_;
+	std::vector<std::string> configPaths_;
+	std::vector<std::string> execPaths_;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/matrix.h 0.6.0-2/include/libcamera/internal/matrix.h
--- 0.5.0-1/include/libcamera/internal/matrix.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/matrix.h	2025-11-27 11:55:28.000000000 +0000
@@ -8,6 +8,7 @@
 
 #include <algorithm>
 #include <sstream>
+#include <type_traits>
 #include <vector>
 
 #include <libcamera/base/log.h>
@@ -20,17 +21,19 @@ namespace libcamera {
 LOG_DECLARE_CATEGORY(Matrix)
 
 #ifndef __DOXYGEN__
-template<typename T, unsigned int Rows, unsigned int Cols,
-	 std::enable_if_t<std::is_arithmetic_v<T>> * = nullptr>
-#else
-template<typename T, unsigned int Rows, unsigned int Cols>
+template<typename T>
+bool matrixInvert(Span<const T> dataIn, Span<T> dataOut, unsigned int dim,
+		  Span<T> scratchBuffer, Span<unsigned int> swapBuffer);
 #endif /* __DOXYGEN__ */
+
+template<typename T, unsigned int Rows, unsigned int Cols>
 class Matrix
 {
+	static_assert(std::is_arithmetic_v<T>, "Matrix type must be arithmetic");
+
 public:
-	Matrix()
+	constexpr Matrix()
 	{
-		data_.fill(static_cast<T>(0));
 	}
 
 	Matrix(const std::array<T, Rows * Cols> &data)
@@ -38,7 +41,12 @@ public:
 		std::copy(data.begin(), data.end(), data_.begin());
 	}
 
-	static Matrix identity()
+	Matrix(const Span<const T, Rows * Cols> data)
+	{
+		std::copy(data.begin(), data.end(), data_.begin());
+	}
+
+	static constexpr Matrix identity()
 	{
 		Matrix ret;
 		for (size_t i = 0; i < std::min(Rows, Cols); i++)
@@ -48,7 +56,7 @@ public:
 
 	~Matrix() = default;
 
-	const std::string toString() const
+	std::string toString() const
 	{
 		std::stringstream out;
 
@@ -66,14 +74,14 @@ public:
 		return out.str();
 	}
 
-	Span<const T, Rows * Cols> data() const { return data_; }
+	constexpr Span<const T, Rows * Cols> data() const { return data_; }
 
-	Span<const T, Cols> operator[](size_t i) const
+	constexpr Span<const T, Cols> operator[](size_t i) const
 	{
 		return Span<const T, Cols>{ &data_.data()[i * Cols], Cols };
 	}
 
-	Span<T, Cols> operator[](size_t i)
+	constexpr Span<T, Cols> operator[](size_t i)
 	{
 		return Span<T, Cols>{ &data_.data()[i * Cols], Cols };
 	}
@@ -90,8 +98,30 @@ public:
 		return *this;
 	}
 
+	Matrix<T, Rows, Cols> inverse(bool *ok = nullptr) const
+	{
+		static_assert(Rows == Cols, "Matrix must be square");
+
+		Matrix<T, Rows, Cols> inverse;
+		std::array<T, Rows * Cols * 2> scratchBuffer;
+		std::array<unsigned int, Rows> swapBuffer;
+		bool res = matrixInvert(Span<const T>(data_),
+					Span<T>(inverse.data_),
+					Rows,
+					Span<T>(scratchBuffer),
+					Span<unsigned int>(swapBuffer));
+		if (ok)
+			*ok = res;
+		return inverse;
+	}
+
 private:
-	std::array<T, Rows * Cols> data_;
+	/*
+	 * \todo The initializer is only necessary for the constructor to be
+	 * constexpr in C++17. Remove the initializer as soon as we are on
+	 * C++20.
+	 */
+	std::array<T, Rows * Cols> data_ = {};
 };
 
 #ifndef __DOXYGEN__
@@ -123,21 +153,16 @@ Matrix<U, Rows, Cols> operator*(const Ma
 	return d * m;
 }
 
-#ifndef __DOXYGEN__
-template<typename T,
-	 unsigned int R1, unsigned int C1,
-	 unsigned int R2, unsigned int C2,
-	 std::enable_if_t<C1 == R2> * = nullptr>
-#else
-template<typename T, unsigned int R1, unsigned int C1, unsigned int R2, unsigned in C2>
-#endif /* __DOXYGEN__ */
-Matrix<T, R1, C2> operator*(const Matrix<T, R1, C1> &m1, const Matrix<T, R2, C2> &m2)
+template<typename T1, unsigned int R1, unsigned int C1, typename T2, unsigned int R2, unsigned int C2>
+constexpr Matrix<std::common_type_t<T1, T2>, R1, C2> operator*(const Matrix<T1, R1, C1> &m1,
+							       const Matrix<T2, R2, C2> &m2)
 {
-	Matrix<T, R1, C2> result;
+	static_assert(C1 == R2, "Matrix dimensions must match for multiplication");
+	Matrix<std::common_type_t<T1, T2>, R1, C2> result;
 
 	for (unsigned int i = 0; i < R1; i++) {
 		for (unsigned int j = 0; j < C2; j++) {
-			T sum = 0;
+			std::common_type_t<T1, T2> sum = 0;
 
 			for (unsigned int k = 0; k < C1; k++)
 				sum += m1[i][k] * m2[k][j];
@@ -150,7 +175,7 @@ Matrix<T, R1, C2> operator*(const Matrix
 }
 
 template<typename T, unsigned int Rows, unsigned int Cols>
-Matrix<T, Rows, Cols> operator+(const Matrix<T, Rows, Cols> &m1, const Matrix<T, Rows, Cols> &m2)
+constexpr Matrix<T, Rows, Cols> operator+(const Matrix<T, Rows, Cols> &m1, const Matrix<T, Rows, Cols> &m2)
 {
 	Matrix<T, Rows, Cols> result;
 
diff -pruN 0.5.0-1/include/libcamera/internal/media_device.h 0.6.0-2/include/libcamera/internal/media_device.h
--- 0.5.0-1/include/libcamera/internal/media_device.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/media_device.h	2025-11-27 11:55:28.000000000 +0000
@@ -8,6 +8,7 @@
 #pragma once
 
 #include <map>
+#include <optional>
 #include <string>
 #include <vector>
 
@@ -18,6 +19,7 @@
 #include <libcamera/base/unique_fd.h>
 
 #include "libcamera/internal/media_object.h"
+#include "libcamera/internal/v4l2_request.h"
 
 namespace libcamera {
 
@@ -55,6 +57,13 @@ public:
 
 	Signal<> disconnected;
 
+	std::vector<MediaEntity *> locateEntities(unsigned int function);
+
+	int allocateRequests(unsigned int count,
+			     std::vector<std::unique_ptr<V4L2Request>> *requests);
+
+	bool supportsRequests();
+
 protected:
 	std::string logPrefix() const override;
 
@@ -85,6 +94,7 @@ private:
 	UniqueFD fd_;
 	bool valid_;
 	bool acquired_;
+	std::optional<bool> supportsRequests_;
 
 	std::map<unsigned int, MediaObject *> objects_;
 	std::vector<MediaEntity *> entities_;
diff -pruN 0.5.0-1/include/libcamera/internal/media_pipeline.h 0.6.0-2/include/libcamera/internal/media_pipeline.h
--- 0.5.0-1/include/libcamera/internal/media_pipeline.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/media_pipeline.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Ideas on Board Oy
+ *
+ * Media pipeline support
+ */
+
+#pragma once
+
+#include <list>
+#include <string>
+
+#include <libcamera/base/log.h>
+
+namespace libcamera {
+
+class CameraSensor;
+class MediaEntity;
+class MediaLink;
+class MediaPad;
+struct V4L2SubdeviceFormat;
+
+class MediaPipeline
+{
+public:
+	int init(MediaEntity *source, std::string_view sink);
+	int initLinks();
+	int configure(CameraSensor *sensor, V4L2SubdeviceFormat *);
+
+private:
+	struct Entity {
+		/* The media entity, always valid. */
+		MediaEntity *entity;
+		/*
+		 * Whether or not the entity is a subdev that supports the
+		 * routing API.
+		 */
+		bool supportsRouting;
+		/*
+		 * The local sink pad connected to the upstream entity, null for
+		 * the camera sensor at the beginning of the pipeline.
+		 */
+		const MediaPad *sink;
+		/*
+		 * The local source pad connected to the downstream entity, null
+		 * for the video node at the end of the pipeline.
+		 */
+		const MediaPad *source;
+		/*
+		 * The link on the source pad, to the downstream entity, null
+		 * for the video node at the end of the pipeline.
+		 */
+		MediaLink *sourceLink;
+	};
+
+	std::list<Entity> entities_;
+};
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/meson.build 0.6.0-2/include/libcamera/internal/meson.build
--- 0.5.0-1/include/libcamera/internal/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -11,6 +11,7 @@ libcamera_internal_headers = files([
     'camera_manager.h',
     'camera_sensor.h',
     'camera_sensor_properties.h',
+    'clock_recovery.h',
     'control_serializer.h',
     'control_validator.h',
     'converter.h',
@@ -22,6 +23,7 @@ libcamera_internal_headers = files([
     'dma_buf_allocator.h',
     'formats.h',
     'framebuffer.h',
+    'global_configuration.h',
     'ipa_data_serializer.h',
     'ipa_manager.h',
     'ipa_module.h',
@@ -32,6 +34,7 @@ libcamera_internal_headers = files([
     'matrix.h',
     'media_device.h',
     'media_object.h',
+    'media_pipeline.h',
     'pipeline_handler.h',
     'process.h',
     'pub_key.h',
@@ -41,6 +44,7 @@ libcamera_internal_headers = files([
     'sysfs.h',
     'v4l2_device.h',
     'v4l2_pixelformat.h',
+    'v4l2_request.h',
     'v4l2_subdevice.h',
     'v4l2_videodevice.h',
     'vector.h',
diff -pruN 0.5.0-1/include/libcamera/internal/pipeline_handler.h 0.6.0-2/include/libcamera/internal/pipeline_handler.h
--- 0.5.0-1/include/libcamera/internal/pipeline_handler.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/pipeline_handler.h	2025-11-27 11:55:28.000000000 +0000
@@ -8,7 +8,6 @@
 #pragma once
 
 #include <memory>
-#include <queue>
 #include <string>
 #include <sys/types.h>
 #include <vector>
@@ -34,12 +33,13 @@ class PipelineHandler : public std::enab
 			public Object
 {
 public:
-	PipelineHandler(CameraManager *manager);
+	PipelineHandler(CameraManager *manager,
+			unsigned int maxQueuedRequestsDevice = 32);
 	virtual ~PipelineHandler();
 
 	virtual bool match(DeviceEnumerator *enumerator) = 0;
-	MediaDevice *acquireMediaDevice(DeviceEnumerator *enumerator,
-					const DeviceMatch &dm);
+	std::shared_ptr<MediaDevice> acquireMediaDevice(DeviceEnumerator *enumerator,
+							const DeviceMatch &dm);
 
 	bool acquire(Camera *camera);
 	void release(Camera *camera);
@@ -72,7 +72,8 @@ public:
 
 protected:
 	void registerCamera(std::shared_ptr<Camera> camera);
-	void hotplugMediaDevice(MediaDevice *media);
+	void hotplugMediaDevice(std::shared_ptr<MediaDevice> media);
+	unsigned int useCount() const { return useCount_; }
 
 	virtual int queueRequestDevice(Camera *camera, Request *request) = 0;
 	virtual void stopDevice(Camera *camera) = 0;
@@ -81,21 +82,20 @@ protected:
 	virtual void releaseDevice(Camera *camera);
 
 	CameraManager *manager_;
+	const unsigned int maxQueuedRequestsDevice_;
 
 private:
 	void unlockMediaDevices();
 
-	void mediaDeviceDisconnected(MediaDevice *media);
+	void mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media);
 	virtual void disconnect();
 
 	void doQueueRequest(Request *request);
-	void doQueueRequests();
+	void doQueueRequests(Camera *camera);
 
 	std::vector<std::shared_ptr<MediaDevice>> mediaDevices_;
 	std::vector<std::weak_ptr<Camera>> cameras_;
 
-	std::queue<Request *> waitingRequests_;
-
 	const char *name_;
 	unsigned int useCount_;
 
diff -pruN 0.5.0-1/include/libcamera/internal/process.h 0.6.0-2/include/libcamera/internal/process.h
--- 0.5.0-1/include/libcamera/internal/process.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/process.h	2025-11-27 11:55:28.000000000 +0000
@@ -7,11 +7,11 @@
 
 #pragma once
 
-#include <signal.h>
 #include <string>
-#include <vector>
 
+#include <libcamera/base/class.h>
 #include <libcamera/base/signal.h>
+#include <libcamera/base/span.h>
 #include <libcamera/base/unique_fd.h>
 
 namespace libcamera {
@@ -31,8 +31,8 @@ public:
 	~Process();
 
 	int start(const std::string &path,
-		  const std::vector<std::string> &args = std::vector<std::string>(),
-		  const std::vector<int> &fds = std::vector<int>());
+		  Span<const std::string> args = {},
+		  Span<const int> fds = {});
 
 	ExitStatus exitStatus() const { return exitStatus_; }
 	int exitCode() const { return exitCode_; }
@@ -42,43 +42,16 @@ public:
 	Signal<enum ExitStatus, int> finished;
 
 private:
-	void closeAllFdsExcept(const std::vector<int> &fds);
-	int isolate();
-	void died(int wstatus);
+	LIBCAMERA_DISABLE_COPY_AND_MOVE(Process)
+
+	void onPidfdNotify();
 
 	pid_t pid_;
-	bool running_;
 	enum ExitStatus exitStatus_;
 	int exitCode_;
 
-	friend class ProcessManager;
-};
-
-class ProcessManager
-{
-public:
-	ProcessManager();
-	~ProcessManager();
-
-	void registerProcess(Process *proc);
-
-	static ProcessManager *instance();
-
-	int writePipe() const;
-
-	const struct sigaction &oldsa() const;
-
-private:
-	static ProcessManager *self_;
-
-	void sighandler();
-
-	std::list<Process *> processes_;
-
-	struct sigaction oldsa_;
-
-	EventNotifier *sigEvent_;
-	UniqueFD pipe_[2];
+	UniqueFD pidfd_;
+	std::unique_ptr<EventNotifier> pidfdNotify_;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/request.h 0.6.0-2/include/libcamera/internal/request.h
--- 0.5.0-1/include/libcamera/internal/request.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/request.h	2025-11-27 11:55:28.000000000 +0000
@@ -59,7 +59,7 @@ private:
 	bool prepared_ = false;
 
 	std::unordered_set<FrameBuffer *> pending_;
-	std::map<FrameBuffer *, std::unique_ptr<EventNotifier>> notifiers_;
+	std::map<FrameBuffer *, EventNotifier> notifiers_;
 	std::unique_ptr<Timer> timer_;
 };
 
diff -pruN 0.5.0-1/include/libcamera/internal/software_isp/swisp_stats.h 0.6.0-2/include/libcamera/internal/software_isp/swisp_stats.h
--- 0.5.0-1/include/libcamera/internal/software_isp/swisp_stats.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/software_isp/swisp_stats.h	2025-11-27 11:55:28.000000000 +0000
@@ -21,6 +21,11 @@ namespace libcamera {
  */
 struct SwIspStats {
 	/**
+	 * \brief True if the statistics buffer contains valid data, false if
+	 *        no statistics were generated for this frame
+	 */
+	bool valid;
+	/**
 	 * \brief Holds the sum of all sampled red pixels
 	 */
 	uint64_t sumR_;
diff -pruN 0.5.0-1/include/libcamera/internal/v4l2_device.h 0.6.0-2/include/libcamera/internal/v4l2_device.h
--- 0.5.0-1/include/libcamera/internal/v4l2_device.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/v4l2_device.h	2025-11-27 11:55:28.000000000 +0000
@@ -24,6 +24,7 @@
 #include <libcamera/controls.h>
 
 #include "libcamera/internal/formats.h"
+#include "libcamera/internal/v4l2_request.h"
 
 namespace libcamera {
 
@@ -37,8 +38,8 @@ public:
 
 	const ControlInfoMap &controls() const { return controls_; }
 
-	ControlList getControls(const std::vector<uint32_t> &ids);
-	int setControls(ControlList *ctrls);
+	ControlList getControls(Span<const uint32_t> ids, const V4L2Request *request = nullptr);
+	int setControls(ControlList *ctrls, const V4L2Request *request = nullptr);
 
 	const struct v4l2_query_ext_ctrl *controlInfo(uint32_t id) const;
 
diff -pruN 0.5.0-1/include/libcamera/internal/v4l2_request.h 0.6.0-2/include/libcamera/internal/v4l2_request.h
--- 0.5.0-1/include/libcamera/internal/v4l2_request.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/v4l2_request.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas On Board
+ *
+ * V4L2 Request
+ */
+
+#pragma once
+
+#include <string>
+
+#include <linux/videodev2.h>
+
+#include <libcamera/base/event_notifier.h>
+#include <libcamera/base/log.h>
+#include <libcamera/base/signal.h>
+#include <libcamera/base/unique_fd.h>
+
+namespace libcamera {
+
+class V4L2Request : protected Loggable
+{
+public:
+	bool isValid() const { return fd_.isValid(); }
+	int fd() const { return fd_.get(); }
+
+	int reinit();
+	int queue();
+
+	V4L2Request(UniqueFD &&fd);
+
+	Signal<V4L2Request *> requestDone;
+
+private:
+	LIBCAMERA_DISABLE_COPY_AND_MOVE(V4L2Request)
+
+	void requestReady();
+	std::string logPrefix() const override;
+
+	UniqueFD fd_;
+	EventNotifier fdNotifier_;
+};
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/include/libcamera/internal/v4l2_subdevice.h 0.6.0-2/include/libcamera/internal/v4l2_subdevice.h
--- 0.5.0-1/include/libcamera/internal/v4l2_subdevice.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/v4l2_subdevice.h	2025-11-27 11:55:28.000000000 +0000
@@ -66,7 +66,7 @@ struct V4L2SubdeviceFormat {
 	Size size;
 	std::optional<ColorSpace> colorSpace;
 
-	const std::string toString() const;
+	std::string toString() const;
 };
 
 std::ostream &operator<<(std::ostream &out, const V4L2SubdeviceFormat &f);
diff -pruN 0.5.0-1/include/libcamera/internal/v4l2_videodevice.h 0.6.0-2/include/libcamera/internal/v4l2_videodevice.h
--- 0.5.0-1/include/libcamera/internal/v4l2_videodevice.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/v4l2_videodevice.h	2025-11-27 11:55:28.000000000 +0000
@@ -33,6 +33,7 @@
 #include "libcamera/internal/formats.h"
 #include "libcamera/internal/v4l2_device.h"
 #include "libcamera/internal/v4l2_pixelformat.h"
+#include "libcamera/internal/v4l2_request.h"
 
 namespace libcamera {
 
@@ -178,7 +179,7 @@ public:
 	std::array<Plane, 3> planes;
 	unsigned int planesCount = 0;
 
-	const std::string toString() const;
+	std::string toString() const;
 };
 
 std::ostream &operator<<(std::ostream &out, const V4L2DeviceFormat &f);
@@ -217,7 +218,7 @@ public:
 	int importBuffers(unsigned int count);
 	int releaseBuffers();
 
-	int queueBuffer(FrameBuffer *buffer);
+	int queueBuffer(FrameBuffer *buffer, const V4L2Request *request = nullptr);
 	Signal<FrameBuffer *> bufferReady;
 
 	int streamOn();
diff -pruN 0.5.0-1/include/libcamera/internal/vector.h 0.6.0-2/include/libcamera/internal/vector.h
--- 0.5.0-1/include/libcamera/internal/vector.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/internal/vector.h	2025-11-27 11:55:28.000000000 +0000
@@ -13,6 +13,7 @@
 #include <numeric>
 #include <optional>
 #include <ostream>
+#include <type_traits>
 
 #include <libcamera/base/log.h>
 #include <libcamera/base/span.h>
@@ -42,8 +43,12 @@ public:
 
 	constexpr Vector(const std::array<T, Rows> &data)
 	{
-		for (unsigned int i = 0; i < Rows; i++)
-			data_[i] = data[i];
+		std::copy(data.begin(), data.end(), data_.begin());
+	}
+
+	constexpr Vector(const Span<const T, Rows> data)
+	{
+		std::copy(data.begin(), data.end(), data_.begin());
 	}
 
 	const T &operator[](size_t i) const
@@ -291,13 +296,13 @@ private:
 template<typename T>
 using RGB = Vector<T, 3>;
 
-template<typename T, unsigned int Rows, unsigned int Cols>
-Vector<T, Rows> operator*(const Matrix<T, Rows, Cols> &m, const Vector<T, Cols> &v)
+template<typename T, typename U, unsigned int Rows, unsigned int Cols>
+Vector<std::common_type_t<T, U>, Rows> operator*(const Matrix<T, Rows, Cols> &m, const Vector<U, Cols> &v)
 {
-	Vector<T, Rows> result;
+	Vector<std::common_type_t<T, U>, Rows> result;
 
 	for (unsigned int i = 0; i < Rows; i++) {
-		T sum = 0;
+		std::common_type_t<T, U> sum = 0;
 		for (unsigned int j = 0; j < Cols; j++)
 			sum += m[i][j] * v[j];
 		result[i] = sum;
diff -pruN 0.5.0-1/include/libcamera/ipa/ipa_controls.h 0.6.0-2/include/libcamera/ipa/ipa_controls.h
--- 0.5.0-1/include/libcamera/ipa/ipa_controls.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/ipa/ipa_controls.h	2025-11-27 11:55:28.000000000 +0000
@@ -15,7 +15,7 @@ namespace libcamera {
 extern "C" {
 #endif
 
-#define IPA_CONTROLS_FORMAT_VERSION	1
+#define IPA_CONTROLS_FORMAT_VERSION	2
 
 enum ipa_controls_id_map_type {
 	IPA_CONTROL_ID_MAP_CONTROLS,
@@ -34,20 +34,26 @@ struct ipa_controls_header {
 };
 
 struct ipa_control_value_entry {
-	uint32_t id;
 	uint8_t type;
 	uint8_t is_array;
 	uint16_t count;
 	uint32_t offset;
-	uint32_t padding[1];
+	uint32_t reserved[2];
+};
+
+struct ipa_control_list_entry {
+	uint32_t id;
+	struct ipa_control_value_entry value;
 };
 
 struct ipa_control_info_entry {
 	uint32_t id;
 	uint32_t type;
-	uint32_t offset;
 	uint8_t direction;
-	uint8_t padding[3];
+	uint8_t padding[7];
+	struct ipa_control_value_entry min;
+	struct ipa_control_value_entry max;
+	struct ipa_control_value_entry def;
 };
 
 #ifdef __cplusplus
diff -pruN 0.5.0-1/include/libcamera/ipa/mali-c55.mojom 0.6.0-2/include/libcamera/ipa/mali-c55.mojom
--- 0.5.0-1/include/libcamera/ipa/mali-c55.mojom	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/ipa/mali-c55.mojom	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@ interface IPAMaliC55Interface {
 };
 
 interface IPAMaliC55EventInterface {
-	paramsComputed(uint32 request);
+	paramsComputed(uint32 request, uint32 bytesused);
 	statsProcessed(uint32 request, libcamera.ControlList metadata);
 	setSensorControls(libcamera.ControlList sensorControls);
 };
diff -pruN 0.5.0-1/include/libcamera/ipa/raspberrypi.mojom 0.6.0-2/include/libcamera/ipa/raspberrypi.mojom
--- 0.5.0-1/include/libcamera/ipa/raspberrypi.mojom	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/ipa/raspberrypi.mojom	2025-11-27 11:55:28.000000000 +0000
@@ -52,7 +52,8 @@ struct ConfigResult {
 
 struct StartResult {
 	libcamera.ControlList controls;
-	int32 dropFrameCount;
+	int32 startupFrameCount;
+	int32 invalidFrameCount;
 };
 
 struct PrepareParams {
diff -pruN 0.5.0-1/include/libcamera/ipa/rkisp1.mojom 0.6.0-2/include/libcamera/ipa/rkisp1.mojom
--- 0.5.0-1/include/libcamera/ipa/rkisp1.mojom	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/ipa/rkisp1.mojom	2025-11-27 11:55:28.000000000 +0000
@@ -16,7 +16,7 @@ struct IPAConfigInfo {
 
 interface IPARkISP1Interface {
 	init(libcamera.IPASettings settings,
-	     uint32 hwRevision,
+	     uint32 hwRevision, uint32 supportedBlocks,
 	     libcamera.IPACameraSensorInfo sensorInfo,
 	     libcamera.ControlInfoMap sensorControls)
 		=> (int32 ret, libcamera.ControlInfoMap ipaControls);
diff -pruN 0.5.0-1/include/libcamera/meson.build 0.6.0-2/include/libcamera/meson.build
--- 0.5.0-1/include/libcamera/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -90,6 +90,7 @@ foreach mode, entry : controls_map
                                      command : [gen_controls, '-o', '@OUTPUT@',
                                                 '--mode', mode, '-t', template_file,
                                                 '-r', ranges_file, '@INPUT@'],
+                                     depend_files : [py_mod_controls],
                                      env : py_build_env,
                                      install : true,
                                      install_dir : libcamera_headers_install_dir)
diff -pruN 0.5.0-1/include/libcamera/request.h 0.6.0-2/include/libcamera/request.h
--- 0.5.0-1/include/libcamera/request.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/libcamera/request.h	2025-11-27 11:55:28.000000000 +0000
@@ -53,7 +53,7 @@ public:
 	ControlList &metadata() { return *metadata_; }
 	const BufferMap &buffers() const { return bufferMap_; }
 	int addBuffer(const Stream *stream, FrameBuffer *buffer,
-		      std::unique_ptr<Fence> fence = nullptr);
+		      std::unique_ptr<Fence> &&fence = {});
 	FrameBuffer *findBuffer(const Stream *stream) const;
 
 	uint32_t sequence() const;
diff -pruN 0.5.0-1/include/linux/dw100.h 0.6.0-2/include/linux/dw100.h
--- 0.5.0-1/include/linux/dw100.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/include/linux/dw100.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
+/* Copyright 2022 NXP */
+
+#ifndef __UAPI_DW100_H__
+#define __UAPI_DW100_H__
+
+#include <linux/v4l2-controls.h>
+
+/*
+ * Check Documentation/userspace-api/media/drivers/dw100.rst for control details.
+ */
+#define V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP (V4L2_CID_USER_DW100_BASE + 1)
+
+#endif
diff -pruN 0.5.0-1/include/linux/rkisp1-config.h 0.6.0-2/include/linux/rkisp1-config.h
--- 0.5.0-1/include/linux/rkisp1-config.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/linux/rkisp1-config.h	2025-11-27 11:55:28.000000000 +0000
@@ -170,6 +170,13 @@
 #define RKISP1_CIF_ISP_COMPAND_NUM_POINTS	64
 
 /*
+ * Wide Dynamic Range
+ */
+#define RKISP1_CIF_ISP_WDR_CURVE_NUM_INTERV	32
+#define RKISP1_CIF_ISP_WDR_CURVE_NUM_COEFF	(RKISP1_CIF_ISP_WDR_CURVE_NUM_INTERV + 1)
+#define RKISP1_CIF_ISP_WDR_CURVE_NUM_DY_REGS	4
+
+/*
  * Measurement types
  */
 #define RKISP1_CIF_ISP_STAT_AWB           (1U << 0)
@@ -889,6 +896,72 @@ struct rkisp1_cif_isp_compand_curve_conf
 	__u32 y[RKISP1_CIF_ISP_COMPAND_NUM_POINTS];
 };
 
+/**
+ * struct rkisp1_cif_isp_wdr_tone_curve - Tone mapping curve definition for WDR.
+ *
+ * @dY: the dYn increments for horizontal (input) axis of the tone curve.
+ *      each 3-bit dY value represents an increment of 2**(value+3).
+ *      dY[0] bits 0:2 is increment dY1, bit 3 unused
+ *      dY[0] bits 4:6 is increment dY2, bit 7 unused
+ *      ...
+ *      dY[0] bits 28:30 is increment dY8, bit 31 unused
+ *      ... and so on till dY[3] bits 28:30 is increment dY32, bit 31 unused.
+ * @ym: the Ym values for the vertical (output) axis of the tone curve.
+ *      each value is 13 bit.
+ */
+struct rkisp1_cif_isp_wdr_tone_curve {
+	__u32 dY[RKISP1_CIF_ISP_WDR_CURVE_NUM_DY_REGS];
+	__u16 ym[RKISP1_CIF_ISP_WDR_CURVE_NUM_COEFF];
+};
+
+/**
+ * struct rkisp1_cif_isp_wdr_iref_config - Illumination reference config for WDR.
+ *
+ * Use illumination reference value as described below, instead of only the
+ * luminance (Y) value for tone mapping and gain calculations:
+ * IRef = (rgb_factor * RGBMax_tr + (8 - rgb_factor) * Y)/8
+ *
+ * @rgb_factor: defines how much influence the RGBmax approach has in
+ *              comparison to Y (valid values are 0..8).
+ * @use_y9_8: use Y*9/8 for maximum value calculation along with the
+ *            default of R, G, B for noise reduction.
+ * @use_rgb7_8: decrease RGBMax by 7/8 for noise reduction.
+ * @disable_transient: disable transient calculation between Y and RGBY_max.
+ */
+struct rkisp1_cif_isp_wdr_iref_config {
+	__u8 rgb_factor;
+	__u8 use_y9_8;
+	__u8 use_rgb7_8;
+	__u8 disable_transient;
+};
+
+/**
+ * struct rkisp1_cif_isp_wdr_config - Configuration for wide dynamic range.
+ *
+ * @tone_curve: tone mapping curve.
+ * @iref_config: illumination reference configuration. (when use_iref is true)
+ * @rgb_offset: RGB offset value for RGB operation mode. (12 bits)
+ * @luma_offset: luminance offset value for RGB operation mode. (12 bits)
+ * @dmin_thresh: lower threshold for deltaMin value. (12 bits)
+ * @dmin_strength: strength factor for deltaMin. (valid range is 0x00..0x10)
+ * @use_rgb_colorspace: use RGB instead of luminance/chrominance colorspace.
+ * @bypass_chroma_mapping: disable chrominance mapping (only valid if
+ *                         use_rgb_colorspace = 0)
+ * @use_iref: use illumination reference instead of Y for tone mapping
+ *            and gain calculations.
+ */
+struct rkisp1_cif_isp_wdr_config {
+	struct rkisp1_cif_isp_wdr_tone_curve tone_curve;
+	struct rkisp1_cif_isp_wdr_iref_config iref_config;
+	__u16 rgb_offset;
+	__u16 luma_offset;
+	__u16 dmin_thresh;
+	__u8 dmin_strength;
+	__u8 use_rgb_colorspace;
+	__u8 bypass_chroma_mapping;
+	__u8 use_iref;
+};
+
 /*---------- PART2: Measurement Statistics ------------*/
 
 /**
@@ -1059,6 +1132,7 @@ struct rkisp1_stat_buffer {
  * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS: BLS in the compand block
  * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND: Companding expand curve
  * @RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS: Companding compress curve
+ * @RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR: Wide dynamic range
  */
 enum rkisp1_ext_params_block_type {
 	RKISP1_EXT_PARAMS_BLOCK_TYPE_BLS,
@@ -1081,11 +1155,15 @@ enum rkisp1_ext_params_block_type {
 	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_BLS,
 	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_EXPAND,
 	RKISP1_EXT_PARAMS_BLOCK_TYPE_COMPAND_COMPRESS,
+	RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR,
 };
 
 #define RKISP1_EXT_PARAMS_FL_BLOCK_DISABLE	(1U << 0)
 #define RKISP1_EXT_PARAMS_FL_BLOCK_ENABLE	(1U << 1)
 
+/* A bitmask of parameters blocks supported on the current hardware. */
+#define RKISP1_CID_SUPPORTED_PARAMS_BLOCKS	(V4L2_CID_USER_RKISP1_BASE + 0x01)
+
 /**
  * struct rkisp1_ext_params_block_header - RkISP1 extensible parameters block
  *					   header
@@ -1460,6 +1538,23 @@ struct rkisp1_ext_params_compand_curve_c
 	struct rkisp1_cif_isp_compand_curve_config config;
 } __attribute__((aligned(8)));
 
+/**
+ * struct rkisp1_ext_params_wdr_config - RkISP1 extensible params
+ *                                       Wide dynamic range config
+ *
+ * RkISP1 extensible parameters WDR block.
+ * Identified by :c:type:`RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR`
+ *
+ * @header: The RkISP1 extensible parameters header, see
+ *	    :c:type:`rkisp1_ext_params_block_header`
+ * @config: WDR configuration, see
+ *	    :c:type:`rkisp1_cif_isp_wdr_config`
+ */
+struct rkisp1_ext_params_wdr_config {
+	struct rkisp1_ext_params_block_header header;
+	struct rkisp1_cif_isp_wdr_config config;
+} __attribute__((aligned(8)));
+
 /*
  * The rkisp1_ext_params_compand_curve_config structure is counted twice as it
  * is used for both the COMPAND_EXPAND and COMPAND_COMPRESS block types.
@@ -1484,7 +1579,8 @@ struct rkisp1_ext_params_compand_curve_c
 	sizeof(struct rkisp1_ext_params_afc_config)			+\
 	sizeof(struct rkisp1_ext_params_compand_bls_config)		+\
 	sizeof(struct rkisp1_ext_params_compand_curve_config)		+\
-	sizeof(struct rkisp1_ext_params_compand_curve_config))
+	sizeof(struct rkisp1_ext_params_compand_curve_config)		+\
+	sizeof(struct rkisp1_ext_params_wdr_config))
 
 /**
  * enum rksip1_ext_param_buffer_version - RkISP1 extensible parameters version
@@ -1520,6 +1616,14 @@ enum rksip1_ext_param_buffer_version {
  * V4L2 control. If such control is not available, userspace should assume only
  * RKISP1_EXT_PARAM_BUFFER_V1 is supported by the driver.
  *
+ * The read-only V4L2 control ``RKISP1_CID_SUPPORTED_PARAMS_BLOCKS`` can be used
+ * to query the blocks supported by the device. It contains a bitmask where each
+ * bit represents the availability of the corresponding entry from the
+ * :c:type:`rkisp1_ext_params_block_type` enum. The current and default values
+ * of the control represents the blocks supported by the device instance, while
+ * the maximum value represents the blocks supported by the kernel driver,
+ * independently of the device instance.
+ *
  * For each ISP block that userspace wants to configure, a block-specific
  * structure is appended to the @data buffer, one after the other without gaps
  * in between nor overlaps. Userspace shall populate the @data_size field with
@@ -1528,7 +1632,7 @@ enum rksip1_ext_param_buffer_version {
  * The expected memory layout of the parameters buffer is::
  *
  *	+-------------------- struct rkisp1_ext_params_cfg -------------------+
- *	| version = RKISP_EXT_PARAMS_BUFFER_V1;                               |
+ *	| version = RKISP1_EXT_PARAM_BUFFER_V1;                               |
  *	| data_size = sizeof(struct rkisp1_ext_params_bls_config)             |
  *	|           + sizeof(struct rkisp1_ext_params_dpcc_config);           |
  *	| +------------------------- data  ---------------------------------+ |
diff -pruN 0.5.0-1/include/linux/v4l2-controls.h 0.6.0-2/include/linux/v4l2-controls.h
--- 0.5.0-1/include/linux/v4l2-controls.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/include/linux/v4l2-controls.h	2025-11-27 11:55:28.000000000 +0000
@@ -217,6 +217,12 @@ enum v4l2_colorfx {
  */
 #define V4L2_CID_USER_THP7312_BASE		(V4L2_CID_USER_BASE + 0x11c0)
 
+/*
+ * The base for Rockchip ISP1 driver controls.
+ * We reserve 16 controls for this driver.
+ */
+#define V4L2_CID_USER_RKISP1_BASE		(V4L2_CID_USER_BASE + 0x1220)
+
 /* MPEG-class control IDs */
 /* The MPEG controls are applicable to all codec controls
  * and the 'MPEG' part of the define is historical */
diff -pruN 0.5.0-1/meson.build 0.6.0-2/meson.build
--- 0.5.0-1/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: CC0-1.0
 
 project('libcamera', 'c', 'cpp',
-    meson_version : '>= 0.63',
-    version : '0.5.0',
+    meson_version : '>= 1.0.1',
+    version : '0.6.0',
     default_options : [
         'werror=true',
         'warning_level=2',
@@ -74,6 +74,10 @@ cc = meson.get_compiler('c')
 cxx = meson.get_compiler('cpp')
 config_h = configuration_data()
 
+if cc.has_header_symbol('unistd.h', 'close_range', prefix : '#define _GNU_SOURCE')
+    config_h.set('HAVE_CLOSE_RANGE', 1)
+endif
+
 if cc.has_header_symbol('fcntl.h', 'F_ADD_SEALS', prefix : '#define _GNU_SOURCE')
     config_h.set('HAVE_FILE_SEALS', 1)
 endif
@@ -261,7 +265,7 @@ subdir('Documentation')
 subdir('test')
 
 if not meson.is_cross_build()
-    kernel_version_req = '>= 5.0.0'
+    kernel_version_req = '>= 5.4.0'
     kernel_version = run_command('uname', '-r', check : true).stdout().strip()
     if not kernel_version.version_compare(kernel_version_req)
         warning('The current running kernel version @0@ is too old to run libcamera.'
@@ -279,9 +283,14 @@ run_command('ln', '-fsT', meson.project_
 
 configure_file(output : 'config.h', configuration : config_h)
 
-# Check for python installation and modules.
-py_mod = import('python')
-py_mod.find_installation('python3', modules : py_modules)
+# Check for python modules.
+foreach module : py_modules
+    result = run_command('python3', '-c' , 'import @0@'.format(module),
+                         capture : false, check : false)
+    if result.returncode() != 0
+        error('Python module \'@0@\' not found'.format(module))
+    endif
+endforeach
 
 ## Summarise Configurations
 summary({
diff -pruN 0.5.0-1/meson_options.txt 0.6.0-2/meson_options.txt
--- 0.5.0-1/meson_options.txt	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/meson_options.txt	2025-11-27 11:55:28.000000000 +0000
@@ -18,6 +18,7 @@ option('cam',
 
 option('documentation',
         type : 'feature',
+        value : 'auto',
         description : 'Generate the project documentation')
 
 option('doc_werror',
@@ -41,6 +42,11 @@ option('lc-compliance',
         value : 'auto',
         description : 'Compile the lc-compliance test application')
 
+option('libunwind',
+        type : 'feature',
+        value : 'auto',
+        description : 'Enable libunwind integration for backtrace generation')
+
 option('pipelines',
         type : 'array',
         value : ['auto'],
diff -pruN 0.5.0-1/package/gentoo/media-libs/libcamera/libcamera-9999.ebuild 0.6.0-2/package/gentoo/media-libs/libcamera/libcamera-9999.ebuild
--- 0.5.0-1/package/gentoo/media-libs/libcamera/libcamera-9999.ebuild	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/package/gentoo/media-libs/libcamera/libcamera-9999.ebuild	1970-01-01 00:00:00.000000000 +0000
@@ -1,45 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-# Copyright 2019 Google Inc.
-
-EAPI=6
-PYTHON_COMPAT=( python3_{7..10} )
-
-inherit git-r3 meson python-any-r1
-
-DESCRIPTION="Camera support library for Linux"
-HOMEPAGE="http://libcamera.org"
-EGIT_REPO_URI="https://git.libcamera.org/libcamera/libcamera.git"
-EGIT_BRANCH="master"
-
-LICENSE="LGPL-2.1+"
-SLOT="0"
-KEYWORDS="*"
-IUSE="debug doc test udev"
-
-RDEPEND="
-	>=net-libs/gnutls-3.3:=
-	udev? ( virtual/libudev )
-"
-
-DEPEND="
-	${RDEPEND}
-	dev-libs/openssl
-	$(python_gen_any_dep 'dev-python/pyyaml[${PYTHON_USEDEP}]')
-"
-
-src_configure() {
-	local emesonargs=(
-		$(meson_feature doc documentation)
-		$(meson_use test)
-		--buildtype $(usex debug debug plain)
-	)
-	meson_src_configure
-}
-
-src_compile() {
-	meson_src_compile
-}
-
-src_install() {
-	meson_src_install
-}
diff -pruN 0.5.0-1/src/android/camera_device.cpp 0.6.0-2/src/android/camera_device.cpp
--- 0.5.0-1/src/android/camera_device.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/android/camera_device.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -1079,7 +1079,7 @@ int CameraDevice::processCaptureRequest(
 		buffer.internalBuffer = frameBuffer;
 
 		descriptor->request_->addBuffer(sourceStream->stream(),
-						frameBuffer, nullptr);
+						frameBuffer);
 
 		requestedStreams.insert(sourceStream);
 	}
diff -pruN 0.5.0-1/src/android/camera_hal_manager.cpp 0.6.0-2/src/android/camera_hal_manager.cpp
--- 0.5.0-1/src/android/camera_hal_manager.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/android/camera_hal_manager.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -125,7 +125,7 @@ void CameraHalManager::cameraAdded(std::
 		 * Now check if this is an external camera and assign
 		 * its id accordingly.
 		 */
-		if (cameraLocation(cam.get()) == properties::CameraLocationExternal) {
+		if (cam->properties().get(properties::Location) == properties::CameraLocationExternal) {
 			isCameraExternal = true;
 			id = nextExternalCameraId_;
 		} else {
@@ -227,11 +227,6 @@ void CameraHalManager::cameraRemoved(std
 	LOG(HAL, Debug) << "Camera ID: " << id << " removed successfully.";
 }
 
-int32_t CameraHalManager::cameraLocation(const Camera *cam)
-{
-	return cam->properties().get(properties::Location).value_or(-1);
-}
-
 CameraDevice *CameraHalManager::cameraDeviceFromHalId(unsigned int id)
 {
 	auto iter = std::find_if(cameras_.begin(), cameras_.end(),
diff -pruN 0.5.0-1/src/android/camera_hal_manager.h 0.6.0-2/src/android/camera_hal_manager.h
--- 0.5.0-1/src/android/camera_hal_manager.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/android/camera_hal_manager.h	2025-11-27 11:55:28.000000000 +0000
@@ -48,8 +48,6 @@ private:
 
 	CameraHalManager();
 
-	static int32_t cameraLocation(const libcamera::Camera *cam);
-
 	void cameraAdded(std::shared_ptr<libcamera::Camera> cam);
 	void cameraRemoved(std::shared_ptr<libcamera::Camera> cam);
 
diff -pruN 0.5.0-1/src/android/mm/cros_frame_buffer_allocator.cpp 0.6.0-2/src/android/mm/cros_frame_buffer_allocator.cpp
--- 0.5.0-1/src/android/mm/cros_frame_buffer_allocator.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/android/mm/cros_frame_buffer_allocator.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -29,7 +29,7 @@ class CrosFrameBufferData : public Frame
 
 public:
 	CrosFrameBufferData(cros::ScopedBufferHandle scopedHandle,
-			    const std::vector<FrameBuffer::Plane> &planes)
+			    Span<const FrameBuffer::Plane> planes)
 		: FrameBuffer::Private(planes), scopedHandle_(std::move(scopedHandle))
 	{
 	}
diff -pruN 0.5.0-1/src/android/mm/generic_frame_buffer_allocator.cpp 0.6.0-2/src/android/mm/generic_frame_buffer_allocator.cpp
--- 0.5.0-1/src/android/mm/generic_frame_buffer_allocator.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/android/mm/generic_frame_buffer_allocator.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -35,7 +35,7 @@ class GenericFrameBufferData : public Fr
 public:
 	GenericFrameBufferData(struct alloc_device_t *allocDevice,
 			       buffer_handle_t handle,
-			       const std::vector<FrameBuffer::Plane> &planes)
+			       Span<const FrameBuffer::Plane> planes)
 		: FrameBuffer::Private(planes), allocDevice_(allocDevice),
 		  handle_(handle)
 	{
diff -pruN 0.5.0-1/src/apps/cam/camera_session.cpp 0.6.0-2/src/apps/cam/camera_session.cpp
--- 0.5.0-1/src/apps/cam/camera_session.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/camera_session.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -62,11 +62,32 @@ CameraSession::CameraSession(CameraManag
 		return;
 	}
 
-	std::vector<StreamRole> roles = StreamKeyValueParser::roles(options_[OptStream]);
+	std::vector<StreamRole> roles =
+		StreamKeyValueParser::roles(options_[OptStream]);
+	std::vector<std::vector<StreamRole>> tryRoles;
+	if (!roles.empty()) {
+		/*
+		 * If the roles are explicitly specified then there's no need
+		 * to try other roles
+		 */
+		tryRoles.push_back(roles);
+	} else {
+		tryRoles.push_back({ StreamRole::Viewfinder });
+		tryRoles.push_back({ StreamRole::Raw });
+	}
+
+	std::unique_ptr<CameraConfiguration> config;
+	bool valid = false;
+	for (std::vector<StreamRole> &rolesIt : tryRoles) {
+		config = camera_->generateConfiguration(rolesIt);
+		if (config && config->size() == rolesIt.size()) {
+			roles = rolesIt;
+			valid = true;
+			break;
+		}
+	}
 
-	std::unique_ptr<CameraConfiguration> config =
-		camera_->generateConfiguration(roles);
-	if (!config || config->size() != roles.size()) {
+	if (!valid) {
 		std::cerr << "Failed to get default stream configuration"
 			  << std::endl;
 		return;
@@ -215,7 +236,17 @@ void CameraSession::listProperties() con
 		const ControlId *id = properties::properties.at(key);
 
 		std::cout << "Property: " << id->name() << " = "
-			  << value.toString() << std::endl;
+			  << value.toString();
+
+		if (!id->enumerators().empty()) {
+			int32_t val = value.get<int32_t>();
+			const auto &iter = id->enumerators().find(val);
+
+			if (iter != id->enumerators().end())
+				std::cout << " (" << iter->second << ")";
+		}
+
+		std::cout << std::endl;
 	}
 }
 
diff -pruN 0.5.0-1/src/apps/cam/capture_script.cpp 0.6.0-2/src/apps/cam/capture_script.cpp
--- 0.5.0-1/src/apps/cam/capture_script.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/capture_script.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -8,6 +8,7 @@
 #include "capture_script.h"
 
 #include <iostream>
+#include <memory>
 #include <stdio.h>
 #include <stdlib.h>
 
@@ -501,7 +502,7 @@ ControlValue CaptureScript::parseScalarC
 		break;
 	}
 	case ControlTypeString: {
-		value.set<std::string>(repr);
+		value.set<std::string_view>(repr);
 		break;
 	}
 	default:
@@ -521,45 +522,22 @@ ControlValue CaptureScript::parseArrayCo
 	case ControlTypeNone:
 		break;
 	case ControlTypeBool: {
-		/*
-		 * This is unpleasant, but we cannot use an std::vector<> as its
-		 * boolean type overload does not allow to access the raw data,
-		 * as boolean values are stored in a bitmask for efficiency.
-		 *
-		 * As we need a contiguous memory region to wrap in a Span<>,
-		 * use an array instead but be strict about not overflowing it
-		 * by limiting the number of controls we can store.
-		 *
-		 * Be loud but do not fail, as the issue would present at
-		 * runtime and it's not fatal.
-		 */
-		static constexpr unsigned int kMaxNumBooleanControls = 1024;
-		std::array<bool, kMaxNumBooleanControls> values;
-		unsigned int idx = 0;
+		auto values = std::make_unique<bool[]>(repr.size());
 
-		for (const std::string &s : repr) {
-			bool val;
+		for (std::size_t i = 0; i < repr.size(); i++) {
+			const auto &s = repr[i];
 
 			if (s == "true") {
-				val = true;
+				values[i] = true;
 			} else if (s == "false") {
-				val = false;
+				values[i] = false;
 			} else {
 				unpackFailure(id, s);
 				return value;
 			}
-
-			if (idx == kMaxNumBooleanControls) {
-				std::cerr << "Cannot parse more than "
-					  << kMaxNumBooleanControls
-					  << " boolean controls" << std::endl;
-				break;
-			}
-
-			values[idx++] = val;
 		}
 
-		value = Span<bool>(values.data(), idx);
+		value = Span<bool>(values.get(), repr.size());
 		break;
 	}
 	case ControlTypeByte: {
@@ -600,10 +578,6 @@ ControlValue CaptureScript::parseArrayCo
 		value = Span<const float>(values.data(), values.size());
 		break;
 	}
-	case ControlTypeString: {
-		value = Span<const std::string>(repr.data(), repr.size());
-		break;
-	}
 	default:
 		std::cerr << "Unsupported control type" << std::endl;
 		break;
diff -pruN 0.5.0-1/src/apps/cam/drm.cpp 0.6.0-2/src/apps/cam/drm.cpp
--- 0.5.0-1/src/apps/cam/drm.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/drm.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -450,8 +450,6 @@ int Device::openCard()
 	}
 
 	for (struct dirent *res; (res = readdir(folder));) {
-		uint64_t cap;
-
 		if (strncmp(res->d_name, "card", 4))
 			continue;
 
@@ -465,15 +463,22 @@ int Device::openCard()
 		}
 
 		/*
-		 * Skip devices that don't support the modeset API, to avoid
-		 * selecting a DRM device corresponding to a GPU. There is no
-		 * modeset capability, but the kernel returns an error for most
-		 * caps if mode setting isn't support by the driver. The
-		 * DRM_CAP_DUMB_BUFFER capability is one of those, other would
-		 * do as well. The capability value itself isn't relevant.
+		 * Skip non-display devices. While this could in theory be done
+		 * by checking for support of the mode setting API, some
+		 * out-of-tree render-only GPU drivers (namely powervr)
+		 * incorrectly set the DRIVER_MODESET driver feature. Check for
+		 * the presence of at least one CRTC, encoder and connector
+		 * instead.
 		 */
-		ret = drmGetCap(fd_, DRM_CAP_DUMB_BUFFER, &cap);
-		if (ret < 0) {
+		std::unique_ptr<drmModeRes, decltype(&drmModeFreeResources)> resources{
+			drmModeGetResources(fd_),
+			&drmModeFreeResources
+		};
+		if (!resources ||
+		    resources->count_connectors <= 0 ||
+		    resources->count_crtcs <= 0 ||
+		    resources->count_encoders <= 0) {
+			resources.reset();
 			drmClose(fd_);
 			fd_ = -1;
 			continue;
@@ -654,10 +659,8 @@ std::unique_ptr<FrameBuffer> Device::cre
 	uint32_t offsets[4] = {};
 	int ret;
 
-	const std::vector<libcamera::FrameBuffer::Plane> &planes = buffer.planes();
-
 	unsigned int i = 0;
-	for (const libcamera::FrameBuffer::Plane &plane : planes) {
+	for (const libcamera::FrameBuffer::Plane &plane : buffer.planes()) {
 		int fd = plane.fd.get();
 		uint32_t handle;
 
diff -pruN 0.5.0-1/src/apps/cam/drm.h 0.6.0-2/src/apps/cam/drm.h
--- 0.5.0-1/src/apps/cam/drm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/drm.h	2025-11-27 11:55:28.000000000 +0000
@@ -97,9 +97,9 @@ public:
 
 	bool isImmutable() const { return flags_ & DRM_MODE_PROP_IMMUTABLE; }
 
-	const std::vector<uint64_t> values() const { return values_; }
+	const std::vector<uint64_t> &values() const { return values_; }
 	const std::map<uint32_t, std::string> &enums() const { return enums_; }
-	const std::vector<uint32_t> blobs() const { return blobs_; }
+	const std::vector<uint32_t> &blobs() const { return blobs_; }
 
 private:
 	Type type_;
diff -pruN 0.5.0-1/src/apps/cam/main.cpp 0.6.0-2/src/apps/cam/main.cpp
--- 0.5.0-1/src/apps/cam/main.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/main.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -10,8 +10,11 @@
 #include <atomic>
 #include <iomanip>
 #include <iostream>
+#include <pthread.h>
 #include <signal.h>
 #include <string.h>
+#include <sys/signalfd.h>
+#include <unistd.h>
 
 #include <libcamera/libcamera.h>
 #include <libcamera/property_ids.h>
@@ -29,13 +32,10 @@ class CamApp
 public:
 	CamApp();
 
-	static CamApp *instance();
-
 	int init(int argc, char **argv);
 	void cleanup();
 
 	int exec();
-	void quit();
 
 private:
 	void cameraAdded(std::shared_ptr<Camera> cam);
@@ -46,32 +46,45 @@ private:
 
 	static std::string cameraName(const Camera *camera);
 
-	static CamApp *app_;
 	OptionsParser::Options options_;
 
+	UniqueFD signalFd_;
+
 	std::unique_ptr<CameraManager> cm_;
 
 	std::atomic_uint loopUsers_;
 	EventLoop loop_;
 };
 
-CamApp *CamApp::app_ = nullptr;
-
 CamApp::CamApp()
 	: loopUsers_(0)
 {
-	CamApp::app_ = this;
-}
-
-CamApp *CamApp::instance()
-{
-	return CamApp::app_;
 }
 
 int CamApp::init(int argc, char **argv)
 {
+	sigset_t ss;
 	int ret;
 
+	sigemptyset(&ss);
+	sigaddset(&ss, SIGINT);
+
+	ret = -pthread_sigmask(SIG_BLOCK, &ss, nullptr);
+	if (ret < 0)
+		return ret;
+
+	signalFd_.reset(signalfd(-1, &ss, SFD_CLOEXEC | SFD_NONBLOCK));
+	if (!signalFd_.isValid())
+		return -errno;
+
+	loop_.addFdEvent(signalFd_.get(), EventLoop::Read, [this] {
+		signalfd_siginfo si;
+		std::ignore = read(signalFd_.get(), &si, sizeof(si));
+
+		std::cout << "Exiting" << std::endl;
+		loop_.exit();
+	});
+
 	ret = parseOptions(argc, argv);
 	if (ret < 0)
 		return ret;
@@ -103,11 +116,6 @@ int CamApp::exec()
 	return ret;
 }
 
-void CamApp::quit()
-{
-	loop_.exit();
-}
-
 int CamApp::parseOptions(int argc, char *argv[])
 {
 	StreamKeyValueParser streamKeyValue;
@@ -205,7 +213,7 @@ void CamApp::cameraRemoved(std::shared_p
 void CamApp::captureDone()
 {
 	if (--loopUsers_ == 0)
-		EventLoop::instance()->exit(0);
+		loop_.exit(0);
 }
 
 int CamApp::run()
@@ -337,7 +345,7 @@ std::string CamApp::cameraName(const Cam
 		 */
 		const auto &model = props.get(properties::Model);
 		if (model)
-			name = "'" + *model + "' ";
+			name.append("'").append(*model).append("' ");
 	}
 
 	name += "(" + camera->id() + ")";
@@ -345,16 +353,6 @@ std::string CamApp::cameraName(const Cam
 	return name;
 }
 
-namespace {
-
-void signalHandler([[maybe_unused]] int signal)
-{
-	std::cout << "Exiting" << std::endl;
-	CamApp::instance()->quit();
-}
-
-} /* namespace */
-
 int main(int argc, char **argv)
 {
 	CamApp app;
@@ -364,10 +362,6 @@ int main(int argc, char **argv)
 	if (ret)
 		return ret == -EINTR ? 0 : EXIT_FAILURE;
 
-	struct sigaction sa = {};
-	sa.sa_handler = &signalHandler;
-	sigaction(SIGINT, &sa, nullptr);
-
 	if (app.exec())
 		return EXIT_FAILURE;
 
diff -pruN 0.5.0-1/src/apps/cam/meson.build 0.6.0-2/src/apps/cam/meson.build
--- 0.5.0-1/src/apps/cam/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -34,6 +34,7 @@ if libsdl2.found()
     cam_sources += files([
         'sdl_sink.cpp',
         'sdl_texture.cpp',
+        'sdl_texture_1plane.cpp',
         'sdl_texture_yuv.cpp',
     ])
 
@@ -55,6 +56,7 @@ cam  = executable('cam', cam_sources,
                       libjpeg,
                       libsdl2,
                       libtiff,
+                      libthreads,
                       libyaml,
                   ],
                   cpp_args : cam_cpp_args,
diff -pruN 0.5.0-1/src/apps/cam/sdl_sink.cpp 0.6.0-2/src/apps/cam/sdl_sink.cpp
--- 0.5.0-1/src/apps/cam/sdl_sink.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_sink.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -11,6 +11,7 @@
 #include <fcntl.h>
 #include <iomanip>
 #include <iostream>
+#include <optional>
 #include <signal.h>
 #include <sstream>
 #include <string.h>
@@ -22,6 +23,7 @@
 #include "../common/event_loop.h"
 #include "../common/image.h"
 
+#include "sdl_texture_1plane.h"
 #ifdef HAVE_LIBJPEG
 #include "sdl_texture_mjpg.h"
 #endif
@@ -31,6 +33,46 @@ using namespace libcamera;
 
 using namespace std::chrono_literals;
 
+namespace {
+
+std::optional<SDL_PixelFormatEnum> singlePlaneFormatToSDL(const libcamera::PixelFormat &f)
+{
+	switch (f) {
+	case libcamera::formats::RGB888:
+		return SDL_PIXELFORMAT_BGR24;
+	case libcamera::formats::BGR888:
+		return SDL_PIXELFORMAT_RGB24;
+	case libcamera::formats::RGBA8888:
+		return SDL_PIXELFORMAT_ABGR32;
+	case libcamera::formats::ARGB8888:
+		return SDL_PIXELFORMAT_BGRA32;
+	case libcamera::formats::BGRA8888:
+		return SDL_PIXELFORMAT_ARGB32;
+	case libcamera::formats::ABGR8888:
+		return SDL_PIXELFORMAT_RGBA32;
+#if SDL_VERSION_ATLEAST(2, 29, 1)
+	case libcamera::formats::RGBX8888:
+		return SDL_PIXELFORMAT_XBGR32;
+	case libcamera::formats::XRGB8888:
+		return SDL_PIXELFORMAT_BGRX32;
+	case libcamera::formats::BGRX8888:
+		return SDL_PIXELFORMAT_XRGB32;
+	case libcamera::formats::XBGR8888:
+		return SDL_PIXELFORMAT_RGBX32;
+#endif
+	case libcamera::formats::YUYV:
+		return SDL_PIXELFORMAT_YUY2;
+	case libcamera::formats::UYVY:
+		return SDL_PIXELFORMAT_UYVY;
+	case libcamera::formats::YVYU:
+		return SDL_PIXELFORMAT_YVYU;
+	}
+
+	return {};
+}
+
+} /* namespace */
+
 SDLSink::SDLSink()
 	: window_(nullptr), renderer_(nullptr), rect_({}),
 	  init_(false)
@@ -62,25 +104,22 @@ int SDLSink::configure(const libcamera::
 	rect_.w = cfg.size.width;
 	rect_.h = cfg.size.height;
 
-	switch (cfg.pixelFormat) {
+	if (auto sdlFormat = singlePlaneFormatToSDL(cfg.pixelFormat))
+		texture_ = std::make_unique<SDLTexture1Plane>(rect_, *sdlFormat, cfg.stride);
 #ifdef HAVE_LIBJPEG
-	case libcamera::formats::MJPEG:
+	else if (cfg.pixelFormat == libcamera::formats::MJPEG)
 		texture_ = std::make_unique<SDLTextureMJPG>(rect_);
-		break;
 #endif
 #if SDL_VERSION_ATLEAST(2, 0, 16)
-	case libcamera::formats::NV12:
-		texture_ = std::make_unique<SDLTextureNV12>(rect_, cfg.stride);
-		break;
+	else if (cfg.pixelFormat == libcamera::formats::NV12)
+		texture_ = std::make_unique<SDLTextureNV>(rect_, SDL_PIXELFORMAT_NV12, cfg.stride);
+	else if (cfg.pixelFormat == libcamera::formats::NV21)
+		texture_ = std::make_unique<SDLTextureNV>(rect_, SDL_PIXELFORMAT_NV21, cfg.stride);
 #endif
-	case libcamera::formats::YUYV:
-		texture_ = std::make_unique<SDLTextureYUYV>(rect_, cfg.stride);
-		break;
-	default:
-		std::cerr << "Unsupported pixel format "
-			  << cfg.pixelFormat.toString() << std::endl;
+	else {
+		std::cerr << "Unsupported pixel format " << cfg.pixelFormat << std::endl;
 		return -EINVAL;
-	};
+	}
 
 	return 0;
 }
diff -pruN 0.5.0-1/src/apps/cam/sdl_texture.h 0.6.0-2/src/apps/cam/sdl_texture.h
--- 0.5.0-1/src/apps/cam/sdl_texture.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_texture.h	2025-11-27 11:55:28.000000000 +0000
@@ -7,7 +7,7 @@
 
 #pragma once
 
-#include <vector>
+#include <libcamera/base/span.h>
 
 #include <SDL2/SDL.h>
 
@@ -19,7 +19,7 @@ public:
 	SDLTexture(const SDL_Rect &rect, uint32_t pixelFormat, const int stride);
 	virtual ~SDLTexture();
 	int create(SDL_Renderer *renderer);
-	virtual void update(const std::vector<libcamera::Span<const uint8_t>> &data) = 0;
+	virtual void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) = 0;
 	SDL_Texture *get() const { return ptr_; }
 
 protected:
diff -pruN 0.5.0-1/src/apps/cam/sdl_texture_1plane.cpp 0.6.0-2/src/apps/cam/sdl_texture_1plane.cpp
--- 0.5.0-1/src/apps/cam/sdl_texture_1plane.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_texture_1plane.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ *
+ * SDL single plane textures
+ */
+
+#include "sdl_texture_1plane.h"
+
+#include <assert.h>
+
+void SDLTexture1Plane::update(libcamera::Span<const libcamera::Span<const uint8_t>> data)
+{
+	assert(data.size() == 1);
+	assert(data[0].size_bytes() == std::size_t(rect_.h) * std::size_t(stride_));
+	SDL_UpdateTexture(ptr_, nullptr, data[0].data(), stride_);
+}
diff -pruN 0.5.0-1/src/apps/cam/sdl_texture_1plane.h 0.6.0-2/src/apps/cam/sdl_texture_1plane.h
--- 0.5.0-1/src/apps/cam/sdl_texture_1plane.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_texture_1plane.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ *
+ * SDL single plane textures
+ */
+
+#pragma once
+
+#include "sdl_texture.h"
+
+class SDLTexture1Plane final : public SDLTexture
+{
+public:
+	using SDLTexture::SDLTexture;
+
+	void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) override;
+};
diff -pruN 0.5.0-1/src/apps/cam/sdl_texture_mjpg.cpp 0.6.0-2/src/apps/cam/sdl_texture_mjpg.cpp
--- 0.5.0-1/src/apps/cam/sdl_texture_mjpg.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_texture_mjpg.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -76,7 +76,7 @@ int SDLTextureMJPG::decompress(Span<cons
 	return 0;
 }
 
-void SDLTextureMJPG::update(const std::vector<libcamera::Span<const uint8_t>> &data)
+void SDLTextureMJPG::update(libcamera::Span<const libcamera::Span<const uint8_t>> data)
 {
 	decompress(data[0]);
 	SDL_UpdateTexture(ptr_, nullptr, rgb_.get(), stride_);
diff -pruN 0.5.0-1/src/apps/cam/sdl_texture_mjpg.h 0.6.0-2/src/apps/cam/sdl_texture_mjpg.h
--- 0.5.0-1/src/apps/cam/sdl_texture_mjpg.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_texture_mjpg.h	2025-11-27 11:55:28.000000000 +0000
@@ -14,7 +14,7 @@ class SDLTextureMJPG : public SDLTexture
 public:
 	SDLTextureMJPG(const SDL_Rect &rect);
 
-	void update(const std::vector<libcamera::Span<const uint8_t>> &data) override;
+	void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) override;
 
 private:
 	int decompress(libcamera::Span<const uint8_t> data);
diff -pruN 0.5.0-1/src/apps/cam/sdl_texture_yuv.cpp 0.6.0-2/src/apps/cam/sdl_texture_yuv.cpp
--- 0.5.0-1/src/apps/cam/sdl_texture_yuv.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_texture_yuv.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,27 +7,24 @@
 
 #include "sdl_texture_yuv.h"
 
+#include <assert.h>
+
 using namespace libcamera;
 
 #if SDL_VERSION_ATLEAST(2, 0, 16)
-SDLTextureNV12::SDLTextureNV12(const SDL_Rect &rect, unsigned int stride)
-	: SDLTexture(rect, SDL_PIXELFORMAT_NV12, stride)
+SDLTextureNV::SDLTextureNV(const SDL_Rect &rect, uint32_t pixelFormat, unsigned int stride)
+	: SDLTexture(rect, pixelFormat, stride)
 {
+	assert(pixelFormat == SDL_PIXELFORMAT_NV12 || pixelFormat == SDL_PIXELFORMAT_NV21);
 }
 
-void SDLTextureNV12::update(const std::vector<libcamera::Span<const uint8_t>> &data)
+void SDLTextureNV::update(libcamera::Span<const libcamera::Span<const uint8_t>> data)
 {
-	SDL_UpdateNVTexture(ptr_, &rect_, data[0].data(), stride_,
+	assert(data.size() == 2);
+	assert(data[0].size_bytes() == std::size_t(rect_.h) * std::size_t(stride_));
+	assert(data[1].size_bytes() == std::size_t(rect_.h) * std::size_t(stride_) / 2);
+
+	SDL_UpdateNVTexture(ptr_, nullptr, data[0].data(), stride_,
 			    data[1].data(), stride_);
 }
 #endif
-
-SDLTextureYUYV::SDLTextureYUYV(const SDL_Rect &rect, unsigned int stride)
-	: SDLTexture(rect, SDL_PIXELFORMAT_YUY2, stride)
-{
-}
-
-void SDLTextureYUYV::update(const std::vector<libcamera::Span<const uint8_t>> &data)
-{
-	SDL_UpdateTexture(ptr_, &rect_, data[0].data(), stride_);
-}
diff -pruN 0.5.0-1/src/apps/cam/sdl_texture_yuv.h 0.6.0-2/src/apps/cam/sdl_texture_yuv.h
--- 0.5.0-1/src/apps/cam/sdl_texture_yuv.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/cam/sdl_texture_yuv.h	2025-11-27 11:55:28.000000000 +0000
@@ -10,17 +10,10 @@
 #include "sdl_texture.h"
 
 #if SDL_VERSION_ATLEAST(2, 0, 16)
-class SDLTextureNV12 : public SDLTexture
+class SDLTextureNV : public SDLTexture
 {
 public:
-	SDLTextureNV12(const SDL_Rect &rect, unsigned int stride);
-	void update(const std::vector<libcamera::Span<const uint8_t>> &data) override;
+	SDLTextureNV(const SDL_Rect &rect, uint32_t pixelFormat, unsigned int stride);
+	void update(libcamera::Span<const libcamera::Span<const uint8_t>> data) override;
 };
 #endif
-
-class SDLTextureYUYV : public SDLTexture
-{
-public:
-	SDLTextureYUYV(const SDL_Rect &rect, unsigned int stride);
-	void update(const std::vector<libcamera::Span<const uint8_t>> &data) override;
-};
diff -pruN 0.5.0-1/src/apps/common/dng_writer.cpp 0.6.0-2/src/apps/common/dng_writer.cpp
--- 0.5.0-1/src/apps/common/dng_writer.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/common/dng_writer.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -564,7 +564,7 @@ int DNGWriter::write(const char *filenam
 
 	const auto &model = cameraProperties.get(properties::Model);
 	if (model) {
-		TIFFSetField(tif, TIFFTAG_MODEL, model->c_str());
+		TIFFSetField(tif, TIFFTAG_MODEL, std::string(*model).c_str());
 		/* \todo set TIFFTAG_UNIQUECAMERAMODEL. */
 	}
 
diff -pruN 0.5.0-1/src/apps/common/image.cpp 0.6.0-2/src/apps/common/image.cpp
--- 0.5.0-1/src/apps/common/image.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/common/image.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -98,12 +98,12 @@ unsigned int Image::numPlanes() const
 
 Span<uint8_t> Image::data(unsigned int plane)
 {
-	assert(plane <= planes_.size());
+	assert(plane < planes_.size());
 	return planes_[plane];
 }
 
 Span<const uint8_t> Image::data(unsigned int plane) const
 {
-	assert(plane <= planes_.size());
+	assert(plane < planes_.size());
 	return planes_[plane];
 }
diff -pruN 0.5.0-1/src/apps/common/options.cpp 0.6.0-2/src/apps/common/options.cpp
--- 0.5.0-1/src/apps/common/options.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/common/options.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -887,7 +887,7 @@ OptionsParser::Options OptionsParser::pa
 
 	shortOptions[ids++] = ':';
 
-	for (const auto [opt, option] : optionsMap_) {
+	for (const auto &[opt, option] : optionsMap_) {
 		if (option->hasShortOption()) {
 			shortOptions[ids++] = opt;
 			if (option->argument != ArgumentNone)
diff -pruN 0.5.0-1/src/apps/common/ppm_writer.cpp 0.6.0-2/src/apps/common/ppm_writer.cpp
--- 0.5.0-1/src/apps/common/ppm_writer.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/common/ppm_writer.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -10,6 +10,7 @@
 #include <errno.h>
 #include <fstream>
 #include <iostream>
+#include <vector>
 
 #include <libcamera/formats.h>
 #include <libcamera/pixel_format.h>
@@ -20,9 +21,34 @@ int PPMWriter::write(const char *filenam
 		     const StreamConfiguration &config,
 		     const Span<uint8_t> &data)
 {
-	if (config.pixelFormat != formats::BGR888) {
-		std::cerr << "Only BGR888 output pixel format is supported ("
-			  << config.pixelFormat << " requested)" << std::endl;
+	struct FormatTransformation {
+		unsigned int rPos;
+		unsigned int gPos;
+		unsigned int bPos;
+		unsigned int bytesPerPixel;
+	};
+
+	static const std::map<libcamera::PixelFormat, FormatTransformation> transforms = {
+		{ libcamera::formats::R8, { 0, 0, 0, 1 } },
+		{ libcamera::formats::RGB888, { 2, 1, 0, 3 } },
+		{ libcamera::formats::BGR888, { 0, 1, 2, 3 } },
+		{ libcamera::formats::ARGB8888, { 2, 1, 0, 4 } },
+		{ libcamera::formats::XRGB8888, { 2, 1, 0, 4 } },
+		{ libcamera::formats::ABGR8888, { 0, 1, 2, 4 } },
+		{ libcamera::formats::XBGR8888, { 0, 1, 2, 4 } },
+		{ libcamera::formats::RGBA8888, { 3, 2, 1, 4 } },
+		{ libcamera::formats::RGBX8888, { 3, 2, 1, 4 } },
+		{ libcamera::formats::BGRA8888, { 1, 2, 3, 4 } },
+		{ libcamera::formats::BGRX8888, { 1, 2, 3, 4 } },
+	};
+
+	FormatTransformation transformation;
+	if (auto search = transforms.find(config.pixelFormat); search != transforms.end()) {
+		transformation = search->second;
+	} else {
+		std::cerr
+			<< "Only RGB output pixel formats are supported ("
+			<< config.pixelFormat << " requested)" << std::endl;
 		return -EINVAL;
 	}
 
@@ -42,8 +68,22 @@ int PPMWriter::write(const char *filenam
 
 	const unsigned int rowLength = config.size.width * 3;
 	const char *row = reinterpret_cast<const char *>(data.data());
+	const bool transform = config.pixelFormat != formats::BGR888;
+	std::vector<char> transformedRow(transform ? rowLength : 0);
+
 	for (unsigned int y = 0; y < config.size.height; y++, row += config.stride) {
-		output.write(row, rowLength);
+		if (transform) {
+			for (unsigned int x = 0; x < config.size.width; x++) {
+				transformedRow[x * 3] =
+					row[x * transformation.bytesPerPixel + transformation.rPos];
+				transformedRow[x * 3 + 1] =
+					row[x * transformation.bytesPerPixel + transformation.gPos];
+				transformedRow[x * 3 + 2] =
+					row[x * transformation.bytesPerPixel + transformation.bPos];
+			}
+		}
+
+		output.write(transform ? transformedRow.data() : row, rowLength);
 		if (!output) {
 			std::cerr << "Failed to write image data at row " << y << std::endl;
 			return -EIO;
diff -pruN 0.5.0-1/src/apps/common/stream_options.cpp 0.6.0-2/src/apps/common/stream_options.cpp
--- 0.5.0-1/src/apps/common/stream_options.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/common/stream_options.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -42,9 +42,8 @@ KeyValueParser::Options StreamKeyValuePa
 
 std::vector<StreamRole> StreamKeyValueParser::roles(const OptionValue &values)
 {
-	/* If no configuration values to examine default to viewfinder. */
 	if (values.empty())
-		return { StreamRole::Viewfinder };
+		return {};
 
 	const std::vector<OptionValue> &streamParameters = values.toArray();
 
diff -pruN 0.5.0-1/src/apps/lc-compliance/helpers/capture.cpp 0.6.0-2/src/apps/lc-compliance/helpers/capture.cpp
--- 0.5.0-1/src/apps/lc-compliance/helpers/capture.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/lc-compliance/helpers/capture.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -23,18 +23,38 @@ Capture::~Capture()
 	stop();
 }
 
-void Capture::configure(StreamRole role)
+void Capture::configure(libcamera::Span<const libcamera::StreamRole> roles)
 {
-	config_ = camera_->generateConfiguration({ role });
+	assert(!roles.empty());
 
+	config_ = camera_->generateConfiguration(roles);
 	if (!config_)
-		GTEST_SKIP() << "Role not supported by camera";
+		GTEST_SKIP() << "Roles not supported by camera";
+
+	ASSERT_EQ(config_->size(), roles.size()) << "Unexpected number of streams in configuration";
+
+	/*
+	 * Set the buffers count to the largest value across all streams.
+	 * \todo: Should all streams from a Camera have the same buffer count ?
+	 */
+	auto largest =
+		std::max_element(config_->begin(), config_->end(),
+				 [](const StreamConfiguration &l, const StreamConfiguration &r)
+				 { return l.bufferCount < r.bufferCount; });
+
+	assert(largest != config_->end());
+
+	for (auto &cfg : *config_)
+		cfg.bufferCount = largest->bufferCount;
 
 	if (config_->validate() != CameraConfiguration::Valid) {
 		config_.reset();
 		FAIL() << "Configuration not valid";
 	}
 
+	for (const auto &cfg : *config_)
+		EXPECT_TRUE(cfg.colorSpace) << "Colorspace not set for " << cfg;
+
 	if (camera_->configure(config_.get())) {
 		config_.reset();
 		FAIL() << "Failed to configure camera";
@@ -103,29 +123,37 @@ void Capture::start()
 	assert(!allocator_.allocated());
 	assert(requests_.empty());
 
-	Stream *stream = config_->at(0).stream();
-	int count = allocator_.allocate(stream);
-
-	ASSERT_GE(count, 0) << "Failed to allocate buffers";
-	EXPECT_EQ(count, config_->at(0).bufferCount) << "Allocated less buffers than expected";
-
-	const std::vector<std::unique_ptr<FrameBuffer>> &buffers = allocator_.buffers(stream);
+	const auto bufferCount = config_->at(0).bufferCount;
 
 	/* No point in testing less requests then the camera depth. */
-	if (queueLimit_ && *queueLimit_ < buffers.size()) {
-		GTEST_SKIP() << "Camera needs " << buffers.size()
+	if (queueLimit_ && *queueLimit_ < bufferCount) {
+		GTEST_SKIP() << "Camera needs " << bufferCount
 			     << " requests, can't test only " << *queueLimit_;
 	}
 
-	for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
+	for (std::size_t i = 0; i < bufferCount; i++) {
 		std::unique_ptr<Request> request = camera_->createRequest();
 		ASSERT_TRUE(request) << "Can't create request";
+		requests_.push_back(std::move(request));
+	}
 
-		ASSERT_EQ(request->addBuffer(stream, buffer.get()), 0) << "Can't set buffer for request";
+	for (const auto &cfg : *config_) {
+		Stream *stream = cfg.stream();
 
-		requests_.push_back(std::move(request));
+		int count = allocator_.allocate(stream);
+		ASSERT_GE(count, 0) << "Failed to allocate buffers";
+
+		const auto &buffers = allocator_.buffers(stream);
+		ASSERT_EQ(buffers.size(), bufferCount) << "Mismatching buffer count";
+
+		for (std::size_t i = 0; i < bufferCount; i++) {
+			ASSERT_EQ(requests_[i]->addBuffer(stream, buffers[i].get()), 0)
+				<< "Failed to add buffer to request";
+		}
 	}
 
+	ASSERT_TRUE(allocator_.allocated());
+
 	camera_->requestCompleted.connect(this, &Capture::requestComplete);
 
 	ASSERT_EQ(camera_->start(), 0) << "Failed to start camera";
@@ -140,7 +168,12 @@ void Capture::stop()
 
 	camera_->requestCompleted.disconnect(this);
 
-	Stream *stream = config_->at(0).stream();
 	requests_.clear();
-	allocator_.free(stream);
+
+	for (const auto &cfg : *config_) {
+		EXPECT_EQ(allocator_.free(cfg.stream()), 0)
+			<< "Failed to free buffers associated with stream";
+	}
+
+	EXPECT_FALSE(allocator_.allocated());
 }
diff -pruN 0.5.0-1/src/apps/lc-compliance/helpers/capture.h 0.6.0-2/src/apps/lc-compliance/helpers/capture.h
--- 0.5.0-1/src/apps/lc-compliance/helpers/capture.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/lc-compliance/helpers/capture.h	2025-11-27 11:55:28.000000000 +0000
@@ -20,7 +20,7 @@ public:
 	Capture(std::shared_ptr<libcamera::Camera> camera);
 	~Capture();
 
-	void configure(libcamera::StreamRole role);
+	void configure(libcamera::Span<const libcamera::StreamRole> roles);
 	void run(unsigned int captureLimit, std::optional<unsigned int> queueLimit = {});
 
 private:
diff -pruN 0.5.0-1/src/apps/lc-compliance/meson.build 0.6.0-2/src/apps/lc-compliance/meson.build
--- 0.5.0-1/src/apps/lc-compliance/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/lc-compliance/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -15,6 +15,7 @@ lc_compliance_sources = files([
     'environment.cpp',
     'helpers/capture.cpp',
     'main.cpp',
+    'test_base.cpp',
     'tests/capture_test.cpp',
 ])
 
diff -pruN 0.5.0-1/src/apps/lc-compliance/test_base.cpp 0.6.0-2/src/apps/lc-compliance/test_base.cpp
--- 0.5.0-1/src/apps/lc-compliance/test_base.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/apps/lc-compliance/test_base.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2021, Collabora Ltd.
+ *
+ * Base definitions for tests
+ */
+
+#include "test_base.h"
+
+#include "environment.h"
+
+void CameraHolder::acquireCamera()
+{
+	Environment *env = Environment::get();
+
+	camera_ = env->cm()->get(env->cameraId());
+
+	ASSERT_EQ(camera_->acquire(), 0);
+}
+
+void CameraHolder::releaseCamera()
+{
+	if (!camera_)
+		return;
+
+	camera_->release();
+	camera_.reset();
+}
diff -pruN 0.5.0-1/src/apps/lc-compliance/test_base.h 0.6.0-2/src/apps/lc-compliance/test_base.h
--- 0.5.0-1/src/apps/lc-compliance/test_base.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/apps/lc-compliance/test_base.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2021, Collabora Ltd.
+ *
+ * Base definitions for tests
+ */
+#pragma once
+
+#include <libcamera/libcamera.h>
+
+#include <gtest/gtest.h>
+
+class CameraHolder
+{
+protected:
+	void acquireCamera();
+	void releaseCamera();
+
+	std::shared_ptr<libcamera::Camera> camera_;
+};
diff -pruN 0.5.0-1/src/apps/lc-compliance/tests/capture_test.cpp 0.6.0-2/src/apps/lc-compliance/tests/capture_test.cpp
--- 0.5.0-1/src/apps/lc-compliance/tests/capture_test.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/lc-compliance/tests/capture_test.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -8,72 +8,54 @@
 
 #include "capture.h"
 
-#include <iostream>
+#include <sstream>
+#include <string>
+#include <tuple>
+#include <vector>
 
 #include <gtest/gtest.h>
 
-#include "environment.h"
+#include "test_base.h"
 
 namespace {
 
 using namespace libcamera;
 
-const int NUMREQUESTS[] = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
-
-const StreamRole ROLES[] = {
-	StreamRole::Raw,
-	StreamRole::StillCapture,
-	StreamRole::VideoRecording,
-	StreamRole::Viewfinder
-};
-
-class SingleStream : public testing::TestWithParam<std::tuple<StreamRole, int>>
+class SimpleCapture : public testing::TestWithParam<std::tuple<std::vector<StreamRole>, int>>, public CameraHolder
 {
 public:
-	static std::string nameParameters(const testing::TestParamInfo<SingleStream::ParamType> &info);
+	static std::string nameParameters(const testing::TestParamInfo<SimpleCapture::ParamType> &info);
 
 protected:
 	void SetUp() override;
 	void TearDown() override;
-
-	std::shared_ptr<Camera> camera_;
 };
 
 /*
  * We use gtest's SetUp() and TearDown() instead of constructor and destructor
  * in order to be able to assert on them.
  */
-void SingleStream::SetUp()
+void SimpleCapture::SetUp()
 {
-	Environment *env = Environment::get();
-
-	camera_ = env->cm()->get(env->cameraId());
-
-	ASSERT_EQ(camera_->acquire(), 0);
+	acquireCamera();
 }
 
-void SingleStream::TearDown()
+void SimpleCapture::TearDown()
 {
-	if (!camera_)
-		return;
-
-	camera_->release();
-	camera_.reset();
+	releaseCamera();
 }
 
-std::string SingleStream::nameParameters(const testing::TestParamInfo<SingleStream::ParamType> &info)
+std::string SimpleCapture::nameParameters(const testing::TestParamInfo<SimpleCapture::ParamType> &info)
 {
-	std::map<StreamRole, std::string> rolesMap = {
-		{ StreamRole::Raw, "Raw" },
-		{ StreamRole::StillCapture, "StillCapture" },
-		{ StreamRole::VideoRecording, "VideoRecording" },
-		{ StreamRole::Viewfinder, "Viewfinder" }
-	};
+	const auto &[roles, numRequests] = info.param;
+	std::ostringstream ss;
+
+	for (StreamRole r : roles)
+		ss << r << '_';
 
-	std::string roleName = rolesMap[std::get<0>(info.param)];
-	std::string numRequestsName = std::to_string(std::get<1>(info.param));
+	ss << '_' << numRequests;
 
-	return roleName + "_" + numRequestsName;
+	return ss.str();
 }
 
 /*
@@ -83,13 +65,13 @@ std::string SingleStream::nameParameters
  * failure is a camera that completes less requests than the number of requests
  * queued.
  */
-TEST_P(SingleStream, Capture)
+TEST_P(SimpleCapture, Capture)
 {
-	auto [role, numRequests] = GetParam();
+	const auto &[roles, numRequests] = GetParam();
 
 	Capture capture(camera_);
 
-	capture.configure(role);
+	capture.configure(roles);
 
 	capture.run(numRequests, numRequests);
 }
@@ -101,14 +83,14 @@ TEST_P(SingleStream, Capture)
  * a camera that does not clean up correctly in its error path but is only
  * tested by single-capture applications.
  */
-TEST_P(SingleStream, CaptureStartStop)
+TEST_P(SimpleCapture, CaptureStartStop)
 {
-	auto [role, numRequests] = GetParam();
+	const auto &[roles, numRequests] = GetParam();
 	unsigned int numRepeats = 3;
 
 	Capture capture(camera_);
 
-	capture.configure(role);
+	capture.configure(roles);
 
 	for (unsigned int starts = 0; starts < numRepeats; starts++)
 		capture.run(numRequests, numRequests);
@@ -121,21 +103,43 @@ TEST_P(SingleStream, CaptureStartStop)
  * is a camera that does not handle cancelation of buffers coming back from the
  * video device while stopping.
  */
-TEST_P(SingleStream, UnbalancedStop)
+TEST_P(SimpleCapture, UnbalancedStop)
 {
-	auto [role, numRequests] = GetParam();
+	const auto &[roles, numRequests] = GetParam();
 
 	Capture capture(camera_);
 
-	capture.configure(role);
+	capture.configure(roles);
 
 	capture.run(numRequests);
 }
 
-INSTANTIATE_TEST_SUITE_P(CaptureTests,
-			 SingleStream,
-			 testing::Combine(testing::ValuesIn(ROLES),
+const int NUMREQUESTS[] = { 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 };
+
+const std::vector<StreamRole> SINGLEROLES[] = {
+	{ StreamRole::Raw, },
+	{ StreamRole::StillCapture, },
+	{ StreamRole::VideoRecording, },
+	{ StreamRole::Viewfinder, },
+};
+
+const std::vector<StreamRole> MULTIROLES[] = {
+	{ StreamRole::Raw, StreamRole::StillCapture },
+	{ StreamRole::Raw, StreamRole::VideoRecording },
+	{ StreamRole::StillCapture, StreamRole::VideoRecording },
+	{ StreamRole::VideoRecording, StreamRole::VideoRecording },
+};
+
+INSTANTIATE_TEST_SUITE_P(SingleStream,
+			 SimpleCapture,
+			 testing::Combine(testing::ValuesIn(SINGLEROLES),
+					  testing::ValuesIn(NUMREQUESTS)),
+			 SimpleCapture::nameParameters);
+
+INSTANTIATE_TEST_SUITE_P(MultiStream,
+			 SimpleCapture,
+			 testing::Combine(testing::ValuesIn(MULTIROLES),
 					  testing::ValuesIn(NUMREQUESTS)),
-			 SingleStream::nameParameters);
+			 SimpleCapture::nameParameters);
 
 } /* namespace */
diff -pruN 0.5.0-1/src/apps/qcam/cam_select_dialog.cpp 0.6.0-2/src/apps/qcam/cam_select_dialog.cpp
--- 0.5.0-1/src/apps/qcam/cam_select_dialog.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/qcam/cam_select_dialog.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -114,8 +114,8 @@ void CameraSelectorDialog::updateCameraI
 		cameraLocation_->setText("Unknown");
 	}
 
-	const auto &model = properties.get(libcamera::properties::Model)
+	const auto model = properties.get(libcamera::properties::Model)
 				    .value_or("Unknown");
 
-	cameraModel_->setText(QString::fromStdString(model));
+	cameraModel_->setText(QString::fromUtf8(model.data(), model.length()));
 }
diff -pruN 0.5.0-1/src/apps/qcam/main_window.cpp 0.6.0-2/src/apps/qcam/main_window.cpp
--- 0.5.0-1/src/apps/qcam/main_window.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/qcam/main_window.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -333,6 +333,9 @@ int MainWindow::openCamera()
 
 void MainWindow::toggleCapture(bool start)
 {
+	if (!camera_)
+		return;
+
 	if (start) {
 		startCapture();
 		startStopAction_->setIcon(iconStop_);
@@ -356,6 +359,9 @@ int MainWindow::startCapture()
 
 	/* Verify roles are supported. */
 	switch (roles.size()) {
+	case 0:
+		roles.push_back(StreamRole::Viewfinder);
+		break;
 	case 1:
 		if (roles[0] != StreamRole::Viewfinder) {
 			qWarning() << "Only viewfinder supported for single stream";
diff -pruN 0.5.0-1/src/apps/qcam/meson.build 0.6.0-2/src/apps/qcam/meson.build
--- 0.5.0-1/src/apps/qcam/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/apps/qcam/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -42,6 +42,13 @@ qt6_cpp_args = [
     '-Wno-extra-semi',
 ]
 
+# gcc 12 and 13 output a false positive variable shadowing warning with Qt
+# 6.9.0 and newer. Silence it.
+if qt6_dep.version().version_compare('>=6.9.0') and \
+   cxx.version().version_compare('>=12') and cxx.version().version_compare('<14')
+    qt6_cpp_args += ['-Wno-shadow']
+endif
+
 resources = qt6.preprocess(moc_headers : qcam_moc_headers,
                            qresources : qcam_resources,
                            dependencies : qt6_dep)
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamera-controls.cpp.in 0.6.0-2/src/gstreamer/gstlibcamera-controls.cpp.in
--- 0.5.0-1/src/gstreamer/gstlibcamera-controls.cpp.in	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamera-controls.cpp.in	2025-11-27 11:55:28.000000000 +0000
@@ -14,50 +14,10 @@
 #include <libcamera/geometry.h>
 
 #include "gstlibcamera-controls.h"
+#include "gstlibcamera-utils.h"
 
 using namespace libcamera;
 
-static void value_set_rectangle(GValue *value, const Rectangle &rect)
-{
-	Point top_left = rect.topLeft();
-	Size size = rect.size();
-
-	GValue x = G_VALUE_INIT;
-	g_value_init(&x, G_TYPE_INT);
-	g_value_set_int(&x, top_left.x);
-	gst_value_array_append_and_take_value(value, &x);
-
-	GValue y = G_VALUE_INIT;
-	g_value_init(&y, G_TYPE_INT);
-	g_value_set_int(&y, top_left.y);
-	gst_value_array_append_and_take_value(value, &y);
-
-	GValue width = G_VALUE_INIT;
-	g_value_init(&width, G_TYPE_INT);
-	g_value_set_int(&width, size.width);
-	gst_value_array_append_and_take_value(value, &width);
-
-	GValue height = G_VALUE_INIT;
-	g_value_init(&height, G_TYPE_INT);
-	g_value_set_int(&height, size.height);
-	gst_value_array_append_and_take_value(value, &height);
-}
-
-static Rectangle value_get_rectangle(const GValue *value)
-{
-	const GValue *r;
-	r = gst_value_array_get_value(value, 0);
-	int x = g_value_get_int(r);
-	r = gst_value_array_get_value(value, 1);
-	int y = g_value_get_int(r);
-	r = gst_value_array_get_value(value, 2);
-	int w = g_value_get_int(r);
-	r = gst_value_array_get_value(value, 3);
-	int h = g_value_get_int(r);
-
-	return Rectangle(x, y, w, h);
-}
-
 {% for vendor, ctrls in controls %}
 {%- for ctrl in ctrls if ctrl.is_enum %}
 static const GEnumValue {{ ctrl.name|snake_case }}_types[] = {
@@ -68,7 +28,7 @@ static const GEnumValue {{ ctrl.name|sna
 		"{{ enum.gst_name }}"
 	},
 {%- endfor %}
-	{0, NULL, NULL}
+	{0, nullptr, nullptr}
 };
 
 #define TYPE_{{ ctrl.name|snake_case|upper }} \
@@ -173,7 +133,7 @@ bool GstCameraControls::getProperty(guin
 			GValue element = G_VALUE_INIT;
 {%- if ctrl.is_rectangle %}
 			g_value_init(&element, GST_TYPE_PARAM_ARRAY_LIST);
-			value_set_rectangle(&element, control[i]);
+			gst_libcamera_gvalue_set_rectangle(&element, control[i]);
 {%- else %}
 			g_value_init(&element, G_TYPE_{{ ctrl.gtype|upper }});
 			g_value_set_{{ ctrl.gtype }}(&element, control[i]);
@@ -182,7 +142,7 @@ bool GstCameraControls::getProperty(guin
 		}
 {%- else %}
 {%- if ctrl.is_rectangle %}
-		value_set_rectangle(value, control);
+		gst_libcamera_gvalue_set_rectangle(value, control);
 {%- else %}
 		g_value_set_{{ ctrl.gtype }}(value, control);
 {%- endif %}
@@ -246,7 +206,7 @@ bool GstCameraControls::setProperty(guin
 					  i);
 				return true;
 			}
-			values[i] = value_get_rectangle(element);
+			values[i] = gst_libcamera_gvalue_get_rectangle(element);
 {%- else %}
 			values[i] = g_value_get_{{ ctrl.gtype }}(element);
 {%- endif %}
@@ -265,7 +225,7 @@ bool GstCameraControls::setProperty(guin
 				  "array of size 4");
 			return true;
 		}
-		Rectangle val = value_get_rectangle(value);
+		Rectangle val = gst_libcamera_gvalue_get_rectangle(value);
 {%- else %}
 		auto val = g_value_get_{{ ctrl.gtype }}(value);
 {%- endif %}
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamera-utils.cpp 0.6.0-2/src/gstreamer/gstlibcamera-utils.cpp
--- 0.5.0-1/src/gstreamer/gstlibcamera-utils.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamera-utils.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -8,19 +8,21 @@
 
 #include "gstlibcamera-utils.h"
 
+#include <string>
+
 #include <libcamera/control_ids.h>
 #include <libcamera/formats.h>
 
 using namespace libcamera;
 
-static struct {
+static const struct {
 	GstVideoFormat gst_format;
 	PixelFormat format;
 } format_map[] = {
 	/* Compressed */
 	{ GST_VIDEO_FORMAT_ENCODED, formats::MJPEG },
 
-	/* Bayer formats, gstreamer only supports 8-bit */
+	/* Bayer formats */
 	{ GST_VIDEO_FORMAT_ENCODED, formats::SBGGR8 },
 	{ GST_VIDEO_FORMAT_ENCODED, formats::SGBRG8 },
 	{ GST_VIDEO_FORMAT_ENCODED, formats::SGRBG8 },
@@ -317,20 +319,42 @@ bare_structure_from_format(const PixelFo
 		return gst_structure_new("video/x-raw", "format", G_TYPE_STRING,
 					 gst_video_format_to_string(gst_format), nullptr);
 
-	switch (format) {
-	case formats::MJPEG:
+	if (format == formats::MJPEG)
 		return gst_structure_new_empty("image/jpeg");
 
-	case formats::SBGGR8:
-	case formats::SGBRG8:
-	case formats::SGRBG8:
-	case formats::SRGGB8:
-		return gst_structure_new("video/x-bayer", "format", G_TYPE_STRING,
-					 bayer_format_to_string(format), nullptr);
+	const gchar *s = bayer_format_to_string(format);
+	if (s)
+		return gst_structure_new("video/x-bayer", "format",
+					 G_TYPE_STRING, s, nullptr);
 
-	default:
-		return nullptr;
+	return nullptr;
+}
+
+static const struct {
+	ControlType c_type;
+	GType g_type;
+} control_type_gtype_map[] = {
+	{ ControlTypeBool, G_TYPE_BOOLEAN },
+	{ ControlTypeByte, G_TYPE_UINT },
+	{ ControlTypeUnsigned16, G_TYPE_UINT },
+	{ ControlTypeUnsigned32, G_TYPE_UINT },
+	{ ControlTypeInteger32, G_TYPE_INT },
+	{ ControlTypeInteger64, G_TYPE_INT64 },
+	{ ControlTypeFloat, G_TYPE_FLOAT },
+	{ ControlTypeString, G_TYPE_STRING },
+	{ ControlTypeRectangle, GST_TYPE_ARRAY },
+	{ ControlTypeSize, GST_TYPE_ARRAY },
+	{ ControlTypePoint, GST_TYPE_ARRAY },
+};
+
+static GType
+control_type_to_gtype(const ControlType &type)
+{
+	for (auto &a : control_type_gtype_map) {
+		if (a.c_type == type)
+			return a.g_type;
 	}
+	return G_TYPE_INVALID;
 }
 
 GstCaps *
@@ -494,9 +518,12 @@ void gst_libcamera_configure_stream_from
 
 	/* Configure colorimetry */
 	if (gst_structure_has_field(s, "colorimetry")) {
-		const gchar *colorimetry_str = gst_structure_get_string(s, "colorimetry");
+		const gchar *colorimetry_str;
 		GstVideoColorimetry colorimetry;
 
+		gst_structure_fixate_field(s, "colorimetry");
+		colorimetry_str = gst_structure_get_string(s, "colorimetry");
+
 		if (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str))
 			g_critical("Invalid colorimetry %s", colorimetry_str);
 
@@ -581,6 +608,53 @@ void gst_libcamera_framerate_to_caps(Gst
 	gst_structure_set(s, "framerate", GST_TYPE_FRACTION, fps_caps_n, fps_caps_d, nullptr);
 }
 
+void gst_libcamera_gvalue_set_point(GValue *value, const Point &point)
+{
+	GValue x = G_VALUE_INIT;
+	g_value_init(&x, G_TYPE_INT);
+	g_value_set_int(&x, point.x);
+	gst_value_array_append_and_take_value(value, &x);
+
+	GValue y = G_VALUE_INIT;
+	g_value_init(&y, G_TYPE_INT);
+	g_value_set_int(&y, point.y);
+	gst_value_array_append_and_take_value(value, &y);
+}
+
+void gst_libcamera_gvalue_set_size(GValue *value, const Size &size)
+{
+	GValue width = G_VALUE_INIT;
+	g_value_init(&width, G_TYPE_INT);
+	g_value_set_int(&width, size.width);
+	gst_value_array_append_and_take_value(value, &width);
+
+	GValue height = G_VALUE_INIT;
+	g_value_init(&height, G_TYPE_INT);
+	g_value_set_int(&height, size.height);
+	gst_value_array_append_and_take_value(value, &height);
+}
+
+void gst_libcamera_gvalue_set_rectangle(GValue *value, const Rectangle &rect)
+{
+	gst_libcamera_gvalue_set_point(value, rect.topLeft());
+	gst_libcamera_gvalue_set_size(value, rect.size());
+}
+
+Rectangle gst_libcamera_gvalue_get_rectangle(const GValue *value)
+{
+	const GValue *r;
+	r = gst_value_array_get_value(value, 0);
+	int x = g_value_get_int(r);
+	r = gst_value_array_get_value(value, 1);
+	int y = g_value_get_int(r);
+	r = gst_value_array_get_value(value, 2);
+	int w = g_value_get_int(r);
+	r = gst_value_array_get_value(value, 3);
+	int h = g_value_get_int(r);
+
+	return Rectangle(x, y, w, h);
+}
+
 #if !GST_CHECK_VERSION(1, 17, 1)
 gboolean
 gst_task_resume(GstTask *task)
@@ -596,6 +670,43 @@ gst_task_resume(GstTask *task)
 }
 #endif
 
+#if !GST_CHECK_VERSION(1, 22, 0)
+/*
+ * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
+ * Library       <2002> Ronald Bultje <rbultje@ronald.bitfreak.net>
+ * Copyright (C) <2007> David A. Schleef <ds@schleef.org>
+ */
+/*
+ * This function has been imported directly from the gstreamer project to
+ * support backwards compatibility and should be removed when the older version
+ * is no longer supported.
+ */
+gint gst_video_format_info_extrapolate_stride(const GstVideoFormatInfo *finfo, gint plane, gint stride)
+{
+	gint estride;
+	gint comp[GST_VIDEO_MAX_COMPONENTS];
+	gint i;
+
+	/* There is nothing to extrapolate on first plane. */
+	if (plane == 0)
+		return stride;
+
+	gst_video_format_info_component(finfo, plane, comp);
+
+	/*
+	 * For now, all planar formats have a single component on first plane, but
+	 * if there was a planar format with more, we'd have to make a ratio of the
+	 * number of component on the first plane against the number of component on
+	 * the current plane.
+	 */
+	estride = 0;
+	for (i = 0; i < GST_VIDEO_MAX_COMPONENTS && comp[i] >= 0; i++)
+		estride += GST_VIDEO_FORMAT_INFO_SCALE_WIDTH(finfo, comp[i], stride);
+
+	return estride;
+}
+#endif
+
 G_LOCK_DEFINE_STATIC(cm_singleton_lock);
 static std::weak_ptr<CameraManager> cm_singleton_ptr;
 
@@ -619,3 +730,171 @@ gst_libcamera_get_camera_manager(int &re
 
 	return cm;
 }
+
+int gst_libcamera_set_structure_field(GstStructure *structure, const ControlId *id,
+				      const ControlValue &value)
+{
+	std::string prop = "api.libcamera." + id->name();
+	g_auto(GValue) v = G_VALUE_INIT;
+	g_auto(GValue) x = G_VALUE_INIT;
+	gboolean is_array = value.isArray();
+
+	GType type = control_type_to_gtype(value.type());
+	if (type == G_TYPE_INVALID)
+		return -EINVAL;
+
+	if (is_array || type == GST_TYPE_ARRAY)
+		g_value_init(&v, GST_TYPE_ARRAY);
+
+	switch (value.type()) {
+	case ControlTypeBool:
+		if (is_array) {
+			Span<const bool> data = value.get<Span<const bool>>();
+			for (auto it = data.begin(); it != data.end(); ++it) {
+				g_value_init(&x, type);
+				g_value_set_boolean(&x, *it);
+				gst_value_array_append_and_take_value(&v, &x);
+			}
+		} else {
+			gst_structure_set(structure, prop.c_str(), G_TYPE_BOOLEAN,
+					  value.get<const bool>(), nullptr);
+		}
+		break;
+	case ControlTypeByte:
+		if (is_array) {
+			Span<const uint8_t> data = value.get<Span<const uint8_t>>();
+			for (auto it = data.begin(); it != data.end(); ++it) {
+				g_value_init(&x, type);
+				g_value_set_uint(&x, *it);
+				gst_value_array_append_and_take_value(&v, &x);
+			}
+		} else {
+			gst_structure_set(structure, prop.c_str(), G_TYPE_UINT,
+					  value.get<const uint8_t>(), nullptr);
+		}
+		break;
+	case ControlTypeUnsigned16:
+		if (is_array) {
+			Span<const uint16_t> data = value.get<Span<const uint16_t>>();
+			for (auto it = data.begin(); it != data.end(); ++it) {
+				g_value_init(&x, type);
+				g_value_set_uint(&x, *it);
+				gst_value_array_append_and_take_value(&v, &x);
+			}
+		} else {
+			gst_structure_set(structure, prop.c_str(), G_TYPE_UINT,
+					  value.get<const uint16_t>(), nullptr);
+		}
+		break;
+	case ControlTypeUnsigned32:
+		if (is_array) {
+			Span<const uint32_t> data = value.get<Span<const uint32_t>>();
+			for (auto it = data.begin(); it != data.end(); ++it) {
+				g_value_init(&x, type);
+				g_value_set_uint(&x, *it);
+				gst_value_array_append_and_take_value(&v, &x);
+			}
+		} else {
+			gst_structure_set(structure, prop.c_str(), G_TYPE_UINT,
+					  value.get<const uint32_t>(), nullptr);
+		}
+		break;
+	case ControlTypeInteger32:
+		if (is_array) {
+			Span<const int32_t> data = value.get<Span<const int32_t>>();
+			for (auto it = data.begin(); it != data.end(); ++it) {
+				g_value_init(&x, type);
+				g_value_set_int(&x, *it);
+				gst_value_array_append_and_take_value(&v, &x);
+			}
+		} else {
+			if (!id->enumerators().empty()) {
+				int32_t val = value.get<int32_t>();
+				const auto &iter = id->enumerators().find(val);
+				if (iter != id->enumerators().end()) {
+					gst_structure_set(structure, prop.c_str(),
+							  G_TYPE_STRING,
+							  iter->second.c_str(),
+							  nullptr);
+				} else {
+					return -EINVAL;
+				}
+			} else {
+				gst_structure_set(structure, prop.c_str(), G_TYPE_INT,
+						  value.get<const int32_t>(), nullptr);
+			}
+		}
+		break;
+	case ControlTypeInteger64:
+		if (is_array) {
+			Span<const int64_t> data = value.get<Span<const int64_t>>();
+			for (auto it = data.begin(); it != data.end(); ++it) {
+				g_value_init(&x, type);
+				g_value_set_int64(&x, *it);
+				gst_value_array_append_and_take_value(&v, &x);
+			}
+		} else {
+			gst_structure_set(structure, prop.c_str(), G_TYPE_INT64,
+					  value.get<const int64_t>(), nullptr);
+		}
+		break;
+	case ControlTypeFloat:
+		if (is_array) {
+			Span<const float> data = value.get<Span<const float>>();
+			for (auto it = data.begin(); it != data.end(); ++it) {
+				g_value_init(&x, type);
+				g_value_set_float(&x, *it);
+				gst_value_array_append_and_take_value(&v, &x);
+			}
+		} else {
+			gst_structure_set(structure, prop.c_str(), G_TYPE_FLOAT,
+					  value.get<const float>(), nullptr);
+		}
+		break;
+	case ControlTypeString:
+		/*
+		 * isArray() is always true for strings hence, unset the GValue
+		 * array because we are going to the toString() helper directly.
+		 */
+		g_value_unset(&v);
+		gst_structure_set(structure, prop.c_str(), G_TYPE_STRING,
+				  value.toString().c_str(), nullptr);
+		break;
+	case ControlTypeSize:
+		if (is_array) {
+			Span<const Size> data = value.get<Span<const Size>>();
+			for (auto it = data.begin(); it != data.end(); ++it)
+				gst_libcamera_gvalue_set_size(&v, *it);
+		} else {
+			gst_libcamera_gvalue_set_size(&v, value.get<const Size>());
+		}
+		break;
+	case ControlTypePoint:
+		if (is_array) {
+			Span<const Point> data = value.get<Span<const Point>>();
+			for (auto it = data.begin(); it != data.end(); ++it)
+				gst_libcamera_gvalue_set_point(&v, *it);
+		} else {
+			gst_libcamera_gvalue_set_point(&v, value.get<const Point>());
+		}
+		break;
+	case ControlTypeRectangle:
+		if (is_array) {
+			Span<const Rectangle> data = value.get<Span<const Rectangle>>();
+			for (auto it = data.begin(); it != data.end(); ++it)
+				gst_libcamera_gvalue_set_rectangle(&v, *it);
+		} else {
+			gst_libcamera_gvalue_set_rectangle(&v, value.get<const Rectangle>());
+		}
+		break;
+	case ControlTypeNone:
+		[[fallthrough]];
+	default:
+		return -EINVAL;
+	}
+
+	if (GST_VALUE_HOLDS_ARRAY(&v))
+		gst_structure_set_value(structure, prop.c_str(), &v);
+
+	return 0;
+}
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamera-utils.h 0.6.0-2/src/gstreamer/gstlibcamera-utils.h
--- 0.5.0-1/src/gstreamer/gstlibcamera-utils.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamera-utils.h	2025-11-27 11:55:28.000000000 +0000
@@ -25,6 +25,13 @@ void gst_libcamera_clamp_and_set_framedu
 					       const libcamera::ControlInfoMap &camera_controls,
 					       GstStructure *element_caps);
 void gst_libcamera_framerate_to_caps(GstCaps *caps, const GstStructure *element_caps);
+void gst_libcamera_gvalue_set_point(GValue *value, const libcamera::Point &point);
+void gst_libcamera_gvalue_set_size(GValue *value, const libcamera::Size &size);
+void gst_libcamera_gvalue_set_rectangle(GValue *value, const libcamera::Rectangle &rect);
+libcamera::Rectangle gst_libcamera_gvalue_get_rectangle(const GValue *value);
+int gst_libcamera_set_structure_field(GstStructure *structure,
+				      const libcamera::ControlId *id,
+				      const libcamera::ControlValue &value);
 
 #if !GST_CHECK_VERSION(1, 16, 0)
 static inline void gst_clear_event(GstEvent **event_ptr)
@@ -36,6 +43,11 @@ static inline void gst_clear_event(GstEv
 #if !GST_CHECK_VERSION(1, 17, 1)
 gboolean gst_task_resume(GstTask *task);
 #endif
+
+#if !GST_CHECK_VERSION(1, 22, 0)
+gint gst_video_format_info_extrapolate_stride(const GstVideoFormatInfo *finfo, gint plane, gint stride);
+#endif
+
 std::shared_ptr<libcamera::CameraManager> gst_libcamera_get_camera_manager(int &ret);
 
 /**
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamerapad.cpp 0.6.0-2/src/gstreamer/gstlibcamerapad.cpp
--- 0.5.0-1/src/gstreamer/gstlibcamerapad.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamerapad.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -18,6 +18,8 @@ struct _GstLibcameraPad {
 	GstPad parent;
 	StreamRole role;
 	GstLibcameraPool *pool;
+	GstBufferPool *video_pool;
+	GstVideoInfo info;
 	GstClockTime latency;
 };
 
@@ -70,6 +72,10 @@ gst_libcamera_pad_query(GstPad *pad, Gst
 	if (query->type != GST_QUERY_LATENCY)
 		return gst_pad_query_default(pad, parent, query);
 
+	GLibLocker lock(GST_OBJECT(self));
+	if (self->latency == GST_CLOCK_TIME_NONE)
+		return FALSE;
+
 	/* TRUE here means live, we assumes that max latency is the same as min
 	 * as we have no idea that duration of frames. */
 	gst_query_set_latency(query, TRUE, self->latency, self->latency);
@@ -79,6 +85,7 @@ gst_libcamera_pad_query(GstPad *pad, Gst
 static void
 gst_libcamera_pad_init(GstLibcameraPad *self)
 {
+	self->latency = GST_CLOCK_TIME_NONE;
 	GST_PAD_QUERYFUNC(self) = gst_libcamera_pad_query;
 }
 
@@ -100,7 +107,7 @@ gst_libcamera_stream_role_get_type()
 			"libcamera::Viewfinder",
 			"view-finder",
 		},
-		{ 0, NULL, NULL }
+		{ 0, nullptr, nullptr }
 	};
 
 	if (!type)
@@ -153,15 +160,45 @@ gst_libcamera_pad_set_pool(GstPad *pad,
 	self->pool = pool;
 }
 
-Stream *
-gst_libcamera_pad_get_stream(GstPad *pad)
+GstBufferPool *
+gst_libcamera_pad_get_video_pool(GstPad *pad)
 {
 	auto *self = GST_LIBCAMERA_PAD(pad);
+	return self->video_pool;
+}
 
-	if (self->pool)
-		return gst_libcamera_pool_get_stream(self->pool);
+void gst_libcamera_pad_set_video_pool(GstPad *pad, GstBufferPool *video_pool)
+{
+	auto *self = GST_LIBCAMERA_PAD(pad);
+
+	if (self->video_pool)
+		g_object_unref(self->video_pool);
+	self->video_pool = video_pool;
+}
+
+GstVideoInfo gst_libcamera_pad_get_video_info(GstPad *pad)
+{
+	auto *self = GST_LIBCAMERA_PAD(pad);
+	return self->info;
+}
+
+void gst_libcamera_pad_set_video_info(GstPad *pad, const GstVideoInfo *info)
+{
+	auto *self = GST_LIBCAMERA_PAD(pad);
 
-	return nullptr;
+	self->info = *info;
+}
+
+Stream *
+gst_libcamera_pad_get_stream(GstPad *pad)
+{
+	return static_cast<Stream *>(gst_pad_get_element_private(pad));
+}
+
+void
+gst_libcamera_pad_set_stream(GstPad *pad, Stream *stream)
+{
+	gst_pad_set_element_private(pad, stream);
 }
 
 void
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamerapad.h 0.6.0-2/src/gstreamer/gstlibcamerapad.h
--- 0.5.0-1/src/gstreamer/gstlibcamerapad.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamerapad.h	2025-11-27 11:55:28.000000000 +0000
@@ -23,6 +23,16 @@ GstLibcameraPool *gst_libcamera_pad_get_
 
 void gst_libcamera_pad_set_pool(GstPad *pad, GstLibcameraPool *pool);
 
+GstBufferPool *gst_libcamera_pad_get_video_pool(GstPad *pad);
+
+void gst_libcamera_pad_set_video_pool(GstPad *pad, GstBufferPool *video_pool);
+
+GstVideoInfo gst_libcamera_pad_get_video_info(GstPad *pad);
+
+void gst_libcamera_pad_set_video_info(GstPad *pad, const GstVideoInfo *info);
+
 libcamera::Stream *gst_libcamera_pad_get_stream(GstPad *pad);
 
+void gst_libcamera_pad_set_stream(GstPad *pad, libcamera::Stream *stream);
+
 void gst_libcamera_pad_set_latency(GstPad *pad, GstClockTime latency);
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamerapool.cpp 0.6.0-2/src/gstreamer/gstlibcamerapool.cpp
--- 0.5.0-1/src/gstreamer/gstlibcamerapool.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamerapool.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -134,8 +134,20 @@ gst_libcamera_pool_class_init(GstLibcame
 						     G_TYPE_NONE, 0);
 }
 
+static void
+gst_libcamera_buffer_add_video_meta(GstBuffer *buffer, GstVideoInfo *info)
+{
+	GstVideoMeta *vmeta;
+	vmeta = gst_buffer_add_video_meta_full(buffer, GST_VIDEO_FRAME_FLAG_NONE,
+					       GST_VIDEO_INFO_FORMAT(info), GST_VIDEO_INFO_WIDTH(info),
+					       GST_VIDEO_INFO_HEIGHT(info), GST_VIDEO_INFO_N_PLANES(info),
+					       info->offset, info->stride);
+	GST_META_FLAGS(vmeta) = (GstMetaFlags)(GST_META_FLAGS(vmeta) | GST_META_FLAG_POOLED);
+}
+
 GstLibcameraPool *
-gst_libcamera_pool_new(GstLibcameraAllocator *allocator, Stream *stream)
+gst_libcamera_pool_new(GstLibcameraAllocator *allocator, Stream *stream,
+		       GstVideoInfo *info)
 {
 	auto *pool = GST_LIBCAMERA_POOL(g_object_new(GST_TYPE_LIBCAMERA_POOL, nullptr));
 
@@ -145,6 +157,7 @@ gst_libcamera_pool_new(GstLibcameraAlloc
 	gsize pool_size = gst_libcamera_allocator_get_pool_size(allocator, stream);
 	for (gsize i = 0; i < pool_size; i++) {
 		GstBuffer *buffer = gst_buffer_new();
+		gst_libcamera_buffer_add_video_meta(buffer, info);
 		pool->queue->push_back(buffer);
 	}
 
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamerapool.h 0.6.0-2/src/gstreamer/gstlibcamerapool.h
--- 0.5.0-1/src/gstreamer/gstlibcamerapool.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamerapool.h	2025-11-27 11:55:28.000000000 +0000
@@ -14,6 +14,7 @@
 #include "gstlibcameraallocator.h"
 
 #include <gst/gst.h>
+#include <gst/video/video.h>
 
 #include <libcamera/stream.h>
 
@@ -21,7 +22,7 @@
 G_DECLARE_FINAL_TYPE(GstLibcameraPool, gst_libcamera_pool, GST_LIBCAMERA, POOL, GstBufferPool)
 
 GstLibcameraPool *gst_libcamera_pool_new(GstLibcameraAllocator *allocator,
-					 libcamera::Stream *stream);
+					 libcamera::Stream *stream, GstVideoInfo *info);
 
 libcamera::Stream *gst_libcamera_pool_get_stream(GstLibcameraPool *self);
 
diff -pruN 0.5.0-1/src/gstreamer/gstlibcameraprovider.cpp 0.6.0-2/src/gstreamer/gstlibcameraprovider.cpp
--- 0.5.0-1/src/gstreamer/gstlibcameraprovider.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcameraprovider.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -12,6 +12,7 @@
 
 #include <libcamera/camera.h>
 #include <libcamera/camera_manager.h>
+#include <libcamera/property_ids.h>
 
 #include "gstlibcamerasrc.h"
 #include "gstlibcamera-utils.h"
@@ -144,12 +145,24 @@ gst_libcamera_device_new(const std::shar
 			gst_caps_append(caps, sub_caps);
 	}
 
+	g_autoptr(GstStructure) props = gst_structure_new_empty("camera-properties");
+	for (const auto &[key, value] : camera->properties()) {
+		const ControlId *id = properties::properties.at(key);
+
+		int ret = gst_libcamera_set_structure_field(props, id, value);
+		if (ret < 0) {
+			GST_ERROR("Failed to retrieve value for %s property", id->name().c_str());
+			return nullptr;
+		}
+	}
+
 	return GST_DEVICE(g_object_new(GST_TYPE_LIBCAMERA_DEVICE,
 				       /* \todo Use a unique identifier instead of camera name. */
 				       "name", name,
 				       "display-name", name,
 				       "caps", caps,
 				       "device-class", "Source/Video",
+				       "properties", props,
 				       nullptr));
 }
 
diff -pruN 0.5.0-1/src/gstreamer/gstlibcamerasrc.cpp 0.6.0-2/src/gstreamer/gstlibcamerasrc.cpp
--- 0.5.0-1/src/gstreamer/gstlibcamerasrc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/gstlibcamerasrc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -11,24 +11,20 @@
  *  - Implement GstElement::send_event
  *    + Allowing application to use FLUSH/FLUSH_STOP
  *    + Prevent the main thread from accessing streaming thread
- *  - Implement GstElement::request-new-pad (multi stream)
- *    + Evaluate if a single streaming thread is fine
  *  - Add application driven request (snapshot)
- *  - Add framerate control
  *  - Add buffer importation support
+ *    + Evaluate the feasibility of memory:DMAbuf support
  *
  *  Requires new libcamera API:
- *  - Add framerate negotiation support
- *  - Add colorimetry support
  *  - Add timestamp support
- *  - Use unique names to select the camera devices
- *  - Add GstVideoMeta support (strides and offsets)
  */
 
 #include "gstlibcamerasrc.h"
 
 #include <atomic>
 #include <queue>
+#include <tuple>
+#include <utility>
 #include <vector>
 
 #include <libcamera/camera.h>
@@ -52,11 +48,11 @@ struct RequestWrap {
 	RequestWrap(std::unique_ptr<Request> request);
 	~RequestWrap();
 
-	void attachBuffer(Stream *stream, GstBuffer *buffer);
-	GstBuffer *detachBuffer(Stream *stream);
+	void attachBuffer(GstPad *srcpad, GstBuffer *buffer);
+	GstBuffer *detachBuffer(GstPad *srcpad);
 
 	std::unique_ptr<Request> request_;
-	std::map<Stream *, GstBuffer *> buffers_;
+	std::map<GstPad *, GstBuffer *> buffers_;
 
 	GstClockTime latency_;
 	GstClockTime pts_;
@@ -69,32 +65,33 @@ RequestWrap::RequestWrap(std::unique_ptr
 
 RequestWrap::~RequestWrap()
 {
-	for (std::pair<Stream *const, GstBuffer *> &item : buffers_) {
+	for (std::pair<GstPad *const, GstBuffer *> &item : buffers_) {
 		if (item.second)
 			gst_buffer_unref(item.second);
 	}
 }
 
-void RequestWrap::attachBuffer(Stream *stream, GstBuffer *buffer)
+void RequestWrap::attachBuffer(GstPad *srcpad, GstBuffer *buffer)
 {
 	FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer);
+	Stream *stream = gst_libcamera_pad_get_stream(srcpad);
 
 	request_->addBuffer(stream, fb);
 
-	auto item = buffers_.find(stream);
+	auto item = buffers_.find(srcpad);
 	if (item != buffers_.end()) {
 		gst_buffer_unref(item->second);
 		item->second = buffer;
 	} else {
-		buffers_[stream] = buffer;
+		buffers_[srcpad] = buffer;
 	}
 }
 
-GstBuffer *RequestWrap::detachBuffer(Stream *stream)
+GstBuffer *RequestWrap::detachBuffer(GstPad *srcpad)
 {
 	GstBuffer *buffer = nullptr;
 
-	auto item = buffers_.find(stream);
+	auto item = buffers_.find(srcpad);
 	if (item != buffers_.end()) {
 		buffer = item->second;
 		item->second = nullptr;
@@ -193,7 +190,6 @@ int GstLibcameraSrcState::queueRequest()
 		std::make_unique<RequestWrap>(std::move(request));
 
 	for (GstPad *srcpad : srcpads_) {
-		Stream *stream = gst_libcamera_pad_get_stream(srcpad);
 		GstLibcameraPool *pool = gst_libcamera_pad_get_pool(srcpad);
 		GstBuffer *buffer;
 		GstFlowReturn ret;
@@ -208,7 +204,7 @@ int GstLibcameraSrcState::queueRequest()
 			return -ENOBUFS;
 		}
 
-		wrap->attachBuffer(stream, buffer);
+		wrap->attachBuffer(srcpad, buffer);
 	}
 
 	GST_TRACE_OBJECT(src_, "Requesting buffers");
@@ -268,6 +264,69 @@ GstLibcameraSrcState::requestCompleted(R
 	gst_task_resume(src_->task);
 }
 
+static void
+gst_libcamera_extrapolate_info(GstVideoInfo *info, guint32 stride)
+{
+	guint i, estride;
+	gsize offset = 0;
+
+	/* This should be updated if tiled formats get added in the future. */
+	for (i = 0; i < GST_VIDEO_INFO_N_PLANES(info); i++) {
+		estride = gst_video_format_info_extrapolate_stride(info->finfo, i, stride);
+		info->stride[i] = estride;
+		info->offset[i] = offset;
+		offset += estride * GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT(info->finfo, i,
+								       GST_VIDEO_INFO_HEIGHT(info));
+	}
+}
+
+static GstFlowReturn
+gst_libcamera_video_frame_copy(GstBuffer *src, GstBuffer *dest,
+			       const GstVideoInfo *dest_info, guint32 stride)
+{
+	/*
+	 * When dropping support for versions earlier than v1.22.0, use
+	 *
+	 * g_auto (GstVideoFrame) src_frame = GST_VIDEO_FRAME_INIT;
+	 * g_auto (GstVideoFrame) dest_frame = GST_VIDEO_FRAME_INIT;
+	 *
+	 * and drop the gst_video_frame_unmap() calls.
+	 */
+	GstVideoFrame src_frame, dest_frame;
+	GstVideoInfo src_info = *dest_info;
+
+	gst_libcamera_extrapolate_info(&src_info, stride);
+	src_info.size = gst_buffer_get_size(src);
+
+	if (!gst_video_frame_map(&src_frame, &src_info, src, GST_MAP_READ)) {
+		GST_ERROR("Could not map src buffer");
+		return GST_FLOW_ERROR;
+	}
+
+	/*
+	 * When dropping support for versions earlier than 1.20.0, drop the
+	 * const_cast<>().
+	 */
+	if (!gst_video_frame_map(&dest_frame, const_cast<GstVideoInfo *>(dest_info),
+				 dest, GST_MAP_WRITE)) {
+		GST_ERROR("Could not map dest buffer");
+		gst_video_frame_unmap(&src_frame);
+		return GST_FLOW_ERROR;
+	}
+
+	if (!gst_video_frame_copy(&dest_frame, &src_frame)) {
+		GST_ERROR("Could not copy frame");
+		gst_video_frame_unmap(&src_frame);
+		gst_video_frame_unmap(&dest_frame);
+		return GST_FLOW_ERROR;
+	}
+
+	gst_video_frame_unmap(&src_frame);
+	gst_video_frame_unmap(&dest_frame);
+
+	return GST_FLOW_OK;
+}
+
 /* Must be called with stream_lock held. */
 int GstLibcameraSrcState::processRequest()
 {
@@ -292,11 +351,41 @@ int GstLibcameraSrcState::processRequest
 	GstFlowReturn ret = GST_FLOW_OK;
 	gst_flow_combiner_reset(src_->flow_combiner);
 
-	for (GstPad *srcpad : srcpads_) {
+	for (gsize i = 0; i < srcpads_.size(); i++) {
+		GstPad *srcpad = srcpads_[i];
 		Stream *stream = gst_libcamera_pad_get_stream(srcpad);
-		GstBuffer *buffer = wrap->detachBuffer(stream);
+		GstBuffer *buffer = wrap->detachBuffer(srcpad);
 
 		FrameBuffer *fb = gst_libcamera_buffer_get_frame_buffer(buffer);
+		const StreamConfiguration &stream_cfg = stream->configuration();
+		GstBufferPool *video_pool = gst_libcamera_pad_get_video_pool(srcpad);
+
+		if (video_pool) {
+			/* Only set video pool when a copy is needed. */
+			GstBuffer *copy = nullptr;
+			const GstVideoInfo info = gst_libcamera_pad_get_video_info(srcpad);
+
+			ret = gst_buffer_pool_acquire_buffer(video_pool, &copy, nullptr);
+			if (ret != GST_FLOW_OK) {
+				gst_buffer_unref(buffer);
+				GST_ELEMENT_ERROR(src_, RESOURCE, SETTINGS,
+						  ("Failed to acquire buffer"),
+						  ("GstLibcameraSrcState::processRequest() failed: %s", g_strerror(-ret)));
+				return -EPIPE;
+			}
+
+			ret = gst_libcamera_video_frame_copy(buffer, copy, &info, stream_cfg.stride);
+			gst_buffer_unref(buffer);
+			if (ret != GST_FLOW_OK) {
+				gst_buffer_unref(copy);
+				GST_ELEMENT_ERROR(src_, RESOURCE, SETTINGS,
+						  ("Failed to copy buffer"),
+						  ("GstLibcameraSrcState::processRequest() failed: %s", g_strerror(-ret)));
+				return -EPIPE;
+			}
+
+			buffer = copy;
+		}
 
 		if (GST_CLOCK_TIME_IS_VALID(wrap->pts_)) {
 			GST_BUFFER_PTS(buffer) = wrap->pts_;
@@ -428,6 +517,69 @@ gst_libcamera_src_open(GstLibcameraSrc *
 	return true;
 }
 
+/**
+ * \brief Create a video pool for a pad
+ * \param[in] self The libcamerasrc instance
+ * \param[in] srcpad The pad
+ * \param[in] caps The pad caps
+ * \param[in] info The video info for the pad
+ *
+ * This function creates and returns a video buffer pool for the given pad if
+ * needed to accommodate stride mismatch. If the peer element supports stride
+ * negotiation through the meta API, no pool is needed and the function will
+ * return a null pool.
+ *
+ * \return A tuple containing the video buffers pool pointer and an error code
+ */
+static std::tuple<GstBufferPool *, int>
+gst_libcamera_create_video_pool(GstLibcameraSrc *self, GstPad *srcpad,
+				GstCaps *caps, const GstVideoInfo *info)
+{
+	g_autoptr(GstQuery) query = nullptr;
+	g_autoptr(GstBufferPool) pool = nullptr;
+	const gboolean need_pool = true;
+
+	/*
+	 * Get the peer allocation hints to check if it supports the meta API.
+	 * If so, the stride will be negotiated, and there's no need to create a
+	 * video pool.
+	 */
+	query = gst_query_new_allocation(caps, need_pool);
+
+	if (!gst_pad_peer_query(srcpad, query))
+		GST_DEBUG_OBJECT(self, "Didn't get downstream ALLOCATION hints");
+	else if (gst_query_find_allocation_meta(query, GST_VIDEO_META_API_TYPE, nullptr))
+		return { nullptr, 0 };
+
+	GST_WARNING_OBJECT(self, "Downstream doesn't support video meta, need to copy frame.");
+
+	/*
+	 * If the allocation query has pools, use the first one. Otherwise,
+	 * create a new pool.
+	 */
+	if (gst_query_get_n_allocation_pools(query) > 0)
+		gst_query_parse_nth_allocation_pool(query, 0, &pool, nullptr,
+						    nullptr, nullptr);
+
+	if (!pool) {
+		GstStructure *config;
+		guint min_buffers = 3;
+
+		pool = gst_video_buffer_pool_new();
+		config = gst_buffer_pool_get_config(pool);
+		gst_buffer_pool_config_set_params(config, caps, info->size, min_buffers, 0);
+
+		GST_DEBUG_OBJECT(self, "Own pool config is %" GST_PTR_FORMAT, config);
+
+		gst_buffer_pool_set_config(GST_BUFFER_POOL_CAST(pool), config);
+	}
+
+	if (!gst_buffer_pool_set_active(pool, true))
+		return { nullptr, -EINVAL };
+
+	return { std::exchange(pool, nullptr), 0 };
+}
+
 /* Must be called with stream_lock held. */
 static bool
 gst_libcamera_src_negotiate(GstLibcameraSrc *self)
@@ -455,8 +607,13 @@ gst_libcamera_src_negotiate(GstLibcamera
 	}
 
 	/* Validate the configuration. */
-	if (state->config_->validate() == CameraConfiguration::Invalid)
+	CameraConfiguration::Status status = state->config_->validate();
+	if (status == CameraConfiguration::Invalid)
 		return false;
+	else if (status == CameraConfiguration::Adjusted)
+		GST_ELEMENT_INFO(self, RESOURCE, SETTINGS,
+				 ("Configuration was adjusted"),
+				 ("CameraConfiguration::validate() returned CameraConfiguration::Adjusted"));
 
 	int ret = state->cam_->configure(state->config_.get());
 	if (ret) {
@@ -481,6 +638,10 @@ gst_libcamera_src_negotiate(GstLibcamera
 		g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg, transfer[i]);
 		gst_libcamera_framerate_to_caps(caps, element_caps);
 
+		if (status == CameraConfiguration::Adjusted &&
+		    !gst_pad_peer_query_accept_caps(srcpad, caps))
+			return false;
+
 		if (!gst_pad_push_event(srcpad, gst_event_new_caps(caps)))
 			return false;
 	}
@@ -499,13 +660,40 @@ gst_libcamera_src_negotiate(GstLibcamera
 	for (gsize i = 0; i < state->srcpads_.size(); i++) {
 		GstPad *srcpad = state->srcpads_[i];
 		const StreamConfiguration &stream_cfg = state->config_->at(i);
+		GstBufferPool *video_pool = nullptr;
+		GstVideoInfo info;
+
+		g_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg, transfer[i]);
+
+		gst_video_info_from_caps(&info, caps);
+		gst_libcamera_pad_set_video_info(srcpad, &info);
+
+		/* Stride mismatch between camera stride and that calculated by video-info. */
+		if (static_cast<unsigned int>(info.stride[0]) != stream_cfg.stride &&
+		    GST_VIDEO_INFO_FORMAT(&info) != GST_VIDEO_FORMAT_ENCODED) {
+			gst_libcamera_extrapolate_info(&info, stream_cfg.stride);
+
+			std::tie(video_pool, ret) =
+				gst_libcamera_create_video_pool(self, srcpad,
+								caps, &info);
+			if (ret) {
+				GST_ELEMENT_ERROR(self, RESOURCE, SETTINGS,
+						  ("Failed to create video pool: %s", g_strerror(-ret)),
+						  ("gst_libcamera_src_negotiate() failed."));
+				return false;
+			}
+		}
 
 		GstLibcameraPool *pool = gst_libcamera_pool_new(self->allocator,
-								stream_cfg.stream());
+								stream_cfg.stream(), &info);
 		g_signal_connect_swapped(pool, "buffer-notify",
 					 G_CALLBACK(gst_task_resume), self->task);
 
 		gst_libcamera_pad_set_pool(srcpad, pool);
+		gst_libcamera_pad_set_video_pool(srcpad, video_pool);
+
+		/* Associate the configured stream with the source pad. */
+		gst_libcamera_pad_set_stream(srcpad, stream_cfg.stream());
 
 		/* Clear all reconfigure flags. */
 		gst_pad_check_reconfigure(srcpad);
@@ -548,7 +736,8 @@ gst_libcamera_src_task_run(gpointer user
 		if (gst_pad_check_reconfigure(srcpad)) {
 			/* Check if the caps even need changing. */
 			g_autoptr(GstCaps) caps = gst_pad_get_current_caps(srcpad);
-			if (!gst_pad_peer_query_accept_caps(srcpad, caps)) {
+			g_autoptr(GstCaps) peercaps = gst_pad_peer_query_caps(srcpad, caps);
+			if (gst_caps_is_empty(peercaps)) {
 				reconfigure = true;
 				break;
 			}
@@ -699,8 +888,11 @@ gst_libcamera_src_task_leave([[maybe_unu
 
 	{
 		GLibRecLocker locker(&self->stream_lock);
-		for (GstPad *srcpad : state->srcpads_)
+		for (GstPad *srcpad : state->srcpads_) {
+			gst_libcamera_pad_set_latency(srcpad, GST_CLOCK_TIME_NONE);
 			gst_libcamera_pad_set_pool(srcpad, nullptr);
+			gst_libcamera_pad_set_stream(srcpad, nullptr);
+		}
 	}
 
 	g_clear_object(&self->allocator);
@@ -884,7 +1076,7 @@ gst_libcamera_src_request_new_pad(GstEle
 				  const gchar *name, [[maybe_unused]] const GstCaps *caps)
 {
 	GstLibcameraSrc *self = GST_LIBCAMERA_SRC(element);
-	g_autoptr(GstPad) pad = NULL;
+	g_autoptr(GstPad) pad = nullptr;
 
 	GST_DEBUG_OBJECT(self, "new request pad created");
 
@@ -898,12 +1090,12 @@ gst_libcamera_src_request_new_pad(GstEle
 		GST_ELEMENT_ERROR(element, STREAM, FAILED,
 				  ("Internal data stream error."),
 				  ("Could not add pad to element"));
-		return NULL;
+		return nullptr;
 	}
 
 	gst_child_proxy_child_added(GST_CHILD_PROXY(self), G_OBJECT(pad), GST_OBJECT_NAME(pad));
 
-	return reinterpret_cast<GstPad *>(g_steal_pointer(&pad));
+	return std::exchange(pad, nullptr);
 }
 
 static void
@@ -922,6 +1114,12 @@ gst_libcamera_src_release_pad(GstElement
 		auto end_iterator = pads.end();
 		auto pad_iterator = std::find(begin_iterator, end_iterator, pad);
 
+		GstBufferPool *video_pool = gst_libcamera_pad_get_video_pool(pad);
+		if (video_pool) {
+			gst_buffer_pool_set_active(video_pool, false);
+			gst_object_unref(video_pool);
+		}
+
 		if (pad_iterator != end_iterator) {
 			g_object_unref(*pad_iterator);
 			pads.erase(pad_iterator);
diff -pruN 0.5.0-1/src/gstreamer/meson.build 0.6.0-2/src/gstreamer/meson.build
--- 0.5.0-1/src/gstreamer/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/gstreamer/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -33,6 +33,7 @@ libcamera_gst_sources += custom_target('
                                        output : 'gstlibcamera-controls.cpp',
                                        command : [gen_gst_controls, '-o', '@OUTPUT@',
                                                   '-t', gen_gst_controls_template, '@INPUT@'],
+                                       depend_files : [py_mod_controls],
                                        env : py_build_env)
 
 libcamera_gst_cpp_args = [
diff -pruN 0.5.0-1/src/ipa/ipu3/algorithms/agc.cpp 0.6.0-2/src/ipa/ipu3/algorithms/agc.cpp
--- 0.5.0-1/src/ipa/ipu3/algorithms/agc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/ipu3/algorithms/agc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -117,7 +117,7 @@ int Agc::configure(IPAContext &context,
 
 	/* \todo Run this again when FrameDurationLimits is passed in */
 	setLimits(minExposureTime_, maxExposureTime_, minAnalogueGain_,
-		  maxAnalogueGain_);
+		  maxAnalogueGain_, {});
 	resetFrameCount();
 
 	return 0;
@@ -222,8 +222,8 @@ void Agc::process(IPAContext &context, [
 	utils::Duration effectiveExposureValue = exposureTime * analogueGain;
 
 	utils::Duration newExposureTime;
-	double aGain, dGain;
-	std::tie(newExposureTime, aGain, dGain) =
+	double aGain, qGain, dGain;
+	std::tie(newExposureTime, aGain, qGain, dGain) =
 		calculateNewEv(context.activeState.agc.constraintMode,
 			       context.activeState.agc.exposureMode, hist,
 			       effectiveExposureValue);
diff -pruN 0.5.0-1/src/ipa/ipu3/ipu3.cpp 0.6.0-2/src/ipa/ipu3/ipu3.cpp
--- 0.5.0-1/src/ipa/ipu3/ipu3.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/ipu3/ipu3.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -20,6 +20,7 @@
 
 #include <libcamera/base/file.h>
 #include <libcamera/base/log.h>
+#include <libcamera/base/span.h>
 #include <libcamera/base/utils.h>
 
 #include <libcamera/control_ids.h>
@@ -280,10 +281,9 @@ void IPAIPU3::updateControls(const IPACa
 		uint64_t frameSize = lineLength * frameHeights[i];
 		frameDurations[i] = frameSize / (sensorInfo.pixelRate / 1000000U);
 	}
-
 	controls[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],
 							       frameDurations[1],
-							       frameDurations[2]);
+							       Span<const int64_t, 2>{ { frameDurations[2], frameDurations[2] } });
 
 	controls.merge(context_.ctrlMap);
 	*ipaControls = ControlInfoMap(std::move(controls), controls::controls);
diff -pruN 0.5.0-1/src/ipa/libipa/agc_mean_luminance.cpp 0.6.0-2/src/ipa/libipa/agc_mean_luminance.cpp
--- 0.5.0-1/src/ipa/libipa/agc_mean_luminance.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/agc_mean_luminance.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,7 @@
 
 #include "agc_mean_luminance.h"
 
+#include <algorithm>
 #include <cmath>
 
 #include <libcamera/base/log.h>
@@ -44,6 +45,23 @@ static constexpr uint32_t kNumStartupFra
  */
 static constexpr double kDefaultRelativeLuminanceTarget = 0.16;
 
+/*
+ * Maximum relative luminance target
+ *
+ * This value limits the relative luminance target after applying the exposure
+ * compensation. Targeting a value above this limit results in saturation
+ * and the inability to regulate properly.
+ */
+static constexpr double kMaxRelativeLuminanceTarget = 0.95;
+
+/*
+ * Default lux level
+ *
+ * If no lux level or a zero lux level is specified, but PWLs are used to
+ * specify luminance targets, this default level is used.
+ */
+static constexpr unsigned int kDefaultLuxLevel = 500;
+
 /**
  * \struct AgcMeanLuminance::AgcConstraint
  * \brief The boundaries and target for an AeConstraintMode constraint
@@ -134,19 +152,33 @@ static constexpr double kDefaultRelative
  */
 
 AgcMeanLuminance::AgcMeanLuminance()
-	: frameCount_(0), filteredExposure_(0s), relativeLuminanceTarget_(0)
+	: filteredExposure_(0s), luxWarningEnabled_(true),
+	  exposureCompensation_(1.0), frameCount_(0), lux_(0)
 {
 }
 
 AgcMeanLuminance::~AgcMeanLuminance() = default;
 
-void AgcMeanLuminance::parseRelativeLuminanceTarget(const YamlObject &tuningData)
+int AgcMeanLuminance::parseRelativeLuminanceTarget(const YamlObject &tuningData)
 {
-	relativeLuminanceTarget_ =
-		tuningData["relativeLuminanceTarget"].get<double>(kDefaultRelativeLuminanceTarget);
+	auto &target = tuningData["relativeLuminanceTarget"];
+	if (!target) {
+		relativeLuminanceTarget_ = { { { { 0.0, kDefaultRelativeLuminanceTarget } } } };
+		return 0;
+	}
+
+	auto pwl = target.get<Pwl>();
+	if (!pwl) {
+		LOG(AgcMeanLuminance, Error)
+			<< "Failed to load relative luminance target.";
+		return -EINVAL;
+	}
+
+	relativeLuminanceTarget_ = std::move(*pwl);
+	return 0;
 }
 
-void AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)
+int AgcMeanLuminance::parseConstraint(const YamlObject &modeDict, int32_t id)
 {
 	for (const auto &[boundName, content] : modeDict.asDict()) {
 		if (boundName != "upper" && boundName != "lower") {
@@ -159,10 +191,14 @@ void AgcMeanLuminance::parseConstraint(c
 		AgcConstraint::Bound bound = static_cast<AgcConstraint::Bound>(idx);
 		double qLo = content["qLo"].get<double>().value_or(0.98);
 		double qHi = content["qHi"].get<double>().value_or(1.0);
-		double yTarget =
-			content["yTarget"].getList<double>().value_or(std::vector<double>{ 0.5 }).at(0);
+		auto yTarget = content["yTarget"].get<Pwl>();
+		if (!yTarget) {
+			LOG(AgcMeanLuminance, Error)
+				<< "Failed to parse yTarget";
+			return -EINVAL;
+		}
 
-		AgcConstraint constraint = { bound, qLo, qHi, yTarget };
+		AgcConstraint constraint = { bound, qLo, qHi, std::move(*yTarget) };
 
 		if (!constraintModes_.count(id))
 			constraintModes_[id] = {};
@@ -172,6 +208,8 @@ void AgcMeanLuminance::parseConstraint(c
 		else
 			constraintModes_[id].insert(constraintModes_[id].begin(), constraint);
 	}
+
+	return 0;
 }
 
 int AgcMeanLuminance::parseConstraintModes(const YamlObject &tuningData)
@@ -194,8 +232,11 @@ int AgcMeanLuminance::parseConstraintMod
 				return -EINVAL;
 			}
 
-			parseConstraint(modeDict,
-					AeConstraintModeNameValueMap.at(modeName));
+			int ret = parseConstraint(modeDict,
+						  AeConstraintModeNameValueMap.at(modeName));
+			if (ret)
+				return ret;
+
 			availableConstraintModes.push_back(
 				AeConstraintModeNameValueMap.at(modeName));
 		}
@@ -212,14 +253,13 @@ int AgcMeanLuminance::parseConstraintMod
 			AgcConstraint::Bound::Lower,
 			0.98,
 			1.0,
-			0.5
+			Pwl({ { { 0.0, 0.5 } } })
 		};
 
 		constraintModes_[controls::ConstraintNormal].insert(
 			constraintModes_[controls::ConstraintNormal].begin(),
 			constraint);
-		availableConstraintModes.push_back(
-			AeConstraintModeNameValueMap.at("ConstraintNormal"));
+		availableConstraintModes.push_back(controls::ConstraintNormal);
 	}
 
 	controls_[&controls::AeConstraintMode] = ControlInfo(availableConstraintModes);
@@ -287,7 +327,7 @@ int AgcMeanLuminance::parseExposureModes
 	 * possible before touching gain.
 	 */
 	if (availableExposureModes.empty()) {
-		int32_t exposureModeId = AeExposureModeNameValueMap.at("ExposureNormal");
+		int32_t exposureModeId = controls::ExposureNormal;
 		std::vector<std::pair<utils::Duration, double>> stages = { };
 
 		std::shared_ptr<ExposureModeHelper> helper =
@@ -303,6 +343,23 @@ int AgcMeanLuminance::parseExposureModes
 }
 
 /**
+ * \brief Configure the exposure mode helpers
+ * \param[in] lineDuration The sensor line length
+ * \param[in] sensorHelper The sensor helper
+ *
+ * This function configures the exposure mode helpers so they can correctly
+ * take quantization effects into account.
+ */
+void AgcMeanLuminance::configure(utils::Duration lineDuration,
+				 const CameraSensorHelper *sensorHelper)
+{
+	for (auto &[id, helper] : exposureModeHelpers_)
+		helper->configure(lineDuration, sensorHelper);
+
+	luxWarningEnabled_ = true;
+}
+
+/**
  * \brief Parse tuning data for AeConstraintMode and AeExposureMode controls
  * \param[in] tuningData the YamlObject representing the tuning data
  *
@@ -311,8 +368,9 @@ int AgcMeanLuminance::parseExposureModes
  * the data in a specific format; the Agc algorithm's tuning data should contain
  * a dictionary called AeConstraintMode containing per-mode setting dictionaries
  * with the key being a value from \ref controls::AeConstraintModeNameValueMap.
- * Each mode dict may contain either a "lower" or "upper" key or both, for
- * example:
+ * The yTarget can either be provided as single value or as array in which case
+ * it is interpreted as a PWL mapping lux levels to yTarget values. Each mode
+ * dict may contain either a "lower" or "upper" key or both, for example:
  *
  * \code{.unparsed}
  * algorithms:
@@ -331,7 +389,7 @@ int AgcMeanLuminance::parseExposureModes
  *           upper:
  *             qLo: 0.98
  *             qHi: 1.0
- *             yTarget: 0.8
+ *             yTarget: [ 100, 0.8, 20000, 0.5 ]
  *
  * \endcode
  *
@@ -360,7 +418,9 @@ int AgcMeanLuminance::parseTuningData(co
 {
 	int ret;
 
-	parseRelativeLuminanceTarget(tuningData);
+	ret = parseRelativeLuminanceTarget(tuningData);
+	if (ret)
+		return ret;
 
 	ret = parseConstraintModes(tuningData);
 	if (ret)
@@ -370,21 +430,44 @@ int AgcMeanLuminance::parseTuningData(co
 }
 
 /**
+ * \fn AgcMeanLuminance::setExposureCompensation()
+ * \brief Set the exposure compensation value
+ * \param[in] gain The exposure compensation gain
+ *
+ * This function sets the exposure compensation value to be used in the
+ * AGC calculations. It is expressed as gain instead of EV.
+ */
+
+/**
+ * \fn AgcMeanLuminance::setLux(int lux)
+ * \brief Set the lux level
+ * \param[in] lux The lux level
+ *
+ * This function sets the lux level to be used in the AGC calculations. A value
+ * of 0 means no measurement and a default value of \a kDefaultLuxLevel is used
+ * if necessary.
+ */
+
+/**
  * \brief Set the ExposureModeHelper limits for this class
  * \param[in] minExposureTime Minimum exposure time to allow
  * \param[in] maxExposureTime Maximum ewposure time to allow
  * \param[in] minGain Minimum gain to allow
  * \param[in] maxGain Maximum gain to allow
+ * \param[in] constraints Additional constraints to apply
  *
  * This function calls \ref ExposureModeHelper::setLimits() for each
  * ExposureModeHelper that has been created for this class.
  */
 void AgcMeanLuminance::setLimits(utils::Duration minExposureTime,
 				 utils::Duration maxExposureTime,
-				 double minGain, double maxGain)
+				 double minGain, double maxGain,
+				 std::vector<AgcMeanLuminance::AgcConstraint> constraints)
 {
 	for (auto &[id, helper] : exposureModeHelpers_)
 		helper->setLimits(minExposureTime, maxExposureTime, minGain, maxGain);
+
+	additionalConstraints_ = std::move(constraints);
 }
 
 /**
@@ -425,7 +508,7 @@ void AgcMeanLuminance::setLimits(utils::
  */
 double AgcMeanLuminance::estimateInitialGain() const
 {
-	double yTarget = relativeLuminanceTarget_;
+	double yTarget = effectiveYTarget();
 	double yGain = 1.0;
 
 	/*
@@ -462,24 +545,81 @@ double AgcMeanLuminance::constraintClamp
 					     const Histogram &hist,
 					     double gain)
 {
-	std::vector<AgcConstraint> &constraints = constraintModes_[constraintModeIndex];
-	for (const AgcConstraint &constraint : constraints) {
-		double newGain = constraint.yTarget * hist.bins() /
+	auto applyConstraint = [this, &gain, &hist](const AgcConstraint &constraint) {
+		double lux = lux_;
+
+		if (relativeLuminanceTarget_.size() > 1 && lux_ == 0)
+			lux = kDefaultLuxLevel;
+
+		double target = constraint.yTarget.eval(
+			constraint.yTarget.domain().clamp(lux));
+		double newGain = target * hist.bins() /
 				 hist.interQuantileMean(constraint.qLo, constraint.qHi);
 
 		if (constraint.bound == AgcConstraint::Bound::Lower &&
-		    newGain > gain)
+		    newGain > gain) {
+			LOG(AgcMeanLuminance, Debug)
+				<< "Apply lower bound: " << gain << " to "
+				<< newGain;
 			gain = newGain;
+		}
 
 		if (constraint.bound == AgcConstraint::Bound::Upper &&
-		    newGain < gain)
+		    newGain < gain) {
+			LOG(AgcMeanLuminance, Debug)
+				<< "Apply upper bound: " << gain << " to "
+				<< newGain;
 			gain = newGain;
-	}
+		}
+	};
+
+	std::vector<AgcConstraint> &constraints = constraintModes_[constraintModeIndex];
+	std::for_each(constraints.begin(), constraints.end(), applyConstraint);
+
+	std::for_each(additionalConstraints_.begin(), additionalConstraints_.end(), applyConstraint);
 
 	return gain;
 }
 
 /**
+ * \brief Get the currently effective y target
+ *
+ * This function returns the current y target including exposure compensation.
+ *
+ * \return The y target value
+ */
+double AgcMeanLuminance::effectiveYTarget() const
+{
+	double lux = lux_;
+	if (relativeLuminanceTarget_.size() > 1 && lux_ == 0) {
+		/*
+		 * Warn after a few frames if there is still no lux measurement
+		 * available. The number of 10 is chosen a bit arbitrarily. It
+		 * is big enough to skip the frames that get queued on start
+		 * (and therefore are expected to have no valid lux value) and
+		 * small enough to show up quickly.
+		 */
+		if (frameCount_ > 10 && luxWarningEnabled_) {
+			luxWarningEnabled_ = false;
+			LOG(AgcMeanLuminance, Warning)
+				<< "Missing lux value for luminance target "
+				   "calculation, default to "
+				<< kDefaultLuxLevel
+				<< ". Note that the Lux algorithm must be "
+				   "included before the Agc algorithm.";
+		}
+
+		lux = kDefaultLuxLevel;
+	}
+
+	double luminanceTarget = relativeLuminanceTarget_.eval(
+		relativeLuminanceTarget_.domain().clamp(lux));
+
+	return std::min(luminanceTarget * exposureCompensation_,
+			kMaxRelativeLuminanceTarget);
+}
+
+/**
  * \brief Apply a filter on the exposure value to limit the speed of changes
  * \param[in] exposureValue The target exposure from the AGC algorithm
  *
@@ -524,11 +664,12 @@ utils::Duration AgcMeanLuminance::filter
  *
  * Calculate a new exposure value to try to obtain the target. The calculated
  * exposure value is filtered to prevent rapid changes from frame to frame, and
- * divided into exposure time, analogue and digital gain.
+ * divided into exposure time, analogue, quantization and digital gain.
  *
- * \return Tuple of exposure time, analogue gain, and digital gain
+ * \return Tuple of exposure time, analogue gain, quantization gain and digital
+ * gain
  */
-std::tuple<utils::Duration, double, double>
+std::tuple<utils::Duration, double, double, double>
 AgcMeanLuminance::calculateNewEv(uint32_t constraintModeIndex,
 				 uint32_t exposureModeIndex,
 				 const Histogram &yHist,
diff -pruN 0.5.0-1/src/ipa/libipa/agc_mean_luminance.h 0.6.0-2/src/ipa/libipa/agc_mean_luminance.h
--- 0.5.0-1/src/ipa/libipa/agc_mean_luminance.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/agc_mean_luminance.h	2025-11-27 11:55:28.000000000 +0000
@@ -20,6 +20,7 @@
 
 #include "exposure_mode_helper.h"
 #include "histogram.h"
+#include "pwl.h"
 
 namespace libcamera {
 
@@ -39,20 +40,31 @@ public:
 		Bound bound;
 		double qLo;
 		double qHi;
-		double yTarget;
+		Pwl yTarget;
 	};
 
+	void configure(utils::Duration lineDuration, const CameraSensorHelper *sensorHelper);
 	int parseTuningData(const YamlObject &tuningData);
 
+	void setExposureCompensation(double gain)
+	{
+		exposureCompensation_ = gain;
+	}
+
+	void setLux(unsigned int lux)
+	{
+		lux_ = lux;
+	}
+
 	void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
-		       double minGain, double maxGain);
+		       double minGain, double maxGain, std::vector<AgcConstraint> constraints);
 
-	std::map<int32_t, std::vector<AgcConstraint>> constraintModes()
+	const std::map<int32_t, std::vector<AgcConstraint>> &constraintModes() const
 	{
 		return constraintModes_;
 	}
 
-	std::map<int32_t, std::shared_ptr<ExposureModeHelper>> exposureModeHelpers()
+	const std::map<int32_t, std::shared_ptr<ExposureModeHelper>> &exposureModeHelpers() const
 	{
 		return exposureModeHelpers_;
 	}
@@ -62,10 +74,12 @@ public:
 		return controls_;
 	}
 
-	std::tuple<utils::Duration, double, double>
+	std::tuple<utils::Duration, double, double, double>
 	calculateNewEv(uint32_t constraintModeIndex, uint32_t exposureModeIndex,
 		       const Histogram &yHist, utils::Duration effectiveExposureValue);
 
+	double effectiveYTarget() const;
+
 	void resetFrameCount()
 	{
 		frameCount_ = 0;
@@ -74,8 +88,8 @@ public:
 private:
 	virtual double estimateLuminance(const double gain) const = 0;
 
-	void parseRelativeLuminanceTarget(const YamlObject &tuningData);
-	void parseConstraint(const YamlObject &modeDict, int32_t id);
+	int parseRelativeLuminanceTarget(const YamlObject &tuningData);
+	int parseConstraint(const YamlObject &modeDict, int32_t id);
 	int parseConstraintModes(const YamlObject &tuningData);
 	int parseExposureModes(const YamlObject &tuningData);
 	double estimateInitialGain() const;
@@ -84,10 +98,14 @@ private:
 				   double gain);
 	utils::Duration filterExposure(utils::Duration exposureValue);
 
-	uint64_t frameCount_;
 	utils::Duration filteredExposure_;
-	double relativeLuminanceTarget_;
+	mutable bool luxWarningEnabled_;
+	double exposureCompensation_;
+	Pwl relativeLuminanceTarget_;
+	uint64_t frameCount_;
+	unsigned int lux_;
 
+	std::vector<AgcConstraint> additionalConstraints_;
 	std::map<int32_t, std::vector<AgcConstraint>> constraintModes_;
 	std::map<int32_t, std::shared_ptr<ExposureModeHelper>> exposureModeHelpers_;
 	ControlInfoMap::Map controls_;
diff -pruN 0.5.0-1/src/ipa/libipa/awb.cpp 0.6.0-2/src/ipa/libipa/awb.cpp
--- 0.5.0-1/src/ipa/libipa/awb.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/awb.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -114,7 +114,7 @@ namespace ipa {
  * does not take any statistics into account. It is used to compute the colour
  * gains when the user manually specifies a colour temperature.
  *
- * \return The colour gains
+ * \return The colour gains or std::nullopt if the conversion is not possible
  */
 
 /**
diff -pruN 0.5.0-1/src/ipa/libipa/awb.h 0.6.0-2/src/ipa/libipa/awb.h
--- 0.5.0-1/src/ipa/libipa/awb.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/awb.h	2025-11-27 11:55:28.000000000 +0000
@@ -8,6 +8,7 @@
 #pragma once
 
 #include <map>
+#include <optional>
 
 #include <libcamera/control_ids.h>
 #include <libcamera/controls.h>
@@ -39,7 +40,7 @@ public:
 
 	virtual int init(const YamlObject &tuningData) = 0;
 	virtual AwbResult calculateAwb(const AwbStats &stats, unsigned int lux) = 0;
-	virtual RGB<double> gainsFromColourTemperature(double colourTemperature) = 0;
+	virtual std::optional<RGB<double>> gainsFromColourTemperature(double colourTemperature) = 0;
 
 	const ControlInfoMap::Map &controls() const
 	{
diff -pruN 0.5.0-1/src/ipa/libipa/awb_bayes.cpp 0.6.0-2/src/ipa/libipa/awb_bayes.cpp
--- 0.5.0-1/src/ipa/libipa/awb_bayes.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/awb_bayes.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -270,7 +270,7 @@ void AwbBayes::handleControls(const Cont
 	}
 }
 
-RGB<double> AwbBayes::gainsFromColourTemperature(double colourTemperature)
+std::optional<RGB<double>> AwbBayes::gainsFromColourTemperature(double colourTemperature)
 {
 	/*
 	 * \todo In the RaspberryPi code, the ct curve was interpolated in
@@ -278,7 +278,7 @@ RGB<double> AwbBayes::gainsFromColourTem
 	 * intuitive, as the gains are in linear space. But I can't prove it.
 	 */
 	const auto &gains = colourGainCurve_.getInterpolated(colourTemperature);
-	return { { gains[0], 1.0, gains[1] } };
+	return RGB<double>{ { gains[0], 1.0, gains[1] } };
 }
 
 AwbResult AwbBayes::calculateAwb(const AwbStats &stats, unsigned int lux)
diff -pruN 0.5.0-1/src/ipa/libipa/awb_bayes.h 0.6.0-2/src/ipa/libipa/awb_bayes.h
--- 0.5.0-1/src/ipa/libipa/awb_bayes.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/awb_bayes.h	2025-11-27 11:55:28.000000000 +0000
@@ -27,7 +27,7 @@ public:
 
 	int init(const YamlObject &tuningData) override;
 	AwbResult calculateAwb(const AwbStats &stats, unsigned int lux) override;
-	RGB<double> gainsFromColourTemperature(double temperatureK) override;
+	std::optional<RGB<double>> gainsFromColourTemperature(double temperatureK) override;
 	void handleControls(const ControlList &controls) override;
 
 private:
diff -pruN 0.5.0-1/src/ipa/libipa/awb_grey.cpp 0.6.0-2/src/ipa/libipa/awb_grey.cpp
--- 0.5.0-1/src/ipa/libipa/awb_grey.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/awb_grey.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -98,15 +98,15 @@ AwbResult AwbGrey::calculateAwb(const Aw
  * \return The colour gains if a colour temperature curve is available,
  * [1, 1, 1] otherwise.
  */
-RGB<double> AwbGrey::gainsFromColourTemperature(double colourTemperature)
+std::optional<RGB<double>> AwbGrey::gainsFromColourTemperature(double colourTemperature)
 {
 	if (!colourGainCurve_) {
 		LOG(Awb, Error) << "No gains defined";
-		return RGB<double>({ 1.0, 1.0, 1.0 });
+		return std::nullopt;
 	}
 
 	auto gains = colourGainCurve_->getInterpolated(colourTemperature);
-	return { { gains[0], 1.0, gains[1] } };
+	return RGB<double>{ { gains[0], 1.0, gains[1] } };
 }
 
 } /* namespace ipa */
diff -pruN 0.5.0-1/src/ipa/libipa/awb_grey.h 0.6.0-2/src/ipa/libipa/awb_grey.h
--- 0.5.0-1/src/ipa/libipa/awb_grey.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/awb_grey.h	2025-11-27 11:55:28.000000000 +0000
@@ -25,7 +25,7 @@ public:
 
 	int init(const YamlObject &tuningData) override;
 	AwbResult calculateAwb(const AwbStats &stats, unsigned int lux) override;
-	RGB<double> gainsFromColourTemperature(double colourTemperature) override;
+	std::optional<RGB<double>> gainsFromColourTemperature(double colourTemperature) override;
 
 private:
 	std::optional<Interpolator<Vector<double, 2>>> colourGainCurve_;
diff -pruN 0.5.0-1/src/ipa/libipa/camera_sensor_helper.cpp 0.6.0-2/src/ipa/libipa/camera_sensor_helper.cpp
--- 0.5.0-1/src/ipa/libipa/camera_sensor_helper.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/camera_sensor_helper.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -132,6 +132,29 @@ double CameraSensorHelper::gain(uint32_t
 }
 
 /**
+ * \brief Quantize the given gain value
+ * \param[in] _gain The real gain
+ * \param[out] quantizationGain The gain that is lost due to quantization
+ *
+ * This function returns the actual gain that is applied when the sensor's gain
+ * is set to gainCode(_gain).
+ *
+ * It shall be guaranteed that gainCode(_gain) == gainCode(quantizeGain(_gain)).
+ *
+ * If \a quantizationGain is provided it is populated with the gain that must be
+ * applied on top to correct for the losses due to quantization.
+ *
+ * \return The quantized real gain
+ */
+double CameraSensorHelper::quantizeGain(double _gain, double *quantizationGain) const
+{
+	double g = gain(gainCode(_gain));
+	if (quantizationGain)
+		*quantizationGain = _gain / g;
+	return g;
+}
+
+/**
  * \struct CameraSensorHelper::AnalogueGainLinear
  * \brief Analogue gain constants for the linear gain model
  *
@@ -497,6 +520,16 @@ public:
 };
 REGISTER_CAMERA_SENSOR_HELPER("gc08a3", CameraSensorHelperGc08a3)
 
+class CameraSensorHelperHm1246 : public CameraSensorHelper
+{
+public:
+	CameraSensorHelperHm1246()
+	{
+		gain_ = AnalogueGainLinear{ 1, 16, 0, 16 };
+	}
+};
+REGISTER_CAMERA_SENSOR_HELPER("hm1246", CameraSensorHelperHm1246)
+
 class CameraSensorHelperImx214 : public CameraSensorHelper
 {
 public:
@@ -609,6 +642,17 @@ public:
 };
 REGISTER_CAMERA_SENSOR_HELPER("imx477", CameraSensorHelperImx477)
 
+class CameraSensorHelperImx708 : public CameraSensorHelper
+{
+public:
+	CameraSensorHelperImx708()
+	{
+		blackLevel_ = 4096;
+		gain_ = AnalogueGainLinear{ 0, 1024, -1, 1024 };
+	}
+};
+REGISTER_CAMERA_SENSOR_HELPER("imx708", CameraSensorHelperImx708)
+
 class CameraSensorHelperOv2685 : public CameraSensorHelper
 {
 public:
@@ -745,6 +789,30 @@ public:
 };
 REGISTER_CAMERA_SENSOR_HELPER("ov13858", CameraSensorHelperOv13858)
 
+class CameraSensorHelperVd55g1 : public CameraSensorHelper
+{
+public:
+	CameraSensorHelperVd55g1()
+	{
+		/* From datasheet: 0x40 at 10bits. */
+		blackLevel_ = 4096;
+		gain_ = AnalogueGainLinear{ 0, 32, -1, 32 };
+	}
+};
+REGISTER_CAMERA_SENSOR_HELPER("vd55g1", CameraSensorHelperVd55g1)
+
+class CameraSensorHelperVd56g3 : public CameraSensorHelper
+{
+public:
+	CameraSensorHelperVd56g3()
+	{
+		/* From datasheet: 0x40 at 10bits. */
+		blackLevel_ = 4096;
+		gain_ = AnalogueGainLinear{ 0, 32, -1, 32 };
+	}
+};
+REGISTER_CAMERA_SENSOR_HELPER("vd56g3", CameraSensorHelperVd56g3)
+
 #endif /* __DOXYGEN__ */
 
 } /* namespace ipa */
diff -pruN 0.5.0-1/src/ipa/libipa/camera_sensor_helper.h 0.6.0-2/src/ipa/libipa/camera_sensor_helper.h
--- 0.5.0-1/src/ipa/libipa/camera_sensor_helper.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/camera_sensor_helper.h	2025-11-27 11:55:28.000000000 +0000
@@ -29,6 +29,7 @@ public:
 	std::optional<int16_t> blackLevel() const { return blackLevel_; }
 	virtual uint32_t gainCode(double gain) const;
 	virtual double gain(uint32_t gainCode) const;
+	double quantizeGain(double gain, double *quantizationGain) const;
 
 protected:
 	struct AnalogueGainLinear {
diff -pruN 0.5.0-1/src/ipa/libipa/exposure_mode_helper.cpp 0.6.0-2/src/ipa/libipa/exposure_mode_helper.cpp
--- 0.5.0-1/src/ipa/libipa/exposure_mode_helper.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/exposure_mode_helper.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -70,12 +70,9 @@ namespace ipa {
  * the runtime limits set through setLimits() instead.
  */
 ExposureModeHelper::ExposureModeHelper(const Span<std::pair<utils::Duration, double>> stages)
+	: lineDuration_(1us), minExposureTime_(0us), maxExposureTime_(0us),
+	  minGain_(0), maxGain_(0), sensorHelper_(nullptr)
 {
-	minExposureTime_ = 0us;
-	maxExposureTime_ = 0us;
-	minGain_ = 0;
-	maxGain_ = 0;
-
 	for (const auto &[s, g] : stages) {
 		exposureTimes_.push_back(s);
 		gains_.push_back(g);
@@ -83,6 +80,28 @@ ExposureModeHelper::ExposureModeHelper(c
 }
 
 /**
+ * \brief Configure sensor details
+ * \param[in] lineDuration The current line length of the sensor
+ * \param[in] sensorHelper The sensor helper
+ *
+ * This function sets the line length and sensor helper. These are used in
+ * splitExposure() to take the quantization of the exposure and gain into
+ * account.
+ *
+ * When this has not been called, it is assumed that exposure is in micro second
+ * granularity and gain has no quantization at all.
+ *
+ * ExposureModeHelper keeps a pointer to the CameraSensorHelper, so the caller
+ * has to ensure that sensorHelper is valid until the next call to configure().
+ */
+void ExposureModeHelper::configure(utils::Duration lineDuration,
+				   const CameraSensorHelper *sensorHelper)
+{
+	lineDuration_ = lineDuration;
+	sensorHelper_ = sensorHelper;
+}
+
+/**
  * \brief Set the exposure time and gain limits
  * \param[in] minExposureTime The minimum exposure time supported
  * \param[in] maxExposureTime The maximum exposure time supported
@@ -108,14 +127,30 @@ void ExposureModeHelper::setLimits(utils
 	maxGain_ = maxGain;
 }
 
-utils::Duration ExposureModeHelper::clampExposureTime(utils::Duration exposureTime) const
+utils::Duration ExposureModeHelper::clampExposureTime(utils::Duration exposureTime,
+						      double *quantizationGain) const
 {
-	return std::clamp(exposureTime, minExposureTime_, maxExposureTime_);
+	utils::Duration clamped;
+	utils::Duration exp;
+
+	clamped = std::clamp(exposureTime, minExposureTime_, maxExposureTime_);
+	exp = static_cast<long>(clamped / lineDuration_) * lineDuration_;
+	if (quantizationGain)
+		*quantizationGain = clamped / exp;
+
+	return exp;
 }
 
-double ExposureModeHelper::clampGain(double gain) const
+double ExposureModeHelper::clampGain(double gain, double *quantizationGain) const
 {
-	return std::clamp(gain, minGain_, maxGain_);
+	double clamped = std::clamp(gain, minGain_, maxGain_);
+	if (sensorHelper_)
+		return sensorHelper_->quantizeGain(clamped, quantizationGain);
+
+	if (quantizationGain)
+		*quantizationGain = 1.0;
+
+	return clamped;
 }
 
 /**
@@ -147,14 +182,24 @@ double ExposureModeHelper::clampGain(dou
  * required exposure, the helper falls-back to simply maximising the exposure
  * time first, followed by analogue gain, followed by digital gain.
  *
- * \return Tuple of exposure time, analogue gain, and digital gain
+ * During the calculations the gain missed due to quantization is recorded and
+ * returned as quantization gain. The quantization gain is not included in the
+ * digital gain. So to exactly apply the given exposure, both quantization gain
+ * and digital gain must be applied.
+ *
+ * \return Tuple of exposure time, analogue gain, quantization gain and digital
+ * gain
  */
-std::tuple<utils::Duration, double, double>
+std::tuple<utils::Duration, double, double, double>
 ExposureModeHelper::splitExposure(utils::Duration exposure) const
 {
 	ASSERT(maxExposureTime_);
 	ASSERT(maxGain_);
 
+	utils::Duration exposureTime;
+	double gain;
+	double quantGain;
+	double quantGain2;
 	bool gainFixed = minGain_ == maxGain_;
 	bool exposureTimeFixed = minExposureTime_ == maxExposureTime_;
 
@@ -162,16 +207,21 @@ ExposureModeHelper::splitExposure(utils:
 	 * There's no point entering the loop if we cannot change either gain
 	 * nor exposure time anyway.
 	 */
-	if (exposureTimeFixed && gainFixed)
-		return { minExposureTime_, minGain_, exposure / (minExposureTime_ * minGain_) };
+	if (exposureTimeFixed && gainFixed) {
+		exposureTime = clampExposureTime(minExposureTime_, &quantGain);
+		gain = clampGain(minGain_, &quantGain2);
+		quantGain *= quantGain2;
 
-	utils::Duration exposureTime;
-	double stageGain = 1.0;
-	double gain;
+		return { exposureTime, gain, quantGain,
+			 exposure / (exposureTime * gain * quantGain) };
+	}
+
+	double stageGain = clampGain(1.0);
+	double lastStageGain = stageGain;
 
 	for (unsigned int stage = 0; stage < gains_.size(); stage++) {
-		double lastStageGain = stage == 0 ? 1.0 : clampGain(gains_[stage - 1]);
-		utils::Duration stageExposureTime = clampExposureTime(exposureTimes_[stage]);
+		utils::Duration stageExposureTime = clampExposureTime(exposureTimes_[stage],
+								      &quantGain);
 		stageGain = clampGain(gains_[stage]);
 
 		/*
@@ -184,19 +234,25 @@ ExposureModeHelper::splitExposure(utils:
 
 		/* Clamp the gain to lastStageGain and regulate exposureTime. */
 		if (stageExposureTime * lastStageGain >= exposure) {
-			exposureTime = clampExposureTime(exposure / clampGain(lastStageGain));
-			gain = clampGain(exposure / exposureTime);
+			exposureTime = clampExposureTime(exposure / lastStageGain, &quantGain);
+			gain = clampGain(exposure / exposureTime, &quantGain2);
+			quantGain *= quantGain2;
 
-			return { exposureTime, gain, exposure / (exposureTime * gain) };
+			return { exposureTime, gain, quantGain,
+				 exposure / (exposureTime * gain * quantGain) };
 		}
 
 		/* Clamp the exposureTime to stageExposureTime and regulate gain. */
 		if (stageExposureTime * stageGain >= exposure) {
-			exposureTime = clampExposureTime(stageExposureTime);
-			gain = clampGain(exposure / exposureTime);
+			exposureTime = stageExposureTime;
+			gain = clampGain(exposure / exposureTime, &quantGain2);
+			quantGain *= quantGain2;
 
-			return { exposureTime, gain, exposure / (exposureTime * gain) };
+			return { exposureTime, gain, quantGain,
+				 exposure / (exposureTime * gain * quantGain) };
 		}
+
+		lastStageGain = stageGain;
 	}
 
 	/*
@@ -206,10 +262,12 @@ ExposureModeHelper::splitExposure(utils:
 	 * stages to use then the default stageGain of 1.0 is used so that
 	 * exposure time is maxed before gain is touched at all.
 	 */
-	exposureTime = clampExposureTime(exposure / clampGain(stageGain));
-	gain = clampGain(exposure / exposureTime);
+	exposureTime = clampExposureTime(exposure / stageGain, &quantGain);
+	gain = clampGain(exposure / exposureTime, &quantGain2);
+	quantGain *= quantGain2;
 
-	return { exposureTime, gain, exposure / (exposureTime * gain) };
+	return { exposureTime, gain, quantGain,
+		 exposure / (exposureTime * gain * quantGain) };
 }
 
 /**
diff -pruN 0.5.0-1/src/ipa/libipa/exposure_mode_helper.h 0.6.0-2/src/ipa/libipa/exposure_mode_helper.h
--- 0.5.0-1/src/ipa/libipa/exposure_mode_helper.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/exposure_mode_helper.h	2025-11-27 11:55:28.000000000 +0000
@@ -14,6 +14,8 @@
 #include <libcamera/base/span.h>
 #include <libcamera/base/utils.h>
 
+#include "camera_sensor_helper.h"
+
 namespace libcamera {
 
 namespace ipa {
@@ -24,10 +26,11 @@ public:
 	ExposureModeHelper(const Span<std::pair<utils::Duration, double>> stages);
 	~ExposureModeHelper() = default;
 
+	void configure(utils::Duration lineLength, const CameraSensorHelper *sensorHelper);
 	void setLimits(utils::Duration minExposureTime, utils::Duration maxExposureTime,
 		       double minGain, double maxGain);
 
-	std::tuple<utils::Duration, double, double>
+	std::tuple<utils::Duration, double, double, double>
 	splitExposure(utils::Duration exposure) const;
 
 	utils::Duration minExposureTime() const { return minExposureTime_; }
@@ -36,16 +39,19 @@ public:
 	double maxGain() const { return maxGain_; }
 
 private:
-	utils::Duration clampExposureTime(utils::Duration exposureTime) const;
-	double clampGain(double gain) const;
+	utils::Duration clampExposureTime(utils::Duration exposureTime,
+					  double *quantizationGain = nullptr) const;
+	double clampGain(double gain, double *quantizationGain = nullptr) const;
 
 	std::vector<utils::Duration> exposureTimes_;
 	std::vector<double> gains_;
 
+	utils::Duration lineDuration_;
 	utils::Duration minExposureTime_;
 	utils::Duration maxExposureTime_;
 	double minGain_;
 	double maxGain_;
+	const CameraSensorHelper *sensorHelper_;
 };
 
 } /* namespace ipa */
diff -pruN 0.5.0-1/src/ipa/libipa/histogram.h 0.6.0-2/src/ipa/libipa/histogram.h
--- 0.5.0-1/src/ipa/libipa/histogram.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/histogram.h	2025-11-27 11:55:28.000000000 +0000
@@ -36,7 +36,7 @@ public:
 	}
 
 	size_t bins() const { return cumulative_.size() - 1; }
-	const Span<const uint64_t> data() const { return cumulative_; }
+	Span<const uint64_t> data() const { return cumulative_; }
 	uint64_t total() const { return cumulative_[cumulative_.size() - 1]; }
 	uint64_t cumulativeFrequency(double bin) const;
 	double quantile(double q, uint32_t first = 0, uint32_t last = UINT_MAX) const;
diff -pruN 0.5.0-1/src/ipa/libipa/module.cpp 0.6.0-2/src/ipa/libipa/module.cpp
--- 0.5.0-1/src/ipa/libipa/module.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/module.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -94,6 +94,14 @@ namespace ipa {
  * algorithms. The configuration data is expected to be correct, any error
  * causes the function to fail and return immediately.
  *
+ * Algorithms can optionally be disabled via the tuning file of the camera
+ * module as shown here, with AGC being used as an example:
+ *
+ * - Agc:
+ *     enabled: false
+ *
+ * If this is the case, the algorithm will not be instantiated.
+ *
  * \return 0 on success, or a negative error code on failure
  */
 
diff -pruN 0.5.0-1/src/ipa/libipa/module.h 0.6.0-2/src/ipa/libipa/module.h
--- 0.5.0-1/src/ipa/libipa/module.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/module.h	2025-11-27 11:55:28.000000000 +0000
@@ -74,6 +74,18 @@ private:
 	int createAlgorithm(Context &context, const YamlObject &data)
 	{
 		const auto &[name, algoData] = *data.asDict().begin();
+
+		/*
+		 * Optionally, algorithms can be disabled via the tuning file
+		 * by including enabled: false as a parameter within the
+		 * algorithm tuning data. This is not an error, so we return 0.
+		 */
+		if (!algoData["enabled"].get<bool>(true)) {
+			LOG(IPAModuleAlgo, Info)
+				<< "Algorithm '" << name << "' disabled via tuning file";
+			return 0;
+		}
+
 		std::unique_ptr<Algorithm<Module>> algo = createAlgorithm(name);
 		if (!algo) {
 			LOG(IPAModuleAlgo, Error)
diff -pruN 0.5.0-1/src/ipa/libipa/pwl.cpp 0.6.0-2/src/ipa/libipa/pwl.cpp
--- 0.5.0-1/src/ipa/libipa/pwl.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/libipa/pwl.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -35,14 +35,13 @@ namespace ipa {
  *
  * https://en.wikipedia.org/wiki/Piecewise_linear_function
  *
- * A consequence of the Pwl class being defined by knots instead of linear
- * functions is that the values of the piecewise linear function past the ends
- * of the function are constants as opposed to linear functions. In a
- * mathematical piecewise linear function that is defined by multiple linear
- * functions, the ends of the function are also linear functions and hence grow
- * to infinity (or negative infinity). However, since this Pwl class is defined
- * by knots, the y-value of the leftmost and rightmost knots will hold for all
- * x values to negative infinity and positive infinity, respectively.
+ * Outside the domain of the piecewise linear function the closest segment is
+ * extrapolated linearly. If one wants to ensure that the returned values stay
+ * within the range of the pwl, the input can be clamped:
+ *
+ * \code{.cpp}
+ * pwl.eval(pwl.domain().clip(x))
+ * \endcode
  */
 
 /**
@@ -211,6 +210,10 @@ double Pwl::eval(double x, int *span, bo
 					: points_.size() / 2 - 1);
 	if (span && updateSpan)
 		*span = index;
+
+	if (points_.size() == 1)
+		return points_[0].y();
+
 	return points_[index].y() +
 	       (x - points_[index].x()) * (points_[index + 1].y() - points_[index].y()) /
 		       (points_[index + 1].x() - points_[index].x());
@@ -434,6 +437,15 @@ template<>
 std::optional<ipa::Pwl>
 YamlObject::Getter<ipa::Pwl>::get(const YamlObject &obj) const
 {
+	/* Treat a single value as single point PWL. */
+	if (obj.isValue()) {
+		auto v = obj.get<double>();
+		if (!v)
+			return std::nullopt;
+
+		return ipa::Pwl({ { { 0.0, *v } } });
+	}
+
 	if (!obj.size() || obj.size() % 2)
 		return std::nullopt;
 
diff -pruN 0.5.0-1/src/ipa/mali-c55/algorithms/agc.cpp 0.6.0-2/src/ipa/mali-c55/algorithms/agc.cpp
--- 0.5.0-1/src/ipa/mali-c55/algorithms/agc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/algorithms/agc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board Oy
  *
- * agc.cpp - AGC/AEC mean-based control algorithm
+ * AGC/AEC mean-based control algorithm
  */
 
 #include "agc.h"
@@ -173,7 +173,8 @@ int Agc::configure(IPAContext &context,
 	setLimits(context.configuration.agc.minShutterSpeed,
 		  context.configuration.agc.maxShutterSpeed,
 		  context.configuration.agc.minAnalogueGain,
-		  context.configuration.agc.maxAnalogueGain);
+		  context.configuration.agc.maxAnalogueGain,
+		  {});
 
 	resetFrameCount();
 
@@ -381,8 +382,8 @@ void Agc::process(IPAContext &context,
 	utils::Duration effectiveExposureValue = currentShutter * totalGain;
 
 	utils::Duration shutterTime;
-	double aGain, dGain;
-	std::tie(shutterTime, aGain, dGain) =
+	double aGain, qGain, dGain;
+	std::tie(shutterTime, aGain, qGain, dGain) =
 		calculateNewEv(activeState.agc.constraintMode,
 			       activeState.agc.exposureMode, statistics_.yHist,
 			       effectiveExposureValue);
diff -pruN 0.5.0-1/src/ipa/mali-c55/algorithms/agc.h 0.6.0-2/src/ipa/mali-c55/algorithms/agc.h
--- 0.5.0-1/src/ipa/mali-c55/algorithms/agc.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/algorithms/agc.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2023, Ideas on Board Oy
  *
- * agc.h - Mali C55 AGC/AEC mean-based control algorithm
+ * Mali C55 AGC/AEC mean-based control algorithm
  */
 
 #pragma once
diff -pruN 0.5.0-1/src/ipa/mali-c55/algorithms/algorithm.h 0.6.0-2/src/ipa/mali-c55/algorithms/algorithm.h
--- 0.5.0-1/src/ipa/mali-c55/algorithms/algorithm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/algorithms/algorithm.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board
  *
- * algorithm.h - Mali-C55 control algorithm interface
+ * Mali-C55 control algorithm interface
  */
 
 #pragma once
diff -pruN 0.5.0-1/src/ipa/mali-c55/algorithms/awb.cpp 0.6.0-2/src/ipa/mali-c55/algorithms/awb.cpp
--- 0.5.0-1/src/ipa/mali-c55/algorithms/awb.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/algorithms/awb.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board Oy
  *
- * awb.cpp - Mali C55 grey world auto white balance algorithm
+ * Mali C55 grey world auto white balance algorithm
  */
 
 #include "awb.h"
diff -pruN 0.5.0-1/src/ipa/mali-c55/algorithms/awb.h 0.6.0-2/src/ipa/mali-c55/algorithms/awb.h
--- 0.5.0-1/src/ipa/mali-c55/algorithms/awb.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/algorithms/awb.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas on Board Oy
  *
- * awb.h - Mali C55 grey world auto white balance algorithm
+ * Mali C55 grey world auto white balance algorithm
  */
 
 #include "algorithm.h"
diff -pruN 0.5.0-1/src/ipa/mali-c55/algorithms/lsc.cpp 0.6.0-2/src/ipa/mali-c55/algorithms/lsc.cpp
--- 0.5.0-1/src/ipa/mali-c55/algorithms/lsc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/algorithms/lsc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board Oy
  *
- * lsc.cpp - Mali-C55 Lens shading correction algorithm
+ * Mali-C55 Lens shading correction algorithm
  */
 
 #include "lsc.h"
diff -pruN 0.5.0-1/src/ipa/mali-c55/algorithms/lsc.h 0.6.0-2/src/ipa/mali-c55/algorithms/lsc.h
--- 0.5.0-1/src/ipa/mali-c55/algorithms/lsc.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/algorithms/lsc.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board Oy
  *
- * lsc.h - Mali-C55 Lens shading correction algorithm
+ * Mali-C55 Lens shading correction algorithm
  */
 
 #include <map>
diff -pruN 0.5.0-1/src/ipa/mali-c55/ipa_context.cpp 0.6.0-2/src/ipa/mali-c55/ipa_context.cpp
--- 0.5.0-1/src/ipa/mali-c55/ipa_context.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/ipa_context.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board
  *
- * ipa_context.cpp - MaliC55 IPA Context
+ * Mali-C55 IPA Context
  */
 
 #include "ipa_context.h"
diff -pruN 0.5.0-1/src/ipa/mali-c55/ipa_context.h 0.6.0-2/src/ipa/mali-c55/ipa_context.h
--- 0.5.0-1/src/ipa/mali-c55/ipa_context.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/ipa_context.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board
  *
- * ipa_context.h - Mali-C55 IPA Context
+ * Mali-C55 IPA Context
  */
 
 #pragma once
diff -pruN 0.5.0-1/src/ipa/mali-c55/mali-c55.cpp 0.6.0-2/src/ipa/mali-c55/mali-c55.cpp
--- 0.5.0-1/src/ipa/mali-c55/mali-c55.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/mali-c55.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,9 +2,10 @@
 /*
  * Copyright (C) 2023, Ideas on Board Oy
  *
- * mali-c55.cpp - Mali-C55 ISP image processing algorithms
+ * Mali-C55 ISP image processing algorithms
  */
 
+#include <array>
 #include <map>
 #include <string.h>
 #include <vector>
@@ -14,6 +15,7 @@
 
 #include <libcamera/base/file.h>
 #include <libcamera/base/log.h>
+#include <libcamera/base/span.h>
 
 #include <libcamera/control_ids.h>
 #include <libcamera/ipa/ipa_interface.h>
@@ -236,7 +238,7 @@ void IPAMaliC55::updateControls(const IP
 
 	ctrlMap[&controls::FrameDurationLimits] = ControlInfo(frameDurations[0],
 							      frameDurations[1],
-							      frameDurations[2]);
+							      Span<const int64_t, 2>{ { frameDurations[2], frameDurations[2] } });
 
 	/*
 	 * Compute exposure time limits from the V4L2_CID_EXPOSURE control
@@ -346,7 +348,8 @@ void IPAMaliC55::fillParams(unsigned int
 		ASSERT(params->total_size <= MALI_C55_PARAMS_MAX_SIZE);
 	}
 
-	paramsComputed.emit(request);
+	size_t bytesused = offsetof(struct mali_c55_params_buffer, data) + params->total_size;
+	paramsComputed.emit(request, bytesused);
 }
 
 void IPAMaliC55::processStats(unsigned int request, unsigned int bufferId,
diff -pruN 0.5.0-1/src/ipa/mali-c55/module.h 0.6.0-2/src/ipa/mali-c55/module.h
--- 0.5.0-1/src/ipa/mali-c55/module.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/mali-c55/module.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board
  *
- * module.h - Mali-C55 IPA Module
+ * Mali-C55 IPA Module
  */
 
 #pragma once
diff -pruN 0.5.0-1/src/ipa/meson.build 0.6.0-2/src/ipa/meson.build
--- 0.5.0-1/src/ipa/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -4,7 +4,7 @@ ipa_includes = [
     libcamera_includes,
 ]
 
-ipa_install_dir = libcamera_libdir
+ipa_install_dir = libcamera_libdir / 'ipa'
 ipa_data_dir = libcamera_datadir / 'ipa'
 ipa_sysconf_dir = libcamera_sysconfdir / 'ipa'
 
@@ -24,8 +24,6 @@ subdir('libipa')
 
 ipa_sign = files('ipa-sign.sh')
 
-ipa_names = []
-
 ipa_modules = get_option('ipas')
 
 # Tests require the vimc IPA, similar to vimc pipline-handler for their
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/agc.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/agc.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/agc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/agc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -56,7 +56,7 @@ int Agc::parseMeteringModes(IPAContext &
 
 		std::vector<uint8_t> weights =
 			value.getList<uint8_t>().value_or(std::vector<uint8_t>{});
-		if (weights.size() != context.hw->numHistogramWeights) {
+		if (weights.size() != context.hw.numHistogramWeights) {
 			LOG(RkISP1Agc, Warning)
 				<< "Failed to read metering mode'" << key << "'";
 			continue;
@@ -68,10 +68,9 @@ int Agc::parseMeteringModes(IPAContext &
 	if (meteringModes_.empty()) {
 		LOG(RkISP1Agc, Warning)
 			<< "No metering modes read from tuning file; defaulting to matrix";
-		int32_t meteringModeId = controls::AeMeteringModeNameValueMap.at("MeteringMatrix");
-		std::vector<uint8_t> weights(context.hw->numHistogramWeights, 1);
+		std::vector<uint8_t> weights(context.hw.numHistogramWeights, 1);
 
-		meteringModes_[meteringModeId] = weights;
+		meteringModes_[controls::MeteringMatrix] = weights;
 	}
 
 	std::vector<ControlValue> meteringModes;
@@ -158,6 +157,7 @@ int Agc::init(IPAContext &context, const
 			    ControlValue(controls::AnalogueGainModeAuto));
 	/* \todo Move this to the Camera class */
 	context.ctrlMap[&controls::AeEnable] = ControlInfo(false, true, true);
+	context.ctrlMap[&controls::ExposureValue] = ControlInfo(-8.0f, 8.0f, 0.0f);
 	context.ctrlMap.merge(controls());
 
 	return 0;
@@ -176,10 +176,12 @@ int Agc::configure(IPAContext &context,
 	context.activeState.agc.automatic.gain = context.configuration.sensor.minAnalogueGain;
 	context.activeState.agc.automatic.exposure =
 		10ms / context.configuration.sensor.lineDuration;
+	context.activeState.agc.automatic.quantizationGain = 1.0;
 	context.activeState.agc.manual.gain = context.activeState.agc.automatic.gain;
 	context.activeState.agc.manual.exposure = context.activeState.agc.automatic.exposure;
 	context.activeState.agc.autoExposureEnabled = !context.configuration.raw;
 	context.activeState.agc.autoGainEnabled = !context.configuration.raw;
+	context.activeState.agc.exposureValue = 0.0;
 
 	context.activeState.agc.constraintMode =
 		static_cast<controls::AeConstraintModeEnum>(constraintModes().begin()->first);
@@ -198,10 +200,15 @@ int Agc::configure(IPAContext &context,
 	context.configuration.agc.measureWindow.h_size = configInfo.outputSize.width;
 	context.configuration.agc.measureWindow.v_size = configInfo.outputSize.height;
 
+	AgcMeanLuminance::configure(context.configuration.sensor.lineDuration,
+				    context.camHelper.get());
+
 	setLimits(context.configuration.sensor.minExposureTime,
 		  context.configuration.sensor.maxExposureTime,
 		  context.configuration.sensor.minAnalogueGain,
-		  context.configuration.sensor.maxAnalogueGain);
+		  context.configuration.sensor.maxAnalogueGain, {});
+
+	context.activeState.agc.automatic.yTarget = effectiveYTarget();
 
 	resetFrameCount();
 
@@ -282,6 +289,10 @@ void Agc::queueRequest(IPAContext &conte
 	if (!frameContext.agc.autoGainEnabled)
 		frameContext.agc.gain = agc.manual.gain;
 
+	if (!frameContext.agc.autoExposureEnabled &&
+	    !frameContext.agc.autoGainEnabled)
+		frameContext.agc.quantizationGain = 1.0;
+
 	const auto &meteringMode = controls.get(controls::AeMeteringMode);
 	if (meteringMode) {
 		frameContext.agc.updateMetering = agc.meteringMode != *meteringMode;
@@ -302,6 +313,11 @@ void Agc::queueRequest(IPAContext &conte
 			static_cast<controls::AeConstraintModeEnum>(*constraintMode);
 	frameContext.agc.constraintMode = agc.constraintMode;
 
+	const auto &exposureValue = controls.get(controls::ExposureValue);
+	if (exposureValue)
+		agc.exposureValue = *exposureValue;
+	frameContext.agc.exposureValue = agc.exposureValue;
+
 	const auto &frameDurationLimits = controls.get(controls::FrameDurationLimits);
 	if (frameDurationLimits) {
 		/* Limit the control value to the limits in ControlInfo */
@@ -330,12 +346,17 @@ void Agc::prepare(IPAContext &context, c
 {
 	uint32_t activeAutoExposure = context.activeState.agc.automatic.exposure;
 	double activeAutoGain = context.activeState.agc.automatic.gain;
+	double activeAutoQGain = context.activeState.agc.automatic.quantizationGain;
 
 	/* Populate exposure and gain in auto mode */
-	if (frameContext.agc.autoExposureEnabled)
+	if (frameContext.agc.autoExposureEnabled) {
 		frameContext.agc.exposure = activeAutoExposure;
-	if (frameContext.agc.autoGainEnabled)
+		frameContext.agc.quantizationGain = activeAutoQGain;
+	}
+	if (frameContext.agc.autoGainEnabled) {
 		frameContext.agc.gain = activeAutoGain;
+		frameContext.agc.quantizationGain = activeAutoQGain;
+	}
 
 	/*
 	 * Populate manual exposure and gain from the active auto values when
@@ -348,8 +369,16 @@ void Agc::prepare(IPAContext &context, c
 	if (!frameContext.agc.autoGainEnabled && frameContext.agc.autoGainModeChange) {
 		context.activeState.agc.manual.gain = activeAutoGain;
 		frameContext.agc.gain = activeAutoGain;
+		frameContext.agc.quantizationGain = activeAutoQGain;
 	}
 
+	if (context.configuration.compress.supported) {
+		frameContext.compress.enable = true;
+		frameContext.compress.gain = frameContext.agc.quantizationGain;
+	}
+
+	frameContext.agc.yTarget = context.activeState.agc.automatic.yTarget;
+
 	if (frame > 0 && !frameContext.agc.updateMetering)
 		return;
 
@@ -372,11 +401,28 @@ void Agc::prepare(IPAContext &context, c
 	hstConfig.setEnabled(true);
 
 	hstConfig->meas_window = context.configuration.agc.measureWindow;
-	hstConfig->mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_Y_HISTOGRAM;
+	/*
+	 * The Y mode of the histogram gets captured at the ISP output, before
+	 * the output formatter.  This has the side effect that the first and
+	 * the last bins are empty in case of limited YUV range.  Another side
+	 * effect is that gamma and GWDR processing is included in the histogram
+	 * which makes algorithm development very difficult. In RGB mode the
+	 * histogram is taken after xtalk (CCM) and is therefore independent of
+	 * gamma and WDR. The limited range issue also does not apply. In the
+	 * ISP reference it is however stated that "it is not possible to
+	 * calculate a luminance or grayscale histogram from an RGB histogram
+	 * since the position information is lost during its generation".
+	 *
+	 * During testing the RGB histogram provided good data and better
+	 * algorithmic stability at a possible (but not measured) inaccuracy.
+	 *
+	 * \todo For a proper fix support for HIST64 is needed.
+	 */
+	hstConfig->mode = RKISP1_CIF_ISP_HISTOGRAM_MODE_RGB_COMBINED;
 
 	Span<uint8_t> weights{
 		hstConfig->hist_weight,
-		context.hw->numHistogramWeights
+		context.hw.numHistogramWeights
 	};
 	std::vector<uint8_t> &modeWeights = meteringModes_.at(frameContext.agc.meteringMode);
 	std::copy(modeWeights.begin(), modeWeights.end(), weights.begin());
@@ -408,6 +454,7 @@ void Agc::fillMetadata(IPAContext &conte
 	metadata.set(controls::AeMeteringMode, frameContext.agc.meteringMode);
 	metadata.set(controls::AeExposureMode, frameContext.agc.exposureMode);
 	metadata.set(controls::AeConstraintMode, frameContext.agc.constraintMode);
+	metadata.set(controls::ExposureValue, frameContext.agc.exposureValue);
 }
 
 /**
@@ -513,9 +560,9 @@ void Agc::process(IPAContext &context, [
 	const rkisp1_cif_isp_stat *params = &stats->params;
 
 	/* The lower 4 bits are fractional and meant to be discarded. */
-	Histogram hist({ params->hist.hist_bins, context.hw->numHistogramBins },
+	Histogram hist({ params->hist.hist_bins, context.hw.numHistogramBins },
 		       [](uint32_t x) { return x >> 4; });
-	expMeans_ = { params->ae.exp_mean, context.hw->numAeCells };
+	expMeans_ = { params->ae.exp_mean, context.hw.numAeCells };
 	std::vector<uint8_t> &modeWeights = meteringModes_.at(frameContext.agc.meteringMode);
 	weights_ = { modeWeights.data(), modeWeights.size() };
 
@@ -547,7 +594,12 @@ void Agc::process(IPAContext &context, [
 		maxAnalogueGain = frameContext.agc.gain;
 	}
 
-	setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain);
+	std::vector<AgcMeanLuminance::AgcConstraint> additionalConstraints;
+	if (context.activeState.wdr.mode != controls::WdrOff)
+		additionalConstraints.push_back(context.activeState.wdr.constraint);
+
+	setLimits(minExposureTime, maxExposureTime, minAnalogueGain, maxAnalogueGain,
+		  std::move(additionalConstraints));
 
 	/*
 	 * The Agc algorithm needs to know the effective exposure value that was
@@ -557,22 +609,35 @@ void Agc::process(IPAContext &context, [
 	double analogueGain = frameContext.sensor.gain;
 	utils::Duration effectiveExposureValue = exposureTime * analogueGain;
 
+	/*
+	 * Include the quantization gain if it was applied. Do not use
+	 * compress.gain because it will include gains that shall not be
+	 * reported to the user when HDR is implemented.
+	 */
+	if (frameContext.compress.enable)
+		effectiveExposureValue *= frameContext.agc.quantizationGain;
+
+	setExposureCompensation(pow(2.0, frameContext.agc.exposureValue));
+	setLux(frameContext.lux.lux);
+
 	utils::Duration newExposureTime;
-	double aGain, dGain;
-	std::tie(newExposureTime, aGain, dGain) =
+	double aGain, qGain, dGain;
+	std::tie(newExposureTime, aGain, qGain, dGain) =
 		calculateNewEv(frameContext.agc.constraintMode,
 			       frameContext.agc.exposureMode,
 			       hist, effectiveExposureValue);
 
 	LOG(RkISP1Agc, Debug)
-		<< "Divided up exposure time, analogue gain and digital gain are "
-		<< newExposureTime << ", " << aGain << " and " << dGain;
+		<< "Divided up exposure time, analogue gain, quantization gain"
+		<< " and digital gain are " << newExposureTime << ", " << aGain
+		<< ", " << qGain << " and " << dGain;
 
 	IPAActiveState &activeState = context.activeState;
 	/* Update the estimated exposure and gain. */
 	activeState.agc.automatic.exposure = newExposureTime / lineDuration;
 	activeState.agc.automatic.gain = aGain;
-
+	activeState.agc.automatic.quantizationGain = qGain;
+	activeState.agc.automatic.yTarget = effectiveYTarget();
 	/*
 	 * Expand the target frame duration so that we do not run faster than
 	 * the minimum frame duration when we have short exposures.
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/awb.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/awb.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/awb.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/awb.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -90,6 +90,10 @@ int Awb::init(IPAContext &context, const
 	cmap[&controls::ColourTemperature] = ControlInfo(kMinColourTemperature,
 							 kMaxColourTemperature,
 							 kDefaultColourTemperature);
+	cmap[&controls::AwbEnable] = ControlInfo(false, true);
+
+	cmap[&controls::ColourGains] = ControlInfo(0.0f, 3.996f,
+						   Span<const float, 2>{ { 1.0f, 1.0f } });
 
 	if (!tuningData.contains("algorithm"))
 		LOG(RkISP1Awb, Info) << "No AWB algorithm specified."
@@ -124,11 +128,16 @@ int Awb::init(IPAContext &context, const
 int Awb::configure(IPAContext &context,
 		   const IPACameraSensorInfo &configInfo)
 {
-	context.activeState.awb.gains.manual = RGB<double>{ 1.0 };
-	context.activeState.awb.gains.automatic =
-		awbAlgo_->gainsFromColourTemperature(kDefaultColourTemperature);
+	context.activeState.awb.manual.gains = RGB<double>{ 1.0 };
+	auto gains = awbAlgo_->gainsFromColourTemperature(kDefaultColourTemperature);
+	if (gains)
+		context.activeState.awb.automatic.gains = *gains;
+	else
+		context.activeState.awb.automatic.gains = RGB<double>{ 1.0 };
+
 	context.activeState.awb.autoEnabled = true;
-	context.activeState.awb.temperatureK = kDefaultColourTemperature;
+	context.activeState.awb.manual.temperatureK = kDefaultColourTemperature;
+	context.activeState.awb.automatic.temperatureK = kDefaultColourTemperature;
 
 	/*
 	 * Define the measurement window for AWB as a centered rectangle
@@ -173,8 +182,8 @@ void Awb::queueRequest(IPAContext &conte
 	const auto &colourTemperature = controls.get(controls::ColourTemperature);
 	bool update = false;
 	if (colourGains) {
-		awb.gains.manual.r() = (*colourGains)[0];
-		awb.gains.manual.b() = (*colourGains)[1];
+		awb.manual.gains.r() = (*colourGains)[0];
+		awb.manual.gains.b() = (*colourGains)[1];
 		/*
 		 * \todo Colour temperature reported in metadata is now
 		 * incorrect, as we can't deduce the temperature from the gains.
@@ -182,19 +191,21 @@ void Awb::queueRequest(IPAContext &conte
 		 */
 		update = true;
 	} else if (colourTemperature) {
+		awb.manual.temperatureK = *colourTemperature;
 		const auto &gains = awbAlgo_->gainsFromColourTemperature(*colourTemperature);
-		awb.gains.manual.r() = gains.r();
-		awb.gains.manual.b() = gains.b();
-		awb.temperatureK = *colourTemperature;
-		update = true;
+		if (gains) {
+			awb.manual.gains.r() = gains->r();
+			awb.manual.gains.b() = gains->b();
+			update = true;
+		}
 	}
 
 	if (update)
 		LOG(RkISP1Awb, Debug)
-			<< "Set colour gains to " << awb.gains.manual;
+			<< "Set colour gains to " << awb.manual.gains;
 
-	frameContext.awb.gains = awb.gains.manual;
-	frameContext.awb.temperatureK = awb.temperatureK;
+	frameContext.awb.gains = awb.manual.gains;
+	frameContext.awb.temperatureK = awb.manual.temperatureK;
 }
 
 /**
@@ -208,8 +219,9 @@ void Awb::prepare(IPAContext &context, c
 	 * most up-to-date automatic values we can read.
 	 */
 	if (frameContext.awb.autoEnabled) {
-		frameContext.awb.gains = context.activeState.awb.gains.automatic;
-		frameContext.awb.temperatureK = context.activeState.awb.temperatureK;
+		const auto &awb = context.activeState.awb;
+		frameContext.awb.gains = awb.automatic.gains;
+		frameContext.awb.temperatureK = awb.automatic.temperatureK;
 	}
 
 	auto gainConfig = params->block<BlockType::AwbGain>();
@@ -296,6 +308,11 @@ void Awb::process(IPAContext &context,
 	const rkisp1_cif_isp_stat *params = &stats->params;
 	const rkisp1_cif_isp_awb_stat *awb = &params->awb;
 
+	if (awb->awb_mean[0].cnt == 0) {
+		LOG(RkISP1Awb, Debug) << "AWB statistics are empty";
+		return;
+	}
+
 	RGB<double> rgbMeans = calculateRgbMeans(frameContext, awb);
 
 	/*
@@ -309,11 +326,6 @@ void Awb::process(IPAContext &context,
 	RkISP1AwbStats awbStats{ rgbMeans };
 	AwbResult awbResult = awbAlgo_->calculateAwb(awbStats, frameContext.lux.lux);
 
-	activeState.awb.temperatureK = awbResult.colourTemperature;
-
-	/* Metadata shall contain the up to date measurement */
-	metadata.set(controls::ColourTemperature, activeState.awb.temperatureK);
-
 	/*
 	 * Clamp the gain values to the hardware, which expresses gains as Q2.8
 	 * unsigned integer values. Set the minimum just above zero to avoid
@@ -324,16 +336,19 @@ void Awb::process(IPAContext &context,
 
 	/* Filter the values to avoid oscillations. */
 	double speed = 0.2;
+	double ct = awbResult.colourTemperature;
+	ct = ct * speed + activeState.awb.automatic.temperatureK * (1 - speed);
 	awbResult.gains = awbResult.gains * speed +
-			  activeState.awb.gains.automatic * (1 - speed);
+			  activeState.awb.automatic.gains * (1 - speed);
 
-	activeState.awb.gains.automatic = awbResult.gains;
+	activeState.awb.automatic.temperatureK = static_cast<unsigned int>(ct);
+	activeState.awb.automatic.gains = awbResult.gains;
 
 	LOG(RkISP1Awb, Debug)
 		<< std::showpoint
 		<< "Means " << rgbMeans << ", gains "
-		<< activeState.awb.gains.automatic << ", temp "
-		<< activeState.awb.temperatureK << "K";
+		<< activeState.awb.automatic.gains << ", temp "
+		<< activeState.awb.automatic.temperatureK << "K";
 }
 
 RGB<double> Awb::calculateRgbMeans(const IPAFrameContext &frameContext, const rkisp1_cif_isp_awb_stat *awb) const
@@ -392,11 +407,17 @@ RGB<double> Awb::calculateRgbMeans(const
 	}
 
 	/*
+	 * The ISP computes the AWB means after applying the CCM. Apply the
+	 * inverse as we want to get the raw means before the colour gains.
+	 */
+	rgbMeans = frameContext.ccm.ccm.inverse() * rgbMeans;
+
+	/*
 	 * The ISP computes the AWB means after applying the colour gains,
 	 * divide by the gains that were used to get the raw means from the
-	 * sensor.
+	 * sensor. Apply a minimum value to avoid divisions by near-zero.
 	 */
-	rgbMeans /= frameContext.awb.gains;
+	rgbMeans /= frameContext.awb.gains.max(0.01);
 
 	return rgbMeans;
 }
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/awb.h 0.6.0-2/src/ipa/rkisp1/algorithms/awb.h
--- 0.5.0-1/src/ipa/rkisp1/algorithms/awb.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/awb.h	2025-11-27 11:55:28.000000000 +0000
@@ -7,8 +7,6 @@
 
 #pragma once
 
-#include <optional>
-
 #include "libcamera/internal/vector.h"
 
 #include "libipa/awb.h"
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/blc.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/blc.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/blc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/blc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -114,7 +114,7 @@ int BlackLevelCorrection::configure(IPAC
 	 * of the extensible parameters format.
 	 */
 	supported_ = context.configuration.paramFormat == V4L2_META_FMT_RK_ISP1_EXT_PARAMS ||
-		     !context.hw->compand;
+		     !context.hw.compand;
 
 	if (!supported_)
 		LOG(RkISP1Blc, Warning)
@@ -140,7 +140,7 @@ void BlackLevelCorrection::prepare(IPACo
 	if (!supported_)
 		return;
 
-	if (context.hw->compand) {
+	if (context.hw.compand) {
 		auto config = params->block<BlockType::CompandBls>();
 		config.setEnabled(true);
 
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/ccm.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/ccm.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/ccm.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/ccm.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -36,17 +36,25 @@ namespace ipa::rkisp1::algorithms {
 
 LOG_DEFINE_CATEGORY(RkISP1Ccm)
 
+constexpr Matrix<float, 3, 3> kIdentity3x3 = Matrix<float, 3, 3>::identity();
+
 /**
  * \copydoc libcamera::ipa::Algorithm::init
  */
 int Ccm::init([[maybe_unused]] IPAContext &context, const YamlObject &tuningData)
 {
+	auto &cmap = context.ctrlMap;
+	cmap[&controls::ColourCorrectionMatrix] = ControlInfo(
+		ControlValue(-8.0f),
+		ControlValue(7.993f),
+		ControlValue(kIdentity3x3.data()));
+
 	int ret = ccm_.readYaml(tuningData["ccms"], "ct", "ccm");
 	if (ret < 0) {
 		LOG(RkISP1Ccm, Warning)
 			<< "Failed to parse 'ccm' "
 			<< "parameter from tuning file; falling back to unit matrix";
-		ccm_.setData({ { 0, Matrix<float, 3, 3>::identity() } });
+		ccm_.setData({ { 0, kIdentity3x3 } });
 	}
 
 	ret = offsets_.readYaml(tuningData["ccms"], "ct", "offsets");
@@ -61,13 +69,51 @@ int Ccm::init([[maybe_unused]] IPAContex
 	return 0;
 }
 
+/**
+ * \copydoc libcamera::ipa::Algorithm::configure
+ */
+int Ccm::configure(IPAContext &context,
+		   [[maybe_unused]] const IPACameraSensorInfo &configInfo)
+{
+	auto &as = context.activeState;
+	as.ccm.manual = kIdentity3x3;
+	as.ccm.automatic = ccm_.getInterpolated(as.awb.automatic.temperatureK);
+	return 0;
+}
+
+void Ccm::queueRequest(IPAContext &context,
+		       [[maybe_unused]] const uint32_t frame,
+		       IPAFrameContext &frameContext,
+		       const ControlList &controls)
+{
+	/* Nothing to do here, the ccm will be calculated in prepare() */
+	if (frameContext.awb.autoEnabled)
+		return;
+
+	auto &ccm = context.activeState.ccm;
+
+	const auto &colourTemperature = controls.get(controls::ColourTemperature);
+	const auto &ccmMatrix = controls.get(controls::ColourCorrectionMatrix);
+	if (ccmMatrix) {
+		ccm.manual = Matrix<float, 3, 3>(*ccmMatrix);
+		LOG(RkISP1Ccm, Debug)
+			<< "Setting manual CCM from CCM control to " << ccm.manual;
+	} else if (colourTemperature) {
+		ccm.manual = ccm_.getInterpolated(*colourTemperature);
+		LOG(RkISP1Ccm, Debug)
+			<< "Setting manual CCM from CT control to " << ccm.manual;
+	}
+
+	frameContext.ccm.ccm = ccm.manual;
+}
+
 void Ccm::setParameters(struct rkisp1_cif_isp_ctk_config &config,
 			const Matrix<float, 3, 3> &matrix,
 			const Matrix<int16_t, 3, 1> &offsets)
 {
 	/*
 	 * 4 bit integer and 7 bit fractional, ranging from -8 (0x400) to
-	 * +7.992 (0x3ff)
+	 * +7.9921875 (0x3ff)
 	 */
 	for (unsigned int i = 0; i < 3; i++) {
 		for (unsigned int j = 0; j < 3; j++)
@@ -88,14 +134,16 @@ void Ccm::setParameters(struct rkisp1_ci
 void Ccm::prepare(IPAContext &context, const uint32_t frame,
 		  IPAFrameContext &frameContext, RkISP1Params *params)
 {
-	uint32_t ct = context.activeState.awb.temperatureK;
+	if (!frameContext.awb.autoEnabled) {
+		auto config = params->block<BlockType::Ctk>();
+		config.setEnabled(true);
+		setParameters(*config, frameContext.ccm.ccm, Matrix<int16_t, 3, 1>());
+		return;
+	}
 
-	/*
-	 * \todo The colour temperature will likely be noisy, add filtering to
-	 * avoid updating the CCM matrix all the time.
-	 */
+	uint32_t ct = frameContext.awb.temperatureK;
 	if (frame > 0 && ct == ct_) {
-		frameContext.ccm.ccm = context.activeState.ccm.ccm;
+		frameContext.ccm.ccm = context.activeState.ccm.automatic;
 		return;
 	}
 
@@ -103,7 +151,7 @@ void Ccm::prepare(IPAContext &context, c
 	Matrix<float, 3, 3> ccm = ccm_.getInterpolated(ct);
 	Matrix<int16_t, 3, 1> offsets = offsets_.getInterpolated(ct);
 
-	context.activeState.ccm.ccm = ccm;
+	context.activeState.ccm.automatic = ccm;
 	frameContext.ccm.ccm = ccm;
 
 	auto config = params->block<BlockType::Ctk>();
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/ccm.h 0.6.0-2/src/ipa/rkisp1/algorithms/ccm.h
--- 0.5.0-1/src/ipa/rkisp1/algorithms/ccm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/ccm.h	2025-11-27 11:55:28.000000000 +0000
@@ -26,6 +26,12 @@ public:
 	~Ccm() = default;
 
 	int init(IPAContext &context, const YamlObject &tuningData) override;
+	int configure(IPAContext &context,
+		      const IPACameraSensorInfo &configInfo) override;
+	void queueRequest(IPAContext &context,
+			  const uint32_t frame,
+			  IPAFrameContext &frameContext,
+			  const ControlList &controls) override;
 	void prepare(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     RkISP1Params *params) override;
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/compress.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/compress.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/compress.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/compress.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas On Board
+ *
+ * RkISP1 Compression curve
+ */
+#include "compress.h"
+
+#include <linux/videodev2.h>
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
+#include "linux/rkisp1-config.h"
+
+/**
+ * \file compress.h
+ */
+
+namespace libcamera {
+
+namespace ipa::rkisp1::algorithms {
+
+/**
+ * \class Compress
+ * \brief RkISP1 Compress curve
+ *
+ * This algorithm implements support for the compression curve in the compand
+ * block available in the i.MX8 M Plus
+ *
+ * In its current version it only supports a static gain. This is useful for
+ * the agc algorithm to compensate for exposure/gain quantization effects.
+ *
+ * This algorithm doesn't have any configuration options. It needs to be
+ * configured per frame by other algorithms.
+ *
+ * Other algorithms can check configuration.compress.supported to see if
+ * compression is available. If it is available they can configure it per frame
+ * using frameContext.compress.enable and frameContext.compress.gain.
+ */
+
+LOG_DEFINE_CATEGORY(RkISP1Compress)
+
+constexpr static int kRkISP1CompressInBits = 20;
+constexpr static int kRkISP1CompressOutBits = 12;
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::configure
+ */
+int Compress::configure(IPAContext &context,
+			[[maybe_unused]] const IPACameraSensorInfo &configInfo)
+{
+	if (context.configuration.paramFormat != V4L2_META_FMT_RK_ISP1_EXT_PARAMS ||
+	    !context.hw.compand) {
+		LOG(RkISP1Compress, Warning)
+			<< "Compression is not supported by the hardware or kernel.";
+		return 0;
+	}
+
+	context.configuration.compress.supported = true;
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void Compress::prepare([[maybe_unused]] IPAContext &context,
+		       [[maybe_unused]] const uint32_t frame,
+		       IPAFrameContext &frameContext,
+		       RkISP1Params *params)
+{
+	if (!context.configuration.compress.supported)
+		return;
+
+	auto comp = params->block<BlockType::CompandCompress>();
+	comp.setEnabled(frameContext.compress.enable);
+
+	if (!frameContext.compress.enable)
+		return;
+
+	int xmax = (1 << kRkISP1CompressInBits);
+	int ymax = (1 << kRkISP1CompressOutBits);
+	int inLogStep = std::log2(xmax / RKISP1_CIF_ISP_COMPAND_NUM_POINTS);
+
+	for (unsigned int i = 0; i < RKISP1_CIF_ISP_COMPAND_NUM_POINTS; i++) {
+		double x = (i + 1) * (1.0 / RKISP1_CIF_ISP_COMPAND_NUM_POINTS);
+		double y = x * frameContext.compress.gain;
+
+		comp->px[i] = inLogStep;
+		comp->x[i] = std::min<int>(x * xmax, xmax - 1);
+		comp->y[i] = std::min<int>(y * ymax, ymax - 1);
+	}
+
+	LOG(RkISP1Compress, Debug) << "Compression: " << kRkISP1CompressInBits
+				   << " bits to " << kRkISP1CompressOutBits
+				   << " bits gain: " << frameContext.compress.gain;
+}
+
+REGISTER_IPA_ALGORITHM(Compress, "Compress")
+
+} /* namespace ipa::rkisp1::algorithms */
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/compress.h 0.6.0-2/src/ipa/rkisp1/algorithms/compress.h
--- 0.5.0-1/src/ipa/rkisp1/algorithms/compress.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/compress.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas On Board
+ *
+ * RkISP1 Compression curve
+ */
+
+#pragma once
+
+#include "algorithm.h"
+
+namespace libcamera {
+
+namespace ipa::rkisp1::algorithms {
+
+class Compress : public Algorithm
+{
+public:
+	Compress() = default;
+	~Compress() = default;
+
+	int configure(IPAContext &context,
+		      const IPACameraSensorInfo &configInfo) override;
+	void prepare(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     RkISP1Params *params) override;
+};
+
+} /* namespace ipa::rkisp1::algorithms */
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/dpf.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/dpf.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/dpf.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/dpf.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -225,8 +225,12 @@ void Dpf::prepare(IPAContext &context, c
 	auto config = params->block<BlockType::Dpf>();
 	config.setEnabled(frameContext.dpf.denoise);
 
+	auto strengthConfig = params->block<BlockType::DpfStrength>();
+	strengthConfig.setEnabled(frameContext.dpf.denoise);
+
 	if (frameContext.dpf.denoise) {
 		*config = config_;
+		*strengthConfig = strengthConfig_;
 
 		const auto &awb = context.configuration.awb;
 		const auto &lsc = context.configuration.lsc;
@@ -250,12 +254,6 @@ void Dpf::prepare(IPAContext &context, c
 		else
 			mode = RKISP1_CIF_ISP_DPF_GAIN_USAGE_DISABLED;
 	}
-
-	if (frame == 0) {
-		auto strengthConfig = params->block<BlockType::DpfStrength>();
-		strengthConfig.setEnabled(true);
-		*strengthConfig = strengthConfig_;
-	}
 }
 
 REGISTER_IPA_ALGORITHM(Dpf, "Dpf")
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/filter.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/filter.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/filter.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/filter.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -40,6 +40,17 @@ static constexpr uint32_t kFiltLumWeight
 static constexpr uint32_t kFiltModeDefault = 0x000004f2;
 
 /**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int Filter::init(IPAContext &context,
+		 [[maybe_unused]] const YamlObject &tuningData)
+{
+	auto &cmap = context.ctrlMap;
+	cmap[&controls::Sharpness] = ControlInfo(0.0f, 10.0f, 1.0f);
+
+	return 0;
+}
+/**
  * \copydoc libcamera::ipa::Algorithm::queueRequest
  */
 void Filter::queueRequest(IPAContext &context,
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/filter.h 0.6.0-2/src/ipa/rkisp1/algorithms/filter.h
--- 0.5.0-1/src/ipa/rkisp1/algorithms/filter.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/filter.h	2025-11-27 11:55:28.000000000 +0000
@@ -21,6 +21,7 @@ public:
 	Filter() = default;
 	~Filter() = default;
 
+	int init(IPAContext &context, const YamlObject &tuningData) override;
 	void queueRequest(IPAContext &context, const uint32_t frame,
 			  IPAFrameContext &frameContext,
 			  const ControlList &controls) override;
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/goc.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/goc.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/goc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/goc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -50,7 +50,7 @@ const float kDefaultGamma = 2.2f;
  */
 int GammaOutCorrection::init(IPAContext &context, const YamlObject &tuningData)
 {
-	if (context.hw->numGammaOutSamples !=
+	if (context.hw.numGammaOutSamples !=
 	    RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10) {
 		LOG(RkISP1Gamma, Error)
 			<< "Gamma is not implemented for RkISP1 V12";
@@ -101,7 +101,7 @@ void GammaOutCorrection::prepare(IPACont
 				 IPAFrameContext &frameContext,
 				 RkISP1Params *params)
 {
-	ASSERT(context.hw->numGammaOutSamples ==
+	ASSERT(context.hw.numGammaOutSamples ==
 	       RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10);
 
 	if (!frameContext.goc.update)
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/lsc.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/lsc.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/lsc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/lsc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -404,12 +404,12 @@ void LensShadingCorrection::copyTable(rk
 /**
  * \copydoc libcamera::ipa::Algorithm::prepare
  */
-void LensShadingCorrection::prepare(IPAContext &context,
+void LensShadingCorrection::prepare([[maybe_unused]] IPAContext &context,
 				    [[maybe_unused]] const uint32_t frame,
-				    [[maybe_unused]] IPAFrameContext &frameContext,
+				    IPAFrameContext &frameContext,
 				    RkISP1Params *params)
 {
-	uint32_t ct = context.activeState.awb.temperatureK;
+	uint32_t ct = frameContext.awb.temperatureK;
 	if (std::abs(static_cast<int>(ct) - static_cast<int>(lastAppliedCt_)) <
 	    kColourTemperatureChangeThreshhold)
 		return;
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/lux.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/lux.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/lux.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/lux.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board
  *
- * lux.cpp - RkISP1 Lux control
+ * RkISP1 Lux control
  */
 
 #include "lux.h"
@@ -47,6 +47,16 @@ int Lux::init([[maybe_unused]] IPAContex
 }
 
 /**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void Lux::prepare(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+		  IPAFrameContext &frameContext,
+		  [[maybe_unused]] RkISP1Params *params)
+{
+	frameContext.lux.lux = context.activeState.lux.lux;
+}
+
+/**
  * \copydoc libcamera::ipa::Algorithm::process
  */
 void Lux::process(IPAContext &context,
@@ -55,18 +65,25 @@ void Lux::process(IPAContext &context,
 		  const rkisp1_stat_buffer *stats,
 		  ControlList &metadata)
 {
-	utils::Duration exposureTime = context.configuration.sensor.lineDuration
-				     * frameContext.sensor.exposure;
+	/*
+	 * Report the lux level used by algorithms to prepare this frame
+	 * not the lux level *of* this frame.
+	 */
+	metadata.set(controls::Lux, frameContext.lux.lux);
+
+	if (!stats)
+		return;
+
+	utils::Duration exposureTime = context.configuration.sensor.lineDuration *
+				       frameContext.sensor.exposure;
 	double gain = frameContext.sensor.gain;
 
 	/* \todo Deduplicate the histogram calculation from AGC */
 	const rkisp1_cif_isp_stat *params = &stats->params;
-	Histogram yHist({ params->hist.hist_bins, context.hw->numHistogramBins },
+	Histogram yHist({ params->hist.hist_bins, context.hw.numHistogramBins },
 			[](uint32_t x) { return x >> 4; });
 
-	double lux = lux_.estimateLux(exposureTime, gain, 1.0, yHist);
-	frameContext.lux.lux = lux;
-	metadata.set(controls::Lux, lux);
+	context.activeState.lux.lux = lux_.estimateLux(exposureTime, gain, 1.0, yHist);
 }
 
 REGISTER_IPA_ALGORITHM(Lux, "Lux")
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/lux.h 0.6.0-2/src/ipa/rkisp1/algorithms/lux.h
--- 0.5.0-1/src/ipa/rkisp1/algorithms/lux.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/lux.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas On Board
  *
- * lux.h - RkISP1 Lux control
+ * RkISP1 Lux control
  */
 
 #pragma once
@@ -23,6 +23,9 @@ public:
 	Lux();
 
 	int init(IPAContext &context, const YamlObject &tuningData) override;
+	void prepare(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     RkISP1Params *params) override;
 	void process(IPAContext &context, const uint32_t frame,
 		     IPAFrameContext &frameContext,
 		     const rkisp1_stat_buffer *stats,
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/meson.build 0.6.0-2/src/ipa/rkisp1/algorithms/meson.build
--- 0.5.0-1/src/ipa/rkisp1/algorithms/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -5,6 +5,7 @@ rkisp1_ipa_algorithms = files([
     'awb.cpp',
     'blc.cpp',
     'ccm.cpp',
+    'compress.cpp',
     'cproc.cpp',
     'dpcc.cpp',
     'dpf.cpp',
@@ -13,4 +14,5 @@ rkisp1_ipa_algorithms = files([
     'gsl.cpp',
     'lsc.cpp',
     'lux.cpp',
+    'wdr.cpp',
 ])
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/wdr.cpp 0.6.0-2/src/ipa/rkisp1/algorithms/wdr.cpp
--- 0.5.0-1/src/ipa/rkisp1/algorithms/wdr.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/wdr.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,494 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas On Board
+ *
+ * RkISP1 Wide Dynamic Range control
+ */
+
+#include "wdr.h"
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
+#include <libipa/agc_mean_luminance.h>
+#include <libipa/histogram.h>
+#include <libipa/pwl.h>
+
+#include "linux/rkisp1-config.h"
+
+/**
+ * \file wdr.h
+ */
+
+namespace libcamera {
+
+namespace ipa::rkisp1::algorithms {
+
+/**
+ * \class WideDynamicRange
+ * \brief RkISP1 Wide Dynamic Range algorithm
+ *
+ * This algorithm implements automatic global tone mapping for the RkISP1.
+ * Global tone mapping is done by the GWDR hardware block and applies
+ * a global tone mapping curve to the image to increase the perceived dynamic
+ * range. Imagine an indoor scene with bright outside visible through the
+ * windows. With normal exposure settings, the windows will be completely
+ * saturated and no structure (sky/clouds) will be visible because the AEGC has
+ * to increase overall exposure to reach a certain level of mean brightness. In
+ * WDR mode, the algorithm will artifically reduce the exposure time so that the
+ * texture and colours become visible in the formerly saturated areas. Then the
+ * global tone mapping curve is applied to mitigate the loss of brightness.
+ *
+ * Calculating that tone mapping curve is the most difficult part. This
+ * algorithm implements four tone mapping strategies:
+ * - Linear: The tone mapping curve is a combination of two linear functions
+ *   with one kneepoint
+ * - Power: The tone mapping curve follows a power function
+ * - Exponential: The tone mapping curve follows an exponential function
+ * - HistogramEqualization: The tone mapping curve tries to equalize the
+ *   histogram
+ *
+ * The overall strategy is the same in all cases: Add a constraint to the AEGC
+ * regulation so that the number of nearly saturated pixels goes below a given
+ * threshold (default 2%). This threshold can either be specified in the tuning
+ * file or set via the WdrMaxBrightPixels control.
+ *
+ * The global tone mapping curve is then calculated so that it accounts for the
+ * reduction of brightness due to the exposure constraint. We'll call this the
+ * WDR-gain. As the result of tone mapping is very difficult to quantize and is
+ * by definition a lossy process there is not a single "correct" solution on how
+ * this curve should look like.
+ *
+ * The approach taken here is based on a simple linear model. Consider a pixel
+ * that was originally 50% grey. It will have its exposure pushed down by the
+ * WDR's initial exposure compensation. This value then needs to be pushed back
+ * up by the tone mapping curve so that it is 50% grey again. This point serves
+ * as our kneepoint. To get to this kneepoint, this pixel and all darker pixels
+ * (to the left of the kneepoint on the tone mapping curve) will simply have the
+ * exposure compensation undone by WDR-gain. This cancels out the
+ * original exposure compensation, which was 1/WDR-gain. The remaining
+ * brigher pixels (to the right of the kneepoint on the tone mapping curve) will
+ * be compressed. The WdrStrength control adjusts the gain of the left part of
+ * the tone mapping curve.
+ *
+ * In the Power and Exponential modes, the curves are calculated so that they
+ * pass through that kneepoint.
+ *
+ * The histogram equalization mode tries to equalize the histogram of the
+ * image and acts independently of the calculated exposure value.
+ *
+ * \code{.unparsed}
+ * algorithms:
+ *   - WideDynamicRange:
+ *       ExposureConstraint:
+ *         MaxBrightPixels: 0.02
+ *         yTarget: 0.95
+ * \endcode
+ */
+
+LOG_DEFINE_CATEGORY(RkISP1Wdr)
+
+static constexpr unsigned int kTonecurveXIntervals = RKISP1_CIF_ISP_WDR_CURVE_NUM_INTERV;
+
+/*
+ * Increasing interval sizes. The intervals are crafted so that they sum
+ * up to 4096. This results in better fitting curves than the constant intervals
+ * (all entries are 4)
+ */
+static constexpr std::array<int, kTonecurveXIntervals> kLoglikeIntervals = {
+	{ 0, 0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4,
+	  4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6 }
+};
+
+WideDynamicRange::WideDynamicRange()
+{
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::init
+ */
+int WideDynamicRange::init([[maybe_unused]] IPAContext &context,
+			   [[maybe_unused]] const YamlObject &tuningData)
+{
+	if (!(context.hw.supportedBlocks & 1 << RKISP1_EXT_PARAMS_BLOCK_TYPE_WDR)) {
+		LOG(RkISP1Wdr, Error)
+			<< "Wide Dynamic Range not supported by the hardware or kernel.";
+		return -ENOTSUP;
+	}
+
+	toneCurveIntervalValues_ = kLoglikeIntervals;
+
+	/* Calculate a list of normed x values */
+	toneCurveX_[0] = 0.0;
+	int lastValue = 0;
+	for (unsigned int i = 1; i < toneCurveX_.size(); i++) {
+		lastValue += std::pow(2, toneCurveIntervalValues_[i - 1] + 3);
+		lastValue = std::min(lastValue, 4096);
+		toneCurveX_[i] = lastValue / 4096.0;
+	}
+
+	exposureConstraintMaxBrightPixels_ = 0.02;
+	exposureConstraintY_ = 0.95;
+
+	const auto &constraint = tuningData["ExposureConstraint"];
+	if (!constraint.isDictionary()) {
+		LOG(RkISP1Wdr, Warning)
+			<< "ExposureConstraint not found in tuning data."
+			   "Using default values MaxBrightPixels: "
+			<< exposureConstraintMaxBrightPixels_
+			<< " yTarget: " << exposureConstraintY_;
+	} else {
+		exposureConstraintMaxBrightPixels_ =
+			constraint["MaxBrightPixels"]
+				.get<double>()
+				.value_or(exposureConstraintMaxBrightPixels_);
+		exposureConstraintY_ =
+			constraint["yTarget"]
+				.get<double>()
+				.value_or(exposureConstraintY_);
+	}
+
+	context.ctrlMap[&controls::WdrMode] =
+		ControlInfo(controls::WdrModeValues, controls::WdrOff);
+	context.ctrlMap[&controls::WdrStrength] =
+		ControlInfo(0.0f, 2.0f, 1.0f);
+	context.ctrlMap[&controls::WdrMaxBrightPixels] =
+		ControlInfo(0.0f, 1.0f, static_cast<float>(exposureConstraintMaxBrightPixels_));
+
+	applyCompensationLinear(1.0, 0.0);
+
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::configure
+ */
+int WideDynamicRange::configure(IPAContext &context,
+				[[maybe_unused]] const IPACameraSensorInfo &configInfo)
+{
+	context.activeState.wdr.mode = controls::WdrOff;
+	context.activeState.wdr.gain = 1.0;
+	context.activeState.wdr.strength = 1.0;
+	auto &constraint = context.activeState.wdr.constraint;
+	constraint.bound = AgcMeanLuminance::AgcConstraint::Bound::Upper;
+	constraint.qHi = 1.0;
+	constraint.qLo = 1.0 - exposureConstraintMaxBrightPixels_;
+	constraint.yTarget.clear();
+	constraint.yTarget.append(0, exposureConstraintY_);
+	return 0;
+}
+
+void WideDynamicRange::applyHistogramEqualization(double strength)
+{
+	if (hist_.empty())
+		return;
+
+	/*
+	 * Apply a factor on strength, so that it roughly matches the optical
+	 * impression that is produced by the other algorithms. The goal is that
+	 * the user can switch algorithms for different looks but similar
+	 * "strength".
+	 */
+	strength *= 0.65;
+
+	/*
+	 * In a fully equalized histogram, all bins have the same value. Try
+	 * to equalize the histogram by applying a gain or damping depending on
+	 * the distance of the actual bin value from that norm.
+	 */
+	std::vector<double> gains;
+	gains.resize(hist_.size());
+	double sum = 0;
+	double norm = 1.0 / (gains.size());
+	for (unsigned i = 0; i < hist_.size(); i++) {
+		double diff = 1.0 + strength * (hist_[i] - norm) / norm;
+		gains[i] = diff;
+		sum += diff;
+	}
+
+	/* Never amplify the last entry. */
+	gains.back() = std::max(gains.back(), 1.0);
+
+	double scale = gains.size() / sum;
+	for (auto &v : gains)
+		v *= scale;
+
+	Pwl pwl;
+	double step = 1.0 / gains.size();
+	double lastX = 0;
+	double lastY = 0;
+
+	pwl.append(lastX, lastY);
+	for (unsigned int i = 0; i < gains.size() - 1; i++) {
+		lastY += gains[i] * step;
+		lastX += step;
+		pwl.append(lastX, lastY);
+	}
+	pwl.append(1.0, 1.0);
+
+	for (unsigned int i = 0; i < toneCurveX_.size(); i++)
+		toneCurveY_[i] = pwl.eval(toneCurveX_[i]);
+}
+
+Vector<double, 2> WideDynamicRange::kneePoint(double gain, double strength)
+{
+	gain = std::pow(gain, strength);
+	double y = 0.5;
+	double x = y / gain;
+
+	return { { x, y } };
+}
+
+void WideDynamicRange::applyCompensationLinear(double gain, double strength)
+{
+	auto kp = kneePoint(gain, strength);
+	double g1 = kp.y() / kp.x();
+	double g2 = (kp.y() - 1) / (kp.x() - 1);
+
+	for (unsigned int i = 0; i < toneCurveX_.size(); i++) {
+		double x = toneCurveX_[i];
+		double y;
+		if (x <= kp.x()) {
+			y = g1 * x;
+		} else {
+			y = g2 * x + 1 - g2;
+		}
+		toneCurveY_[i] = y;
+	}
+}
+
+void WideDynamicRange::applyCompensationPower(double gain, double strength)
+{
+	double e = 1.0;
+	if (strength > 1e-6) {
+		auto kp = kneePoint(gain, strength);
+		/* Calculate an exponent to go through the knee point. */
+		e = log(kp.y()) / log(kp.x());
+	}
+
+	/*
+	 * The power function tends to be extremely steep at the beginning. This
+	 * leads to noise and image artifacts in the dark areas. To mitigate
+	 * that, we add a short linear section at the beginning of the curve.
+	 * The connection between linear and power is the point where the linear
+	 * section reaches the y level yLin. The power curve is then scaled so
+	 * that it starts at the connection point with the steepness it would
+	 * have at y=yLin but still goes through 1,1
+	 */
+	double yLin = 0.1;
+	/* x position of the connection point */
+	double xb = yLin / gain;
+	/* x offset for the scaled power function */
+	double q = xb - std::exp(std::log(yLin) / e);
+
+	for (unsigned int i = 0; i < toneCurveX_.size(); i++) {
+		double x = toneCurveX_[i];
+		if (x < xb) {
+			toneCurveY_[i] = x * gain;
+		} else {
+			x = (x - q) / (1 - q);
+			toneCurveY_[i] = std::pow(x, e);
+		}
+	}
+}
+
+void WideDynamicRange::applyCompensationExponential(double gain, double strength)
+{
+	double k = 0.1;
+	auto kp = kneePoint(gain, strength);
+	double kx = kp.x();
+	double ky = kp.y();
+
+	if (kx > ky) {
+		LOG(RkISP1Wdr, Warning) << "Invalid knee point: " << kp;
+		kx = ky;
+	}
+
+	/*
+	 * The exponential curve is based on the function proposed by Glozman
+	 * et al. in
+	 * S. Glozman, T. Kats, and O. Yadid-Pecht, "Exponent Operator Based
+	 * Tone Mapping Algorithm for Color Wide Dynamic Range Images," 2011.
+	 *
+	 * That function uses a k factor as parameter for the WDR compression
+	 * curve:
+	 * k=0: maximum compression
+	 * k=infinity: linear curve
+	 *
+	 * To calculate a k factor that results in a curve that passes through
+	 * the kneepoint, the equation needs to be solved for k after inserting
+	 * the kneepoint.  This can be formulated as search for a zero point.
+	 * Unfortunately there is no closed solution for that transformation.
+	 * Using newton's method to approximate the value is numerically
+	 * unstable.
+	 *
+	 * Luckily the function only crosses the x axis once and for the set of
+	 * possible kneepoints, a negative and a positive point can be guessed.
+	 * The approximation is then implemented using bisection.
+	 */
+	if (std::abs(kx - ky) < 0.001) {
+		k = 1e8;
+	} else {
+		double kl = 0.0001;
+		double kh = 1000;
+
+		auto fk = [=](double v) {
+			return std::exp(-kx / v) -
+			       ky * std::exp(-1.0 / v) + ky - 1.0;
+		};
+
+		ASSERT(fk(kl) < 0);
+		ASSERT(fk(kh) > 0);
+
+		k = kh / 10.0;
+		while (fk(k) > 0) {
+			kh = k;
+			k /= 10.0;
+		}
+
+		do {
+			k = (kl + kh) / 2;
+			if (fk(k) < 0)
+				kl = k;
+			else
+				kh = k;
+		} while (std::abs(kh - kl) > 1e-3);
+	}
+
+	double a = 1.0 / (1.0 - std::exp(-1.0 / k));
+	for (unsigned int i = 0; i < toneCurveX_.size(); i++)
+		toneCurveY_[i] = a * (1.0 - std::exp(-toneCurveX_[i] / k));
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::queueRequest
+ */
+void WideDynamicRange::queueRequest([[maybe_unused]] IPAContext &context,
+				    [[maybe_unused]] const uint32_t frame,
+				    IPAFrameContext &frameContext,
+				    const ControlList &controls)
+{
+	auto &activeState = context.activeState;
+
+	const auto &mode = controls.get(controls::WdrMode);
+	if (mode)
+		activeState.wdr.mode = static_cast<controls::WdrModeEnum>(*mode);
+
+	const auto &brightPixels = controls.get(controls::WdrMaxBrightPixels);
+	if (brightPixels)
+		activeState.wdr.constraint.qLo = 1.0 - *brightPixels;
+
+	const auto &strength = controls.get(controls::WdrStrength);
+	if (strength)
+		activeState.wdr.strength = *strength;
+
+	frameContext.wdr.mode = activeState.wdr.mode;
+	frameContext.wdr.strength = activeState.wdr.strength;
+}
+
+/**
+ * \copydoc libcamera::ipa::Algorithm::prepare
+ */
+void WideDynamicRange::prepare(IPAContext &context,
+			       [[maybe_unused]] const uint32_t frame,
+			       IPAFrameContext &frameContext,
+			       RkISP1Params *params)
+{
+	if (!params) {
+		LOG(RkISP1Wdr, Warning) << "Params is null";
+		return;
+	}
+
+	auto mode = frameContext.wdr.mode;
+
+	auto config = params->block<BlockType::Wdr>();
+	config.setEnabled(mode != controls::WdrOff);
+
+	/* Calculate how much EV we need to compensate with the WDR curve. */
+	double gain = context.activeState.wdr.gain;
+	frameContext.wdr.gain = gain;
+
+	if (mode == controls::WdrOff) {
+		applyCompensationLinear(1.0, 0.0);
+	} else if (mode == controls::WdrLinear) {
+		applyCompensationLinear(gain, frameContext.wdr.strength);
+	} else if (mode == controls::WdrPower) {
+		applyCompensationPower(gain, frameContext.wdr.strength);
+	} else if (mode == controls::WdrExponential) {
+		applyCompensationExponential(gain, frameContext.wdr.strength);
+	} else if (mode == controls::WdrHistogramEqualization) {
+		applyHistogramEqualization(frameContext.wdr.strength);
+	}
+
+	/* Reset value */
+	config->dmin_strength = 0x10;
+	config->dmin_thresh = 0;
+
+	for (unsigned int i = 0; i < kTonecurveXIntervals; i++) {
+		int v = toneCurveIntervalValues_[i];
+		config->tone_curve.dY[i / 8] |= (v & 0x07) << ((i % 8) * 4);
+	}
+
+	/*
+	 * Fix the curve to adhere to the hardware constraints. Don't apply a
+	 * constraint on the first element, which is most likely zero anyways.
+	 */
+	int lastY = toneCurveY_[0] * 4096.0;
+	for (unsigned int i = 0; i < toneCurveX_.size(); i++) {
+		int diff = static_cast<int>(toneCurveY_[i] * 4096.0) - lastY;
+		diff = std::clamp(diff, -2048, 2048);
+		lastY = lastY + diff;
+		config->tone_curve.ym[i] = lastY;
+	}
+}
+
+void WideDynamicRange::process(IPAContext &context, [[maybe_unused]] const uint32_t frame,
+			       IPAFrameContext &frameContext,
+			       const rkisp1_stat_buffer *stats,
+			       ControlList &metadata)
+{
+	if (!stats || !(stats->meas_type & RKISP1_CIF_ISP_STAT_HIST)) {
+		LOG(RkISP1Wdr, Warning) << "No histogram data in statistics";
+		return;
+	}
+
+	const rkisp1_cif_isp_stat *params = &stats->params;
+	auto mode = frameContext.wdr.mode;
+
+	metadata.set(controls::WdrMode, mode);
+
+	Histogram cumHist({ params->hist.hist_bins, context.hw.numHistogramBins },
+			  [](uint32_t x) { return x >> 4; });
+
+	/* Calculate the gain needed to reach the requested yTarget. */
+	double value = cumHist.interQuantileMean(0, 1.0) / cumHist.bins();
+	double gain = context.activeState.agc.automatic.yTarget / value;
+	gain = std::max(gain, 1.0);
+
+	double speed = 0.2;
+	gain = gain * speed + context.activeState.wdr.gain * (1.0 - speed);
+
+	context.activeState.wdr.gain = gain;
+
+	std::vector<double> hist;
+	double sum = 0;
+	for (unsigned i = 0; i < context.hw.numHistogramBins; i++) {
+		double v = params->hist.hist_bins[i] >> 4;
+		hist.push_back(v);
+		sum += v;
+	}
+
+	/* Scale so that the entries sum up to 1. */
+	double scale = 1.0 / sum;
+	for (auto &v : hist)
+		v *= scale;
+	hist_.swap(hist);
+}
+
+REGISTER_IPA_ALGORITHM(WideDynamicRange, "WideDynamicRange")
+
+} /* namespace ipa::rkisp1::algorithms */
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/ipa/rkisp1/algorithms/wdr.h 0.6.0-2/src/ipa/rkisp1/algorithms/wdr.h
--- 0.5.0-1/src/ipa/rkisp1/algorithms/wdr.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/algorithms/wdr.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas On Board
+ *
+ * RkISP1 Wide Dynamic Range control
+ */
+
+#pragma once
+
+#include <libcamera/control_ids.h>
+
+#include "linux/rkisp1-config.h"
+
+#include "algorithm.h"
+
+namespace libcamera {
+
+namespace ipa::rkisp1::algorithms {
+
+class WideDynamicRange : public Algorithm
+{
+public:
+	WideDynamicRange();
+	~WideDynamicRange() = default;
+
+	int init(IPAContext &context, const YamlObject &tuningData) override;
+	int configure(IPAContext &context, const IPACameraSensorInfo &configInfo) override;
+
+	void queueRequest(IPAContext &context, const uint32_t frame,
+			  IPAFrameContext &frameContext,
+			  const ControlList &controls) override;
+	void prepare(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     RkISP1Params *params) override;
+	void process(IPAContext &context, const uint32_t frame,
+		     IPAFrameContext &frameContext,
+		     const rkisp1_stat_buffer *stats,
+		     ControlList &metadata) override;
+
+private:
+	Vector<double, 2> kneePoint(double gain, double strength);
+	void applyCompensationLinear(double gain, double strength);
+	void applyCompensationPower(double gain, double strength);
+	void applyCompensationExponential(double gain, double strength);
+	void applyHistogramEqualization(double strength);
+
+	double exposureConstraintMaxBrightPixels_;
+	double exposureConstraintY_;
+
+	std::vector<double> hist_;
+
+	std::array<int, RKISP1_CIF_ISP_WDR_CURVE_NUM_INTERV> toneCurveIntervalValues_;
+	std::array<double, RKISP1_CIF_ISP_WDR_CURVE_NUM_INTERV + 1> toneCurveX_;
+	std::array<double, RKISP1_CIF_ISP_WDR_CURVE_NUM_INTERV + 1> toneCurveY_;
+};
+
+} /* namespace ipa::rkisp1::algorithms */
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/ipa/rkisp1/ipa_context.cpp 0.6.0-2/src/ipa/rkisp1/ipa_context.cpp
--- 0.5.0-1/src/ipa/rkisp1/ipa_context.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/ipa_context.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -67,6 +67,14 @@ namespace libcamera::ipa::rkisp1 {
  */
 
 /**
+ * \var IPASessionConfiguration::compress
+ * \brief Compress parameters configuration of the IPA
+ *
+ * \var IPASessionConfiguration::agc.supported
+ * \brief true if compression is supported and the algorithm is loaded
+ */
+
+/**
  * \var IPASessionConfiguration::lsc
  * \brief Lens Shading Correction configuration of the IPA
  *
@@ -191,23 +199,37 @@ namespace libcamera::ipa::rkisp1 {
  * \var IPAActiveState::awb
  * \brief State for the Automatic White Balance algorithm
  *
- * \struct IPAActiveState::awb.gains
+ * \struct IPAActiveState::awb::AwbState
+ * \brief Struct for the AWB regulation state
+ *
+ * \var IPAActiveState::awb::AwbState.gains
  * \brief White balance gains
  *
- * \var IPAActiveState::awb.gains.manual
- * \brief Manual white balance gains (set through requests)
+ * \var IPAActiveState::awb::AwbState.temperatureK
+ * \brief Color temperature
  *
- * \var IPAActiveState::awb.gains.automatic
- * \brief Automatic white balance gains (computed by the algorithm)
+ * \var IPAActiveState::awb.manual
+ * \brief Manual regulation state (set through requests)
  *
- * \var IPAActiveState::awb.temperatureK
- * \brief Estimated color temperature
+ * \var IPAActiveState::awb.automatic
+ * \brief Automatic regulation state (computed by the algorithm)
  *
  * \var IPAActiveState::awb.autoEnabled
  * \brief Whether the Auto White Balance algorithm is enabled
  */
 
 /**
+ * \var IPAActiveState::ccm
+ * \brief State for the Colour Correction Matrix algorithm
+ *
+ * \var IPAActiveState::ccm.manual
+ * \brief Manual CCM (set through requests)
+ *
+ * \var IPAActiveState::awb.automatic
+ * \brief Automatic CCM (computed by the algorithm)
+ */
+
+/**
  * \var IPAActiveState::cproc
  * \brief State for the Color Processing algorithm
  *
@@ -346,13 +368,35 @@ namespace libcamera::ipa::rkisp1 {
  * \brief White balance gains
  *
  * \var IPAFrameContext::awb.temperatureK
- * \brief Estimated color temperature
+ * \brief Color temperature used for processing this frame
+ *
+ * This does not match the color temperature estimated for this frame as the
+ * measurements were taken on a previous frame.
  *
  * \var IPAFrameContext::awb.autoEnabled
  * \brief Whether the Auto White Balance algorithm is enabled
  */
 
 /**
+ * \var IPAFrameContext::ccm
+ * \brief Colour Correction Matrix parameters for this frame
+ *
+ * \struct IPAFrameContext::ccm.ccm
+ * \brief Colour Correction Matrix
+ */
+
+/**
+ * \var IPAFrameContext::compress
+ * \brief Compress parameters for this frame
+ *
+ * \struct IPAFrameContext::compress.enable
+ * \brief True if compression is enabled
+ *
+ * \var IPAFrameContext::compress.gain
+ * \brief The gain applied with the compression curve
+ */
+
+/**
  * \var IPAFrameContext::cproc
  * \brief Color Processing parameters for this frame
  *
diff -pruN 0.5.0-1/src/ipa/rkisp1/ipa_context.h 0.6.0-2/src/ipa/rkisp1/ipa_context.h
--- 0.5.0-1/src/ipa/rkisp1/ipa_context.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/ipa_context.h	2025-11-27 11:55:28.000000000 +0000
@@ -26,6 +26,7 @@
 
 #include <libipa/camera_sensor_helper.h>
 #include <libipa/fc_queue.h>
+#include "libipa/agc_mean_luminance.h"
 
 namespace libcamera {
 
@@ -36,6 +37,7 @@ struct IPAHwSettings {
 	unsigned int numHistogramBins;
 	unsigned int numHistogramWeights;
 	unsigned int numGammaOutSamples;
+	uint32_t supportedBlocks;
 	bool compand;
 };
 
@@ -50,6 +52,10 @@ struct IPASessionConfiguration {
 	} awb;
 
 	struct {
+		bool supported;
+	} compress;
+
+	struct {
 		bool enabled;
 	} lsc;
 
@@ -77,10 +83,13 @@ struct IPAActiveState {
 		struct {
 			uint32_t exposure;
 			double gain;
+			double quantizationGain;
+			double yTarget;
 		} automatic;
 
 		bool autoExposureEnabled;
 		bool autoGainEnabled;
+		double exposureValue;
 		controls::AeConstraintModeEnum constraintMode;
 		controls::AeExposureModeEnum exposureMode;
 		controls::AeMeteringModeEnum meteringMode;
@@ -89,17 +98,20 @@ struct IPAActiveState {
 	} agc;
 
 	struct {
-		struct {
-			RGB<double> manual;
-			RGB<double> automatic;
-		} gains;
+		struct AwbState {
+			RGB<double> gains;
+			unsigned int temperatureK;
+		};
+
+		AwbState manual;
+		AwbState automatic;
 
-		unsigned int temperatureK;
 		bool autoEnabled;
 	} awb;
 
 	struct {
-		Matrix<float, 3, 3> ccm;
+		Matrix<float, 3, 3> manual;
+		Matrix<float, 3, 3> automatic;
 	} ccm;
 
 	struct {
@@ -120,13 +132,27 @@ struct IPAActiveState {
 	struct {
 		double gamma;
 	} goc;
+
+	struct {
+		double lux;
+	} lux;
+
+	struct {
+		controls::WdrModeEnum mode;
+		AgcMeanLuminance::AgcConstraint constraint;
+		double gain;
+		double strength;
+	} wdr;
 };
 
 struct IPAFrameContext : public FrameContext {
 	struct {
 		uint32_t exposure;
 		double gain;
+		double exposureValue;
+		double quantizationGain;
 		uint32_t vblank;
+		double yTarget;
 		bool autoExposureEnabled;
 		bool autoGainEnabled;
 		controls::AeConstraintModeEnum constraintMode;
@@ -154,6 +180,11 @@ struct IPAFrameContext : public FrameCon
 	} cproc;
 
 	struct {
+		bool enable;
+		double gain;
+	} compress;
+
+	struct {
 		bool denoise;
 		bool update;
 	} dpf;
@@ -181,15 +212,21 @@ struct IPAFrameContext : public FrameCon
 	struct {
 		double lux;
 	} lux;
+
+	struct {
+		controls::WdrModeEnum mode;
+		double strength;
+		double gain;
+	} wdr;
 };
 
 struct IPAContext {
 	IPAContext(unsigned int frameContextSize)
-		: hw(nullptr), frameContexts(frameContextSize)
+		: frameContexts(frameContextSize)
 	{
 	}
 
-	const IPAHwSettings *hw;
+	IPAHwSettings hw;
 	IPACameraSensorInfo sensorInfo;
 	IPASessionConfiguration configuration;
 	IPAActiveState activeState;
diff -pruN 0.5.0-1/src/ipa/rkisp1/params.cpp 0.6.0-2/src/ipa/rkisp1/params.cpp
--- 0.5.0-1/src/ipa/rkisp1/params.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/params.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -74,6 +74,7 @@ const std::map<BlockType, BlockTypeInfo>
 	RKISP1_BLOCK_TYPE_ENTRY_EXT(CompandBls, COMPAND_BLS, compand_bls),
 	RKISP1_BLOCK_TYPE_ENTRY_EXT(CompandExpand, COMPAND_EXPAND, compand_curve),
 	RKISP1_BLOCK_TYPE_ENTRY_EXT(CompandCompress, COMPAND_COMPRESS, compand_curve),
+	RKISP1_BLOCK_TYPE_ENTRY_EXT(Wdr, WDR, wdr),
 };
 
 } /* namespace */
diff -pruN 0.5.0-1/src/ipa/rkisp1/params.h 0.6.0-2/src/ipa/rkisp1/params.h
--- 0.5.0-1/src/ipa/rkisp1/params.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/params.h	2025-11-27 11:55:28.000000000 +0000
@@ -40,6 +40,7 @@ enum class BlockType {
 	CompandBls,
 	CompandExpand,
 	CompandCompress,
+	Wdr,
 };
 
 namespace details {
@@ -74,6 +75,7 @@ RKISP1_DEFINE_BLOCK_TYPE(Afc, afc)
 RKISP1_DEFINE_BLOCK_TYPE(CompandBls, compand_bls)
 RKISP1_DEFINE_BLOCK_TYPE(CompandExpand, compand_curve)
 RKISP1_DEFINE_BLOCK_TYPE(CompandCompress, compand_curve)
+RKISP1_DEFINE_BLOCK_TYPE(Wdr, wdr)
 
 } /* namespace details */
 
diff -pruN 0.5.0-1/src/ipa/rkisp1/rkisp1.cpp 0.6.0-2/src/ipa/rkisp1/rkisp1.cpp
--- 0.5.0-1/src/ipa/rkisp1/rkisp1.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rkisp1/rkisp1.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -52,6 +52,7 @@ public:
 	IPARkISP1();
 
 	int init(const IPASettings &settings, unsigned int hwRevision,
+		 uint32_t supportedBlocks,
 		 const IPACameraSensorInfo &sensorInfo,
 		 const ControlInfoMap &sensorControls,
 		 ControlInfoMap *ipaControls) override;
@@ -94,6 +95,7 @@ const IPAHwSettings ipaHwSettingsV10{
 	RKISP1_CIF_ISP_HIST_BIN_N_MAX_V10,
 	RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE_V10,
 	RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10,
+	0,
 	false,
 };
 
@@ -102,6 +104,7 @@ const IPAHwSettings ipaHwSettingsIMX8MP{
 	RKISP1_CIF_ISP_HIST_BIN_N_MAX_V10,
 	RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE_V10,
 	RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V10,
+	0,
 	true,
 };
 
@@ -110,15 +113,13 @@ const IPAHwSettings ipaHwSettingsV12{
 	RKISP1_CIF_ISP_HIST_BIN_N_MAX_V12,
 	RKISP1_CIF_ISP_HISTOGRAM_WEIGHT_GRIDS_SIZE_V12,
 	RKISP1_CIF_ISP_GAMMA_OUT_MAX_SAMPLES_V12,
+	0,
 	false,
 };
 
 /* List of controls handled by the RkISP1 IPA */
 const ControlInfoMap::Map rkisp1Controls{
-	{ &controls::AwbEnable, ControlInfo(false, true) },
-	{ &controls::ColourGains, ControlInfo(0.0f, 3.996f, 1.0f) },
 	{ &controls::DebugMetadataEnable, ControlInfo(false, true, false) },
-	{ &controls::Sharpness, ControlInfo(0.0f, 10.0f, 1.0f) },
 	{ &controls::draft::NoiseReductionMode, ControlInfo(controls::draft::NoiseReductionModeValues) },
 };
 
@@ -135,6 +136,7 @@ std::string IPARkISP1::logPrefix() const
 }
 
 int IPARkISP1::init(const IPASettings &settings, unsigned int hwRevision,
+		    uint32_t supportedBlocks,
 		    const IPACameraSensorInfo &sensorInfo,
 		    const ControlInfoMap &sensorControls,
 		    ControlInfoMap *ipaControls)
@@ -142,13 +144,13 @@ int IPARkISP1::init(const IPASettings &s
 	/* \todo Add support for other revisions */
 	switch (hwRevision) {
 	case RKISP1_V10:
-		context_.hw = &ipaHwSettingsV10;
+		context_.hw = ipaHwSettingsV10;
 		break;
 	case RKISP1_V_IMX8MP:
-		context_.hw = &ipaHwSettingsIMX8MP;
+		context_.hw = ipaHwSettingsIMX8MP;
 		break;
 	case RKISP1_V12:
-		context_.hw = &ipaHwSettingsV12;
+		context_.hw = ipaHwSettingsV12;
 		break;
 	default:
 		LOG(IPARkISP1, Error)
@@ -156,6 +158,7 @@ int IPARkISP1::init(const IPASettings &s
 			<< " is currently not supported";
 		return -ENODEV;
 	}
+	context_.hw.supportedBlocks = supportedBlocks;
 
 	LOG(IPARkISP1, Debug) << "Hardware revision is " << hwRevision;
 
@@ -436,7 +439,8 @@ void IPARkISP1::updateControls(const IPA
 
 	/* \todo Move this (and other agc-related controls) to agc */
 	context_.ctrlMap[&controls::FrameDurationLimits] =
-		ControlInfo(frameDurations[0], frameDurations[1], frameDurations[2]);
+		ControlInfo(frameDurations[0], frameDurations[1],
+			    ControlValue(Span<const int64_t, 2>{ { frameDurations[2], frameDurations[2] } }));
 
 	ctrlMap.insert(context_.ctrlMap.begin(), context_.ctrlMap.end());
 	*ipaControls = ControlInfoMap(std::move(ctrlMap), controls::controls);
diff -pruN 0.5.0-1/src/ipa/rpi/cam_helper/cam_helper_imx283.cpp 0.6.0-2/src/ipa/rpi/cam_helper/cam_helper_imx283.cpp
--- 0.5.0-1/src/ipa/rpi/cam_helper/cam_helper_imx283.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/cam_helper/cam_helper_imx283.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Raspberry Pi Ltd
  *
- * cam_helper_Imx283.cpp - camera information for Imx283 sensor
+ * camera information for Imx283 sensor
  */
 
 #include <assert.h>
diff -pruN 0.5.0-1/src/ipa/rpi/cam_helper/cam_helper_vd55g1.cpp 0.6.0-2/src/ipa/rpi/cam_helper/cam_helper_vd55g1.cpp
--- 0.5.0-1/src/ipa/rpi/cam_helper/cam_helper_vd55g1.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/cam_helper/cam_helper_vd55g1.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) STMicroelectronics SA 2025
+ *
+ * Camera information for vd55g1 sensor
+ */
+
+#include <assert.h>
+
+#include "cam_helper.h"
+
+using namespace RPiController;
+
+class CamHelperVd55g1 : public CamHelper
+{
+public:
+	CamHelperVd55g1();
+	uint32_t gainCode(double gain) const override;
+	double gain(uint32_t gainCode) const override;
+
+private:
+	/*
+	 * Smallest difference between the frame length and integration time,
+	 * in units of lines.
+	 */
+	static constexpr int frameIntegrationDiff = 64;
+};
+
+CamHelperVd55g1::CamHelperVd55g1()
+	: CamHelper({}, frameIntegrationDiff)
+{
+}
+
+uint32_t CamHelperVd55g1::gainCode(double gain) const
+{
+	return static_cast<uint32_t>(32.0 - 32.0 / gain);
+}
+
+double CamHelperVd55g1::gain(uint32_t gainCode) const
+{
+	return 32.0 / (32.0 - static_cast<double>(gainCode));
+}
+
+static CamHelper *create()
+{
+	return new CamHelperVd55g1();
+}
+
+static RegisterCamHelper reg("vd55g1", &create);
diff -pruN 0.5.0-1/src/ipa/rpi/cam_helper/cam_helper_vd56g3.cpp 0.6.0-2/src/ipa/rpi/cam_helper/cam_helper_vd56g3.cpp
--- 0.5.0-1/src/ipa/rpi/cam_helper/cam_helper_vd56g3.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/cam_helper/cam_helper_vd56g3.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) STMicroelectronics SA 2025
+ *
+ * Camera information for vd56g3 sensor
+ */
+
+#include <assert.h>
+
+#include "cam_helper.h"
+
+using namespace RPiController;
+
+class CamHelperVd56g3 : public CamHelper
+{
+public:
+	CamHelperVd56g3();
+	uint32_t gainCode(double gain) const override;
+	double gain(uint32_t gainCode) const override;
+
+private:
+	/*
+	 * Smallest difference between the frame length and integration time,
+	 * in units of lines.
+	 */
+	static constexpr int frameIntegrationDiff = 75;
+};
+
+CamHelperVd56g3::CamHelperVd56g3()
+	: CamHelper({}, frameIntegrationDiff)
+{
+}
+
+uint32_t CamHelperVd56g3::gainCode(double gain) const
+{
+	return static_cast<uint32_t>(32.0 - 32.0 / gain);
+}
+
+double CamHelperVd56g3::gain(uint32_t gainCode) const
+{
+	return static_cast<double>(32.0 / (32 - gainCode));
+}
+
+static CamHelper *create()
+{
+	return new CamHelperVd56g3();
+}
+
+static RegisterCamHelper reg("vd56g3", &create);
diff -pruN 0.5.0-1/src/ipa/rpi/cam_helper/meson.build 0.6.0-2/src/ipa/rpi/cam_helper/meson.build
--- 0.5.0-1/src/ipa/rpi/cam_helper/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/cam_helper/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -14,6 +14,8 @@ rpi_ipa_cam_helper_sources = files([
     'cam_helper_ov64a40.cpp',
     'cam_helper_ov7251.cpp',
     'cam_helper_ov9281.cpp',
+    'cam_helper_vd55g1.cpp',
+    'cam_helper_vd56g3.cpp',
     'md_parser_smia.cpp',
 ])
 
diff -pruN 0.5.0-1/src/ipa/rpi/common/ipa_base.cpp 0.6.0-2/src/ipa/rpi/common/ipa_base.cpp
--- 0.5.0-1/src/ipa/rpi/common/ipa_base.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/common/ipa_base.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,7 @@
 
 #include "ipa_base.h"
 
+#include <array>
 #include <cmath>
 
 #include <libcamera/base/log.h>
@@ -58,23 +59,24 @@ const ControlInfoMap::Map ipaControls{
 	/* \todo Move this to the Camera class */
 	{ &controls::AeEnable, ControlInfo(false, true, true) },
 	{ &controls::ExposureTimeMode,
-	  ControlInfo(static_cast<int32_t>(controls::ExposureTimeModeAuto),
-		      static_cast<int32_t>(controls::ExposureTimeModeManual),
-		      static_cast<int32_t>(controls::ExposureTimeModeAuto)) },
+	  ControlInfo({ { ControlValue(controls::ExposureTimeModeAuto),
+			  ControlValue(controls::ExposureTimeModeManual) } },
+		      ControlValue(controls::ExposureTimeModeAuto)) },
 	{ &controls::ExposureTime,
 	  ControlInfo(1, 66666, static_cast<int32_t>(defaultExposureTime.get<std::micro>())) },
 	{ &controls::AnalogueGainMode,
-	  ControlInfo(static_cast<int32_t>(controls::AnalogueGainModeAuto),
-		      static_cast<int32_t>(controls::AnalogueGainModeManual),
-		      static_cast<int32_t>(controls::AnalogueGainModeAuto)) },
+	  ControlInfo({ { ControlValue(controls::AnalogueGainModeAuto),
+			  ControlValue(controls::AnalogueGainModeManual) } },
+		      ControlValue(controls::AnalogueGainModeAuto)) },
 	{ &controls::AnalogueGain, ControlInfo(1.0f, 16.0f, 1.0f) },
 	{ &controls::AeMeteringMode, ControlInfo(controls::AeMeteringModeValues) },
 	{ &controls::AeConstraintMode, ControlInfo(controls::AeConstraintModeValues) },
 	{ &controls::AeExposureMode, ControlInfo(controls::AeExposureModeValues) },
 	{ &controls::ExposureValue, ControlInfo(-8.0f, 8.0f, 0.0f) },
-	{ &controls::AeFlickerMode, ControlInfo(static_cast<int>(controls::FlickerOff),
-						static_cast<int>(controls::FlickerManual),
-						static_cast<int>(controls::FlickerOff)) },
+	{ &controls::AeFlickerMode,
+	  ControlInfo({ { ControlValue(controls::FlickerOff),
+			  ControlValue(controls::FlickerManual) } },
+		      ControlValue(controls::FlickerOff)) },
 	{ &controls::AeFlickerPeriod, ControlInfo(100, 1000000) },
 	{ &controls::Brightness, ControlInfo(-1.0f, 1.0f, 0.0f) },
 	{ &controls::Contrast, ControlInfo(0.0f, 32.0f, 1.0f) },
@@ -93,6 +95,7 @@ const ControlInfoMap::Map ipaColourContr
 	{ &controls::AwbEnable, ControlInfo(false, true) },
 	{ &controls::AwbMode, ControlInfo(controls::AwbModeValues) },
 	{ &controls::ColourGains, ControlInfo(0.0f, 32.0f) },
+	{ &controls::ColourCorrectionMatrix, ControlInfo(0.0f, 8.0f) },
 	{ &controls::ColourTemperature, ControlInfo(100, 100000) },
 	{ &controls::Saturation, ControlInfo(0.0f, 32.0f, 1.0f) },
 };
@@ -103,7 +106,8 @@ const ControlInfoMap::Map ipaAfControls{
 	{ &controls::AfRange, ControlInfo(controls::AfRangeValues) },
 	{ &controls::AfSpeed, ControlInfo(controls::AfSpeedValues) },
 	{ &controls::AfMetering, ControlInfo(controls::AfMeteringValues) },
-	{ &controls::AfWindows, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535), Rectangle{}) },
+	{ &controls::AfWindows, ControlInfo(Rectangle{}, Rectangle(65535, 65535, 65535, 65535),
+					    Span<const Rectangle, 1>{ { Rectangle{} } }) },
 	{ &controls::AfTrigger, ControlInfo(controls::AfTriggerValues) },
 	{ &controls::AfPause, ControlInfo(controls::AfPauseValues) },
 	{ &controls::LensPosition, ControlInfo(0.0f, 32.0f, 1.0f) }
@@ -125,7 +129,7 @@ namespace ipa::RPi {
 IpaBase::IpaBase()
 	: controller_(), frameLengths_(FrameLengthsQueueSize, 0s), statsMetadataOutput_(false),
 	  stitchSwapBuffers_(false), frameCount_(0), mistrustCount_(0), lastRunTimestamp_(0),
-	  firstStart_(true), flickerState_({ 0, 0s })
+	  firstStart_(true), flickerState_({ 0, 0s }), awbEnabled_(true)
 {
 }
 
@@ -232,25 +236,6 @@ int32_t IpaBase::configure(const IPACame
 		agcStatus.analogueGain = defaultAnalogueGain;
 		applyAGC(&agcStatus, ctrls);
 
-		/*
-		 * Set the lens to the default (typically hyperfocal) position
-		 * on first start.
-		 */
-		if (lensPresent_) {
-			RPiController::AfAlgorithm *af =
-				dynamic_cast<RPiController::AfAlgorithm *>(controller_.getAlgorithm("af"));
-
-			if (af) {
-				float defaultPos =
-					ipaAfControls.at(&controls::LensPosition).def().get<float>();
-				ControlList lensCtrl(lensCtrls_);
-				int32_t hwpos;
-
-				af->setLensPosition(defaultPos, &hwpos);
-				lensCtrl.set(V4L2_CID_FOCUS_ABSOLUTE, hwpos);
-				result->lensControls = std::move(lensCtrl);
-			}
-		}
 	}
 
 	result->sensorControls = std::move(ctrls);
@@ -263,7 +248,8 @@ int32_t IpaBase::configure(const IPACame
 	ctrlMap[&controls::FrameDurationLimits] =
 		ControlInfo(static_cast<int64_t>(mode_.minFrameDuration.get<std::micro>()),
 			    static_cast<int64_t>(mode_.maxFrameDuration.get<std::micro>()),
-			    static_cast<int64_t>(defaultMinFrameDuration.get<std::micro>()));
+			    Span<const int64_t, 2>{ { static_cast<int64_t>(defaultMinFrameDuration.get<std::micro>()),
+						      static_cast<int64_t>(defaultMinFrameDuration.get<std::micro>()) } });
 
 	ctrlMap[&controls::AnalogueGain] =
 		ControlInfo(static_cast<float>(mode_.minAnalogueGain),
@@ -280,8 +266,20 @@ int32_t IpaBase::configure(const IPACame
 		ctrlMap.merge(ControlInfoMap::Map(ipaColourControls));
 
 	/* Declare Autofocus controls, only if we have a controllable lens */
-	if (lensPresent_)
+	if (lensPresent_) {
 		ctrlMap.merge(ControlInfoMap::Map(ipaAfControls));
+		RPiController::AfAlgorithm *af =
+			dynamic_cast<RPiController::AfAlgorithm *>(controller_.getAlgorithm("af"));
+		if (af) {
+			double min, max, dflt;
+			af->getLensLimits(min, max);
+			dflt = af->getDefaultLensPosition();
+			ctrlMap[&controls::LensPosition] =
+				ControlInfo(static_cast<float>(min),
+					    static_cast<float>(max),
+					    static_cast<float>(dflt));
+		}
+	}
 
 	result->controlInfo = ControlInfoMap(std::move(ctrlMap), controls::controls);
 
@@ -304,29 +302,53 @@ void IpaBase::start(const ControlList &c
 	frameLengths_.clear();
 	frameLengths_.resize(FrameLengthsQueueSize, 0s);
 
-	/* SwitchMode may supply updated exposure/gain values to use. */
-	AgcStatus agcStatus;
-	agcStatus.exposureTime = 0.0s;
-	agcStatus.analogueGain = 0.0;
+	/*
+	 * SwitchMode may supply updated exposure/gain values to use.
+	 * agcStatus_ will store these values for us to use until delayed_status values
+	 * start to appear.
+	 */
+	agcStatus_.exposureTime = 0.0s;
+	agcStatus_.analogueGain = 0.0;
 
-	metadata.get("agc.status", agcStatus);
-	if (agcStatus.exposureTime && agcStatus.analogueGain) {
+	metadata.get("agc.status", agcStatus_);
+	if (agcStatus_.exposureTime && agcStatus_.analogueGain) {
 		ControlList ctrls(sensorCtrls_);
-		applyAGC(&agcStatus, ctrls);
+		applyAGC(&agcStatus_, ctrls);
 		result->controls = std::move(ctrls);
 		setCameraTimeoutValue();
 	}
 	/* Make a note of this as it tells us the HDR status of the first few frames. */
-	hdrStatus_ = agcStatus.hdr;
+	hdrStatus_ = agcStatus_.hdr;
+
+	/*
+	 * AF: If no lens position was specified, drive lens to a default position.
+	 * This had to be deferred (not initialised by a constructor) until here
+	 * to ensure that exactly ONE starting position is sent to the lens driver.
+	 * It should be the static API default, not dependent on AF range or mode.
+	 */
+	if (firstStart_ && lensPresent_) {
+		RPiController::AfAlgorithm *af = dynamic_cast<RPiController::AfAlgorithm *>(
+			controller_.getAlgorithm("af"));
+		if (af && !af->getLensPosition()) {
+			int32_t hwpos;
+			double pos = af->getDefaultLensPosition();
+			if (af->setLensPosition(pos, &hwpos, true)) {
+				ControlList lensCtrls(lensCtrls_);
+				lensCtrls.set(V4L2_CID_FOCUS_ABSOLUTE, hwpos);
+				setLensControls.emit(lensCtrls);
+			}
+		}
+	}
 
 	/*
 	 * Initialise frame counts, and decide how many frames must be hidden or
 	 * "mistrusted", which depends on whether this is a startup from cold,
 	 * or merely a mode switch in a running system.
 	 */
+	unsigned int agcConvergenceFrames = 0, awbConvergenceFrames = 0;
 	frameCount_ = 0;
 	if (firstStart_) {
-		dropFrameCount_ = helper_->hideFramesStartup();
+		invalidCount_ = helper_->hideFramesStartup();
 		mistrustCount_ = helper_->mistrustFramesStartup();
 
 		/*
@@ -336,7 +358,6 @@ void IpaBase::start(const ControlList &c
 		 * (mistrustCount_) that they won't see. But if zero (i.e.
 		 * no convergence necessary), no frames need to be dropped.
 		 */
-		unsigned int agcConvergenceFrames = 0;
 		RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
 			controller_.getAlgorithm("agc"));
 		if (agc) {
@@ -345,7 +366,6 @@ void IpaBase::start(const ControlList &c
 				agcConvergenceFrames += mistrustCount_;
 		}
 
-		unsigned int awbConvergenceFrames = 0;
 		RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
 			controller_.getAlgorithm("awb"));
 		if (awb) {
@@ -353,15 +373,18 @@ void IpaBase::start(const ControlList &c
 			if (awbConvergenceFrames)
 				awbConvergenceFrames += mistrustCount_;
 		}
-
-		dropFrameCount_ = std::max({ dropFrameCount_, agcConvergenceFrames, awbConvergenceFrames });
-		LOG(IPARPI, Debug) << "Drop " << dropFrameCount_ << " frames on startup";
 	} else {
-		dropFrameCount_ = helper_->hideFramesModeSwitch();
+		invalidCount_ = helper_->hideFramesModeSwitch();
 		mistrustCount_ = helper_->mistrustFramesModeSwitch();
 	}
 
-	result->dropFrameCount = dropFrameCount_;
+	result->startupFrameCount = std::max({ agcConvergenceFrames, awbConvergenceFrames });
+	result->invalidFrameCount = invalidCount_;
+
+	invalidCount_ = std::max({ invalidCount_, agcConvergenceFrames, awbConvergenceFrames });
+
+	LOG(IPARPI, Debug) << "Startup frames: " << result->startupFrameCount
+			   << " Invalid frames: " << result->invalidFrameCount;
 
 	firstStart_ = false;
 	lastRunTimestamp_ = 0;
@@ -441,7 +464,7 @@ void IpaBase::prepareIsp(const PreparePa
 
 	/* Allow a 10% margin on the comparison below. */
 	Duration delta = (frameTimestamp - lastRunTimestamp_) * 1.0ns;
-	if (lastRunTimestamp_ && frameCount_ > dropFrameCount_ &&
+	if (lastRunTimestamp_ && frameCount_ > invalidCount_ &&
 	    delta < controllerMinFrameDuration * 0.9 && !hdrChange) {
 		/*
 		 * Ensure we merge the previous frame's metadata with the current
@@ -470,7 +493,9 @@ void IpaBase::prepareIsp(const PreparePa
 		controller_.prepare(&rpiMetadata);
 		/* Actually prepare the ISP parameters for the frame. */
 		platformPrepareIsp(params, rpiMetadata);
-	}
+		platformPrepareAgc(rpiMetadata);
+	} else
+		platformPrepareAgc(rpiMetadata);
 
 	frameCount_++;
 
@@ -485,10 +510,9 @@ void IpaBase::prepareIsp(const PreparePa
 void IpaBase::processStats(const ProcessParams &params)
 {
 	unsigned int ipaContext = params.ipaContext % rpiMetadata_.size();
+	RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext];
 
 	if (processPending_ && frameCount_ >= mistrustCount_) {
-		RPiController::Metadata &rpiMetadata = rpiMetadata_[ipaContext];
-
 		auto it = buffers_.find(params.buffers.stats);
 		if (it == buffers_.end()) {
 			LOG(IPARPI, Error) << "Could not find stats buffer!";
@@ -502,14 +526,15 @@ void IpaBase::processStats(const Process
 
 		helper_->process(statistics, rpiMetadata);
 		controller_.process(statistics, &rpiMetadata);
+	}
 
-		struct AgcStatus agcStatus;
-		if (rpiMetadata.get("agc.status", agcStatus) == 0) {
-			ControlList ctrls(sensorCtrls_);
-			applyAGC(&agcStatus, ctrls);
-			setDelayedControls.emit(ctrls, ipaContext);
-			setCameraTimeoutValue();
-		}
+	struct AgcStatus agcStatus;
+	if (rpiMetadata.get("agc.status", agcStatus) == 0) {
+		ControlList ctrls(sensorCtrls_);
+		applyAGC(&agcStatus, ctrls);
+		rpiMetadata.set("agc.status", agcStatus);
+		setDelayedControls.emit(ctrls, ipaContext);
+		setCameraTimeoutValue();
 	}
 
 	/*
@@ -800,6 +825,102 @@ void IpaBase::applyControls(const Contro
 		}
 	}
 
+	/*
+	 * We must also handle any AWB on/off changes first, so that the CCM algorithm
+	 * knows its state correctly.
+	 */
+	const auto awbEnable = controls.get(controls::AwbEnable);
+	if (awbEnable)
+		do {
+			/* Silently ignore this control for a mono sensor. */
+			if (monoSensor_)
+				break;
+
+			RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
+				controller_.getAlgorithm("awb"));
+			if (!awb) {
+				LOG(IPARPI, Warning)
+					<< "Could not set AWB_ENABLE - no AWB algorithm";
+				break;
+			}
+
+			awbEnabled_ = *awbEnable;
+
+			if (!awbEnabled_)
+				awb->disableAuto();
+			else {
+				awb->enableAuto();
+
+				/* The CCM algorithm must go back to auto as well. */
+				RPiController::CcmAlgorithm *ccm = dynamic_cast<RPiController::CcmAlgorithm *>(
+					controller_.getAlgorithm("ccm"));
+				if (ccm)
+					ccm->enableAuto();
+			}
+
+			libcameraMetadata_.set(controls::AwbEnable, awbEnabled_);
+		} while (false);
+
+	const auto colourGains = controls.get(controls::ColourGains);
+	if (colourGains)
+		do {
+			/* Silently ignore this control for a mono sensor. */
+			if (monoSensor_)
+				break;
+
+			auto gains = *colourGains;
+			RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
+				controller_.getAlgorithm("awb"));
+			if (!awb) {
+				LOG(IPARPI, Warning)
+					<< "Could not set COLOUR_GAINS - no AWB algorithm";
+				break;
+			}
+
+			awb->setManualGains(gains[0], gains[1]);
+			if (gains[0] != 0.0f && gains[1] != 0.0f) {
+				/* A gain of 0.0f will switch back to auto mode. */
+				libcameraMetadata_.set(controls::ColourGains,
+						       { gains[0], gains[1] });
+
+				awbEnabled_ = false; /* doing this puts AWB into manual mode */
+			} else {
+				awbEnabled_ = true; /* doing this puts AWB into auto mode */
+
+				/* The CCM algorithm must go back to auto as well. */
+				RPiController::CcmAlgorithm *ccm = dynamic_cast<RPiController::CcmAlgorithm *>(
+					controller_.getAlgorithm("ccm"));
+				if (ccm)
+					ccm->enableAuto();
+			}
+
+			/* This metadata will get reported back automatically. */
+			break;
+		} while (false);
+
+	const auto colourTemperature = controls.get(controls::ColourTemperature);
+	if (colourTemperature)
+		do {
+			/* Silently ignore this control for a mono sensor. */
+			if (monoSensor_)
+				break;
+
+			auto temperatureK = *colourTemperature;
+			RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
+				controller_.getAlgorithm("awb"));
+			if (!awb) {
+				LOG(IPARPI, Warning)
+					<< "Could not set COLOUR_TEMPERATURE - no AWB algorithm";
+				break;
+			}
+
+			awb->setColourTemperature(temperatureK);
+			awbEnabled_ = false; /* doing this puts AWB into manual mode */
+
+			/* This metadata will get reported back automatically. */
+			break;
+		} while (false);
+
 	/* Iterate over controls */
 	for (auto const &ctrl : controls) {
 		LOG(IPARPI, Debug) << "Request ctrl: "
@@ -852,7 +973,7 @@ void IpaBase::applyControls(const Contro
 			if (agc->autoGainEnabled())
 				break;
 
-			agc->setFixedAnalogueGain(0, ctrl.second.get<float>());
+			agc->setFixedGain(0, ctrl.second.get<float>());
 
 			libcameraMetadata_.set(controls::AnalogueGain,
 					       ctrl.second.get<float>());
@@ -908,13 +1029,6 @@ void IpaBase::applyControls(const Contro
 				break;
 			}
 
-			/*
-			 * Ignore AE_EXPOSURE_MODE if the shutter or the gain
-			 * are in auto mode.
-			 */
-			if (agc->autoExposureEnabled() || agc->autoGainEnabled())
-				break;
-
 			int32_t idx = ctrl.second.get<int32_t>();
 			if (ExposureModeTable.count(idx)) {
 				agc->setExposureMode(ExposureModeTable.at(idx));
@@ -946,6 +1060,17 @@ void IpaBase::applyControls(const Contro
 			break;
 		}
 
+		case controls::AE_ENABLE: {
+			/*
+			 * The AeEnable control is now just a wrapper that will already have been
+			 * converted to ExposureTimeMode and AnalogueGainMode equivalents, so there
+			 * would be nothing to do here. Nonetheless, "handle" the control so as to
+			 * avoid warnings from the "default:" clause of the switch statement.
+			 */
+
+			break;
+		}
+
 		case controls::AE_FLICKER_MODE: {
 			RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
 				controller_.getAlgorithm("agc"));
@@ -1005,25 +1130,7 @@ void IpaBase::applyControls(const Contro
 		}
 
 		case controls::AWB_ENABLE: {
-			/* Silently ignore this control for a mono sensor. */
-			if (monoSensor_)
-				break;
-
-			RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
-				controller_.getAlgorithm("awb"));
-			if (!awb) {
-				LOG(IPARPI, Warning)
-					<< "Could not set AWB_ENABLE - no AWB algorithm";
-				break;
-			}
-
-			if (ctrl.second.get<bool>() == false)
-				awb->disableAuto();
-			else
-				awb->enableAuto();
-
-			libcameraMetadata_.set(controls::AwbEnable,
-					       ctrl.second.get<bool>());
+			/* We handled this one above. */
 			break;
 		}
 
@@ -1048,47 +1155,60 @@ void IpaBase::applyControls(const Contro
 				LOG(IPARPI, Error) << "AWB mode " << idx
 						   << " not recognised";
 			}
+
 			break;
 		}
 
 		case controls::COLOUR_GAINS: {
-			/* Silently ignore this control for a mono sensor. */
-			if (monoSensor_)
-				break;
-
-			auto gains = ctrl.second.get<Span<const float>>();
-			RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
-				controller_.getAlgorithm("awb"));
-			if (!awb) {
-				LOG(IPARPI, Warning)
-					<< "Could not set COLOUR_GAINS - no AWB algorithm";
-				break;
-			}
-
-			awb->setManualGains(gains[0], gains[1]);
-			if (gains[0] != 0.0f && gains[1] != 0.0f)
-				/* A gain of 0.0f will switch back to auto mode. */
-				libcameraMetadata_.set(controls::ColourGains,
-						       { gains[0], gains[1] });
+			/* We handled this one above. */
 			break;
 		}
 
 		case controls::COLOUR_TEMPERATURE: {
-			/* Silently ignore this control for a mono sensor. */
+			/* We handled this one above. */
+			break;
+		}
+
+		case controls::COLOUR_CORRECTION_MATRIX: {
 			if (monoSensor_)
 				break;
 
-			auto temperatureK = ctrl.second.get<int32_t>();
+			auto floats = ctrl.second.get<Span<const float>>();
+			RPiController::CcmAlgorithm *ccm = dynamic_cast<RPiController::CcmAlgorithm *>(
+				controller_.getAlgorithm("ccm"));
+			if (!ccm) {
+				LOG(IPARPI, Warning)
+					<< "Could not set COLOUR_CORRECTION_MATRIX - no CCM algorithm";
+				break;
+			}
+
 			RPiController::AwbAlgorithm *awb = dynamic_cast<RPiController::AwbAlgorithm *>(
 				controller_.getAlgorithm("awb"));
-			if (!awb) {
+			if (awb && awbEnabled_) {
 				LOG(IPARPI, Warning)
-					<< "Could not set COLOUR_TEMPERATURE - no AWB algorithm";
+					<< "Could not set COLOUR_CORRECTION_MATRIX - AWB is active";
 				break;
 			}
 
-			awb->setColourTemperature(temperatureK);
-			/* This metadata will get reported back automatically. */
+			/* We are guaranteed this control contains 9 values. Nevertheless: */
+			assert(floats.size() == 9);
+
+			Matrix<double, 3, 3> matrix;
+			for (std::size_t i = 0; i < 3; ++i)
+				for (std::size_t j = 0; j < 3; ++j)
+					matrix[i][j] = static_cast<double>(floats[i * 3 + j]);
+
+			ccm->setCcm(matrix);
+
+			/*
+			 * But if AWB is running, go back to auto mode. The CCM gets remembered,
+			 * which avoids the race between setting the CCM and disabling AWB in
+			 * the same set of controls.
+			 */
+			if (awbEnabled_)
+				ccm->enableAuto();
+
+			/* This metadata will be reported back automatically. */
 			break;
 		}
 
@@ -1394,9 +1514,6 @@ void IpaBase::reportMetadata(unsigned in
 	}
 
 	AgcPrepareStatus *agcPrepareStatus = rpiMetadata.getLocked<AgcPrepareStatus>("agc.prepare_status");
-	if (agcPrepareStatus)
-		libcameraMetadata_.set(controls::DigitalGain, agcPrepareStatus->digitalGain);
-
 	RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
 		controller_.getAlgorithm("agc"));
 	if (agc) {
@@ -1409,6 +1526,13 @@ void IpaBase::reportMetadata(unsigned in
 						       : controls::AeStateSearching);
 	}
 
+	const AgcStatus *agcStatus = rpiMetadata.getLocked<AgcStatus>("agc.delayed_status");
+	if (agcStatus)
+		libcameraMetadata_.set(controls::DigitalGain, agcStatus->digitalGain);
+	else
+		libcameraMetadata_.set(controls::DigitalGain, agcStatus_.digitalGain);
+	/* The HDR metadata reporting will use this agcStatus too. */
+
 	LuxStatus *luxStatus = rpiMetadata.getLocked<LuxStatus>("lux.status");
 	if (luxStatus)
 		libcameraMetadata_.set(controls::Lux, luxStatus->lux);
@@ -1498,7 +1622,6 @@ void IpaBase::reportMetadata(unsigned in
 	 * delayed_status to be available, we use the HDR status that came out of the
 	 * switchMode call.
 	 */
-	const AgcStatus *agcStatus = rpiMetadata.getLocked<AgcStatus>("agc.delayed_status");
 	const HdrStatus &hdrStatus = agcStatus ? agcStatus->hdr : hdrStatus_;
 	if (!hdrStatus.mode.empty() && hdrStatus.mode != "Off") {
 		int32_t hdrMode = controls::HdrModeOff;
@@ -1552,10 +1675,11 @@ void IpaBase::applyFrameDurations(Durati
 
 	RPiController::AgcAlgorithm *agc = dynamic_cast<RPiController::AgcAlgorithm *>(
 		controller_.getAlgorithm("agc"));
-	agc->setMaxExposureTime(maxExposureTime);
+	if (agc)
+		agc->setMaxExposureTime(maxExposureTime);
 }
 
-void IpaBase::applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls)
+void IpaBase::applyAGC(struct AgcStatus *agcStatus, ControlList &ctrls)
 {
 	const int32_t minGainCode = helper_->gainCode(mode_.minAnalogueGain);
 	const int32_t maxGainCode = helper_->gainCode(mode_.maxAnalogueGain);
@@ -1585,6 +1709,19 @@ void IpaBase::applyAGC(const struct AgcS
 	ctrls.set(V4L2_CID_ANALOGUE_GAIN, gainCode);
 
 	/*
+	 * We must update the digital gain to make up for any quantisation that happens, and
+	 * communicate that back into the metadata so that it will appear as the "delayed" status.
+	 * (Note that "exposure" is already the "actual" exposure.)
+	 */
+	double actualGain = helper_->gain(gainCode);
+	double ratio = agcStatus->analogueGain / actualGain;
+	ratio *= agcStatus->exposureTime / exposure;
+	double newDigitalGain = agcStatus->digitalGain * ratio;
+	agcStatus->digitalGain = newDigitalGain;
+	agcStatus->analogueGain = actualGain;
+	agcStatus->exposureTime = exposure;
+
+	/*
 	 * At present, there is no way of knowing if a control is read-only.
 	 * As a workaround, assume that if the minimum and maximum values of
 	 * the V4L2_CID_HBLANK control are the same, it implies the control
diff -pruN 0.5.0-1/src/ipa/rpi/common/ipa_base.h 0.6.0-2/src/ipa/rpi/common/ipa_base.h
--- 0.5.0-1/src/ipa/rpi/common/ipa_base.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/common/ipa_base.h	2025-11-27 11:55:28.000000000 +0000
@@ -73,6 +73,9 @@ protected:
 	/* Remember the HDR status after a mode switch. */
 	HdrStatus hdrStatus_;
 
+	/* Remember the AGC status after a mode switch. */
+	AgcStatus agcStatus_;
+
 	/* Whether the stitch block (if available) needs to swap buffers. */
 	bool stitchSwapBuffers_;
 
@@ -86,6 +89,7 @@ private:
 
 	virtual void platformPrepareIsp(const PrepareParams &params,
 					RPiController::Metadata &rpiMetadata) = 0;
+	virtual void platformPrepareAgc(RPiController::Metadata &rpiMetadata) = 0;
 	virtual RPiController::StatisticsPtr platformProcessStats(Span<uint8_t> mem) = 0;
 
 	void setMode(const IPACameraSensorInfo &sensorInfo);
@@ -97,7 +101,7 @@ private:
 	void fillDeviceStatus(const ControlList &sensorControls, unsigned int ipaContext);
 	void reportMetadata(unsigned int ipaContext);
 	void applyFrameDurations(utils::Duration minFrameDuration, utils::Duration maxFrameDuration);
-	void applyAGC(const struct AgcStatus *agcStatus, ControlList &ctrls);
+	void applyAGC(struct AgcStatus *agcStatus, ControlList &ctrls);
 
 	std::map<unsigned int, MappedFrameBuffer> buffers_;
 
@@ -115,8 +119,8 @@ private:
 	/* How many frames we should avoid running control algos on. */
 	unsigned int mistrustCount_;
 
-	/* Number of frames that need to be dropped on startup. */
-	unsigned int dropFrameCount_;
+	/* Number of frames that need to be marked as dropped on startup. */
+	unsigned int invalidCount_;
 
 	/* Frame timestamp for the last run of the controller. */
 	uint64_t lastRunTimestamp_;
@@ -136,6 +140,8 @@ private:
 		int32_t mode;
 		utils::Duration manualPeriod;
 	} flickerState_;
+
+	bool awbEnabled_;
 };
 
 } /* namespace ipa::RPi */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/af_algorithm.h 0.6.0-2/src/ipa/rpi/controller/af_algorithm.h
--- 0.5.0-1/src/ipa/rpi/controller/af_algorithm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/af_algorithm.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2022, Raspberry Pi Ltd
  *
- * af_algorithm.hpp - auto focus algorithm interface
+ * Auto focus algorithm interface
  */
 #pragma once
 
@@ -33,6 +33,10 @@ public:
 	 *
 	 * getMode() is provided mainly for validating controls.
 	 * getLensPosition() is provided for populating DeviceStatus.
+	 *
+	 * getDefaultlensPosition() and getLensLimits() were added for
+	 * populating ControlInfoMap. They return the static API limits
+	 * which should be independent of the current range or mode.
 	 */
 
 	enum AfRange { AfRangeNormal = 0,
@@ -66,7 +70,9 @@ public:
 	}
 	virtual void setMode(AfMode mode) = 0;
 	virtual AfMode getMode() const = 0;
-	virtual bool setLensPosition(double dioptres, int32_t *hwpos) = 0;
+	virtual double getDefaultLensPosition() const = 0;
+	virtual void getLensLimits(double &min, double &max) const = 0;
+	virtual bool setLensPosition(double dioptres, int32_t *hwpos, bool force = false) = 0;
 	virtual std::optional<double> getLensPosition() const = 0;
 	virtual void triggerScan() = 0;
 	virtual void cancelScan() = 0;
diff -pruN 0.5.0-1/src/ipa/rpi/controller/agc_algorithm.h 0.6.0-2/src/ipa/rpi/controller/agc_algorithm.h
--- 0.5.0-1/src/ipa/rpi/controller/agc_algorithm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/agc_algorithm.h	2025-11-27 11:55:28.000000000 +0000
@@ -26,7 +26,7 @@ public:
 	virtual void setFixedExposureTime(unsigned int channel,
 					  libcamera::utils::Duration fixedExposureTime) = 0;
 	virtual void setMaxExposureTime(libcamera::utils::Duration maxExposureTime) = 0;
-	virtual void setFixedAnalogueGain(unsigned int channel, double fixedAnalogueGain) = 0;
+	virtual void setFixedGain(unsigned int channel, double fixedGain) = 0;
 	virtual void setMeteringMode(std::string const &meteringModeName) = 0;
 	virtual void setExposureMode(std::string const &exposureModeName) = 0;
 	virtual void setConstraintMode(std::string const &contraintModeName) = 0;
diff -pruN 0.5.0-1/src/ipa/rpi/controller/agc_status.h 0.6.0-2/src/ipa/rpi/controller/agc_status.h
--- 0.5.0-1/src/ipa/rpi/controller/agc_status.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/agc_status.h	2025-11-27 11:55:28.000000000 +0000
@@ -30,6 +30,7 @@ struct AgcStatus {
 	libcamera::utils::Duration targetExposureValue; /* (unfiltered) target total exposure AGC is aiming for */
 	libcamera::utils::Duration exposureTime;
 	double analogueGain;
+	double digitalGain;
 	std::string exposureMode;
 	std::string constraintMode;
 	std::string meteringMode;
@@ -37,12 +38,11 @@ struct AgcStatus {
 	libcamera::utils::Duration flickerPeriod;
 	int floatingRegionEnable;
 	libcamera::utils::Duration fixedExposureTime;
-	double fixedAnalogueGain;
+	double fixedGain;
 	unsigned int channel;
 	HdrStatus hdr;
 };
 
 struct AgcPrepareStatus {
-	double digitalGain;
 	int locked;
 };
diff -pruN 0.5.0-1/src/ipa/rpi/controller/ccm_algorithm.h 0.6.0-2/src/ipa/rpi/controller/ccm_algorithm.h
--- 0.5.0-1/src/ipa/rpi/controller/ccm_algorithm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/ccm_algorithm.h	2025-11-27 11:55:28.000000000 +0000
@@ -6,16 +6,22 @@
  */
 #pragma once
 
+#include "libcamera/internal/matrix.h"
+
 #include "algorithm.h"
 
 namespace RPiController {
 
+using Matrix3x3 = libcamera::Matrix<double, 3, 3>;
+
 class CcmAlgorithm : public Algorithm
 {
 public:
 	CcmAlgorithm(Controller *controller) : Algorithm(controller) {}
 	/* A CCM algorithm must provide the following: */
+	virtual void enableAuto() = 0;
 	virtual void setSaturation(double saturation) = 0;
+	virtual void setCcm(Matrix3x3 const &matrix) = 0;
 };
 
 } /* namespace RPiController */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/controller.cpp 0.6.0-2/src/ipa/rpi/controller/controller.cpp
--- 0.5.0-1/src/ipa/rpi/controller/controller.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/controller.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -21,61 +21,70 @@ using namespace std::literals::chrono_li
 
 LOG_DEFINE_CATEGORY(RPiController)
 
-static const std::map<std::string, Controller::HardwareConfig> HardwareConfigMap = {
-	{
-		"bcm2835",
+namespace {
+
+const std::map<std::string, Controller::HardwareConfig> &hardwareConfigMap()
+{
+	static const std::map<std::string, Controller::HardwareConfig> map = {
 		{
-			/*
-			 * There are only ever 15 AGC regions computed by the firmware
-			 * due to zoning, but the HW defines AGC_REGIONS == 16!
-			 */
-			.agcRegions = { 15 , 1 },
-			.agcZoneWeights = { 15 , 1 },
-			.awbRegions = { 16, 12 },
-			.cacRegions = { 0, 0 },
-			.focusRegions = { 4, 3 },
-			.numHistogramBins = 128,
-			.numGammaPoints = 33,
-			.pipelineWidth = 13,
-			.statsInline = false,
-			.minPixelProcessingTime = 0s,
-			.dataBufferStrided = true,
-		}
-	},
-	{
-		"pisp",
+			"bcm2835",
+			{
+				/*
+				* There are only ever 15 AGC regions computed by the firmware
+				* due to zoning, but the HW defines AGC_REGIONS == 16!
+				*/
+				.agcRegions = { 15 , 1 },
+				.agcZoneWeights = { 15 , 1 },
+				.awbRegions = { 16, 12 },
+				.cacRegions = { 0, 0 },
+				.focusRegions = { 4, 3 },
+				.numHistogramBins = 128,
+				.numGammaPoints = 33,
+				.pipelineWidth = 13,
+				.statsInline = false,
+				.minPixelProcessingTime = 0s,
+				.dataBufferStrided = true,
+			}
+		},
 		{
-			.agcRegions = { 0, 0 },
-			.agcZoneWeights = { 15, 15 },
-			.awbRegions = { 32, 32 },
-			.cacRegions = { 8, 8 },
-			.focusRegions = { 8, 8 },
-			.numHistogramBins = 1024,
-			.numGammaPoints = 64,
-			.pipelineWidth = 16,
-			.statsInline = true,
-
-			/*
-			 * The constraint below is on the rate of pixels going
-			 * from CSI2 peripheral to ISP-FE (400Mpix/s, plus tiny
-			 * overheads per scanline, for which 380Mpix/s is a
-			 * conservative bound).
-			 *
-			 * There is a 64kbit data FIFO before the bottleneck,
-			 * which means that in all reasonable cases the
-			 * constraint applies at a timescale >= 1 scanline, so
-			 * adding horizontal blanking can prevent loss.
-			 *
-			 * If the backlog were to grow beyond 64kbit during a
-			 * single scanline, there could still be loss. This
-			 * could happen using 4 lanes at 1.5Gbps at 10bpp with
-			 * frames wider than ~16,000 pixels.
-			 */
-			.minPixelProcessingTime = 1.0us / 380,
-			.dataBufferStrided = false,
-		}
-	},
-};
+			"pisp",
+			{
+				.agcRegions = { 0, 0 },
+				.agcZoneWeights = { 15, 15 },
+				.awbRegions = { 32, 32 },
+				.cacRegions = { 8, 8 },
+				.focusRegions = { 8, 8 },
+				.numHistogramBins = 1024,
+				.numGammaPoints = 64,
+				.pipelineWidth = 16,
+				.statsInline = true,
+
+				/*
+				* The constraint below is on the rate of pixels going
+				* from CSI2 peripheral to ISP-FE (400Mpix/s, plus tiny
+				* overheads per scanline, for which 380Mpix/s is a
+				* conservative bound).
+				*
+				* There is a 64kbit data FIFO before the bottleneck,
+				* which means that in all reasonable cases the
+				* constraint applies at a timescale >= 1 scanline, so
+				* adding horizontal blanking can prevent loss.
+				*
+				* If the backlog were to grow beyond 64kbit during a
+				* single scanline, there could still be loss. This
+				* could happen using 4 lanes at 1.5Gbps at 10bpp with
+				* frames wider than ~16,000 pixels.
+				*/
+				.minPixelProcessingTime = 1.0us / 380,
+				.dataBufferStrided = false,
+			}
+		},
+	};
+
+	return map;
+}
+
+} /* namespace */
 
 Controller::Controller()
 	: switchModeCalled_(false)
@@ -211,12 +220,12 @@ const std::string &Controller::getTarget
 
 const Controller::HardwareConfig &Controller::getHardwareConfig() const
 {
-	auto cfg = HardwareConfigMap.find(getTarget());
+	auto cfg = hardwareConfigMap().find(getTarget());
 
 	/*
 	 * This really should not happen, the IPA ought to validate the target
 	 * on initialisation.
 	 */
-	ASSERT(cfg != HardwareConfigMap.end());
+	ASSERT(cfg != hardwareConfigMap().end());
 	return cfg->second;
 }
diff -pruN 0.5.0-1/src/ipa/rpi/controller/decompand_algorithm.h 0.6.0-2/src/ipa/rpi/controller/decompand_algorithm.h
--- 0.5.0-1/src/ipa/rpi/controller/decompand_algorithm.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/decompand_algorithm.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2025, Raspberry Pi Ltd
+ *
+ * Decompand control algorithm interface
+ */
+#pragma once
+
+#include "libipa/pwl.h"
+
+#include "algorithm.h"
+
+namespace RPiController {
+
+class DecompandAlgorithm : public Algorithm
+{
+public:
+	DecompandAlgorithm(Controller *controller = NULL)
+		: Algorithm(controller)
+	{
+	}
+	/* A decompand algorithm must provide the following: */
+	virtual void initialValues(libcamera::ipa::Pwl &decompandCurve) = 0;
+};
+
+} /* namespace RPiController */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/decompand_status.h 0.6.0-2/src/ipa/rpi/controller/decompand_status.h
--- 0.5.0-1/src/ipa/rpi/controller/decompand_status.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/decompand_status.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,8 @@
+#pragma once
+
+#include "libipa/pwl.h"
+
+struct DecompandStatus {
+	uint32_t bitdepth;
+	libcamera::ipa::Pwl decompandCurve;
+};
diff -pruN 0.5.0-1/src/ipa/rpi/controller/meson.build 0.6.0-2/src/ipa/rpi/controller/meson.build
--- 0.5.0-1/src/ipa/rpi/controller/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -14,6 +14,7 @@ rpi_ipa_controller_sources = files([
     'rpi/cac.cpp',
     'rpi/ccm.cpp',
     'rpi/contrast.cpp',
+    'rpi/decompand.cpp',
     'rpi/denoise.cpp',
     'rpi/dpc.cpp',
     'rpi/geq.cpp',
diff -pruN 0.5.0-1/src/ipa/rpi/controller/region_stats.h 0.6.0-2/src/ipa/rpi/controller/region_stats.h
--- 0.5.0-1/src/ipa/rpi/controller/region_stats.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/region_stats.h	2025-11-27 11:55:28.000000000 +0000
@@ -76,7 +76,7 @@ public:
 	{
 		if (index >= numFloatingRegions())
 			return;
-		set(numRegions() + index, region);
+		set_(numRegions() + index, region);
 	}
 
 	const Region &get(unsigned int index) const
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/af.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/af.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/af.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/af.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -46,6 +46,8 @@ Af::SpeedDependentParams::SpeedDependent
 	: stepCoarse(1.0),
 	  stepFine(0.25),
 	  contrastRatio(0.75),
+	  retriggerRatio(0.75),
+	  retriggerDelay(10),
 	  pdafGain(-0.02),
 	  pdafSquelch(0.125),
 	  maxSlew(2.0),
@@ -60,6 +62,7 @@ Af::CfgParams::CfgParams()
 	  confThresh(16),
 	  confClip(512),
 	  skipFrames(5),
+	  checkForIR(false),
 	  map()
 {
 }
@@ -87,6 +90,8 @@ void Af::SpeedDependentParams::read(cons
 	readNumber<double>(stepCoarse, params, "step_coarse");
 	readNumber<double>(stepFine, params, "step_fine");
 	readNumber<double>(contrastRatio, params, "contrast_ratio");
+	readNumber<double>(retriggerRatio, params, "retrigger_ratio");
+	readNumber<uint32_t>(retriggerDelay, params, "retrigger_delay");
 	readNumber<double>(pdafGain, params, "pdaf_gain");
 	readNumber<double>(pdafSquelch, params, "pdaf_squelch");
 	readNumber<double>(maxSlew, params, "max_slew");
@@ -137,6 +142,7 @@ int Af::CfgParams::read(const libcamera:
 	readNumber<uint32_t>(confThresh, params, "conf_thresh");
 	readNumber<uint32_t>(confClip, params, "conf_clip");
 	readNumber<uint32_t>(skipFrames, params, "skip_frames");
+	readNumber<bool>(checkForIR, params, "check_for_ir");
 
 	if (params.contains("map"))
 		map = params["map"].get<ipa::Pwl>(ipa::Pwl{});
@@ -176,27 +182,38 @@ Af::Af(Controller *controller)
 	  useWindows_(false),
 	  phaseWeights_(),
 	  contrastWeights_(),
+	  awbWeights_(),
 	  scanState_(ScanState::Idle),
 	  initted_(false),
+	  irFlag_(false),
 	  ftarget_(-1.0),
 	  fsmooth_(-1.0),
 	  prevContrast_(0.0),
+	  oldSceneContrast_(0.0),
+	  prevAverage_{ 0.0, 0.0, 0.0 },
+	  oldSceneAverage_{ 0.0, 0.0, 0.0 },
+	  prevPhase_(0.0),
 	  skipCount_(0),
 	  stepCount_(0),
 	  dropCount_(0),
+	  sameSignCount_(0),
+	  sceneChangeCount_(0),
 	  scanMaxContrast_(0.0),
 	  scanMinContrast_(1.0e9),
+	  scanStep_(0.0),
 	  scanData_(),
 	  reportState_(AfState::Idle)
 {
 	/*
-	 * Reserve space for data, to reduce memory fragmentation. It's too early
-	 * to query the size of the PDAF (from camera) and Contrast (from ISP)
-	 * statistics, but these are plausible upper bounds.
+	 * Reserve space for data structures, to reduce memory fragmentation.
+	 * It's too early to query the size of the PDAF sensor data, so guess.
 	 */
+	windows_.reserve(1);
 	phaseWeights_.w.reserve(16 * 12);
 	contrastWeights_.w.reserve(getHardwareConfig().focusRegions.width *
 				   getHardwareConfig().focusRegions.height);
+	contrastWeights_.w.reserve(getHardwareConfig().awbRegions.width *
+				   getHardwareConfig().awbRegions.height);
 	scanData_.reserve(32);
 }
 
@@ -235,13 +252,14 @@ void Af::switchMode(CameraMode const &ca
 			  << statsRegion_.height;
 	invalidateWeights();
 
-	if (scanState_ >= ScanState::Coarse && scanState_ < ScanState::Settle) {
+	if (scanState_ >= ScanState::Coarse1 && scanState_ < ScanState::Settle) {
 		/*
 		 * If a scan was in progress, re-start it, as CDAF statistics
 		 * may have changed. Though if the application is just about
 		 * to take a still picture, this will not help...
 		 */
 		startProgrammedScan();
+		updateLensPosition();
 	}
 	skipCount_ = cfg_.skipFrames;
 }
@@ -307,6 +325,7 @@ void Af::invalidateWeights()
 {
 	phaseWeights_.sum = 0;
 	contrastWeights_.sum = 0;
+	awbWeights_.sum = 0;
 }
 
 bool Af::getPhase(PdafRegions const &regions, double &phase, double &conf)
@@ -328,9 +347,8 @@ bool Af::getPhase(PdafRegions const &reg
 			if (c >= cfg_.confThresh) {
 				if (c > cfg_.confClip)
 					c = cfg_.confClip;
-				c -= (cfg_.confThresh >> 2);
+				c -= (cfg_.confThresh >> 1);
 				sumWc += w * c;
-				c -= (cfg_.confThresh >> 2);
 				sumWcp += (int64_t)(w * c) * (int64_t)data.phase;
 			}
 		}
@@ -364,6 +382,54 @@ double Af::getContrast(const FocusRegion
 	return (contrastWeights_.sum > 0) ? ((double)sumWc / (double)contrastWeights_.sum) : 0.0;
 }
 
+/*
+ * Get the average R, G, B values in AF window[s] (from AWB statistics).
+ * Optionally, check if all of {R,G,B} are within 4:5 of each other
+ * across more than 50% of the counted area and within the AF window:
+ * for an RGB sensor this strongly suggests that IR lighting is in use.
+ */
+
+bool Af::getAverageAndTestIr(const RgbyRegions &awbStats, double rgb[3])
+{
+	libcamera::Size size = awbStats.size();
+	if (size.height != awbWeights_.rows ||
+	    size.width != awbWeights_.cols || awbWeights_.sum == 0) {
+		LOG(RPiAf, Debug) << "Recompute RGB weights " << size.width << 'x' << size.height;
+		computeWeights(&awbWeights_, size.height, size.width);
+	}
+
+	uint64_t sr = 0, sg = 0, sb = 0, sw = 1;
+	uint64_t greyCount = 0, allCount = 0;
+	for (unsigned i = 0; i < awbStats.numRegions(); ++i) {
+		uint64_t r = awbStats.get(i).val.rSum;
+		uint64_t g = awbStats.get(i).val.gSum;
+		uint64_t b = awbStats.get(i).val.bSum;
+		uint64_t w = awbWeights_.w[i];
+		if (w) {
+			sw += w;
+			sr += w * r;
+			sg += w * g;
+			sb += w * b;
+		}
+		if (cfg_.checkForIR) {
+			if (4 * r < 5 * b && 4 * b < 5 * r &&
+			    4 * r < 5 * g && 4 * g < 5 * r &&
+			    4 * b < 5 * g && 4 * g < 5 * b)
+				greyCount += awbStats.get(i).counted;
+			allCount += awbStats.get(i).counted;
+		}
+	}
+
+	rgb[0] = sr / (double)sw;
+	rgb[1] = sg / (double)sw;
+	rgb[2] = sb / (double)sw;
+
+	return (cfg_.checkForIR && 2 * greyCount > allCount &&
+		4 * sr < 5 * sb && 4 * sb < 5 * sr &&
+		4 * sr < 5 * sg && 4 * sg < 5 * sr &&
+		4 * sb < 5 * sg && 4 * sg < 5 * sb);
+}
+
 void Af::doPDAF(double phase, double conf)
 {
 	/* Apply loop gain */
@@ -410,7 +476,7 @@ void Af::doPDAF(double phase, double con
 bool Af::earlyTerminationByPhase(double phase)
 {
 	if (scanData_.size() > 0 &&
-	    scanData_[scanData_.size() - 1].conf >= cfg_.confEpsilon) {
+	    scanData_[scanData_.size() - 1].conf >= cfg_.confThresh) {
 		double oldFocus = scanData_[scanData_.size() - 1].focus;
 		double oldPhase = scanData_[scanData_.size() - 1].phase;
 
@@ -419,11 +485,12 @@ bool Af::earlyTerminationByPhase(double
 		 * Interpolate/extrapolate the lens position for zero phase.
 		 * Check that the extrapolation is well-conditioned.
 		 */
-		if ((ftarget_ - oldFocus) * (phase - oldPhase) > 0.0) {
+		if ((ftarget_ - oldFocus) * (phase - oldPhase) * cfg_.speeds[speed_].pdafGain < 0.0) {
 			double param = phase / (phase - oldPhase);
-			if (-3.0 <= param && param <= 3.5) {
-				ftarget_ += param * (oldFocus - ftarget_);
+			if ((-2.5 <= param || mode_ == AfModeContinuous) && param <= 3.0) {
 				LOG(RPiAf, Debug) << "ETBP: param=" << param;
+				param = std::max(param, -2.5);
+				ftarget_ += param * (oldFocus - ftarget_);
 				return true;
 			}
 		}
@@ -436,15 +503,28 @@ double Af::findPeak(unsigned i) const
 {
 	double f = scanData_[i].focus;
 
-	if (i > 0 && i + 1 < scanData_.size()) {
-		double dropLo = scanData_[i].contrast - scanData_[i - 1].contrast;
-		double dropHi = scanData_[i].contrast - scanData_[i + 1].contrast;
-		if (0.0 <= dropLo && dropLo < dropHi) {
-			double param = 0.3125 * (1.0 - dropLo / dropHi) * (1.6 - dropLo / dropHi);
-			f += param * (scanData_[i - 1].focus - f);
-		} else if (0.0 <= dropHi && dropHi < dropLo) {
-			double param = 0.3125 * (1.0 - dropHi / dropLo) * (1.6 - dropHi / dropLo);
-			f += param * (scanData_[i + 1].focus - f);
+	if (scanData_.size() >= 3) {
+		/*
+		 * Given the sample with the highest contrast score and its two
+		 * neighbours either side (or same side if at the end of a scan),
+		 * solve for the best lens position by fitting a parabola.
+		 * Adapted from awb.cpp: interpolateQaudaratic()
+		 */
+
+		if (i == 0)
+			i++;
+		else if (i + 1 >= scanData_.size())
+			i--;
+
+		double abx = scanData_[i - 1].focus - scanData_[i].focus;
+		double aby = scanData_[i - 1].contrast - scanData_[i].contrast;
+		double cbx = scanData_[i + 1].focus - scanData_[i].focus;
+		double cby = scanData_[i + 1].contrast - scanData_[i].contrast;
+		double denom = 2.0 * (aby * cbx - cby * abx);
+		if (std::abs(denom) >= (1.0 / 64.0) && denom * abx > 0.0) {
+			f = (aby * cbx * cbx - cby * abx * abx) / denom;
+			f = std::clamp(f, std::min(abx, cbx), std::max(abx, cbx));
+			f += scanData_[i].focus;
 		}
 	}
 
@@ -458,36 +538,49 @@ void Af::doScan(double contrast, double
 	if (scanData_.empty() || contrast > scanMaxContrast_) {
 		scanMaxContrast_ = contrast;
 		scanMaxIndex_ = scanData_.size();
+		if (scanState_ != ScanState::Fine)
+			std::copy(prevAverage_, prevAverage_ + 3, oldSceneAverage_);
 	}
 	if (contrast < scanMinContrast_)
 		scanMinContrast_ = contrast;
 	scanData_.emplace_back(ScanRecord{ ftarget_, contrast, phase, conf });
 
-	if (scanState_ == ScanState::Coarse) {
-		if (ftarget_ >= cfg_.ranges[range_].focusMax ||
-		    contrast < cfg_.speeds[speed_].contrastRatio * scanMaxContrast_) {
-			/*
-			 * Finished course scan, or termination based on contrast.
-			 * Jump to just after max contrast and start fine scan.
-			 */
-			ftarget_ = std::min(ftarget_, findPeak(scanMaxIndex_) +
-					2.0 * cfg_.speeds[speed_].stepFine);
-			scanState_ = ScanState::Fine;
-			scanData_.clear();
-		} else
-			ftarget_ += cfg_.speeds[speed_].stepCoarse;
-	} else { /* ScanState::Fine */
-		if (ftarget_ <= cfg_.ranges[range_].focusMin || scanData_.size() >= 5 ||
-		    contrast < cfg_.speeds[speed_].contrastRatio * scanMaxContrast_) {
-			/*
-			 * Finished fine scan, or termination based on contrast.
-			 * Use quadratic peak-finding to find best contrast position.
-			 */
-			ftarget_ = findPeak(scanMaxIndex_);
+	if ((scanStep_ >= 0.0 && ftarget_ >= cfg_.ranges[range_].focusMax) ||
+	    (scanStep_ <= 0.0 && ftarget_ <= cfg_.ranges[range_].focusMin) ||
+	    (scanState_ == ScanState::Fine && scanData_.size() >= 3) ||
+	    contrast < cfg_.speeds[speed_].contrastRatio * scanMaxContrast_) {
+		double pk = findPeak(scanMaxIndex_);
+		/*
+		 * Finished a scan, by hitting a limit or due to constrast dropping off.
+		 * If this is a first coarse scan and we didn't bracket the peak, reverse!
+		 * If this is a fine scan, or no fine step was defined, we've finished.
+		 * Otherwise, start fine scan in opposite direction.
+		 */
+		if (scanState_ == ScanState::Coarse1 &&
+		    scanData_[0].contrast >= cfg_.speeds[speed_].contrastRatio * scanMaxContrast_) {
+			scanStep_ = -scanStep_;
+			scanState_ = ScanState::Coarse2;
+		} else if (scanState_ == ScanState::Fine || cfg_.speeds[speed_].stepFine <= 0.0) {
+			ftarget_ = pk;
 			scanState_ = ScanState::Settle;
-		} else
-			ftarget_ -= cfg_.speeds[speed_].stepFine;
-	}
+		} else if (scanState_ == ScanState::Coarse1 &&
+			   scanData_[0].contrast >= cfg_.speeds[speed_].contrastRatio * scanMaxContrast_) {
+			scanStep_ = -scanStep_;
+			scanState_ = ScanState::Coarse2;
+		} else if (scanStep_ >= 0.0) {
+			ftarget_ = std::min(pk + cfg_.speeds[speed_].stepFine,
+					    cfg_.ranges[range_].focusMax);
+			scanStep_ = -cfg_.speeds[speed_].stepFine;
+			scanState_ = ScanState::Fine;
+		} else {
+			ftarget_ = std::max(pk - cfg_.speeds[speed_].stepFine,
+					    cfg_.ranges[range_].focusMin);
+			scanStep_ = cfg_.speeds[speed_].stepFine;
+			scanState_ = ScanState::Fine;
+		}
+		scanData_.clear();
+	} else
+		ftarget_ += scanStep_;
 
 	stepCount_ = (ftarget_ == fsmooth_) ? 0 : cfg_.speeds[speed_].stepFrames;
 }
@@ -501,26 +594,70 @@ void Af::doAF(double contrast, double ph
 		return;
 	}
 
+	/* Count frames for which PDAF phase has had same sign */
+	if (phase * prevPhase_ <= 0.0)
+		sameSignCount_ = 0;
+	else
+		sameSignCount_++;
+	prevPhase_ = phase;
+
+	if (mode_ == AfModeManual)
+		return; /* nothing to do */
+
 	if (scanState_ == ScanState::Pdaf) {
 		/*
 		 * Use PDAF closed-loop control whenever available, in both CAF
 		 * mode and (for a limited number of iterations) when triggered.
-		 * If PDAF fails (due to poor contrast, noise or large defocus),
-		 * fall back to a CDAF-based scan. To avoid "nuisance" scans,
-		 * scan only after a number of frames with low PDAF confidence.
+		 * If PDAF fails (due to poor contrast, noise or large defocus)
+		 * for at least dropoutFrames, fall back to a CDAF-based scan
+		 * immediately (in triggered-auto) or on scene change (in CAF).
 		 */
-		if (conf > (dropCount_ ? 1.0 : 0.25) * cfg_.confEpsilon) {
-			doPDAF(phase, conf);
+		if (conf >= cfg_.confEpsilon) {
+			if (mode_ == AfModeAuto || sameSignCount_ >= 3)
+				doPDAF(phase, conf);
 			if (stepCount_ > 0)
 				stepCount_--;
 			else if (mode_ != AfModeContinuous)
 				scanState_ = ScanState::Idle;
+			oldSceneContrast_ = contrast;
+			std::copy(prevAverage_, prevAverage_ + 3, oldSceneAverage_);
+			sceneChangeCount_ = 0;
 			dropCount_ = 0;
-		} else if (++dropCount_ == cfg_.speeds[speed_].dropoutFrames)
+			return;
+		} else {
+			dropCount_++;
+			if (dropCount_ < cfg_.speeds[speed_].dropoutFrames)
+				return;
+			if (mode_ != AfModeContinuous) {
+				startProgrammedScan();
+				return;
+			}
+			/* else fall through to waiting for a scene change */
+		}
+	}
+	if (scanState_ < ScanState::Coarse1 && mode_ == AfModeContinuous) {
+		/*
+		 * In CAF mode, not in a scan, and PDAF is unavailable.
+		 * Wait for a scene change, followed by stability.
+		 */
+		if (contrast + 1.0 < cfg_.speeds[speed_].retriggerRatio * oldSceneContrast_ ||
+		    oldSceneContrast_ + 1.0 < cfg_.speeds[speed_].retriggerRatio * contrast ||
+		    prevAverage_[0] + 1.0 < cfg_.speeds[speed_].retriggerRatio * oldSceneAverage_[0] ||
+		    oldSceneAverage_[0] + 1.0 < cfg_.speeds[speed_].retriggerRatio * prevAverage_[0] ||
+		    prevAverage_[1] + 1.0 < cfg_.speeds[speed_].retriggerRatio * oldSceneAverage_[1] ||
+		    oldSceneAverage_[1] + 1.0 < cfg_.speeds[speed_].retriggerRatio * prevAverage_[1] ||
+		    prevAverage_[2] + 1.0 < cfg_.speeds[speed_].retriggerRatio * oldSceneAverage_[2] ||
+		    oldSceneAverage_[2] + 1.0 < cfg_.speeds[speed_].retriggerRatio * prevAverage_[2]) {
+			oldSceneContrast_ = contrast;
+			std::copy(prevAverage_, prevAverage_ + 3, oldSceneAverage_);
+			sceneChangeCount_ = 1;
+		} else if (sceneChangeCount_)
+			sceneChangeCount_++;
+		if (sceneChangeCount_ >= cfg_.speeds[speed_].retriggerDelay)
 			startProgrammedScan();
-	} else if (scanState_ >= ScanState::Coarse && fsmooth_ == ftarget_) {
+	} else if (scanState_ >= ScanState::Coarse1 && fsmooth_ == ftarget_) {
 		/*
-		 * Scanning sequence. This means PDAF has become unavailable.
+		 * CDAF-based scanning sequence.
 		 * Allow a delay between steps for CDAF FoM statistics to be
 		 * updated, and a "settling time" at the end of the sequence.
 		 * [A coarse or fine scan can be abandoned if two PDAF samples
@@ -539,11 +676,14 @@ void Af::doAF(double contrast, double ph
 				scanState_ = ScanState::Pdaf;
 			else
 				scanState_ = ScanState::Idle;
+			dropCount_ = 0;
+			sceneChangeCount_ = 0;
+			oldSceneContrast_ = std::max(scanMaxContrast_, prevContrast_);
 			scanData_.clear();
-		} else if (conf >= cfg_.confEpsilon && earlyTerminationByPhase(phase)) {
+		} else if (conf >= cfg_.confThresh && earlyTerminationByPhase(phase)) {
+			std::copy(prevAverage_, prevAverage_ + 3, oldSceneAverage_);
 			scanState_ = ScanState::Settle;
-			stepCount_ = (mode_ == AfModeContinuous) ? 0
-								 : cfg_.speeds[speed_].stepFrames;
+			stepCount_ = (mode_ == AfModeContinuous) ? 0 : cfg_.speeds[speed_].stepFrames;
 		} else
 			doScan(contrast, phase, conf);
 	}
@@ -573,7 +713,8 @@ void Af::updateLensPosition()
 void Af::startAF()
 {
 	/* Use PDAF if the tuning file allows it; else CDAF. */
-	if (cfg_.speeds[speed_].dropoutFrames > 0 &&
+	if (cfg_.speeds[speed_].pdafGain != 0.0 &&
+	    cfg_.speeds[speed_].dropoutFrames > 0 &&
 	    (mode_ == AfModeContinuous || cfg_.speeds[speed_].pdafFrames > 0)) {
 		if (!initted_) {
 			ftarget_ = cfg_.ranges[range_].focusDefault;
@@ -583,16 +724,30 @@ void Af::startAF()
 		scanState_ = ScanState::Pdaf;
 		scanData_.clear();
 		dropCount_ = 0;
+		oldSceneContrast_ = 0.0;
+		sceneChangeCount_ = 0;
 		reportState_ = AfState::Scanning;
-	} else
+	} else {
 		startProgrammedScan();
+		updateLensPosition();
+	}
 }
 
 void Af::startProgrammedScan()
 {
-	ftarget_ = cfg_.ranges[range_].focusMin;
-	updateLensPosition();
-	scanState_ = ScanState::Coarse;
+	if (!initted_ || mode_ != AfModeContinuous ||
+	    fsmooth_ <= cfg_.ranges[range_].focusMin + 2.0 * cfg_.speeds[speed_].stepCoarse) {
+		ftarget_ = cfg_.ranges[range_].focusMin;
+		scanStep_ = cfg_.speeds[speed_].stepCoarse;
+		scanState_ = ScanState::Coarse2;
+	} else if (fsmooth_ >= cfg_.ranges[range_].focusMax - 2.0 * cfg_.speeds[speed_].stepCoarse) {
+		ftarget_ = cfg_.ranges[range_].focusMax;
+		scanStep_ = -cfg_.speeds[speed_].stepCoarse;
+		scanState_ = ScanState::Coarse2;
+	} else {
+		scanStep_ = -cfg_.speeds[speed_].stepCoarse;
+		scanState_ = ScanState::Coarse1;
+	}
 	scanMaxContrast_ = 0.0;
 	scanMinContrast_ = 1.0e9;
 	scanMaxIndex_ = 0;
@@ -633,7 +788,7 @@ void Af::prepare(Metadata *imageMetadata
 		uint32_t oldSt = stepCount_;
 		if (imageMetadata->get("pdaf.regions", regions) == 0)
 			getPhase(regions, phase, conf);
-		doAF(prevContrast_, phase, conf);
+		doAF(prevContrast_, phase, irFlag_ ? 0 : conf);
 		updateLensPosition();
 		LOG(RPiAf, Debug) << std::fixed << std::setprecision(2)
 				  << static_cast<unsigned int>(reportState_)
@@ -643,7 +798,8 @@ void Af::prepare(Metadata *imageMetadata
 				  << " ft" << oldFt << "->" << ftarget_
 				  << " fs" << oldFs << "->" << fsmooth_
 				  << " cont=" << (int)prevContrast_
-				  << " phase=" << (int)phase << " conf=" << (int)conf;
+				  << " phase=" << (int)phase << " conf=" << (int)conf
+				  << (irFlag_ ? " IR" : "");
 	}
 
 	/* Report status and produce new lens setting */
@@ -656,6 +812,8 @@ void Af::prepare(Metadata *imageMetadata
 
 	if (mode_ == AfModeAuto && scanState_ != ScanState::Idle)
 		status.state = AfState::Scanning;
+	else if (mode_ == AfModeManual)
+		status.state = AfState::Idle;
 	else
 		status.state = reportState_;
 	status.lensSetting = initted_ ? std::optional<int>(cfg_.map.eval(fsmooth_))
@@ -667,6 +825,7 @@ void Af::process(StatisticsPtr &stats, [
 {
 	(void)imageMetadata;
 	prevContrast_ = getContrast(stats->focusRegions);
+	irFlag_ = getAverageAndTestIr(stats->awbRegions, prevAverage_);
 }
 
 /* Controls */
@@ -715,11 +874,23 @@ void Af::setWindows(libcamera::Span<libc
 		invalidateWeights();
 }
 
-bool Af::setLensPosition(double dioptres, int *hwpos)
+double Af::getDefaultLensPosition() const
+{
+	return cfg_.ranges[AfRangeNormal].focusDefault;
+}
+
+void Af::getLensLimits(double &min, double &max) const
+{
+	/* Limits for manual focus are set by map, not by ranges */
+	min = cfg_.map.domain().start;
+	max = cfg_.map.domain().end;
+}
+
+bool Af::setLensPosition(double dioptres, int *hwpos, bool force)
 {
 	bool changed = false;
 
-	if (mode_ == AfModeManual) {
+	if (mode_ == AfModeManual || force) {
 		LOG(RPiAf, Debug) << "setLensPosition: " << dioptres;
 		ftarget_ = cfg_.map.domain().clamp(dioptres);
 		changed = !(initted_ && fsmooth_ == ftarget_);
@@ -763,7 +934,7 @@ void Af::setMode(AfAlgorithm::AfMode mod
 		pauseFlag_ = false;
 		if (mode == AfModeContinuous)
 			scanState_ = ScanState::Trigger;
-		else if (mode != AfModeAuto || scanState_ < ScanState::Coarse)
+		else if (mode != AfModeAuto || scanState_ < ScanState::Coarse1)
 			goIdle();
 	}
 }
@@ -779,12 +950,14 @@ void Af::pause(AfAlgorithm::AfPause paus
 	if (mode_ == AfModeContinuous) {
 		if (pause == AfPauseResume && pauseFlag_) {
 			pauseFlag_ = false;
-			if (scanState_ < ScanState::Coarse)
+			if (scanState_ < ScanState::Coarse1)
 				scanState_ = ScanState::Trigger;
 		} else if (pause != AfPauseResume && !pauseFlag_) {
 			pauseFlag_ = true;
-			if (pause == AfPauseImmediate || scanState_ < ScanState::Coarse)
-				goIdle();
+			if (pause == AfPauseImmediate || scanState_ < ScanState::Coarse1) {
+				scanState_ = ScanState::Idle;
+				scanData_.clear();
+			}
 		}
 	}
 }
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/af.h 0.6.0-2/src/ipa/rpi/controller/rpi/af.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/af.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/af.h	2025-11-27 11:55:28.000000000 +0000
@@ -15,20 +15,28 @@
 /*
  * This algorithm implements a hybrid of CDAF and PDAF, favouring PDAF.
  *
- * Whenever PDAF is available, it is used in a continuous feedback loop.
- * When triggered in auto mode, we simply enable AF for a limited number
- * of frames (it may terminate early if the delta becomes small enough).
+ * Whenever PDAF is available (and reports sufficiently high confidence),
+ * it is used for continuous feedback control of the lens position. When
+ * triggered in Auto mode, we enable the loop for a limited number of frames
+ * (it may terminate sooner if the phase becomes small). In CAF mode, the
+ * PDAF loop runs continuously. Very small lens movements are suppressed.
  *
  * When PDAF confidence is low (due e.g. to low contrast or extreme defocus)
  * or PDAF data are absent, fall back to CDAF with a programmed scan pattern.
- * A coarse and fine scan are performed, using ISP's CDAF focus FoM to
- * estimate the lens position with peak contrast. This is slower due to
- * extra latency in the ISP, and requires a settling time between steps.
+ * A coarse and fine scan are performed, using the ISP's CDAF contrast FoM
+ * to estimate the lens position with peak contrast. (This is slower due to
+ * extra latency in the ISP, and requires a settling time between steps.)
+ * The scan may terminate early if PDAF recovers and allows the zero-phase
+ * lens position to be interpolated.
  *
- * Some hysteresis is applied to the switch between PDAF and CDAF, to avoid
- * "nuisance" scans. During each interval where PDAF is not working, only
- * ONE scan will be performed; CAF cannot track objects using CDAF alone.
+ * In CAF mode, the fallback to a CDAF scan is triggered when PDAF fails to
+ * report high confidence and a configurable number of frames have elapsed
+ * since the last image change since either PDAF was working or a previous
+ * scan found peak contrast. Image changes are detected using both contrast
+ * and AWB statistics (within the AF window[s]).
  *
+ * IR lighting can interfere with the correct operation of PDAF, so we
+ * optionally try to detect it (from AWB statistics).
  */
 
 namespace RPiController {
@@ -54,7 +62,9 @@ public:
 	void setWindows(libcamera::Span<libcamera::Rectangle const> const &wins) override;
 	void setMode(AfMode mode) override;
 	AfMode getMode() const override;
-	bool setLensPosition(double dioptres, int32_t *hwpos) override;
+	double getDefaultLensPosition() const override;
+	void getLensLimits(double &min, double &max) const override;
+	bool setLensPosition(double dioptres, int32_t *hwpos, bool force) override;
 	std::optional<double> getLensPosition() const override;
 	void triggerScan() override;
 	void cancelScan() override;
@@ -65,7 +75,8 @@ private:
 		Idle = 0,
 		Trigger,
 		Pdaf,
-		Coarse,
+		Coarse1,
+		Coarse2,
 		Fine,
 		Settle
 	};
@@ -80,9 +91,11 @@ private:
 	};
 
 	struct SpeedDependentParams {
-		double stepCoarse;		/* used for scans */
-		double stepFine;		/* used for scans */
+		double stepCoarse;		/* in dioptres; used for scans */
+		double stepFine;		/* in dioptres; used for scans */
 		double contrastRatio;		/* used for scan termination and reporting */
+		double retriggerRatio;          /* contrast and RGB ratio for re-triggering */
+		uint32_t retriggerDelay;        /* frames of stability before re-triggering */
 		double pdafGain;		/* coefficient for PDAF feedback loop */
 		double pdafSquelch;		/* PDAF stability parameter (device-specific) */
 		double maxSlew;			/* limit for lens movement per frame */
@@ -101,6 +114,7 @@ private:
 		uint32_t confThresh;	       	/* PDAF confidence cell min (sensor-specific) */
 		uint32_t confClip;	       	/* PDAF confidence cell max (sensor-specific) */
 		uint32_t skipFrames;	       	/* frames to skip at start or modeswitch */
+		bool checkForIR;                /* Set this if PDAF is unreliable in IR light */
 		libcamera::ipa::Pwl map;       	/* converts dioptres -> lens driver position */
 
 		CfgParams();
@@ -129,6 +143,7 @@ private:
 	void invalidateWeights();
 	bool getPhase(PdafRegions const &regions, double &phase, double &conf);
 	double getContrast(const FocusRegions &focusStats);
+	bool getAverageAndTestIr(const RgbyRegions &awbStats, double rgb[3]);
 	void doPDAF(double phase, double conf);
 	bool earlyTerminationByPhase(double phase);
 	double findPeak(unsigned index) const;
@@ -150,15 +165,20 @@ private:
 	bool useWindows_;
 	RegionWeights phaseWeights_;
 	RegionWeights contrastWeights_;
+	RegionWeights awbWeights_;
 
 	/* Working state. */
 	ScanState scanState_;
-	bool initted_;
+	bool initted_, irFlag_;
 	double ftarget_, fsmooth_;
-	double prevContrast_;
+	double prevContrast_, oldSceneContrast_;
+	double prevAverage_[3], oldSceneAverage_[3];
+	double prevPhase_;
 	unsigned skipCount_, stepCount_, dropCount_;
+	unsigned sameSignCount_;
+	unsigned sceneChangeCount_;
 	unsigned scanMaxIndex_;
-	double scanMaxContrast_, scanMinContrast_;
+	double scanMaxContrast_, scanMinContrast_, scanStep_;
 	std::vector<ScanRecord> scanData_;
 	AfState reportState_;
 };
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/agc.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/agc.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/agc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/agc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -184,14 +184,14 @@ void Agc::setFixedExposureTime(unsigned
 	channelData_[channelIndex].channel.setFixedExposureTime(fixedExposureTime);
 }
 
-void Agc::setFixedAnalogueGain(unsigned int channelIndex, double fixedAnalogueGain)
+void Agc::setFixedGain(unsigned int channelIndex, double fixedGain)
 {
 	if (checkChannel(channelIndex))
 		return;
 
-	LOG(RPiAgc, Debug) << "setFixedAnalogueGain " << fixedAnalogueGain
+	LOG(RPiAgc, Debug) << "setFixedGain " << fixedGain
 			   << " for channel " << channelIndex;
-	channelData_[channelIndex].channel.setFixedAnalogueGain(fixedAnalogueGain);
+	channelData_[channelIndex].channel.setFixedGain(fixedGain);
 }
 
 void Agc::setMeteringMode(std::string const &meteringModeName)
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/agc.h 0.6.0-2/src/ipa/rpi/controller/rpi/agc.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/agc.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/agc.h	2025-11-27 11:55:28.000000000 +0000
@@ -35,8 +35,8 @@ public:
 	void setMaxExposureTime(libcamera::utils::Duration maxExposureTime) override;
 	void setFixedExposureTime(unsigned int channelIndex,
 				  libcamera::utils::Duration fixedExposureTime) override;
-	void setFixedAnalogueGain(unsigned int channelIndex,
-				  double fixedAnalogueGain) override;
+	void setFixedGain(unsigned int channelIndex,
+			  double fixedGain) override;
 	void setMeteringMode(std::string const &meteringModeName) override;
 	void setExposureMode(std::string const &exposureModeName) override;
 	void setConstraintMode(std::string const &contraintModeName) override;
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/agc_channel.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/agc_channel.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/agc_channel.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/agc_channel.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -260,11 +260,13 @@ int AgcConfig::read(const libcamera::Yam
 
 	desaturate = params["desaturate"].get<int>(1);
 
+	maxDigitalGain = params["max_digital_gain"].get<double>(4.0);
+
 	return 0;
 }
 
 AgcChannel::ExposureValues::ExposureValues()
-	: exposureTime(0s), analogueGain(0),
+	: exposureTime(0s), analogueGain(0), digitalGain(0),
 	  totalExposure(0s), totalExposureNoDG(0s)
 {
 }
@@ -273,7 +275,7 @@ AgcChannel::AgcChannel()
 	: meteringMode_(nullptr), exposureMode_(nullptr), constraintMode_(nullptr),
 	  frameCount_(0), lockCount_(0),
 	  lastTargetExposure_(0s), ev_(1.0), flickerPeriod_(0s),
-	  maxExposureTime_(0s), fixedExposureTime_(0s), fixedAnalogueGain_(0.0)
+	  maxExposureTime_(0s), fixedExposureTime_(0s), fixedGain_(0.0)
 {
 	/* Set AWB default values in case early frames have no updates in metadata. */
 	awb_.gainR = 1.0;
@@ -337,17 +339,17 @@ bool AgcChannel::autoExposureEnabled() c
 
 void AgcChannel::disableAutoGain()
 {
-	fixedAnalogueGain_ = status_.analogueGain;
+	fixedGain_ = status_.analogueGain;
 }
 
 void AgcChannel::enableAutoGain()
 {
-	fixedAnalogueGain_ = 0;
+	fixedGain_ = 0;
 }
 
 bool AgcChannel::autoGainEnabled() const
 {
-	return fixedAnalogueGain_ == 0;
+	return fixedGain_ == 0;
 }
 
 unsigned int AgcChannel::getConvergenceFrames() const
@@ -356,7 +358,7 @@ unsigned int AgcChannel::getConvergenceF
 	 * If exposure time and gain have been explicitly set, there is no
 	 * convergence to happen, so no need to drop any frames - return zero.
 	 */
-	if (fixedExposureTime_ && fixedAnalogueGain_)
+	if (fixedExposureTime_ && fixedGain_)
 		return 0;
 	else
 		return config_.convergenceFrames;
@@ -396,11 +398,9 @@ void AgcChannel::setFixedExposureTime(Du
 	status_.exposureTime = limitExposureTime(fixedExposureTime_);
 }
 
-void AgcChannel::setFixedAnalogueGain(double fixedAnalogueGain)
+void AgcChannel::setFixedGain(double fixedGain)
 {
-	fixedAnalogueGain_ = fixedAnalogueGain;
-	/* Set this in case someone calls disableAuto() straight after. */
-	status_.analogueGain = limitGain(fixedAnalogueGain);
+	fixedGain_ = fixedGain;
 }
 
 void AgcChannel::setMeteringMode(std::string const &meteringModeName)
@@ -434,22 +434,10 @@ void AgcChannel::switchMode(CameraMode c
 	mode_ = cameraMode;
 
 	Duration fixedExposureTime = limitExposureTime(fixedExposureTime_);
-	if (fixedExposureTime && fixedAnalogueGain_) {
-		/* We're going to reset the algorithm here with these fixed values. */
-		fetchAwbStatus(metadata);
-		double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
-		ASSERT(minColourGain != 0.0);
-
-		/* This is the equivalent of computeTargetExposure and applyDigitalGain. */
-		target_.totalExposureNoDG = fixedExposureTime_ * fixedAnalogueGain_;
-		target_.totalExposure = target_.totalExposureNoDG / minColourGain;
-
-		/* Equivalent of filterExposure. This resets any "history". */
-		filtered_ = target_;
-
-		/* Equivalent of divideUpExposure. */
-		filtered_.exposureTime = fixedExposureTime;
-		filtered_.analogueGain = fixedAnalogueGain_;
+	double fixedGain = limitGain(fixedGain_);
+	if (fixedExposureTime && fixedGain_) {
+		filtered_.totalExposureNoDG = fixedExposureTime * fixedGain;
+		filtered_.totalExposure = filtered_.totalExposureNoDG;
 	} else if (status_.totalExposureValue) {
 		/*
 		 * On a mode switch, various things could happen:
@@ -462,12 +450,8 @@ void AgcChannel::switchMode(CameraMode c
 		 */
 
 		double ratio = lastSensitivity / cameraMode.sensitivity;
-		target_.totalExposureNoDG *= ratio;
-		target_.totalExposure *= ratio;
-		filtered_.totalExposureNoDG *= ratio;
 		filtered_.totalExposure *= ratio;
-
-		divideUpExposure();
+		filtered_.totalExposureNoDG = filtered_.totalExposure;
 	} else {
 		/*
 		 * We come through here on startup, when at least one of the
@@ -477,54 +461,30 @@ void AgcChannel::switchMode(CameraMode c
 		 * weren't set.
 		 */
 
-		/* Equivalent of divideUpExposure. */
-		filtered_.exposureTime = fixedExposureTime ? fixedExposureTime : config_.defaultExposureTime;
-		filtered_.analogueGain = fixedAnalogueGain_ ? fixedAnalogueGain_ : config_.defaultAnalogueGain;
+		Duration exposureTime = fixedExposureTime ? fixedExposureTime : config_.defaultExposureTime;
+		double gain = fixedGain ? fixedGain : config_.defaultAnalogueGain;
+		filtered_.totalExposure = exposureTime * gain;
+		filtered_.totalExposureNoDG = filtered_.totalExposure;
 	}
 
+	/* Setting target_ to filtered_ removes any history from before the mode switch. */
+	target_ = filtered_;
+	divideUpExposure();
+
 	writeAndFinish(metadata, false);
 }
 
 void AgcChannel::prepare(Metadata *imageMetadata)
 {
-	Duration totalExposureValue = status_.totalExposureValue;
-	AgcStatus delayedStatus;
+	DeviceStatus deviceStatus;
 	AgcPrepareStatus prepareStatus;
 
-	/* Fetch the AWB status now because AWB also sets it in the prepare method. */
-	fetchAwbStatus(imageMetadata);
-
-	if (!imageMetadata->get("agc.delayed_status", delayedStatus))
-		totalExposureValue = delayedStatus.totalExposureValue;
-
-	prepareStatus.digitalGain = 1.0;
 	prepareStatus.locked = false;
 
-	if (status_.totalExposureValue) {
-		/* Process has run, so we have meaningful values. */
-		DeviceStatus deviceStatus;
-		if (imageMetadata->get("device.status", deviceStatus) == 0) {
-			Duration actualExposure = deviceStatus.exposureTime *
-						  deviceStatus.analogueGain;
-			if (actualExposure) {
-				double digitalGain = totalExposureValue / actualExposure;
-				LOG(RPiAgc, Debug) << "Want total exposure " << totalExposureValue;
-				/*
-				 * Never ask for a gain < 1.0, and also impose
-				 * some upper limit. Make it customisable?
-				 */
-				prepareStatus.digitalGain = std::max(1.0, std::min(digitalGain, 4.0));
-				LOG(RPiAgc, Debug) << "Actual exposure " << actualExposure;
-				LOG(RPiAgc, Debug) << "Use digitalGain " << prepareStatus.digitalGain;
-				LOG(RPiAgc, Debug) << "Effective exposure "
-						   << actualExposure * prepareStatus.digitalGain;
-				/* Decide whether AEC/AGC has converged. */
-				prepareStatus.locked = updateLockStatus(deviceStatus);
-			}
-		} else
-			LOG(RPiAgc, Warning) << "AgcChannel: no device metadata";
-		imageMetadata->set("agc.prepare_status", prepareStatus);
-	}
+	if (!imageMetadata->get("device.status", deviceStatus))
+		prepareStatus.locked = updateLockStatus(deviceStatus);
+
+	imageMetadata->set("agc.prepare_status", prepareStatus);
 }
 
 void AgcChannel::process(StatisticsPtr &stats, DeviceStatus const &deviceStatus,
@@ -610,11 +570,11 @@ void AgcChannel::housekeepConfig()
 	/* First fetch all the up-to-date settings, so no one else has to do it. */
 	status_.ev = ev_;
 	status_.fixedExposureTime = limitExposureTime(fixedExposureTime_);
-	status_.fixedAnalogueGain = fixedAnalogueGain_;
+	status_.fixedGain = limitGain(fixedGain_);
 	status_.flickerPeriod = flickerPeriod_;
 	LOG(RPiAgc, Debug) << "ev " << status_.ev << " fixedExposureTime "
-			   << status_.fixedExposureTime << " fixedAnalogueGain "
-			   << status_.fixedAnalogueGain;
+			   << status_.fixedExposureTime << " fixedGain "
+			   << status_.fixedGain;
 	/*
 	 * Make sure the "mode" pointers point to the up-to-date things, if
 	 * they've changed.
@@ -661,6 +621,9 @@ void AgcChannel::fetchCurrentExposure(De
 	current_.analogueGain = deviceStatus.analogueGain;
 	current_.totalExposure = 0s; /* this value is unused */
 	current_.totalExposureNoDG = current_.exposureTime * current_.analogueGain;
+	LOG(RPiAgc, Debug) << "Current frame: exposure time " << current_.exposureTime
+			   << " ag " << current_.analogueGain
+			   << " (total " << current_.totalExposureNoDG << ")";
 }
 
 void AgcChannel::fetchAwbStatus(Metadata *imageMetadata)
@@ -716,8 +679,13 @@ static double computeInitialY(Statistics
 	}
 
 	/* Factor in the AWB correction if needed. */
-	if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb)
-		sum *= RGB<double>{ { awb.gainR, awb.gainR, awb.gainB } };
+	if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) {
+		double minColourGain = std::min({ awb.gainR, awb.gainG, awb.gainB, 1.0 });
+		minColourGain = std::max(minColourGain, 1.0);
+		RGB<double> colourGains{ { awb.gainR, awb.gainG, awb.gainB } };
+		colourGains /= minColourGain;
+		sum *= colourGains;
+	}
 
 	double ySum = ipa::rec601LuminanceFromRGB(sum);
 
@@ -796,17 +764,9 @@ void AgcChannel::computeGain(StatisticsP
 
 void AgcChannel::computeTargetExposure(double gain)
 {
-	if (status_.fixedExposureTime && status_.fixedAnalogueGain) {
-		/*
-		 * When analogue gain and exposure time are both fixed, we need
-		 * to drive the total exposure so that we end up with a digital
-		 * gain of at least 1/minColourGain. Otherwise we'd desaturate
-		 * channels causing white to go cyan or magenta.
-		 */
-		double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
-		ASSERT(minColourGain != 0.0);
+	if (status_.fixedExposureTime && status_.fixedGain) {
 		target_.totalExposure =
-			status_.fixedExposureTime * status_.fixedAnalogueGain / minColourGain;
+			status_.fixedExposureTime * status_.fixedGain;
 	} else {
 		/*
 		 * The statistics reflect the image without digital gain, so the final
@@ -815,14 +775,12 @@ void AgcChannel::computeTargetExposure(d
 		target_.totalExposure = current_.totalExposureNoDG * gain;
 		/* The final target exposure is also limited to what the exposure mode allows. */
 		Duration maxExposureTime = status_.fixedExposureTime
-					 ? status_.fixedExposureTime
-					 : exposureMode_->exposureTime.back();
+					      ? status_.fixedExposureTime
+					      : exposureMode_->exposureTime.back();
 		maxExposureTime = limitExposureTime(maxExposureTime);
-		Duration maxTotalExposure =
-			maxExposureTime *
-			(status_.fixedAnalogueGain != 0.0
-				 ? status_.fixedAnalogueGain
-				 : exposureMode_->gain.back());
+		double maxGain = status_.fixedGain ? status_.fixedGain : exposureMode_->gain.back();
+		maxGain = limitGain(maxGain);
+		Duration maxTotalExposure = maxExposureTime * maxGain;
 		target_.totalExposure = std::min(target_.totalExposure, maxTotalExposure);
 	}
 	LOG(RPiAgc, Debug) << "Target totalExposure " << target_.totalExposure;
@@ -831,8 +789,6 @@ void AgcChannel::computeTargetExposure(d
 bool AgcChannel::applyChannelConstraints(const AgcChannelTotalExposures &channelTotalExposures)
 {
 	bool channelBound = false;
-	LOG(RPiAgc, Debug)
-		<< "Total exposure before channel constraints " << filtered_.totalExposure;
 
 	for (const auto &constraint : config_.channelConstraints) {
 		LOG(RPiAgc, Debug)
@@ -867,15 +823,8 @@ bool AgcChannel::applyChannelConstraints
 
 bool AgcChannel::applyDigitalGain(double gain, double targetY, bool channelBound)
 {
-	double minColourGain = std::min({ awb_.gainR, awb_.gainG, awb_.gainB, 1.0 });
-	ASSERT(minColourGain != 0.0);
-	double dg = 1.0 / minColourGain;
-	/*
-	 * I think this pipeline subtracts black level and rescales before we
-	 * get the stats, so no need to worry about it.
-	 */
-	LOG(RPiAgc, Debug) << "after AWB, target dg " << dg << " gain " << gain
-			   << " target_Y " << targetY;
+	filtered_.totalExposureNoDG = filtered_.totalExposure;
+
 	/*
 	 * Finally, if we're trying to reduce exposure but the target_Y is
 	 * "close" to 1.0, then the gain computed for that constraint will be
@@ -885,15 +834,14 @@ bool AgcChannel::applyDigitalGain(double
 	 * quickly (and we then approach the correct value more quickly from
 	 * below).
 	 */
-	bool desaturate = false;
-	if (config_.desaturate)
-		desaturate = !channelBound &&
-			     targetY > config_.fastReduceThreshold && gain < sqrt(targetY);
-	if (desaturate)
-		dg /= config_.fastReduceThreshold;
-	LOG(RPiAgc, Debug) << "Digital gain " << dg << " desaturate? " << desaturate;
-	filtered_.totalExposureNoDG = filtered_.totalExposure / dg;
-	LOG(RPiAgc, Debug) << "Target totalExposureNoDG " << filtered_.totalExposureNoDG;
+	bool desaturate = config_.desaturate && !channelBound &&
+			  targetY > config_.fastReduceThreshold && gain < sqrt(targetY);
+
+	if (desaturate) {
+		filtered_.totalExposureNoDG *= config_.fastReduceThreshold;
+		LOG(RPiAgc, Debug) << "Desaturating, exposure no dg " << filtered_.totalExposureNoDG;
+	}
+
 	return desaturate;
 }
 
@@ -908,7 +856,7 @@ void AgcChannel::filterExposure()
 	 * region, because we want to reflect any user exposure/gain updates,
 	 * however small.
 	 */
-	if ((status_.fixedExposureTime && status_.fixedAnalogueGain) ||
+	if ((status_.fixedExposureTime && status_.fixedGain) ||
 	    frameCount_ <= config_.startupFrames) {
 		speed = 1.0;
 		stableRegion = 0.0;
@@ -929,8 +877,7 @@ void AgcChannel::filterExposure()
 		filtered_.totalExposure = speed * target_.totalExposure +
 					  filtered_.totalExposure * (1.0 - speed);
 	}
-	LOG(RPiAgc, Debug) << "After filtering, totalExposure " << filtered_.totalExposure
-			   << " no dg " << filtered_.totalExposureNoDG;
+	LOG(RPiAgc, Debug) << "After filtering, totalExposure " << filtered_.totalExposure;
 }
 
 void AgcChannel::divideUpExposure()
@@ -942,63 +889,70 @@ void AgcChannel::divideUpExposure()
 	 */
 	Duration exposureValue = filtered_.totalExposureNoDG;
 	Duration exposureTime;
-	double analogueGain;
+	double gain;
 	exposureTime = status_.fixedExposureTime ? status_.fixedExposureTime
 						 : exposureMode_->exposureTime[0];
 	exposureTime = limitExposureTime(exposureTime);
-	analogueGain = status_.fixedAnalogueGain != 0.0 ? status_.fixedAnalogueGain
-							: exposureMode_->gain[0];
-	analogueGain = limitGain(analogueGain);
-	if (exposureTime * analogueGain < exposureValue) {
+	gain = status_.fixedGain != 0.0 ? status_.fixedGain
+		: exposureMode_->gain[0];
+	gain = limitGain(gain);
+	if (exposureTime * gain < exposureValue) {
 		for (unsigned int stage = 1;
 		     stage < exposureMode_->gain.size(); stage++) {
 			if (!status_.fixedExposureTime) {
 				Duration stageExposureTime =
 					limitExposureTime(exposureMode_->exposureTime[stage]);
-				if (stageExposureTime * analogueGain >= exposureValue) {
-					exposureTime = exposureValue / analogueGain;
+				if (stageExposureTime * gain >= exposureValue) {
+					exposureTime = exposureValue / gain;
 					break;
 				}
 				exposureTime = stageExposureTime;
 			}
-			if (status_.fixedAnalogueGain == 0.0) {
+			if (status_.fixedGain == 0.0) {
 				if (exposureMode_->gain[stage] * exposureTime >= exposureValue) {
-					analogueGain = exposureValue / exposureTime;
+					gain = exposureValue / exposureTime;
 					break;
 				}
-				analogueGain = exposureMode_->gain[stage];
-				analogueGain = limitGain(analogueGain);
+				gain = exposureMode_->gain[stage];
+				gain = limitGain(gain);
 			}
 		}
 	}
-	LOG(RPiAgc, Debug)
-		<< "Divided up exposure time and gain are " << exposureTime
-		<< " and " << analogueGain;
+
 	/*
 	 * Finally adjust exposure time for flicker avoidance (require both
 	 * exposure time and gain not to be fixed).
 	 */
-	if (!status_.fixedExposureTime && !status_.fixedAnalogueGain &&
+	if (!status_.fixedExposureTime && !status_.fixedGain &&
 	    status_.flickerPeriod) {
 		int flickerPeriods = exposureTime / status_.flickerPeriod;
 		if (flickerPeriods) {
 			Duration newExposureTime = flickerPeriods * status_.flickerPeriod;
-			analogueGain *= exposureTime / newExposureTime;
-			/*
-			 * We should still not allow the ag to go over the
-			 * largest value in the exposure mode. Note that this
-			 * may force more of the total exposure into the digital
-			 * gain as a side-effect.
-			 */
-			analogueGain = std::min(analogueGain, exposureMode_->gain.back());
-			analogueGain = limitGain(analogueGain);
+			gain *= exposureTime / newExposureTime;
 			exposureTime = newExposureTime;
 		}
 		LOG(RPiAgc, Debug) << "After flicker avoidance, exposure time "
-				   << exposureTime << " gain " << analogueGain;
+				   << exposureTime << " gain " << gain;
 	}
+
+	/* Limit analogue gain to maximum allowed. */
+	double analogueGain = std::min(gain, mode_.maxAnalogueGain);
+
+	/* Finally work out the digital gain that we will need. */
+	filtered_.totalExposureNoDG = analogueGain * exposureTime;
+	double digitalGain = filtered_.totalExposure / filtered_.totalExposureNoDG;
+	/* Limit dg by what is allowed. */
+	digitalGain = std::min(digitalGain, config_.maxDigitalGain);
+	/* Update total exposure, in case the dg went down. */
+	filtered_.totalExposure = filtered_.totalExposureNoDG * digitalGain;
+
 	filtered_.exposureTime = exposureTime;
 	filtered_.analogueGain = analogueGain;
+	filtered_.digitalGain = digitalGain;
+	LOG(RPiAgc, Debug) << "DivideUpExposure: total " << filtered_.totalExposure
+			   << " no dg " << filtered_.totalExposureNoDG;
+	LOG(RPiAgc, Debug) << "DivideUpExposure: exp " << exposureTime
+			   << " ag " << gain << " dg " << digitalGain;
 }
 
 void AgcChannel::writeAndFinish(Metadata *imageMetadata, bool desaturate)
@@ -1007,6 +961,7 @@ void AgcChannel::writeAndFinish(Metadata
 	status_.targetExposureValue = desaturate ? 0s : target_.totalExposure;
 	status_.exposureTime = filtered_.exposureTime;
 	status_.analogueGain = filtered_.analogueGain;
+	status_.digitalGain = filtered_.digitalGain;
 	/*
 	 * Write to metadata as well, in case anyone wants to update the camera
 	 * immediately.
@@ -1014,8 +969,6 @@ void AgcChannel::writeAndFinish(Metadata
 	imageMetadata->set("agc.status", status_);
 	LOG(RPiAgc, Debug) << "Output written, total exposure requested is "
 			   << filtered_.totalExposure;
-	LOG(RPiAgc, Debug) << "Camera exposure update: exposure time " << filtered_.exposureTime
-			   << " analogue gain " << filtered_.analogueGain;
 }
 
 Duration AgcChannel::limitExposureTime(Duration exposureTime)
@@ -1044,6 +997,7 @@ double AgcChannel::limitGain(double gain
 	if (!gain)
 		return gain;
 
-	gain = std::max(gain, mode_.minAnalogueGain);
+	gain = std::clamp(gain, mode_.minAnalogueGain,
+			  mode_.maxAnalogueGain * config_.maxDigitalGain);
 	return gain;
 }
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/agc_channel.h 0.6.0-2/src/ipa/rpi/controller/rpi/agc_channel.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/agc_channel.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/agc_channel.h	2025-11-27 11:55:28.000000000 +0000
@@ -78,6 +78,7 @@ struct AgcConfig {
 	double defaultAnalogueGain;
 	double stableRegion;
 	bool desaturate;
+	double maxDigitalGain;
 };
 
 class AgcChannel
@@ -92,7 +93,7 @@ public:
 	void setFlickerPeriod(libcamera::utils::Duration flickerPeriod);
 	void setMaxExposureTime(libcamera::utils::Duration maxExposureTime);
 	void setFixedExposureTime(libcamera::utils::Duration fixedExposureTime);
-	void setFixedAnalogueGain(double fixedAnalogueGain);
+	void setFixedGain(double fixedGain);
 	void setMeteringMode(std::string const &meteringModeName);
 	void setExposureMode(std::string const &exposureModeName);
 	void setConstraintMode(std::string const &contraintModeName);
@@ -134,6 +135,7 @@ private:
 
 		libcamera::utils::Duration exposureTime;
 		double analogueGain;
+		double digitalGain;
 		libcamera::utils::Duration totalExposure;
 		libcamera::utils::Duration totalExposureNoDG; /* without digital gain */
 	};
@@ -152,7 +154,7 @@ private:
 	libcamera::utils::Duration flickerPeriod_;
 	libcamera::utils::Duration maxExposureTime_;
 	libcamera::utils::Duration fixedExposureTime_;
-	double fixedAnalogueGain_;
+	double fixedGain_;
 };
 
 } /* namespace RPiController */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/awb.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/awb.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/awb.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/awb.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -165,7 +165,6 @@ int AwbConfig::read(const libcamera::Yam
 			bayes = false;
 		}
 	}
-	fast = params[fast].get<int>(bayes); /* default to fast for Bayesian, otherwise slow */
 	whitepointR = params["whitepoint_r"].get<double>(0.0);
 	whitepointB = params["whitepoint_b"].get<double>(0.0);
 	if (bayes == false)
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/awb.h 0.6.0-2/src/ipa/rpi/controller/rpi/awb.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/awb.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/awb.h	2025-11-27 11:55:28.000000000 +0000
@@ -43,7 +43,6 @@ struct AwbConfig {
 	uint16_t startupFrames;
 	unsigned int convergenceFrames; /* approx number of frames to converge */
 	double speed; /* IIR filter speed applied to algorithm results */
-	bool fast; /* "fast" mode uses a 16x16 rather than 32x32 grid */
 	libcamera::ipa::Pwl ctR; /* function maps CT to r (= R/G) */
 	libcamera::ipa::Pwl ctB; /* function maps CT to b (= B/G) */
 	libcamera::ipa::Pwl ctRInverse; /* inverse of ctR */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/cac.h 0.6.0-2/src/ipa/rpi/controller/rpi/cac.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/cac.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/cac.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2023, Raspberry Pi Ltd
  *
- * cac.hpp - CAC control algorithm
+ * CAC control algorithm
  */
 #pragma once
 
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/ccm.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/ccm.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/ccm.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/ccm.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -29,10 +29,11 @@ LOG_DEFINE_CATEGORY(RPiCcm)
 
 #define NAME "rpi.ccm"
 
-using Matrix3x3 = Matrix<double, 3, 3>;
-
 Ccm::Ccm(Controller *controller)
-	: CcmAlgorithm(controller), saturation_(1.0) {}
+	: CcmAlgorithm(controller), enableAuto_(true), saturation_(1.0),
+	  manualCcm_({ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 })
+{
+}
 
 char const *Ccm::name() const
 {
@@ -78,11 +79,22 @@ int Ccm::read(const libcamera::YamlObjec
 	return 0;
 }
 
+void Ccm::enableAuto()
+{
+	enableAuto_ = true;
+}
+
 void Ccm::setSaturation(double saturation)
 {
 	saturation_ = saturation;
 }
 
+void Ccm::setCcm(Matrix3x3 const &matrix)
+{
+	enableAuto_ = false;
+	manualCcm_ = matrix;
+}
+
 void Ccm::initialise()
 {
 }
@@ -151,7 +163,13 @@ void Ccm::prepare(Metadata *imageMetadat
 		LOG(RPiCcm, Warning) << "no colour temperature found";
 	if (!luxOk)
 		LOG(RPiCcm, Warning) << "no lux value found";
-	Matrix3x3 ccm = calculateCcm(config_.ccms, awb.temperatureK);
+
+	Matrix3x3 ccm;
+	if (enableAuto_)
+		ccm = calculateCcm(config_.ccms, awb.temperatureK);
+	else
+		ccm = manualCcm_;
+
 	double saturation = saturation_;
 	struct CcmStatus ccmStatus;
 	ccmStatus.saturation = saturation;
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/ccm.h 0.6.0-2/src/ipa/rpi/controller/rpi/ccm.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/ccm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/ccm.h	2025-11-27 11:55:28.000000000 +0000
@@ -8,7 +8,6 @@
 
 #include <vector>
 
-#include "libcamera/internal/matrix.h"
 #include <libipa/pwl.h>
 
 #include "../ccm_algorithm.h"
@@ -33,13 +32,17 @@ public:
 	Ccm(Controller *controller = NULL);
 	char const *name() const override;
 	int read(const libcamera::YamlObject &params) override;
+	void enableAuto() override;
 	void setSaturation(double saturation) override;
+	void setCcm(Matrix3x3 const &matrix) override;
 	void initialise() override;
 	void prepare(Metadata *imageMetadata) override;
 
 private:
 	CcmConfig config_;
+	bool enableAuto_;
 	double saturation_;
+	Matrix3x3 manualCcm_;
 };
 
 } /* namespace RPiController */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/decompand.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/decompand.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/decompand.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/decompand.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,66 @@
+#include "decompand.h"
+
+#include <libcamera/base/log.h>
+
+#include "../decompand_status.h"
+#include "../histogram.h"
+
+using namespace RPiController;
+using namespace libcamera;
+
+LOG_DEFINE_CATEGORY(RPiDecompand)
+
+#define NAME "rpi.decompand"
+
+Decompand::Decompand(Controller *controller)
+	: DecompandAlgorithm(controller)
+{
+}
+
+char const *Decompand::name() const
+{
+	return NAME;
+}
+
+int Decompand::read(const libcamera::YamlObject &params)
+{
+	config_.bitdepth = params["bitdepth"].get<uint32_t>(0);
+	config_.decompandCurve = params["decompand_curve"].get<ipa::Pwl>(ipa::Pwl{});
+	return config_.decompandCurve.empty() ? -EINVAL : 0;
+}
+
+void Decompand::initialise()
+{
+}
+
+void Decompand::switchMode(CameraMode const &cameraMode,
+			   [[maybe_unused]] Metadata *metadata)
+{
+	mode_ = cameraMode;
+}
+
+void Decompand::initialValues(libcamera::ipa::Pwl &decompandCurve)
+{
+	if (config_.bitdepth == 0 || mode_.bitdepth == config_.bitdepth) {
+		decompandCurve = config_.decompandCurve;
+	} else
+		decompandCurve = {};
+}
+
+void Decompand::prepare(Metadata *imageMetadata)
+{
+	DecompandStatus decompandStatus;
+
+	if (config_.bitdepth == 0 || mode_.bitdepth == config_.bitdepth) {
+		decompandStatus.decompandCurve = config_.decompandCurve;
+		imageMetadata->set("decompand.status", decompandStatus);
+	}
+}
+
+/* Register algorithm with the system. */
+static Algorithm *create(Controller *controller)
+{
+	return new Decompand(controller);
+}
+
+static RegisterAlgorithm reg(NAME, &create);
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/decompand.h 0.6.0-2/src/ipa/rpi/controller/rpi/decompand.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/decompand.h	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/decompand.h	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <libipa/pwl.h>
+
+#include "../decompand_algorithm.h"
+#include "../decompand_status.h"
+
+namespace RPiController {
+
+struct DecompandConfig {
+	uint32_t bitdepth;
+	libcamera::ipa::Pwl decompandCurve;
+};
+
+class Decompand : public DecompandAlgorithm
+{
+public:
+	Decompand(Controller *controller = nullptr);
+	char const *name() const override;
+	int read(const libcamera::YamlObject &params) override;
+	void initialise() override;
+	void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
+	void initialValues(libcamera::ipa::Pwl &decompandCurve) override;
+	void prepare(Metadata *imageMetadata) override;
+
+private:
+	CameraMode mode_;
+	DecompandConfig config_;
+};
+
+} /* namespace RPiController */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/denoise.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/denoise.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/denoise.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/denoise.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -37,7 +37,18 @@ int DenoiseConfig::read(const libcamera:
 	cdnEnable = params.contains("cdn");
 	if (cdnEnable) {
 		auto &cdnParams = params["cdn"];
-		cdnDeviation = cdnParams["deviation"].get<double>(120);
+		/*
+		 * For backwards compatibility with existing tuning files, interpret "deviation"
+		 * as giving the "no TDN" deviation, where present. But "deviation_no_tdn" takes
+		 * precedence when that's available.
+		 */
+		cdnDeviationNoTdn = cdnParams["deviation"].get<double>(150);
+		cdnDeviationNoTdn = cdnParams["deviation_no_tdn"].get<double>(cdnDeviationNoTdn);
+		/*
+		 * A third the value of the no TDN deviation is about right for with-TDN, if
+		 * the user hasn't specified otherwise.
+		 */
+		cdnDeviationWithTdn = cdnParams["deviation_with_tdn"].get<double>(cdnDeviationNoTdn / 3);
 		cdnStrength = cdnParams["strength"].get<double>(0.2);
 	}
 
@@ -48,13 +59,14 @@ int DenoiseConfig::read(const libcamera:
 		tdnThreshold = tdnParams["threshold"].get<double>(0.75);
 	} else if (sdnEnable) {
 		/*
-		 * If SDN is enabled but TDN isn't, overwrite all the SDN settings
+		 * If SDN is enabled but TDN isn't, overwrite all the SDN/CDN settings
 		 * with the "no TDN" versions. This makes it easier to enable or
 		 * disable TDN in the tuning file without editing all the other
 		 * parameters.
 		 */
 		sdnDeviation = sdnDeviation2 = sdnDeviationNoTdn;
 		sdnStrength = sdnStrengthNoTdn;
+		cdnDeviationWithTdn = cdnDeviationNoTdn;
 	}
 
 	return 0;
@@ -107,6 +119,7 @@ void Denoise::switchMode([[maybe_unused]
 	currentSdnDeviation_ = currentConfig_->sdnDeviationNoTdn;
 	currentSdnStrength_ = currentConfig_->sdnStrengthNoTdn;
 	currentSdnDeviation2_ = currentConfig_->sdnDeviationNoTdn;
+	currentCdnDeviation_ = currentConfig_->cdnDeviationNoTdn;
 }
 
 void Denoise::prepare(Metadata *imageMetadata)
@@ -159,8 +172,12 @@ void Denoise::prepare(Metadata *imageMet
 
 	if (currentConfig_->cdnEnable && mode_ != DenoiseMode::ColourOff) {
 		struct CdnStatus cdn;
-		cdn.threshold = currentConfig_->cdnDeviation * noiseStatus.noiseSlope + noiseStatus.noiseConstant;
+		cdn.threshold = currentCdnDeviation_ * noiseStatus.noiseSlope + noiseStatus.noiseConstant;
 		cdn.strength = currentConfig_->cdnStrength;
+		/* For the next frame, we back off the CDN deviation as TDN ramps up. */
+		double f = currentConfig_->sdnTdnBackoff;
+		currentCdnDeviation_ = f * currentCdnDeviation_ + (1 - f) * currentConfig_->cdnDeviationWithTdn;
+
 		imageMetadata->set("cdn.status", cdn);
 		LOG(RPiDenoise, Debug)
 			<< "programmed cdn threshold " << cdn.threshold
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/denoise.h 0.6.0-2/src/ipa/rpi/controller/rpi/denoise.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/denoise.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/denoise.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2022, Raspberry Pi Ltd
  *
- * denoise.hpp - Denoise (spatial, colour, temporal) control algorithm
+ * Denoise (spatial, colour, temporal) control algorithm
  */
 #pragma once
 
@@ -23,7 +23,8 @@ struct DenoiseConfig {
 	double sdnDeviationNoTdn;
 	double sdnStrengthNoTdn;
 	double sdnTdnBackoff;
-	double cdnDeviation;
+	double cdnDeviationNoTdn;
+	double cdnDeviationWithTdn;
 	double cdnStrength;
 	double tdnDeviation;
 	double tdnThreshold;
@@ -54,6 +55,7 @@ private:
 	double currentSdnDeviation_;
 	double currentSdnStrength_;
 	double currentSdnDeviation2_;
+	double currentCdnDeviation_;
 };
 
 } // namespace RPiController
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/lux.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/lux.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/lux.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/lux.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -20,7 +20,7 @@ LOG_DEFINE_CATEGORY(RPiLux)
 #define NAME "rpi.lux"
 
 Lux::Lux(Controller *controller)
-	: Algorithm(controller)
+	: Algorithm(controller), sensitivity_(1.0)
 {
 	/*
 	 * Put in some defaults as there will be no meaningful values until
@@ -68,6 +68,13 @@ void Lux::setCurrentAperture(double aper
 	currentAperture_ = aperture;
 }
 
+void Lux::switchMode(CameraMode const &cameraMode, [[maybe_unused]] Metadata *metadata)
+{
+	/* We will need to compensate for the camera sensitivity. */
+	ASSERT(cameraMode.sensitivity);
+	sensitivity_ = cameraMode.sensitivity;
+}
+
 void Lux::prepare(Metadata *imageMetadata)
 {
 	std::unique_lock<std::mutex> lock(mutex_);
@@ -78,20 +85,29 @@ void Lux::process(StatisticsPtr &stats,
 {
 	DeviceStatus deviceStatus;
 	if (imageMetadata->get("device.status", deviceStatus) == 0) {
+		/*
+		 * We've set up the first floating AGC region to collect full image stats. This
+		 * is a better choice than the Y-histogram, for example, because it's invariant
+		 * to the metering mode (and cheaper to evaluate).
+		 */
+		auto const &fullImageStats = stats->agcRegions.getFloating(0);
+		double currentY = static_cast<double>(fullImageStats.val.ySum) / fullImageStats.counted;
+
 		double currentGain = deviceStatus.analogueGain;
 		double currentAperture = deviceStatus.aperture.value_or(currentAperture_);
-		double currentY = stats->yHist.interQuantileMean(0, 1);
 		double gainRatio = referenceGain_ / currentGain;
 		double exposureTimeRatio =
 			referenceExposureTime_ / deviceStatus.exposureTime;
 		double apertureRatio = referenceAperture_ / currentAperture;
-		double yRatio = currentY * (65536 / stats->yHist.bins()) / referenceY_;
+		double yRatio = currentY / referenceY_;
 		double estimatedLux = exposureTimeRatio * gainRatio *
 				      apertureRatio * apertureRatio *
-				      yRatio * referenceLux_;
+				      yRatio * referenceLux_ / sensitivity_;
+
 		LuxStatus status;
 		status.lux = estimatedLux;
 		status.aperture = currentAperture;
+
 		LOG(RPiLux, Debug) << ": estimated lux " << estimatedLux;
 		{
 			std::unique_lock<std::mutex> lock(mutex_);
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/lux.h 0.6.0-2/src/ipa/rpi/controller/rpi/lux.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/lux.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/lux.h	2025-11-27 11:55:28.000000000 +0000
@@ -10,6 +10,7 @@
 
 #include <libcamera/base/utils.h>
 
+#include "../camera_mode.h"
 #include "../lux_status.h"
 #include "../algorithm.h"
 
@@ -23,6 +24,7 @@ public:
 	Lux(Controller *controller);
 	char const *name() const override;
 	int read(const libcamera::YamlObject &params) override;
+	void switchMode(CameraMode const &cameraMode, Metadata *metadata) override;
 	void prepare(Metadata *imageMetadata) override;
 	void process(StatisticsPtr &stats, Metadata *imageMetadata) override;
 	void setCurrentAperture(double aperture);
@@ -40,6 +42,7 @@ private:
 	double currentAperture_;
 	LuxStatus status_;
 	std::mutex mutex_;
+	double sensitivity_;
 };
 
 } /* namespace RPiController */
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/saturation.h 0.6.0-2/src/ipa/rpi/controller/rpi/saturation.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/saturation.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/saturation.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2022, Raspberry Pi Ltd
  *
- * saturation.hpp - Saturation control algorithm
+ * Saturation control algorithm
  */
 #pragma once
 
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/sdn.cpp 0.6.0-2/src/ipa/rpi/controller/rpi/sdn.cpp
--- 0.5.0-1/src/ipa/rpi/controller/rpi/sdn.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/sdn.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -37,8 +37,6 @@ char const *Sdn::name() const
 
 int Sdn::read(const libcamera::YamlObject &params)
 {
-	LOG(RPiSdn, Warning)
-		<< "Using legacy SDN tuning - please consider moving SDN inside rpi.denoise";
 	deviation_ = params["deviation"].get<double>(3.2);
 	strength_ = params["strength"].get<double>(0.75);
 	return 0;
diff -pruN 0.5.0-1/src/ipa/rpi/controller/rpi/tonemap.h 0.6.0-2/src/ipa/rpi/controller/rpi/tonemap.h
--- 0.5.0-1/src/ipa/rpi/controller/rpi/tonemap.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/controller/rpi/tonemap.h	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2022, Raspberry Pi Ltd
  *
- * tonemap.hpp - Tonemap control algorithm
+ * Tonemap control algorithm
  */
 #pragma once
 
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx219.json 0.6.0-2/src/ipa/rpi/pisp/data/imx219.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx219.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx219.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 3.661
+                "reference_slope": 5.38
             }
         },
         {
@@ -45,11 +45,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -58,7 +58,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,11 +66,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -79,19 +79,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -100,8 +100,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -271,7 +271,7 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
                                 "gain": [ 1.0, 1.5, 2.0, 4.0, 10.0 ]
                             },
                             "short":
@@ -282,7 +282,7 @@
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 10.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1021,37 +1021,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1120,8 +1138,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx219_noir.json 0.6.0-2/src/ipa/rpi/pisp/data/imx219_noir.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx219_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx219_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 3.661
+                "reference_slope": 5.38
             }
         },
         {
@@ -45,11 +45,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -58,7 +58,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,11 +66,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -79,19 +79,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -100,8 +100,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -188,7 +188,7 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
                                 "gain": [ 1.0, 1.5, 2.0, 4.0, 10.0 ]
                             },
                             "short":
@@ -199,7 +199,7 @@
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 10.0 ]
                             }
                         },
                         "constraint_modes":
@@ -928,37 +928,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1045,8 +1063,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx283.json 0.6.0-2/src/ipa/rpi/pisp/data/imx283.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx283.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx283.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,1352 @@
+{
+    "version": 2.0,
+    "target": "pisp",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 3200
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 10857,
+                "reference_gain": 1.49,
+                "reference_aperture": 1.0,
+                "reference_lux": 1050,
+                "reference_Y": 13959
+            }
+        },
+        {
+            "rpi.dpc":
+            {
+                "strength": 1
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 3.005
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 249,
+                "slope": 0.02036
+            }
+        },
+        {
+            "rpi.denoise":
+            {
+                "normal":
+                {
+                    "sdn":
+                    {
+                        "deviation": 0.6,
+                        "strength": 0.95,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.95
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.0,
+                        "threshold": 0.05
+                    }
+                },
+                "hdr":
+                {
+                    "sdn":
+                    {
+                        "deviation": 0.6,
+                        "strength": 0.95,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.95
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.0,
+                        "threshold": 0.05
+                    }
+                },
+                "night":
+                {
+                    "sdn":
+                    {
+                        "deviation": 0.6,
+                        "strength": 0.95,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.95
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.0,
+                        "threshold": 0.05
+                    }
+                }
+            }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 7700
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 6000,
+                        "hi": 6800,
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    2500.0, 0.9437, 0.2866,
+                    2820.0, 0.8496, 0.3541,
+                    2830.0, 0.8309, 0.3681,
+                    2885.0, 0.8183, 0.3778,
+                    3601.0, 0.6946, 0.4786,
+                    3615.0, 0.6929, 0.4801,
+                    3622.0, 0.6905, 0.4821,
+                    4345.0, 0.6012, 0.5628,
+                    4410.0, 0.5956, 0.5682,
+                    4486.0, 0.5892, 0.5743,
+                    4576.0, 0.5794, 0.5837,
+                    5672.0, 0.5232, 0.6392,
+                    5710.0, 0.5188, 0.6436,
+                    6850.0, 0.4862, 0.6773
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.02634,
+                "transverse_neg": 0.02491
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2940,
+                        "table":
+                        [
+                            1.023, 1.024, 1.028, 1.032, 1.034, 1.036, 1.037, 1.038, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.036, 1.035, 1.033, 1.031, 1.026, 1.022, 1.019, 1.014, 1.012,
+                            1.021, 1.023, 1.026, 1.027, 1.028, 1.029, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.027, 1.025, 1.021, 1.016, 1.012, 1.009,
+                            1.019, 1.022, 1.024, 1.026, 1.028, 1.029, 1.029, 1.031, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.027, 1.026, 1.024, 1.021, 1.016, 1.011, 1.009,
+                            1.021, 1.023, 1.025, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.026, 1.024, 1.022, 1.018, 1.012, 1.011,
+                            1.021, 1.024, 1.025, 1.027, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.025, 1.023, 1.019, 1.014, 1.011,
+                            1.023, 1.025, 1.026, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.027, 1.025, 1.023, 1.021, 1.015, 1.011,
+                            1.023, 1.025, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.026, 1.027, 1.027, 1.027, 1.028, 1.028, 1.029, 1.029, 1.029, 1.028, 1.026, 1.023, 1.021, 1.015, 1.012,
+                            1.023, 1.025, 1.027, 1.028, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.027, 1.027, 1.028, 1.029, 1.029, 1.029, 1.028, 1.026, 1.024, 1.021, 1.016, 1.012,
+                            1.023, 1.025, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.025, 1.026, 1.026, 1.027, 1.027, 1.028, 1.029, 1.029, 1.028, 1.027, 1.025, 1.022, 1.017, 1.014,
+                            1.024, 1.025, 1.027, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.027, 1.025, 1.023, 1.018, 1.015,
+                            1.024, 1.026, 1.027, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.025, 1.025, 1.025, 1.025, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.027, 1.026, 1.023, 1.018, 1.016,
+                            1.025, 1.026, 1.027, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.024, 1.024, 1.025, 1.026, 1.027, 1.028, 1.028, 1.029, 1.029, 1.027, 1.026, 1.023, 1.018, 1.016,
+                            1.025, 1.026, 1.027, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.024, 1.024, 1.025, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.027, 1.026, 1.023, 1.018, 1.016,
+                            1.025, 1.026, 1.027, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.024, 1.024, 1.025, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.028, 1.026, 1.023, 1.018, 1.016,
+                            1.025, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.024, 1.025, 1.025, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.027, 1.026, 1.023, 1.018, 1.016,
+                            1.025, 1.027, 1.028, 1.028, 1.029, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.025, 1.025, 1.026, 1.026, 1.027, 1.028, 1.028, 1.028, 1.027, 1.025, 1.023, 1.018, 1.016,
+                            1.025, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.025, 1.025, 1.026, 1.027, 1.027, 1.028, 1.028, 1.028, 1.027, 1.025, 1.023, 1.018, 1.015,
+                            1.025, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.026, 1.026, 1.025, 1.024, 1.024, 1.024, 1.025, 1.025, 1.025, 1.026, 1.027, 1.027, 1.028, 1.028, 1.028, 1.027, 1.025, 1.023, 1.018, 1.016,
+                            1.025, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.026, 1.026, 1.027, 1.028, 1.029, 1.028, 1.027, 1.025, 1.022, 1.017, 1.015,
+                            1.025, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.025, 1.026, 1.026, 1.026, 1.028, 1.028, 1.029, 1.029, 1.027, 1.025, 1.022, 1.017, 1.015,
+                            1.025, 1.027, 1.028, 1.029, 1.029, 1.031, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.026, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.027, 1.025, 1.022, 1.017, 1.014,
+                            1.025, 1.027, 1.028, 1.029, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.027, 1.027, 1.028, 1.028, 1.029, 1.028, 1.026, 1.024, 1.021, 1.016, 1.014,
+                            1.025, 1.027, 1.028, 1.029, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.026, 1.023, 1.021, 1.014, 1.012,
+                            1.024, 1.027, 1.028, 1.029, 1.031, 1.032, 1.032, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.027, 1.026, 1.023, 1.019, 1.014, 1.011,
+                            1.024, 1.027, 1.028, 1.029, 1.031, 1.032, 1.032, 1.032, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.025, 1.022, 1.018, 1.012, 1.009,
+                            1.024, 1.026, 1.028, 1.029, 1.032, 1.032, 1.032, 1.032, 1.032, 1.031, 1.031, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.029, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.022, 1.018, 1.011, 1.009,
+                            1.023, 1.026, 1.028, 1.029, 1.032, 1.033, 1.033, 1.033, 1.033, 1.032, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.025, 1.024, 1.021, 1.016, 1.011, 1.008,
+                            1.022, 1.026, 1.028, 1.031, 1.032, 1.033, 1.033, 1.034, 1.034, 1.033, 1.032, 1.032, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.025, 1.023, 1.021, 1.015, 1.009, 1.007,
+                            1.022, 1.025, 1.028, 1.031, 1.032, 1.033, 1.034, 1.034, 1.035, 1.034, 1.034, 1.033, 1.032, 1.032, 1.032, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.025, 1.023, 1.019, 1.014, 1.008, 1.006,
+                            1.021, 1.024, 1.027, 1.029, 1.031, 1.033, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.033, 1.033, 1.032, 1.032, 1.032, 1.032, 1.032, 1.032, 1.031, 1.031, 1.031, 1.029, 1.027, 1.026, 1.024, 1.021, 1.017, 1.013, 1.007, 1.004,
+                            1.019, 1.022, 1.026, 1.028, 1.031, 1.032, 1.033, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.033, 1.033, 1.033, 1.032, 1.032, 1.032, 1.032, 1.031, 1.031, 1.029, 1.028, 1.026, 1.024, 1.021, 1.018, 1.015, 1.011, 1.004, 1.002,
+                            1.018, 1.021, 1.025, 1.027, 1.029, 1.031, 1.032, 1.033, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.033, 1.033, 1.032, 1.032, 1.032, 1.031, 1.031, 1.029, 1.029, 1.027, 1.025, 1.023, 1.019, 1.017, 1.013, 1.009, 1.002, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.027, 1.032, 1.036, 1.039, 1.044, 1.047, 1.049, 1.051, 1.051, 1.052, 1.052, 1.051, 1.051, 1.051, 1.051, 1.052, 1.052, 1.052, 1.053, 1.053, 1.053, 1.053, 1.052, 1.051, 1.049, 1.047, 1.043, 1.039, 1.036, 1.031, 1.021, 1.015,
+                            1.027, 1.029, 1.035, 1.038, 1.041, 1.042, 1.042, 1.042, 1.043, 1.043, 1.042, 1.042, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.044, 1.044, 1.044, 1.045, 1.045, 1.044, 1.044, 1.043, 1.041, 1.037, 1.033, 1.026, 1.018, 1.015,
+                            1.025, 1.029, 1.033, 1.036, 1.039, 1.041, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.043, 1.043, 1.043, 1.044, 1.044, 1.044, 1.044, 1.043, 1.042, 1.039, 1.037, 1.033, 1.026, 1.018, 1.014,
+                            1.026, 1.031, 1.034, 1.037, 1.039, 1.041, 1.041, 1.041, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.042, 1.041, 1.038, 1.034, 1.028, 1.021, 1.017,
+                            1.028, 1.032, 1.035, 1.037, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.041, 1.039, 1.036, 1.031, 1.023, 1.019,
+                            1.029, 1.033, 1.036, 1.038, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.043, 1.041, 1.039, 1.036, 1.032, 1.024, 1.019,
+                            1.029, 1.034, 1.036, 1.038, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.042, 1.043, 1.043, 1.043, 1.043, 1.042, 1.039, 1.036, 1.033, 1.024, 1.021,
+                            1.029, 1.034, 1.036, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.042, 1.043, 1.043, 1.043, 1.042, 1.041, 1.037, 1.033, 1.026, 1.022,
+                            1.029, 1.033, 1.036, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.042, 1.043, 1.043, 1.042, 1.041, 1.038, 1.034, 1.027, 1.024,
+                            1.031, 1.033, 1.036, 1.037, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.043, 1.043, 1.042, 1.041, 1.038, 1.034, 1.028, 1.025,
+                            1.031, 1.034, 1.036, 1.037, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.042, 1.042, 1.042, 1.041, 1.039, 1.035, 1.028, 1.025,
+                            1.031, 1.034, 1.036, 1.037, 1.037, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.042, 1.042, 1.042, 1.041, 1.039, 1.035, 1.029, 1.025,
+                            1.031, 1.034, 1.036, 1.037, 1.037, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.042, 1.042, 1.041, 1.039, 1.035, 1.029, 1.025,
+                            1.031, 1.034, 1.036, 1.037, 1.037, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.042, 1.042, 1.041, 1.039, 1.035, 1.029, 1.025,
+                            1.031, 1.034, 1.036, 1.037, 1.037, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.038, 1.034, 1.028, 1.025,
+                            1.031, 1.035, 1.036, 1.037, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.038, 1.034, 1.028, 1.024,
+                            1.031, 1.035, 1.036, 1.037, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.038, 1.034, 1.028, 1.024,
+                            1.031, 1.035, 1.036, 1.037, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.038, 1.034, 1.028, 1.024,
+                            1.031, 1.034, 1.037, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.039, 1.037, 1.033, 1.027, 1.024,
+                            1.031, 1.034, 1.036, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.039, 1.037, 1.033, 1.027, 1.023,
+                            1.029, 1.033, 1.036, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.039, 1.037, 1.033, 1.026, 1.022,
+                            1.029, 1.033, 1.036, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.039, 1.038, 1.036, 1.032, 1.025, 1.021,
+                            1.029, 1.033, 1.036, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.035, 1.031, 1.023, 1.019,
+                            1.029, 1.033, 1.036, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.037, 1.034, 1.029, 1.021, 1.018,
+                            1.028, 1.032, 1.035, 1.038, 1.039, 1.039, 1.041, 1.041, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.037, 1.033, 1.028, 1.019, 1.017,
+                            1.028, 1.031, 1.034, 1.037, 1.039, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.036, 1.032, 1.027, 1.018, 1.015,
+                            1.027, 1.031, 1.034, 1.037, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.039, 1.039, 1.038, 1.036, 1.035, 1.031, 1.025, 1.016, 1.013,
+                            1.025, 1.031, 1.034, 1.037, 1.039, 1.041, 1.041, 1.042, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.036, 1.034, 1.029, 1.022, 1.014, 1.011,
+                            1.023, 1.029, 1.034, 1.037, 1.039, 1.041, 1.042, 1.042, 1.042, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.035, 1.033, 1.028, 1.021, 1.012, 1.009,
+                            1.022, 1.027, 1.032, 1.036, 1.038, 1.039, 1.041, 1.042, 1.042, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.035, 1.033, 1.031, 1.025, 1.018, 1.009, 1.005,
+                            1.019, 1.024, 1.029, 1.034, 1.036, 1.039, 1.039, 1.041, 1.042, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.036, 1.033, 1.031, 1.026, 1.021, 1.014, 1.005, 1.003,
+                            1.017, 1.022, 1.028, 1.032, 1.036, 1.038, 1.039, 1.041, 1.041, 1.042, 1.042, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.036, 1.034, 1.032, 1.028, 1.024, 1.019, 1.012, 1.003, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.021, 1.033, 1.041, 1.046, 1.051, 1.054, 1.057, 1.061, 1.064, 1.066, 1.068, 1.068, 1.068, 1.068, 1.068, 1.069, 1.069, 1.069, 1.069, 1.069, 1.068, 1.067, 1.064, 1.062, 1.058, 1.056, 1.052, 1.047, 1.041, 1.031, 1.019, 1.012,
+                            1.021, 1.029, 1.037, 1.043, 1.048, 1.053, 1.056, 1.058, 1.059, 1.059, 1.061, 1.061, 1.061, 1.061, 1.062, 1.062, 1.062, 1.062, 1.062, 1.062, 1.062, 1.062, 1.061, 1.059, 1.058, 1.054, 1.049, 1.044, 1.039, 1.029, 1.018, 1.012,
+                            1.023, 1.029, 1.037, 1.043, 1.048, 1.052, 1.055, 1.057, 1.058, 1.059, 1.059, 1.061, 1.061, 1.061, 1.062, 1.062, 1.062, 1.062, 1.062, 1.062, 1.062, 1.061, 1.061, 1.059, 1.057, 1.054, 1.049, 1.044, 1.039, 1.029, 1.018, 1.015,
+                            1.025, 1.032, 1.039, 1.045, 1.049, 1.054, 1.057, 1.058, 1.059, 1.059, 1.061, 1.061, 1.061, 1.062, 1.062, 1.062, 1.062, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.058, 1.055, 1.051, 1.046, 1.041, 1.033, 1.022, 1.018,
+                            1.027, 1.035, 1.041, 1.046, 1.051, 1.054, 1.057, 1.058, 1.059, 1.061, 1.061, 1.061, 1.062, 1.062, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.061, 1.061, 1.059, 1.056, 1.053, 1.048, 1.043, 1.036, 1.025, 1.019,
+                            1.029, 1.036, 1.043, 1.049, 1.052, 1.055, 1.057, 1.058, 1.059, 1.061, 1.061, 1.062, 1.062, 1.063, 1.063, 1.063, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.061, 1.061, 1.058, 1.054, 1.051, 1.045, 1.039, 1.027, 1.021,
+                            1.031, 1.039, 1.045, 1.049, 1.053, 1.056, 1.058, 1.059, 1.059, 1.061, 1.062, 1.062, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.056, 1.051, 1.046, 1.039, 1.028, 1.023,
+                            1.032, 1.039, 1.045, 1.051, 1.054, 1.056, 1.058, 1.059, 1.059, 1.061, 1.062, 1.062, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.062, 1.062, 1.062, 1.061, 1.061, 1.057, 1.053, 1.048, 1.041, 1.031, 1.025,
+                            1.033, 1.039, 1.046, 1.051, 1.054, 1.056, 1.058, 1.059, 1.059, 1.061, 1.061, 1.062, 1.063, 1.063, 1.064, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.062, 1.062, 1.061, 1.058, 1.054, 1.049, 1.043, 1.032, 1.027,
+                            1.034, 1.041, 1.046, 1.051, 1.054, 1.056, 1.057, 1.059, 1.059, 1.061, 1.062, 1.063, 1.063, 1.064, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.062, 1.062, 1.061, 1.059, 1.054, 1.049, 1.044, 1.034, 1.029,
+                            1.034, 1.041, 1.046, 1.051, 1.054, 1.056, 1.058, 1.059, 1.059, 1.061, 1.063, 1.063, 1.063, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.062, 1.062, 1.062, 1.061, 1.059, 1.055, 1.051, 1.044, 1.035, 1.029,
+                            1.035, 1.041, 1.047, 1.051, 1.054, 1.056, 1.058, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.062, 1.062, 1.061, 1.059, 1.056, 1.051, 1.045, 1.035, 1.029,
+                            1.036, 1.042, 1.047, 1.052, 1.054, 1.056, 1.058, 1.059, 1.061, 1.062, 1.063, 1.063, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.056, 1.052, 1.045, 1.036, 1.031,
+                            1.036, 1.043, 1.048, 1.052, 1.054, 1.056, 1.058, 1.059, 1.061, 1.062, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.061, 1.056, 1.052, 1.046, 1.036, 1.031,
+                            1.037, 1.043, 1.048, 1.052, 1.055, 1.057, 1.059, 1.061, 1.061, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.056, 1.052, 1.045, 1.036, 1.031,
+                            1.037, 1.044, 1.048, 1.053, 1.055, 1.058, 1.059, 1.061, 1.062, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.056, 1.052, 1.045, 1.036, 1.031,
+                            1.037, 1.044, 1.049, 1.053, 1.056, 1.058, 1.059, 1.061, 1.062, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.056, 1.052, 1.045, 1.036, 1.031,
+                            1.037, 1.044, 1.049, 1.053, 1.056, 1.058, 1.059, 1.062, 1.063, 1.063, 1.064, 1.064, 1.064, 1.065, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.056, 1.051, 1.045, 1.036, 1.031,
+                            1.037, 1.044, 1.049, 1.053, 1.056, 1.058, 1.061, 1.062, 1.063, 1.063, 1.064, 1.064, 1.065, 1.065, 1.065, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.062, 1.062, 1.061, 1.059, 1.056, 1.051, 1.044, 1.035, 1.031,
+                            1.037, 1.043, 1.049, 1.053, 1.056, 1.058, 1.061, 1.062, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.062, 1.062, 1.061, 1.059, 1.055, 1.051, 1.044, 1.034, 1.029,
+                            1.035, 1.042, 1.048, 1.053, 1.056, 1.058, 1.059, 1.061, 1.062, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.061, 1.059, 1.055, 1.051, 1.043, 1.034, 1.027,
+                            1.034, 1.042, 1.048, 1.053, 1.056, 1.058, 1.061, 1.061, 1.062, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.061, 1.058, 1.054, 1.049, 1.042, 1.032, 1.026,
+                            1.034, 1.041, 1.047, 1.053, 1.056, 1.058, 1.061, 1.061, 1.062, 1.062, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.061, 1.059, 1.057, 1.053, 1.048, 1.041, 1.031, 1.026,
+                            1.034, 1.041, 1.047, 1.052, 1.056, 1.059, 1.061, 1.061, 1.062, 1.062, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.058, 1.056, 1.052, 1.046, 1.038, 1.028, 1.024,
+                            1.032, 1.039, 1.045, 1.052, 1.056, 1.058, 1.061, 1.061, 1.062, 1.063, 1.063, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.062, 1.062, 1.061, 1.059, 1.057, 1.055, 1.051, 1.045, 1.037, 1.026, 1.022,
+                            1.032, 1.038, 1.044, 1.049, 1.054, 1.058, 1.061, 1.061, 1.062, 1.063, 1.063, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.062, 1.061, 1.059, 1.057, 1.054, 1.049, 1.044, 1.036, 1.024, 1.019,
+                            1.029, 1.037, 1.044, 1.049, 1.054, 1.058, 1.059, 1.062, 1.062, 1.063, 1.063, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.063, 1.062, 1.061, 1.058, 1.055, 1.052, 1.048, 1.042, 1.033, 1.022, 1.017,
+                            1.027, 1.035, 1.042, 1.049, 1.054, 1.057, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.059, 1.057, 1.054, 1.051, 1.047, 1.039, 1.031, 1.019, 1.014,
+                            1.025, 1.033, 1.041, 1.047, 1.052, 1.056, 1.058, 1.061, 1.062, 1.063, 1.063, 1.063, 1.063, 1.064, 1.064, 1.064, 1.064, 1.064, 1.064, 1.063, 1.063, 1.063, 1.062, 1.059, 1.056, 1.053, 1.049, 1.044, 1.037, 1.028, 1.016, 1.012,
+                            1.022, 1.031, 1.038, 1.045, 1.051, 1.053, 1.056, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.063, 1.064, 1.063, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.059, 1.057, 1.054, 1.051, 1.047, 1.041, 1.034, 1.025, 1.013, 1.007,
+                            1.019, 1.026, 1.035, 1.042, 1.047, 1.051, 1.054, 1.057, 1.059, 1.061, 1.062, 1.062, 1.062, 1.063, 1.063, 1.063, 1.062, 1.063, 1.062, 1.062, 1.061, 1.059, 1.057, 1.054, 1.051, 1.047, 1.042, 1.036, 1.029, 1.019, 1.007, 1.005,
+                            1.016, 1.024, 1.033, 1.041, 1.046, 1.049, 1.053, 1.055, 1.057, 1.059, 1.061, 1.062, 1.062, 1.063, 1.063, 1.062, 1.062, 1.062, 1.062, 1.061, 1.059, 1.057, 1.055, 1.052, 1.049, 1.045, 1.039, 1.033, 1.027, 1.016, 1.005, 1.001
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2940,
+                        "table":
+                        [
+                            1.001, 1.001, 1.014, 1.027, 1.038, 1.047, 1.051, 1.054, 1.058, 1.061, 1.062, 1.064, 1.066, 1.066, 1.066, 1.067, 1.067, 1.067, 1.067, 1.067, 1.067, 1.066, 1.064, 1.063, 1.061, 1.057, 1.055, 1.049, 1.043, 1.032, 1.026, 1.018,
+                            1.001, 1.013, 1.023, 1.032, 1.042, 1.049, 1.056, 1.063, 1.066, 1.069, 1.073, 1.076, 1.077, 1.078, 1.079, 1.079, 1.081, 1.081, 1.079, 1.079, 1.078, 1.077, 1.076, 1.073, 1.071, 1.066, 1.061, 1.053, 1.046, 1.037, 1.031, 1.026,
+                            1.008, 1.019, 1.031, 1.042, 1.049, 1.056, 1.063, 1.066, 1.069, 1.073, 1.076, 1.078, 1.078, 1.081, 1.082, 1.082, 1.082, 1.081, 1.081, 1.081, 1.079, 1.079, 1.077, 1.076, 1.073, 1.071, 1.066, 1.061, 1.053, 1.046, 1.035, 1.032,
+                            1.012, 1.023, 1.036, 1.045, 1.053, 1.059, 1.065, 1.068, 1.072, 1.075, 1.078, 1.079, 1.081, 1.083, 1.084, 1.084, 1.084, 1.084, 1.083, 1.083, 1.081, 1.081, 1.079, 1.078, 1.076, 1.073, 1.069, 1.063, 1.056, 1.049, 1.039, 1.034,
+                            1.015, 1.027, 1.038, 1.048, 1.056, 1.061, 1.067, 1.071, 1.074, 1.076, 1.079, 1.082, 1.084, 1.085, 1.086, 1.086, 1.086, 1.086, 1.085, 1.085, 1.084, 1.083, 1.081, 1.079, 1.077, 1.075, 1.072, 1.066, 1.059, 1.051, 1.041, 1.038,
+                            1.018, 1.031, 1.041, 1.051, 1.058, 1.064, 1.069, 1.073, 1.075, 1.079, 1.082, 1.084, 1.085, 1.087, 1.088, 1.088, 1.088, 1.088, 1.087, 1.087, 1.086, 1.084, 1.083, 1.081, 1.079, 1.077, 1.074, 1.069, 1.061, 1.052, 1.043, 1.038,
+                            1.021, 1.033, 1.045, 1.053, 1.059, 1.066, 1.071, 1.074, 1.078, 1.081, 1.084, 1.085, 1.087, 1.088, 1.089, 1.089, 1.089, 1.089, 1.089, 1.088, 1.087, 1.086, 1.085, 1.083, 1.081, 1.079, 1.075, 1.071, 1.062, 1.054, 1.044, 1.039,
+                            1.023, 1.035, 1.046, 1.055, 1.062, 1.067, 1.072, 1.075, 1.079, 1.083, 1.085, 1.087, 1.088, 1.089, 1.091, 1.091, 1.091, 1.091, 1.091, 1.091, 1.089, 1.087, 1.086, 1.084, 1.082, 1.081, 1.076, 1.072, 1.065, 1.055, 1.045, 1.039,
+                            1.025, 1.036, 1.048, 1.056, 1.063, 1.069, 1.073, 1.077, 1.081, 1.085, 1.087, 1.088, 1.089, 1.091, 1.091, 1.092, 1.092, 1.092, 1.092, 1.091, 1.091, 1.088, 1.087, 1.085, 1.084, 1.081, 1.078, 1.074, 1.066, 1.057, 1.047, 1.042,
+                            1.028, 1.039, 1.051, 1.058, 1.065, 1.071, 1.075, 1.079, 1.083, 1.086, 1.088, 1.089, 1.091, 1.092, 1.093, 1.093, 1.093, 1.093, 1.093, 1.093, 1.092, 1.091, 1.088, 1.086, 1.084, 1.082, 1.079, 1.074, 1.067, 1.058, 1.047, 1.043,
+                            1.029, 1.041, 1.051, 1.059, 1.067, 1.071, 1.076, 1.081, 1.083, 1.087, 1.088, 1.091, 1.092, 1.093, 1.093, 1.094, 1.094, 1.094, 1.094, 1.094, 1.093, 1.092, 1.089, 1.087, 1.085, 1.083, 1.079, 1.074, 1.068, 1.059, 1.048, 1.044,
+                            1.031, 1.042, 1.053, 1.061, 1.068, 1.072, 1.077, 1.081, 1.084, 1.087, 1.089, 1.091, 1.093, 1.093, 1.094, 1.095, 1.095, 1.095, 1.095, 1.095, 1.094, 1.092, 1.089, 1.088, 1.086, 1.083, 1.081, 1.075, 1.069, 1.061, 1.049, 1.044,
+                            1.032, 1.043, 1.054, 1.062, 1.068, 1.073, 1.078, 1.081, 1.085, 1.088, 1.089, 1.092, 1.093, 1.094, 1.095, 1.095, 1.096, 1.096, 1.096, 1.095, 1.094, 1.093, 1.091, 1.089, 1.086, 1.083, 1.081, 1.075, 1.069, 1.061, 1.049, 1.044,
+                            1.033, 1.044, 1.055, 1.062, 1.069, 1.073, 1.079, 1.082, 1.085, 1.088, 1.091, 1.093, 1.094, 1.095, 1.096, 1.096, 1.096, 1.097, 1.096, 1.096, 1.095, 1.093, 1.092, 1.089, 1.087, 1.084, 1.081, 1.076, 1.071, 1.062, 1.049, 1.046,
+                            1.034, 1.045, 1.056, 1.064, 1.069, 1.074, 1.079, 1.082, 1.086, 1.089, 1.091, 1.093, 1.094, 1.095, 1.096, 1.097, 1.097, 1.097, 1.097, 1.096, 1.095, 1.094, 1.092, 1.089, 1.087, 1.084, 1.081, 1.077, 1.071, 1.062, 1.052, 1.046,
+                            1.034, 1.046, 1.057, 1.064, 1.069, 1.074, 1.079, 1.083, 1.086, 1.089, 1.091, 1.093, 1.094, 1.096, 1.096, 1.097, 1.097, 1.097, 1.097, 1.096, 1.095, 1.094, 1.092, 1.089, 1.087, 1.084, 1.081, 1.077, 1.071, 1.063, 1.052, 1.046,
+                            1.035, 1.046, 1.057, 1.064, 1.069, 1.075, 1.079, 1.083, 1.086, 1.089, 1.091, 1.093, 1.094, 1.096, 1.096, 1.097, 1.097, 1.097, 1.097, 1.096, 1.095, 1.094, 1.092, 1.089, 1.087, 1.085, 1.081, 1.077, 1.071, 1.063, 1.052, 1.047,
+                            1.035, 1.046, 1.057, 1.064, 1.069, 1.075, 1.079, 1.083, 1.086, 1.088, 1.091, 1.092, 1.094, 1.095, 1.096, 1.097, 1.097, 1.097, 1.097, 1.096, 1.095, 1.094, 1.091, 1.089, 1.087, 1.085, 1.082, 1.077, 1.071, 1.063, 1.052, 1.046,
+                            1.035, 1.046, 1.057, 1.064, 1.069, 1.075, 1.079, 1.083, 1.086, 1.088, 1.091, 1.092, 1.093, 1.095, 1.096, 1.096, 1.097, 1.097, 1.096, 1.095, 1.095, 1.093, 1.091, 1.089, 1.087, 1.084, 1.082, 1.077, 1.071, 1.062, 1.052, 1.047,
+                            1.035, 1.046, 1.056, 1.063, 1.069, 1.074, 1.077, 1.082, 1.085, 1.087, 1.091, 1.091, 1.093, 1.094, 1.095, 1.096, 1.096, 1.096, 1.095, 1.095, 1.094, 1.093, 1.091, 1.089, 1.086, 1.085, 1.081, 1.077, 1.071, 1.062, 1.052, 1.047,
+                            1.033, 1.045, 1.055, 1.063, 1.068, 1.073, 1.077, 1.082, 1.084, 1.087, 1.089, 1.091, 1.093, 1.093, 1.094, 1.095, 1.095, 1.095, 1.095, 1.095, 1.094, 1.093, 1.091, 1.089, 1.086, 1.084, 1.081, 1.076, 1.069, 1.062, 1.051, 1.047,
+                            1.032, 1.045, 1.054, 1.062, 1.067, 1.072, 1.077, 1.081, 1.083, 1.087, 1.089, 1.091, 1.092, 1.093, 1.093, 1.094, 1.094, 1.094, 1.094, 1.094, 1.093, 1.092, 1.091, 1.088, 1.086, 1.083, 1.079, 1.076, 1.069, 1.061, 1.051, 1.047,
+                            1.031, 1.044, 1.053, 1.061, 1.066, 1.072, 1.077, 1.081, 1.083, 1.087, 1.088, 1.091, 1.091, 1.093, 1.093, 1.093, 1.094, 1.094, 1.094, 1.093, 1.092, 1.091, 1.089, 1.088, 1.086, 1.083, 1.079, 1.075, 1.069, 1.059, 1.051, 1.046,
+                            1.031, 1.043, 1.051, 1.061, 1.065, 1.072, 1.076, 1.079, 1.083, 1.086, 1.087, 1.091, 1.091, 1.091, 1.092, 1.093, 1.093, 1.093, 1.093, 1.092, 1.091, 1.091, 1.089, 1.086, 1.085, 1.083, 1.079, 1.074, 1.066, 1.059, 1.051, 1.045,
+                            1.029, 1.039, 1.051, 1.059, 1.065, 1.071, 1.074, 1.077, 1.082, 1.085, 1.087, 1.088, 1.091, 1.091, 1.091, 1.092, 1.092, 1.092, 1.092, 1.091, 1.091, 1.089, 1.088, 1.085, 1.084, 1.082, 1.077, 1.071, 1.065, 1.058, 1.048, 1.043,
+                            1.028, 1.037, 1.049, 1.057, 1.063, 1.068, 1.073, 1.076, 1.081, 1.082, 1.085, 1.087, 1.089, 1.089, 1.091, 1.091, 1.091, 1.091, 1.091, 1.091, 1.089, 1.088, 1.086, 1.085, 1.083, 1.079, 1.076, 1.071, 1.064, 1.056, 1.046, 1.041,
+                            1.025, 1.035, 1.047, 1.055, 1.061, 1.067, 1.071, 1.075, 1.078, 1.081, 1.084, 1.086, 1.087, 1.088, 1.089, 1.089, 1.089, 1.089, 1.089, 1.089, 1.088, 1.087, 1.085, 1.084, 1.081, 1.078, 1.075, 1.069, 1.062, 1.054, 1.044, 1.039,
+                            1.023, 1.032, 1.044, 1.052, 1.059, 1.065, 1.069, 1.073, 1.076, 1.079, 1.081, 1.084, 1.085, 1.086, 1.087, 1.087, 1.088, 1.088, 1.088, 1.087, 1.087, 1.085, 1.084, 1.081, 1.079, 1.076, 1.072, 1.067, 1.059, 1.052, 1.041, 1.037,
+                            1.019, 1.028, 1.039, 1.048, 1.057, 1.062, 1.067, 1.071, 1.074, 1.077, 1.079, 1.081, 1.083, 1.084, 1.085, 1.085, 1.086, 1.086, 1.085, 1.085, 1.084, 1.083, 1.081, 1.079, 1.077, 1.073, 1.069, 1.063, 1.056, 1.048, 1.038, 1.034,
+                            1.016, 1.025, 1.035, 1.045, 1.053, 1.059, 1.064, 1.069, 1.072, 1.076, 1.077, 1.079, 1.081, 1.081, 1.082, 1.083, 1.084, 1.084, 1.084, 1.083, 1.083, 1.081, 1.079, 1.077, 1.074, 1.069, 1.065, 1.059, 1.053, 1.044, 1.034, 1.029,
+                            1.011, 1.022, 1.032, 1.042, 1.051, 1.057, 1.062, 1.067, 1.069, 1.074, 1.076, 1.077, 1.079, 1.079, 1.081, 1.081, 1.081, 1.082, 1.082, 1.081, 1.081, 1.078, 1.077, 1.075, 1.071, 1.066, 1.061, 1.056, 1.049, 1.041, 1.029, 1.028,
+                            1.008, 1.019, 1.031, 1.039, 1.048, 1.056, 1.061, 1.065, 1.069, 1.073, 1.075, 1.076, 1.078, 1.079, 1.079, 1.079, 1.081, 1.081, 1.081, 1.081, 1.078, 1.078, 1.076, 1.072, 1.069, 1.064, 1.058, 1.054, 1.047, 1.038, 1.029, 1.026
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.001, 1.005, 1.011, 1.015, 1.019, 1.021, 1.021, 1.022, 1.024, 1.025, 1.026, 1.027, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.022, 1.021, 1.018, 1.015, 1.011,
+                            1.005, 1.008, 1.014, 1.021, 1.025, 1.028, 1.031, 1.032, 1.034, 1.035, 1.036, 1.037, 1.038, 1.038, 1.039, 1.038, 1.038, 1.038, 1.038, 1.037, 1.037, 1.036, 1.036, 1.035, 1.035, 1.034, 1.033, 1.029, 1.028, 1.023, 1.021, 1.021,
+                            1.009, 1.014, 1.021, 1.025, 1.028, 1.031, 1.032, 1.034, 1.035, 1.037, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.037, 1.036, 1.036, 1.036, 1.036, 1.034, 1.033, 1.029, 1.028, 1.023, 1.022,
+                            1.011, 1.016, 1.023, 1.027, 1.029, 1.031, 1.034, 1.035, 1.037, 1.038, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.037, 1.036, 1.034, 1.032, 1.029, 1.025, 1.022,
+                            1.013, 1.018, 1.024, 1.027, 1.031, 1.033, 1.035, 1.037, 1.038, 1.039, 1.041, 1.042, 1.042, 1.043, 1.043, 1.043, 1.042, 1.042, 1.042, 1.041, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.037, 1.035, 1.034, 1.029, 1.025, 1.023,
+                            1.014, 1.019, 1.025, 1.029, 1.031, 1.034, 1.037, 1.038, 1.039, 1.041, 1.042, 1.043, 1.043, 1.044, 1.044, 1.044, 1.043, 1.043, 1.043, 1.043, 1.042, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.037, 1.034, 1.029, 1.026, 1.024,
+                            1.016, 1.021, 1.027, 1.031, 1.033, 1.035, 1.038, 1.039, 1.041, 1.042, 1.043, 1.044, 1.044, 1.045, 1.045, 1.045, 1.044, 1.044, 1.044, 1.044, 1.043, 1.042, 1.042, 1.041, 1.041, 1.039, 1.038, 1.038, 1.035, 1.031, 1.027, 1.025,
+                            1.017, 1.022, 1.027, 1.031, 1.034, 1.037, 1.039, 1.041, 1.042, 1.043, 1.044, 1.045, 1.046, 1.046, 1.046, 1.046, 1.046, 1.046, 1.045, 1.045, 1.044, 1.043, 1.043, 1.042, 1.041, 1.041, 1.039, 1.038, 1.036, 1.032, 1.028, 1.025,
+                            1.018, 1.023, 1.028, 1.032, 1.035, 1.038, 1.041, 1.041, 1.043, 1.045, 1.046, 1.046, 1.046, 1.047, 1.047, 1.047, 1.047, 1.047, 1.047, 1.046, 1.045, 1.044, 1.044, 1.043, 1.042, 1.041, 1.041, 1.039, 1.037, 1.032, 1.028, 1.026,
+                            1.019, 1.024, 1.029, 1.033, 1.036, 1.039, 1.041, 1.042, 1.044, 1.046, 1.046, 1.047, 1.048, 1.048, 1.048, 1.048, 1.048, 1.048, 1.048, 1.047, 1.047, 1.045, 1.044, 1.044, 1.043, 1.042, 1.041, 1.039, 1.037, 1.033, 1.029, 1.027,
+                            1.021, 1.026, 1.029, 1.034, 1.037, 1.039, 1.042, 1.043, 1.045, 1.046, 1.047, 1.047, 1.048, 1.048, 1.049, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.047, 1.046, 1.044, 1.044, 1.043, 1.041, 1.039, 1.037, 1.034, 1.029, 1.027,
+                            1.022, 1.026, 1.032, 1.035, 1.038, 1.039, 1.043, 1.044, 1.045, 1.046, 1.047, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.044, 1.043, 1.041, 1.039, 1.038, 1.034, 1.029, 1.027,
+                            1.023, 1.027, 1.032, 1.035, 1.039, 1.041, 1.043, 1.044, 1.045, 1.047, 1.048, 1.049, 1.049, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.041, 1.039, 1.035, 1.029, 1.027,
+                            1.024, 1.028, 1.033, 1.036, 1.039, 1.041, 1.043, 1.045, 1.046, 1.047, 1.049, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.047, 1.046, 1.045, 1.043, 1.042, 1.041, 1.039, 1.035, 1.029, 1.029,
+                            1.024, 1.029, 1.034, 1.037, 1.039, 1.041, 1.044, 1.045, 1.047, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.045, 1.044, 1.042, 1.041, 1.039, 1.036, 1.031, 1.029,
+                            1.024, 1.029, 1.034, 1.037, 1.039, 1.042, 1.044, 1.046, 1.047, 1.048, 1.049, 1.049, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.039, 1.037, 1.031, 1.029,
+                            1.025, 1.031, 1.035, 1.037, 1.039, 1.042, 1.045, 1.046, 1.047, 1.048, 1.049, 1.049, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.047, 1.045, 1.043, 1.042, 1.041, 1.037, 1.032, 1.031,
+                            1.026, 1.031, 1.035, 1.037, 1.039, 1.043, 1.045, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.047, 1.045, 1.044, 1.042, 1.041, 1.037, 1.032, 1.031,
+                            1.026, 1.031, 1.035, 1.038, 1.039, 1.043, 1.044, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.048, 1.047, 1.045, 1.044, 1.043, 1.041, 1.037, 1.032, 1.031,
+                            1.025, 1.031, 1.035, 1.038, 1.039, 1.042, 1.044, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.045, 1.044, 1.043, 1.041, 1.037, 1.032, 1.031,
+                            1.024, 1.031, 1.035, 1.038, 1.039, 1.042, 1.044, 1.046, 1.047, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.046, 1.044, 1.043, 1.041, 1.037, 1.033, 1.031,
+                            1.025, 1.031, 1.035, 1.037, 1.039, 1.041, 1.044, 1.046, 1.047, 1.049, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.037, 1.033, 1.031,
+                            1.024, 1.031, 1.034, 1.037, 1.038, 1.041, 1.044, 1.045, 1.047, 1.049, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.037, 1.034, 1.032,
+                            1.024, 1.031, 1.034, 1.037, 1.038, 1.041, 1.043, 1.045, 1.046, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.038, 1.034, 1.032,
+                            1.024, 1.029, 1.034, 1.037, 1.038, 1.041, 1.043, 1.044, 1.046, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.038, 1.034, 1.031,
+                            1.024, 1.028, 1.034, 1.037, 1.038, 1.041, 1.042, 1.044, 1.046, 1.047, 1.048, 1.049, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.047, 1.045, 1.044, 1.043, 1.039, 1.038, 1.033, 1.031,
+                            1.022, 1.027, 1.034, 1.035, 1.038, 1.039, 1.041, 1.043, 1.044, 1.046, 1.047, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.047, 1.047, 1.046, 1.045, 1.044, 1.043, 1.039, 1.037, 1.032, 1.029,
+                            1.022, 1.026, 1.032, 1.034, 1.037, 1.039, 1.041, 1.042, 1.044, 1.045, 1.046, 1.047, 1.048, 1.048, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.047, 1.047, 1.046, 1.045, 1.045, 1.044, 1.041, 1.039, 1.036, 1.031, 1.029,
+                            1.021, 1.025, 1.029, 1.033, 1.036, 1.038, 1.039, 1.041, 1.042, 1.044, 1.045, 1.046, 1.047, 1.047, 1.047, 1.047, 1.048, 1.048, 1.048, 1.047, 1.047, 1.047, 1.045, 1.045, 1.045, 1.044, 1.042, 1.039, 1.038, 1.034, 1.029, 1.028,
+                            1.019, 1.023, 1.028, 1.032, 1.035, 1.038, 1.039, 1.041, 1.042, 1.044, 1.044, 1.045, 1.045, 1.046, 1.046, 1.046, 1.047, 1.047, 1.047, 1.046, 1.046, 1.045, 1.045, 1.045, 1.044, 1.042, 1.041, 1.038, 1.037, 1.033, 1.029, 1.027,
+                            1.017, 1.022, 1.027, 1.031, 1.034, 1.037, 1.039, 1.041, 1.041, 1.043, 1.044, 1.045, 1.045, 1.045, 1.045, 1.046, 1.046, 1.046, 1.046, 1.046, 1.045, 1.045, 1.045, 1.044, 1.043, 1.041, 1.039, 1.038, 1.035, 1.031, 1.029, 1.027,
+                            1.016, 1.022, 1.027, 1.031, 1.034, 1.037, 1.039, 1.041, 1.041, 1.043, 1.043, 1.044, 1.045, 1.045, 1.045, 1.045, 1.046, 1.046, 1.046, 1.045, 1.045, 1.045, 1.045, 1.044, 1.043, 1.041, 1.038, 1.038, 1.035, 1.031, 1.029, 1.028
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.001, 1.003, 1.005, 1.008, 1.009, 1.011, 1.011, 1.011, 1.011, 1.012, 1.012, 1.012, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.012, 1.012, 1.013, 1.013, 1.013, 1.015, 1.015, 1.015, 1.014, 1.014, 1.014, 1.013, 1.012,
+                            1.007, 1.008, 1.011, 1.015, 1.017, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.022, 1.023, 1.023, 1.023, 1.023, 1.023, 1.023, 1.022, 1.022, 1.022, 1.022, 1.023, 1.023, 1.023, 1.024, 1.024, 1.023, 1.023, 1.022, 1.022, 1.021,
+                            1.008, 1.011, 1.015, 1.017, 1.019, 1.021, 1.021, 1.021, 1.021, 1.022, 1.023, 1.023, 1.023, 1.023, 1.024, 1.024, 1.023, 1.023, 1.023, 1.023, 1.023, 1.023, 1.023, 1.023, 1.024, 1.024, 1.024, 1.024, 1.023, 1.023, 1.022, 1.022,
+                            1.009, 1.012, 1.016, 1.018, 1.019, 1.021, 1.021, 1.021, 1.022, 1.023, 1.023, 1.023, 1.024, 1.024, 1.025, 1.024, 1.024, 1.024, 1.024, 1.023, 1.023, 1.023, 1.024, 1.024, 1.024, 1.025, 1.025, 1.024, 1.024, 1.023, 1.022, 1.021,
+                            1.009, 1.013, 1.016, 1.018, 1.019, 1.021, 1.021, 1.022, 1.023, 1.023, 1.024, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.025, 1.025, 1.025, 1.025, 1.025, 1.024, 1.023, 1.022, 1.021,
+                            1.011, 1.014, 1.017, 1.019, 1.019, 1.021, 1.022, 1.023, 1.023, 1.024, 1.025, 1.025, 1.025, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.025, 1.025, 1.026, 1.026, 1.026, 1.024, 1.022, 1.022, 1.022,
+                            1.011, 1.014, 1.018, 1.019, 1.021, 1.022, 1.022, 1.023, 1.024, 1.025, 1.026, 1.026, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.027, 1.026, 1.026, 1.026, 1.025, 1.026, 1.026, 1.026, 1.026, 1.026, 1.025, 1.022, 1.022, 1.022,
+                            1.012, 1.015, 1.018, 1.019, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.026, 1.027, 1.027, 1.027, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.025, 1.023, 1.022, 1.021,
+                            1.012, 1.015, 1.018, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.026, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.026, 1.025, 1.023, 1.022, 1.021,
+                            1.013, 1.016, 1.019, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.027, 1.027, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.021, 1.021,
+                            1.014, 1.017, 1.019, 1.021, 1.022, 1.023, 1.025, 1.026, 1.026, 1.027, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.021, 1.021,
+                            1.014, 1.017, 1.021, 1.021, 1.022, 1.024, 1.025, 1.026, 1.026, 1.027, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.024, 1.021, 1.021,
+                            1.014, 1.017, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.024, 1.021, 1.021,
+                            1.015, 1.017, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.024, 1.022, 1.021,
+                            1.015, 1.018, 1.021, 1.022, 1.023, 1.024, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.025, 1.022, 1.021,
+                            1.016, 1.019, 1.022, 1.022, 1.023, 1.024, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.023, 1.022,
+                            1.016, 1.019, 1.022, 1.023, 1.023, 1.025, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.027, 1.026, 1.023, 1.022,
+                            1.016, 1.019, 1.022, 1.023, 1.023, 1.025, 1.026, 1.027, 1.027, 1.028, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.027, 1.026, 1.023, 1.022,
+                            1.016, 1.019, 1.022, 1.023, 1.023, 1.025, 1.025, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.028, 1.026, 1.024, 1.023,
+                            1.016, 1.019, 1.022, 1.023, 1.023, 1.024, 1.025, 1.026, 1.027, 1.028, 1.028, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.026, 1.024, 1.023,
+                            1.015, 1.019, 1.022, 1.023, 1.023, 1.024, 1.025, 1.026, 1.027, 1.028, 1.028, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.026, 1.025, 1.024,
+                            1.016, 1.019, 1.022, 1.023, 1.023, 1.024, 1.025, 1.026, 1.026, 1.028, 1.028, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.026, 1.025, 1.025,
+                            1.016, 1.019, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.026, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025,
+                            1.016, 1.019, 1.021, 1.023, 1.023, 1.024, 1.025, 1.025, 1.027, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.026,
+                            1.016, 1.019, 1.021, 1.023, 1.023, 1.024, 1.024, 1.025, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026,
+                            1.016, 1.018, 1.022, 1.023, 1.023, 1.024, 1.024, 1.025, 1.026, 1.027, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026,
+                            1.016, 1.018, 1.021, 1.022, 1.023, 1.023, 1.024, 1.024, 1.025, 1.026, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.026, 1.026,
+                            1.016, 1.017, 1.021, 1.022, 1.022, 1.023, 1.024, 1.024, 1.024, 1.026, 1.026, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.026,
+                            1.015, 1.016, 1.019, 1.021, 1.022, 1.023, 1.024, 1.024, 1.024, 1.025, 1.026, 1.026, 1.026, 1.027, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026,
+                            1.014, 1.016, 1.019, 1.021, 1.022, 1.023, 1.023, 1.024, 1.024, 1.025, 1.025, 1.026, 1.026, 1.026, 1.026, 1.026, 1.027, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.026,
+                            1.015, 1.016, 1.019, 1.021, 1.021, 1.023, 1.024, 1.024, 1.025, 1.025, 1.026, 1.026, 1.025, 1.026, 1.026, 1.026, 1.026, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.028, 1.027, 1.027, 1.027,
+                            1.015, 1.017, 1.019, 1.019, 1.021, 1.023, 1.024, 1.025, 1.025, 1.025, 1.026, 1.026, 1.025, 1.026, 1.026, 1.026, 1.026, 1.027, 1.027, 1.027, 1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.028, 1.028, 1.028, 1.027, 1.029
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    1.319, 1.289, 1.238, 1.198, 1.169, 1.139, 1.116, 1.094, 1.082, 1.074, 1.068, 1.064, 1.062, 1.061, 1.061, 1.061, 1.061, 1.062, 1.064, 1.065, 1.068, 1.074, 1.084, 1.101, 1.123, 1.148, 1.181, 1.221, 1.277, 1.356, 1.468, 1.477,
+                    1.292, 1.255, 1.208, 1.171, 1.145, 1.121, 1.099, 1.086, 1.073, 1.064, 1.058, 1.053, 1.049, 1.047, 1.046, 1.045, 1.048, 1.049, 1.051, 1.053, 1.059, 1.065, 1.074, 1.089, 1.105, 1.125, 1.152, 1.189, 1.238, 1.309, 1.408, 1.468,
+                    1.269, 1.234, 1.189, 1.155, 1.136, 1.112, 1.086, 1.073, 1.064, 1.057, 1.052, 1.047, 1.043, 1.041, 1.041, 1.041, 1.043, 1.047, 1.048, 1.049, 1.053, 1.059, 1.065, 1.074, 1.089, 1.109, 1.136, 1.171, 1.216, 1.278, 1.369, 1.408,
+                    1.249, 1.216, 1.173, 1.142, 1.125, 1.105, 1.078, 1.066, 1.058, 1.053, 1.047, 1.043, 1.038, 1.036, 1.035, 1.035, 1.039, 1.042, 1.043, 1.044, 1.048, 1.053, 1.059, 1.066, 1.079, 1.098, 1.122, 1.155, 1.197, 1.252, 1.337, 1.369,
+                    1.233, 1.199, 1.159, 1.129, 1.111, 1.095, 1.073, 1.061, 1.054, 1.049, 1.044, 1.038, 1.033, 1.031, 1.029, 1.029, 1.033, 1.037, 1.037, 1.037, 1.042, 1.047, 1.052, 1.059, 1.071, 1.087, 1.111, 1.142, 1.181, 1.232, 1.307, 1.337,
+                    1.217, 1.185, 1.146, 1.116, 1.097, 1.083, 1.069, 1.055, 1.049, 1.045, 1.039, 1.033, 1.029, 1.027, 1.025, 1.024, 1.025, 1.028, 1.029, 1.031, 1.035, 1.041, 1.047, 1.053, 1.063, 1.079, 1.101, 1.131, 1.168, 1.215, 1.282, 1.308,
+                    1.206, 1.172, 1.134, 1.106, 1.088, 1.076, 1.064, 1.051, 1.045, 1.041, 1.034, 1.029, 1.026, 1.023, 1.021, 1.021, 1.021, 1.021, 1.024, 1.027, 1.031, 1.035, 1.041, 1.048, 1.058, 1.072, 1.092, 1.121, 1.157, 1.201, 1.262, 1.288,
+                    1.196, 1.161, 1.125, 1.099, 1.081, 1.071, 1.059, 1.047, 1.041, 1.035, 1.029, 1.025, 1.022, 1.019, 1.018, 1.017, 1.017, 1.018, 1.021, 1.023, 1.027, 1.031, 1.036, 1.044, 1.053, 1.066, 1.085, 1.113, 1.148, 1.191, 1.247, 1.273,
+                    1.188, 1.152, 1.118, 1.093, 1.076, 1.064, 1.052, 1.044, 1.037, 1.031, 1.026, 1.022, 1.019, 1.017, 1.015, 1.015, 1.014, 1.015, 1.017, 1.019, 1.023, 1.027, 1.033, 1.041, 1.049, 1.061, 1.078, 1.105, 1.139, 1.181, 1.235, 1.261,
+                    1.182, 1.145, 1.112, 1.088, 1.072, 1.059, 1.049, 1.041, 1.035, 1.028, 1.023, 1.019, 1.016, 1.014, 1.012, 1.012, 1.011, 1.012, 1.015, 1.017, 1.021, 1.024, 1.029, 1.037, 1.045, 1.056, 1.074, 1.099, 1.133, 1.173, 1.224, 1.251,
+                    1.178, 1.139, 1.106, 1.083, 1.068, 1.056, 1.046, 1.039, 1.032, 1.026, 1.021, 1.017, 1.014, 1.011, 1.009, 1.009, 1.009, 1.009, 1.012, 1.015, 1.018, 1.022, 1.028, 1.035, 1.042, 1.054, 1.069, 1.095, 1.127, 1.168, 1.217, 1.244,
+                    1.174, 1.134, 1.102, 1.081, 1.065, 1.053, 1.044, 1.037, 1.029, 1.024, 1.019, 1.015, 1.012, 1.009, 1.007, 1.006, 1.006, 1.007, 1.009, 1.012, 1.016, 1.019, 1.027, 1.034, 1.041, 1.051, 1.067, 1.092, 1.123, 1.161, 1.211, 1.239,
+                    1.173, 1.131, 1.099, 1.078, 1.062, 1.051, 1.042, 1.035, 1.028, 1.023, 1.018, 1.013, 1.009, 1.007, 1.005, 1.004, 1.004, 1.005, 1.007, 1.011, 1.014, 1.018, 1.025, 1.032, 1.039, 1.049, 1.064, 1.089, 1.119, 1.158, 1.207, 1.236,
+                    1.171, 1.129, 1.097, 1.075, 1.061, 1.049, 1.041, 1.033, 1.027, 1.021, 1.017, 1.012, 1.008, 1.005, 1.004, 1.003, 1.003, 1.003, 1.005, 1.009, 1.013, 1.017, 1.025, 1.031, 1.037, 1.047, 1.062, 1.087, 1.117, 1.155, 1.205, 1.233,
+                    1.169, 1.128, 1.097, 1.074, 1.059, 1.049, 1.041, 1.033, 1.026, 1.021, 1.015, 1.011, 1.007, 1.005, 1.004, 1.002, 1.002, 1.002, 1.004, 1.008, 1.012, 1.017, 1.024, 1.031, 1.036, 1.046, 1.061, 1.085, 1.116, 1.155, 1.203, 1.233,
+                    1.169, 1.128, 1.097, 1.074, 1.059, 1.048, 1.039, 1.031, 1.025, 1.021, 1.015, 1.011, 1.006, 1.004, 1.003, 1.001, 1.001, 1.002, 1.004, 1.008, 1.012, 1.017, 1.024, 1.031, 1.036, 1.046, 1.061, 1.084, 1.115, 1.155, 1.203, 1.233,
+                    1.169, 1.129, 1.098, 1.075, 1.059, 1.048, 1.039, 1.031, 1.025, 1.019, 1.015, 1.011, 1.006, 1.004, 1.002, 1.001, 1.001, 1.002, 1.004, 1.008, 1.012, 1.017, 1.025, 1.031, 1.036, 1.046, 1.061, 1.084, 1.116, 1.155, 1.204, 1.234,
+                    1.169, 1.131, 1.099, 1.076, 1.061, 1.049, 1.039, 1.032, 1.025, 1.021, 1.015, 1.011, 1.007, 1.005, 1.003, 1.001, 1.001, 1.002, 1.005, 1.009, 1.013, 1.017, 1.024, 1.031, 1.037, 1.047, 1.061, 1.085, 1.118, 1.158, 1.208, 1.237,
+                    1.171, 1.134, 1.102, 1.078, 1.062, 1.051, 1.041, 1.033, 1.026, 1.021, 1.016, 1.011, 1.009, 1.006, 1.004, 1.002, 1.002, 1.003, 1.006, 1.012, 1.015, 1.018, 1.023, 1.031, 1.038, 1.048, 1.064, 1.088, 1.121, 1.162, 1.212, 1.241,
+                    1.174, 1.139, 1.106, 1.081, 1.064, 1.052, 1.043, 1.034, 1.027, 1.022, 1.017, 1.013, 1.009, 1.008, 1.005, 1.004, 1.004, 1.005, 1.008, 1.013, 1.017, 1.019, 1.024, 1.031, 1.039, 1.051, 1.067, 1.092, 1.125, 1.167, 1.219, 1.246,
+                    1.179, 1.145, 1.112, 1.085, 1.067, 1.054, 1.045, 1.036, 1.029, 1.023, 1.018, 1.014, 1.011, 1.008, 1.007, 1.006, 1.007, 1.008, 1.009, 1.014, 1.018, 1.019, 1.025, 1.032, 1.041, 1.054, 1.071, 1.096, 1.131, 1.174, 1.228, 1.255,
+                    1.186, 1.152, 1.117, 1.089, 1.069, 1.057, 1.046, 1.038, 1.031, 1.025, 1.019, 1.016, 1.013, 1.009, 1.009, 1.008, 1.009, 1.009, 1.011, 1.014, 1.018, 1.021, 1.027, 1.034, 1.044, 1.056, 1.075, 1.102, 1.137, 1.182, 1.239, 1.268,
+                    1.194, 1.159, 1.123, 1.095, 1.075, 1.061, 1.049, 1.041, 1.033, 1.027, 1.022, 1.018, 1.015, 1.013, 1.011, 1.011, 1.011, 1.011, 1.013, 1.016, 1.019, 1.024, 1.031, 1.037, 1.047, 1.061, 1.082, 1.109, 1.147, 1.194, 1.256, 1.281,
+                    1.203, 1.169, 1.132, 1.102, 1.081, 1.065, 1.053, 1.044, 1.036, 1.029, 1.026, 1.021, 1.018, 1.015, 1.013, 1.013, 1.013, 1.014, 1.015, 1.018, 1.022, 1.028, 1.034, 1.041, 1.052, 1.067, 1.091, 1.121, 1.157, 1.207, 1.273, 1.299,
+                    1.214, 1.179, 1.142, 1.111, 1.088, 1.069, 1.057, 1.047, 1.039, 1.033, 1.028, 1.024, 1.021, 1.018, 1.016, 1.015, 1.015, 1.016, 1.018, 1.021, 1.026, 1.031, 1.038, 1.046, 1.058, 1.075, 1.101, 1.133, 1.171, 1.222, 1.293, 1.319,
+                    1.227, 1.194, 1.153, 1.121, 1.096, 1.076, 1.062, 1.052, 1.043, 1.036, 1.031, 1.027, 1.023, 1.021, 1.019, 1.019, 1.018, 1.019, 1.021, 1.025, 1.029, 1.035, 1.042, 1.051, 1.065, 1.085, 1.112, 1.145, 1.185, 1.239, 1.318, 1.346,
+                    1.244, 1.211, 1.167, 1.133, 1.107, 1.088, 1.069, 1.057, 1.047, 1.041, 1.034, 1.031, 1.026, 1.024, 1.022, 1.022, 1.022, 1.023, 1.025, 1.029, 1.034, 1.039, 1.047, 1.059, 1.075, 1.096, 1.124, 1.158, 1.202, 1.261, 1.346, 1.381,
+                    1.264, 1.229, 1.183, 1.147, 1.119, 1.098, 1.077, 1.063, 1.053, 1.045, 1.039, 1.034, 1.031, 1.027, 1.026, 1.026, 1.026, 1.027, 1.029, 1.034, 1.039, 1.045, 1.054, 1.068, 1.086, 1.109, 1.138, 1.175, 1.222, 1.288, 1.381, 1.423,
+                    1.287, 1.251, 1.201, 1.163, 1.134, 1.109, 1.086, 1.071, 1.059, 1.051, 1.044, 1.039, 1.034, 1.032, 1.031, 1.031, 1.031, 1.032, 1.036, 1.039, 1.045, 1.053, 1.064, 1.079, 1.101, 1.125, 1.156, 1.195, 1.246, 1.321, 1.423, 1.479,
+                    1.314, 1.275, 1.222, 1.182, 1.151, 1.123, 1.098, 1.082, 1.068, 1.058, 1.051, 1.045, 1.041, 1.037, 1.036, 1.036, 1.037, 1.039, 1.041, 1.047, 1.053, 1.063, 1.076, 1.093, 1.115, 1.141, 1.174, 1.216, 1.275, 1.361, 1.479, 1.556,
+                    1.349, 1.307, 1.246, 1.203, 1.169, 1.138, 1.114, 1.095, 1.079, 1.067, 1.058, 1.052, 1.048, 1.045, 1.043, 1.043, 1.044, 1.046, 1.049, 1.055, 1.063, 1.075, 1.091, 1.111, 1.134, 1.161, 1.196, 1.242, 1.311, 1.407, 1.556, 1.617,
+                    1.389, 1.333, 1.266, 1.219, 1.184, 1.152, 1.127, 1.106, 1.089, 1.076, 1.066, 1.058, 1.053, 1.049, 1.049, 1.049, 1.049, 1.051, 1.055, 1.062, 1.072, 1.085, 1.102, 1.127, 1.151, 1.177, 1.213, 1.264, 1.339, 1.445, 1.617, 1.667
+                ],
+                "sigma": 0.00092,
+                "sigma_Cb": 0.00149
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 2500,
+                        "ccm":
+                        [
+                            1.82604, -0.41219, -0.41384,
+                            -0.51919, 1.83221, -0.31302,
+                            0.23201, -1.42044, 2.18842
+                        ]
+                    },
+                    {
+                        "ct": 2820,
+                        "ccm":
+                        [
+                            1.80891, -0.47916, -0.32974,
+                            -0.47311, 1.83395, -0.36084,
+                            0.21814, -1.22973, 2.01158
+                        ]
+                    },
+                    {
+                        "ct": 2830,
+                        "ccm":
+                        [
+                            1.80397, -0.51779, -0.28617,
+                            -0.64069, 2.16622, -0.52553,
+                            0.12013, -0.95702, 1.83689
+                        ]
+                    },
+                    {
+                        "ct": 2885,
+                        "ccm":
+                        [
+                            1.78861, -0.50175, -0.28685,
+                            -0.63703, 2.14176, -0.50473,
+                            0.08715, -0.86455, 1.77741
+                        ]
+                    },
+                    {
+                        "ct": 3601,
+                        "ccm":
+                        [
+                            1.85135, -0.56992, -0.28143,
+                            -0.56285, 2.08651, -0.52366,
+                            0.03737, -0.70813, 1.67076
+                        ]
+                    },
+                    {
+                        "ct": 3615,
+                        "ccm":
+                        [
+                            1.87447, -0.60511, -0.26936,
+                            -0.55592, 2.07733, -0.52141,
+                            0.04105, -0.70347, 1.66242
+                        ]
+                    },
+                    {
+                        "ct": 3622,
+                        "ccm":
+                        [
+                            1.85269, -0.58224, -0.27044,
+                            -0.55133, 2.06403, -0.51271,
+                            0.03952, -0.69055, 1.65103
+                        ]
+                    },
+                    {
+                        "ct": 4345,
+                        "ccm":
+                        [
+                            1.81525, -0.56996, -0.24529,
+                            -0.49203, 2.16996, -0.67793,
+                            0.02513, -0.67456, 1.64943
+                        ]
+                    },
+                    {
+                        "ct": 4410,
+                        "ccm":
+                        [
+                            1.83312, -0.59611, -0.23701,
+                            -0.48332, 2.15123, -0.66791,
+                            0.02629, -0.67203, 1.64574
+                        ]
+                    },
+                    {
+                        "ct": 4486,
+                        "ccm":
+                        [
+                            1.84759, -0.60181, -0.24578,
+                            -0.47792, 2.13471, -0.65679,
+                            0.02056, -0.65959, 1.63903
+                        ]
+                    },
+                    {
+                        "ct": 4576,
+                        "ccm":
+                        [
+                            1.83733, -0.58859, -0.24874,
+                            -0.47443, 2.13699, -0.66255,
+                            0.01842, -0.65402, 1.63561
+                        ]
+                    },
+                    {
+                        "ct": 5657,
+                        "ccm":
+                        [
+                            1.84437, -0.57638, -0.26799,
+                            -0.44569, 2.04163, -0.59593,
+                            -0.01759, -0.52787, 1.54546
+                        ]
+                    },
+                    {
+                        "ct": 5672,
+                        "ccm":
+                        [
+                            1.83986, -0.57025, -0.26962,
+                            -0.44974, 2.04763, -0.59789,
+                            -0.03246, -0.51626, 1.54872
+                        ]
+                    },
+                    {
+                        "ct": 5710,
+                        "ccm":
+                        [
+                            1.83822, -0.57688, -0.26134,
+                            -0.44263, 2.03779, -0.59516,
+                            -0.02552, -0.52605, 1.55157
+                        ]
+                    },
+                    {
+                        "ct": 6850,
+                        "ccm":
+                        [
+                            1.80507, -0.22489, -0.58017,
+                            -0.48609, 2.48778, -1.00168,
+                            -0.10995, -0.63701, 1.74696
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.cac": { }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx296.json 0.6.0-2/src/ipa/rpi/pisp/data/imx296.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx296.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx296.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.751
+                "reference_slope": 3.751
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -270,18 +270,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1019,37 +1019,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1127,7 +1145,7 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.06,
+                "threshold": 0.76,
                 "strength": 0.5,
                 "limit": 0.5
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx296_16mm.json 0.6.0-2/src/ipa/rpi/pisp/data/imx296_16mm.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx296_16mm.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx296_16mm.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.751
+                "reference_slope": 3.751
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -270,18 +270,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1019,37 +1019,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1127,7 +1145,7 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.06,
+                "threshold": 0.76,
                 "strength": 0.5,
                 "limit": 0.5
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx296_6mm.json 0.6.0-2/src/ipa/rpi/pisp/data/imx296_6mm.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx296_6mm.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx296_6mm.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.751
+                "reference_slope": 3.751
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -270,18 +270,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1019,37 +1019,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1127,7 +1145,7 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.06,
+                "threshold": 0.76,
                 "strength": 0.5,
                 "limit": 0.5
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx296_mono.json 0.6.0-2/src/ipa/rpi/pisp/data/imx296_mono.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx296_mono.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx296_mono.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.751
+                "reference_slope": 3.751
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -182,18 +182,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -855,37 +855,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -893,7 +911,7 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.06,
+                "threshold": 0.76,
                 "strength": 0.5,
                 "limit": 0.5
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx335.json 0.6.0-2/src/ipa/rpi/pisp/data/imx335.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx335.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx335.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,1475 @@
+{
+    "version": 2.0,
+    "target": "pisp",
+    "vendor": "Arducam",
+    "sku": "B0568",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 3200
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 9994,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 1139,
+                "reference_Y": 12135
+            }
+        },
+        {
+            "rpi.dpc":
+            {
+                "strength": 1
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 3.349
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 247,
+                "slope": 0.02352
+            }
+        },
+        {
+            "rpi.denoise":
+            {
+                "normal":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 0.8,
+                        "threshold": 0.05
+                    }
+                },
+                "hdr":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                },
+                "night":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                }
+            }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 7700
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8000
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    2300.0, 0.9388, 0.3393,
+                    2856.0, 0.7561, 0.3473,
+                    3000.0, 0.6877, 0.3684,
+                    4000.0, 0.5383, 0.4806,
+                    4100.0, 0.5145, 0.5113,
+                    6500.0, 0.4319, 0.6605
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.03574,
+                "transverse_neg": 0.04042
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.062, 1.058, 1.053, 1.047, 1.044, 1.039, 1.036, 1.032, 1.029, 1.025, 1.023, 1.021, 1.019, 1.018, 1.017, 1.017, 1.017, 1.018, 1.019, 1.021, 1.023, 1.026, 1.029, 1.032, 1.035, 1.039, 1.044, 1.048, 1.052, 1.055, 1.061, 1.062,
+                            1.059, 1.057, 1.052, 1.046, 1.042, 1.038, 1.034, 1.031, 1.027, 1.024, 1.022, 1.019, 1.018, 1.017, 1.016, 1.016, 1.017, 1.017, 1.018, 1.019, 1.022, 1.024, 1.027, 1.031, 1.034, 1.038, 1.042, 1.047, 1.051, 1.054, 1.059, 1.061,
+                            1.058, 1.055, 1.049, 1.044, 1.041, 1.037, 1.032, 1.029, 1.025, 1.022, 1.019, 1.018, 1.017, 1.015, 1.015, 1.014, 1.014, 1.015, 1.016, 1.018, 1.021, 1.023, 1.026, 1.029, 1.032, 1.036, 1.041, 1.045, 1.049, 1.054, 1.057, 1.059,
+                            1.056, 1.053, 1.047, 1.043, 1.039, 1.035, 1.031, 1.027, 1.023, 1.021, 1.018, 1.016, 1.014, 1.012, 1.012, 1.012, 1.012, 1.013, 1.014, 1.016, 1.018, 1.021, 1.024, 1.027, 1.031, 1.034, 1.039, 1.043, 1.047, 1.052, 1.056, 1.058,
+                            1.054, 1.051, 1.046, 1.042, 1.037, 1.032, 1.029, 1.024, 1.021, 1.018, 1.015, 1.013, 1.012, 1.011, 1.009, 1.009, 1.009, 1.011, 1.012, 1.014, 1.016, 1.019, 1.022, 1.026, 1.029, 1.033, 1.037, 1.042, 1.046, 1.051, 1.055, 1.057,
+                            1.052, 1.049, 1.044, 1.039, 1.035, 1.031, 1.026, 1.022, 1.019, 1.016, 1.013, 1.011, 1.009, 1.009, 1.008, 1.008, 1.008, 1.009, 1.009, 1.012, 1.014, 1.017, 1.019, 1.024, 1.028, 1.031, 1.035, 1.039, 1.044, 1.049, 1.053, 1.056,
+                            1.051, 1.048, 1.043, 1.039, 1.034, 1.029, 1.025, 1.021, 1.017, 1.014, 1.012, 1.009, 1.008, 1.006, 1.006, 1.006, 1.006, 1.007, 1.009, 1.009, 1.013, 1.015, 1.019, 1.022, 1.026, 1.029, 1.035, 1.039, 1.043, 1.048, 1.053, 1.055,
+                            1.051, 1.048, 1.042, 1.037, 1.032, 1.028, 1.024, 1.019, 1.016, 1.012, 1.011, 1.008, 1.006, 1.005, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.011, 1.014, 1.018, 1.021, 1.025, 1.029, 1.034, 1.038, 1.042, 1.047, 1.052, 1.054,
+                            1.051, 1.046, 1.041, 1.036, 1.031, 1.027, 1.023, 1.019, 1.015, 1.012, 1.008, 1.007, 1.005, 1.004, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.024, 1.028, 1.033, 1.038, 1.041, 1.046, 1.051, 1.053,
+                            1.049, 1.046, 1.041, 1.035, 1.031, 1.026, 1.022, 1.017, 1.014, 1.011, 1.008, 1.006, 1.004, 1.003, 1.002, 1.002, 1.003, 1.004, 1.006, 1.007, 1.009, 1.013, 1.016, 1.019, 1.023, 1.028, 1.032, 1.037, 1.041, 1.045, 1.051, 1.053,
+                            1.049, 1.046, 1.041, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.008, 1.006, 1.004, 1.002, 1.002, 1.001, 1.002, 1.003, 1.005, 1.007, 1.009, 1.012, 1.015, 1.019, 1.023, 1.027, 1.031, 1.036, 1.041, 1.045, 1.051, 1.053,
+                            1.049, 1.046, 1.041, 1.035, 1.031, 1.025, 1.022, 1.017, 1.014, 1.011, 1.007, 1.005, 1.003, 1.002, 1.001, 1.001, 1.002, 1.002, 1.004, 1.007, 1.009, 1.012, 1.015, 1.019, 1.023, 1.027, 1.032, 1.035, 1.041, 1.044, 1.051, 1.052,
+                            1.049, 1.046, 1.039, 1.035, 1.031, 1.026, 1.022, 1.017, 1.014, 1.011, 1.007, 1.005, 1.003, 1.001, 1.001, 1.001, 1.002, 1.003, 1.004, 1.007, 1.009, 1.012, 1.015, 1.019, 1.022, 1.027, 1.032, 1.036, 1.041, 1.045, 1.049, 1.052,
+                            1.049, 1.046, 1.039, 1.035, 1.031, 1.026, 1.021, 1.017, 1.014, 1.011, 1.007, 1.005, 1.003, 1.002, 1.001, 1.001, 1.001, 1.003, 1.004, 1.007, 1.009, 1.012, 1.015, 1.018, 1.022, 1.027, 1.031, 1.036, 1.041, 1.045, 1.049, 1.052,
+                            1.049, 1.046, 1.041, 1.036, 1.031, 1.026, 1.021, 1.017, 1.013, 1.011, 1.008, 1.005, 1.004, 1.002, 1.001, 1.001, 1.002, 1.003, 1.004, 1.007, 1.009, 1.012, 1.015, 1.019, 1.022, 1.027, 1.032, 1.036, 1.041, 1.045, 1.049, 1.052,
+                            1.049, 1.047, 1.041, 1.036, 1.031, 1.027, 1.022, 1.018, 1.014, 1.011, 1.008, 1.006, 1.004, 1.003, 1.002, 1.002, 1.002, 1.003, 1.005, 1.007, 1.009, 1.012, 1.015, 1.019, 1.023, 1.027, 1.032, 1.036, 1.041, 1.045, 1.049, 1.052,
+                            1.051, 1.047, 1.042, 1.036, 1.031, 1.027, 1.023, 1.018, 1.015, 1.012, 1.009, 1.007, 1.005, 1.003, 1.003, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.024, 1.027, 1.032, 1.036, 1.041, 1.045, 1.049, 1.052,
+                            1.051, 1.048, 1.042, 1.037, 1.032, 1.028, 1.023, 1.021, 1.017, 1.013, 1.011, 1.008, 1.006, 1.005, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.014, 1.017, 1.021, 1.025, 1.028, 1.033, 1.037, 1.041, 1.046, 1.051, 1.053,
+                            1.052, 1.049, 1.043, 1.038, 1.034, 1.029, 1.025, 1.022, 1.018, 1.015, 1.012, 1.009, 1.007, 1.006, 1.006, 1.005, 1.006, 1.007, 1.008, 1.011, 1.013, 1.015, 1.018, 1.021, 1.026, 1.029, 1.034, 1.038, 1.042, 1.047, 1.051, 1.053,
+                            1.053, 1.049, 1.044, 1.039, 1.034, 1.031, 1.027, 1.023, 1.019, 1.017, 1.014, 1.012, 1.009, 1.008, 1.008, 1.007, 1.008, 1.009, 1.009, 1.012, 1.014, 1.017, 1.019, 1.023, 1.027, 1.031, 1.035, 1.039, 1.043, 1.048, 1.052, 1.055,
+                            1.053, 1.051, 1.046, 1.041, 1.036, 1.032, 1.028, 1.025, 1.022, 1.019, 1.016, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009, 1.011, 1.012, 1.014, 1.016, 1.018, 1.021, 1.025, 1.029, 1.032, 1.037, 1.041, 1.045, 1.049, 1.053, 1.056,
+                            1.055, 1.052, 1.047, 1.042, 1.039, 1.034, 1.029, 1.027, 1.024, 1.021, 1.018, 1.017, 1.015, 1.013, 1.013, 1.012, 1.012, 1.013, 1.014, 1.017, 1.019, 1.021, 1.024, 1.027, 1.029, 1.033, 1.038, 1.042, 1.046, 1.051, 1.055, 1.057,
+                            1.058, 1.054, 1.049, 1.045, 1.041, 1.037, 1.033, 1.029, 1.027, 1.024, 1.021, 1.019, 1.018, 1.016, 1.016, 1.016, 1.016, 1.016, 1.017, 1.019, 1.021, 1.024, 1.026, 1.029, 1.032, 1.036, 1.039, 1.044, 1.048, 1.052, 1.056, 1.059,
+                            1.061, 1.057, 1.051, 1.047, 1.043, 1.039, 1.035, 1.032, 1.029, 1.026, 1.024, 1.022, 1.021, 1.019, 1.019, 1.018, 1.018, 1.019, 1.019, 1.022, 1.023, 1.025, 1.028, 1.031, 1.034, 1.038, 1.042, 1.046, 1.051, 1.055, 1.058, 1.061,
+                            1.063, 1.059, 1.054, 1.049, 1.045, 1.042, 1.038, 1.034, 1.031, 1.028, 1.026, 1.025, 1.023, 1.022, 1.021, 1.021, 1.021, 1.022, 1.023, 1.024, 1.026, 1.028, 1.031, 1.034, 1.037, 1.041, 1.044, 1.048, 1.052, 1.056, 1.059, 1.062,
+                            1.064, 1.062, 1.056, 1.052, 1.047, 1.044, 1.041, 1.037, 1.034, 1.031, 1.029, 1.027, 1.026, 1.025, 1.024, 1.024, 1.024, 1.025, 1.025, 1.026, 1.029, 1.031, 1.033, 1.036, 1.039, 1.043, 1.047, 1.051, 1.054, 1.058, 1.062, 1.064,
+                            1.066, 1.064, 1.059, 1.055, 1.051, 1.046, 1.042, 1.039, 1.036, 1.033, 1.032, 1.031, 1.029, 1.027, 1.027, 1.027, 1.027, 1.027, 1.028, 1.029, 1.031, 1.034, 1.036, 1.038, 1.042, 1.045, 1.049, 1.053, 1.056, 1.059, 1.064, 1.066,
+                            1.069, 1.067, 1.062, 1.058, 1.053, 1.048, 1.045, 1.042, 1.039, 1.037, 1.035, 1.033, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.031, 1.032, 1.034, 1.036, 1.038, 1.041, 1.045, 1.047, 1.051, 1.054, 1.058, 1.062, 1.065, 1.069,
+                            1.071, 1.068, 1.064, 1.059, 1.056, 1.052, 1.048, 1.045, 1.043, 1.041, 1.038, 1.036, 1.034, 1.033, 1.032, 1.032, 1.032, 1.033, 1.034, 1.035, 1.037, 1.039, 1.041, 1.044, 1.047, 1.051, 1.054, 1.058, 1.061, 1.063, 1.069, 1.071,
+                            1.075, 1.071, 1.067, 1.063, 1.058, 1.055, 1.052, 1.048, 1.046, 1.044, 1.041, 1.039, 1.038, 1.036, 1.036, 1.035, 1.035, 1.036, 1.037, 1.038, 1.039, 1.042, 1.044, 1.047, 1.049, 1.053, 1.057, 1.059, 1.063, 1.067, 1.071, 1.073,
+                            1.078, 1.075, 1.071, 1.065, 1.061, 1.057, 1.054, 1.051, 1.049, 1.046, 1.044, 1.043, 1.041, 1.039, 1.039, 1.038, 1.039, 1.039, 1.041, 1.041, 1.043, 1.045, 1.047, 1.051, 1.052, 1.055, 1.059, 1.062, 1.066, 1.069, 1.072, 1.074,
+                            1.079, 1.077, 1.073, 1.068, 1.063, 1.059, 1.056, 1.053, 1.049, 1.048, 1.046, 1.044, 1.043, 1.041, 1.041, 1.039, 1.041, 1.041, 1.042, 1.043, 1.045, 1.047, 1.049, 1.051, 1.054, 1.057, 1.061, 1.064, 1.067, 1.071, 1.074, 1.076
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.069, 1.066, 1.061, 1.056, 1.051, 1.046, 1.042, 1.038, 1.035, 1.031, 1.028, 1.026, 1.024, 1.023, 1.023, 1.023, 1.023, 1.023, 1.025, 1.027, 1.028, 1.031, 1.035, 1.038, 1.042, 1.046, 1.051, 1.054, 1.059, 1.063, 1.068, 1.069,
+                            1.068, 1.064, 1.058, 1.053, 1.049, 1.044, 1.039, 1.036, 1.032, 1.029, 1.026, 1.024, 1.022, 1.021, 1.021, 1.019, 1.021, 1.022, 1.022, 1.025, 1.027, 1.029, 1.033, 1.036, 1.039, 1.043, 1.048, 1.053, 1.057, 1.062, 1.066, 1.069,
+                            1.066, 1.061, 1.057, 1.051, 1.047, 1.041, 1.037, 1.033, 1.029, 1.026, 1.024, 1.022, 1.021, 1.019, 1.018, 1.018, 1.018, 1.019, 1.021, 1.021, 1.024, 1.027, 1.029, 1.033, 1.037, 1.042, 1.046, 1.049, 1.055, 1.059, 1.064, 1.067,
+                            1.064, 1.059, 1.054, 1.049, 1.044, 1.039, 1.034, 1.031, 1.027, 1.024, 1.021, 1.019, 1.017, 1.016, 1.015, 1.015, 1.015, 1.016, 1.017, 1.019, 1.021, 1.024, 1.028, 1.031, 1.035, 1.039, 1.044, 1.049, 1.053, 1.058, 1.063, 1.066,
+                            1.062, 1.058, 1.052, 1.047, 1.041, 1.037, 1.032, 1.028, 1.025, 1.021, 1.018, 1.017, 1.015, 1.014, 1.013, 1.013, 1.013, 1.014, 1.015, 1.017, 1.019, 1.022, 1.026, 1.029, 1.033, 1.037, 1.043, 1.046, 1.051, 1.057, 1.061, 1.063,
+                            1.061, 1.056, 1.051, 1.045, 1.039, 1.035, 1.031, 1.026, 1.023, 1.018, 1.016, 1.014, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.013, 1.015, 1.017, 1.021, 1.024, 1.028, 1.032, 1.035, 1.041, 1.045, 1.049, 1.054, 1.059, 1.061,
+                            1.058, 1.054, 1.048, 1.044, 1.038, 1.034, 1.029, 1.025, 1.021, 1.017, 1.014, 1.012, 1.011, 1.009, 1.008, 1.008, 1.009, 1.009, 1.011, 1.014, 1.015, 1.019, 1.022, 1.027, 1.031, 1.035, 1.039, 1.044, 1.049, 1.053, 1.058, 1.061,
+                            1.058, 1.054, 1.048, 1.043, 1.037, 1.033, 1.028, 1.023, 1.019, 1.016, 1.013, 1.011, 1.009, 1.007, 1.007, 1.007, 1.008, 1.009, 1.009, 1.012, 1.015, 1.017, 1.021, 1.025, 1.029, 1.034, 1.039, 1.043, 1.048, 1.052, 1.058, 1.061,
+                            1.058, 1.053, 1.047, 1.042, 1.037, 1.032, 1.028, 1.023, 1.018, 1.015, 1.012, 1.011, 1.009, 1.006, 1.006, 1.006, 1.007, 1.007, 1.009, 1.012, 1.014, 1.017, 1.021, 1.024, 1.029, 1.033, 1.038, 1.043, 1.048, 1.052, 1.057, 1.061,
+                            1.056, 1.052, 1.047, 1.041, 1.036, 1.031, 1.027, 1.022, 1.018, 1.015, 1.012, 1.009, 1.007, 1.006, 1.006, 1.006, 1.006, 1.007, 1.008, 1.011, 1.014, 1.017, 1.019, 1.024, 1.028, 1.033, 1.037, 1.042, 1.047, 1.052, 1.057, 1.059,
+                            1.056, 1.052, 1.046, 1.041, 1.035, 1.031, 1.026, 1.021, 1.018, 1.015, 1.011, 1.008, 1.007, 1.005, 1.004, 1.005, 1.005, 1.006, 1.007, 1.011, 1.013, 1.016, 1.019, 1.024, 1.027, 1.032, 1.037, 1.042, 1.047, 1.051, 1.057, 1.059,
+                            1.056, 1.051, 1.045, 1.041, 1.035, 1.029, 1.026, 1.021, 1.017, 1.013, 1.011, 1.008, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.007, 1.009, 1.012, 1.016, 1.019, 1.022, 1.027, 1.031, 1.037, 1.042, 1.046, 1.051, 1.057, 1.058,
+                            1.056, 1.052, 1.045, 1.039, 1.035, 1.031, 1.025, 1.021, 1.017, 1.013, 1.009, 1.007, 1.006, 1.004, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.015, 1.018, 1.022, 1.026, 1.031, 1.036, 1.041, 1.045, 1.051, 1.056, 1.059,
+                            1.056, 1.051, 1.046, 1.041, 1.034, 1.029, 1.025, 1.019, 1.017, 1.013, 1.009, 1.007, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.015, 1.018, 1.022, 1.026, 1.031, 1.036, 1.041, 1.045, 1.049, 1.055, 1.059,
+                            1.056, 1.051, 1.046, 1.039, 1.034, 1.029, 1.024, 1.019, 1.016, 1.012, 1.009, 1.007, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.014, 1.018, 1.021, 1.026, 1.031, 1.035, 1.041, 1.045, 1.049, 1.054, 1.059,
+                            1.056, 1.052, 1.047, 1.041, 1.035, 1.031, 1.025, 1.021, 1.017, 1.013, 1.011, 1.007, 1.005, 1.004, 1.003, 1.003, 1.003, 1.005, 1.006, 1.009, 1.012, 1.015, 1.018, 1.021, 1.026, 1.031, 1.035, 1.041, 1.045, 1.051, 1.054, 1.058,
+                            1.056, 1.052, 1.047, 1.039, 1.035, 1.031, 1.026, 1.022, 1.017, 1.015, 1.011, 1.009, 1.007, 1.005, 1.004, 1.004, 1.004, 1.006, 1.008, 1.009, 1.012, 1.015, 1.019, 1.022, 1.026, 1.031, 1.036, 1.041, 1.046, 1.051, 1.055, 1.058,
+                            1.057, 1.053, 1.047, 1.042, 1.037, 1.031, 1.028, 1.024, 1.019, 1.016, 1.013, 1.011, 1.008, 1.006, 1.006, 1.006, 1.007, 1.007, 1.009, 1.011, 1.014, 1.016, 1.019, 1.024, 1.028, 1.032, 1.037, 1.042, 1.046, 1.051, 1.056, 1.059,
+                            1.058, 1.054, 1.048, 1.043, 1.039, 1.033, 1.029, 1.026, 1.022, 1.018, 1.014, 1.012, 1.011, 1.009, 1.008, 1.008, 1.008, 1.009, 1.011, 1.013, 1.016, 1.018, 1.021, 1.025, 1.029, 1.034, 1.038, 1.043, 1.047, 1.053, 1.057, 1.059,
+                            1.059, 1.056, 1.051, 1.045, 1.041, 1.036, 1.031, 1.028, 1.024, 1.021, 1.018, 1.015, 1.012, 1.011, 1.009, 1.011, 1.011, 1.012, 1.013, 1.015, 1.018, 1.021, 1.023, 1.027, 1.031, 1.036, 1.041, 1.045, 1.049, 1.053, 1.058, 1.062,
+                            1.062, 1.058, 1.051, 1.047, 1.043, 1.037, 1.033, 1.029, 1.026, 1.023, 1.021, 1.018, 1.015, 1.014, 1.013, 1.012, 1.013, 1.014, 1.015, 1.018, 1.021, 1.023, 1.026, 1.029, 1.033, 1.037, 1.042, 1.046, 1.051, 1.055, 1.059, 1.063,
+                            1.064, 1.059, 1.054, 1.049, 1.045, 1.039, 1.035, 1.032, 1.028, 1.026, 1.023, 1.021, 1.019, 1.017, 1.016, 1.016, 1.016, 1.016, 1.018, 1.021, 1.023, 1.024, 1.028, 1.032, 1.035, 1.039, 1.044, 1.048, 1.052, 1.057, 1.061, 1.064,
+                            1.066, 1.061, 1.056, 1.051, 1.047, 1.042, 1.038, 1.034, 1.031, 1.028, 1.025, 1.023, 1.021, 1.019, 1.019, 1.018, 1.018, 1.019, 1.021, 1.023, 1.025, 1.026, 1.031, 1.034, 1.037, 1.041, 1.046, 1.049, 1.054, 1.059, 1.063, 1.066,
+                            1.068, 1.064, 1.057, 1.053, 1.049, 1.044, 1.041, 1.036, 1.033, 1.031, 1.028, 1.026, 1.024, 1.023, 1.022, 1.021, 1.021, 1.022, 1.023, 1.025, 1.027, 1.029, 1.032, 1.036, 1.039, 1.043, 1.047, 1.052, 1.057, 1.061, 1.065, 1.068,
+                            1.069, 1.066, 1.061, 1.056, 1.052, 1.047, 1.043, 1.038, 1.036, 1.032, 1.029, 1.028, 1.027, 1.025, 1.025, 1.024, 1.024, 1.024, 1.026, 1.027, 1.029, 1.032, 1.035, 1.037, 1.041, 1.045, 1.049, 1.054, 1.058, 1.062, 1.066, 1.069,
+                            1.072, 1.068, 1.063, 1.058, 1.054, 1.049, 1.045, 1.042, 1.038, 1.035, 1.032, 1.031, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.028, 1.031, 1.032, 1.034, 1.037, 1.039, 1.043, 1.048, 1.052, 1.055, 1.059, 1.063, 1.068, 1.072,
+                            1.075, 1.071, 1.065, 1.061, 1.056, 1.051, 1.047, 1.045, 1.041, 1.038, 1.036, 1.034, 1.032, 1.031, 1.031, 1.029, 1.029, 1.031, 1.031, 1.032, 1.035, 1.037, 1.039, 1.043, 1.046, 1.051, 1.053, 1.057, 1.061, 1.065, 1.071, 1.073,
+                            1.077, 1.073, 1.068, 1.064, 1.058, 1.054, 1.051, 1.047, 1.044, 1.041, 1.038, 1.037, 1.035, 1.035, 1.033, 1.033, 1.033, 1.034, 1.035, 1.036, 1.038, 1.041, 1.043, 1.046, 1.049, 1.052, 1.057, 1.059, 1.064, 1.068, 1.072, 1.076,
+                            1.079, 1.076, 1.071, 1.066, 1.062, 1.057, 1.054, 1.051, 1.048, 1.045, 1.042, 1.041, 1.039, 1.037, 1.037, 1.036, 1.037, 1.037, 1.038, 1.039, 1.041, 1.044, 1.047, 1.049, 1.052, 1.056, 1.061, 1.064, 1.067, 1.071, 1.076, 1.078,
+                            1.083, 1.079, 1.075, 1.069, 1.066, 1.062, 1.058, 1.055, 1.052, 1.049, 1.047, 1.045, 1.044, 1.042, 1.041, 1.041, 1.041, 1.041, 1.043, 1.043, 1.045, 1.048, 1.051, 1.053, 1.057, 1.059, 1.064, 1.067, 1.071, 1.074, 1.079, 1.082,
+                            1.086, 1.083, 1.079, 1.073, 1.069, 1.065, 1.062, 1.059, 1.056, 1.053, 1.051, 1.049, 1.047, 1.046, 1.045, 1.045, 1.046, 1.046, 1.046, 1.047, 1.049, 1.052, 1.054, 1.057, 1.059, 1.063, 1.066, 1.069, 1.073, 1.077, 1.082, 1.083,
+                            1.089, 1.085, 1.082, 1.076, 1.071, 1.068, 1.065, 1.061, 1.059, 1.056, 1.054, 1.051, 1.049, 1.048, 1.048, 1.048, 1.047, 1.047, 1.048, 1.049, 1.052, 1.054, 1.057, 1.058, 1.061, 1.066, 1.068, 1.072, 1.076, 1.078, 1.083, 1.084
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.022, 1.021, 1.018, 1.016, 1.014, 1.012, 1.011, 1.009, 1.009, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.004, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.009, 1.013, 1.013, 1.015, 1.016, 1.017, 1.019,
+                            1.022, 1.018, 1.016, 1.015, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.016, 1.018, 1.019,
+                            1.021, 1.018, 1.016, 1.014, 1.013, 1.011, 1.011, 1.009, 1.007, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.003, 1.004, 1.004, 1.005, 1.005, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.014, 1.016, 1.017, 1.018,
+                            1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.007, 1.007, 1.005, 1.005, 1.004, 1.004, 1.004, 1.003, 1.003, 1.004, 1.004, 1.004, 1.005, 1.005, 1.006, 1.007, 1.008, 1.011, 1.011, 1.013, 1.014, 1.015, 1.017, 1.018,
+                            1.019, 1.018, 1.015, 1.014, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.014, 1.016, 1.017, 1.018,
+                            1.019, 1.018, 1.015, 1.014, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.014, 1.016, 1.017, 1.018,
+                            1.019, 1.017, 1.015, 1.014, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.014, 1.015, 1.017, 1.018,
+                            1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.009, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.006, 1.007, 1.008, 1.011, 1.011, 1.013, 1.014, 1.015, 1.017, 1.018,
+                            1.019, 1.017, 1.016, 1.014, 1.013, 1.012, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.011, 1.012, 1.013, 1.014, 1.016, 1.017, 1.019,
+                            1.019, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.008, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016, 1.017, 1.019,
+                            1.019, 1.019, 1.016, 1.015, 1.013, 1.012, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.003, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.012, 1.014, 1.015, 1.016, 1.017, 1.019,
+                            1.019, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.011, 1.012, 1.013, 1.015, 1.016, 1.018, 1.019,
+                            1.019, 1.018, 1.016, 1.014, 1.014, 1.012, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.011, 1.012, 1.013, 1.015, 1.016, 1.018, 1.019,
+                            1.019, 1.017, 1.016, 1.014, 1.013, 1.012, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.001, 1.001, 1.002, 1.002, 1.003, 1.004, 1.004, 1.006, 1.007, 1.008, 1.009, 1.012, 1.013, 1.014, 1.016, 1.018, 1.019,
+                            1.019, 1.018, 1.016, 1.015, 1.013, 1.012, 1.011, 1.009, 1.007, 1.007, 1.005, 1.004, 1.003, 1.002, 1.002, 1.001, 1.001, 1.001, 1.002, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.012, 1.013, 1.014, 1.016, 1.017, 1.019,
+                            1.019, 1.018, 1.016, 1.015, 1.014, 1.012, 1.011, 1.009, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.015, 1.018, 1.019,
+                            1.021, 1.019, 1.017, 1.016, 1.014, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.003, 1.003, 1.002, 1.002, 1.003, 1.003, 1.004, 1.004, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.014, 1.015, 1.017, 1.018, 1.019,
+                            1.021, 1.019, 1.018, 1.016, 1.015, 1.013, 1.012, 1.011, 1.011, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.011, 1.013, 1.014, 1.016, 1.017, 1.019, 1.021,
+                            1.021, 1.019, 1.018, 1.017, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.006, 1.008, 1.009, 1.009, 1.011, 1.012, 1.014, 1.016, 1.017, 1.018, 1.019, 1.021,
+                            1.022, 1.021, 1.019, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.007, 1.006, 1.006, 1.006, 1.006, 1.006, 1.007, 1.007, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016, 1.018, 1.019, 1.021, 1.022,
+                            1.023, 1.022, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.008, 1.008, 1.009, 1.009, 1.011, 1.011, 1.013, 1.014, 1.016, 1.018, 1.019, 1.019, 1.022, 1.022,
+                            1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.011, 1.009, 1.009, 1.009, 1.008, 1.008, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.014, 1.015, 1.017, 1.018, 1.019, 1.021, 1.022, 1.023,
+                            1.025, 1.023, 1.021, 1.019, 1.019, 1.017, 1.017, 1.015, 1.015, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.009, 1.009, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.015, 1.016, 1.017, 1.019, 1.021, 1.022, 1.023, 1.024,
+                            1.026, 1.024, 1.022, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.014, 1.013, 1.013, 1.012, 1.012, 1.011, 1.011, 1.011, 1.011, 1.012, 1.012, 1.013, 1.013, 1.014, 1.016, 1.017, 1.019, 1.021, 1.021, 1.022, 1.024, 1.025,
+                            1.027, 1.025, 1.023, 1.021, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.014, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.012, 1.013, 1.013, 1.013, 1.015, 1.016, 1.017, 1.018, 1.019, 1.021, 1.022, 1.022, 1.025, 1.025,
+                            1.028, 1.026, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.015, 1.015, 1.016, 1.018, 1.019, 1.021, 1.021, 1.022, 1.023, 1.025, 1.026,
+                            1.031, 1.027, 1.025, 1.023, 1.021, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.015, 1.015, 1.015, 1.015, 1.015, 1.015, 1.014, 1.015, 1.015, 1.016, 1.017, 1.018, 1.019, 1.021, 1.021, 1.022, 1.023, 1.025, 1.026, 1.027,
+                            1.031, 1.029, 1.027, 1.024, 1.022, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.016, 1.015, 1.015, 1.015, 1.016, 1.017, 1.017, 1.018, 1.019, 1.021, 1.022, 1.023, 1.023, 1.024, 1.025, 1.027, 1.029,
+                            1.033, 1.031, 1.029, 1.026, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.017, 1.016, 1.017, 1.016, 1.017, 1.017, 1.017, 1.018, 1.018, 1.019, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.027, 1.028, 1.029,
+                            1.036, 1.034, 1.031, 1.028, 1.026, 1.025, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.019, 1.019, 1.021, 1.021, 1.022, 1.023, 1.024, 1.026, 1.026, 1.027, 1.028, 1.029, 1.031,
+                            1.039, 1.036, 1.033, 1.031, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.021, 1.022, 1.023, 1.025, 1.026, 1.026, 1.028, 1.028, 1.029, 1.031, 1.032,
+                            1.041, 1.039, 1.035, 1.032, 1.031, 1.027, 1.026, 1.025, 1.024, 1.024, 1.023, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.022, 1.023, 1.024, 1.025, 1.026, 1.028, 1.028, 1.029, 1.031, 1.032, 1.033
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.031, 1.029, 1.025, 1.021, 1.019, 1.018, 1.016, 1.014, 1.012, 1.011, 1.011, 1.009, 1.009, 1.008, 1.008, 1.007, 1.008, 1.008, 1.008, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017, 1.019, 1.021, 1.023, 1.025, 1.026,
+                            1.029, 1.027, 1.023, 1.021, 1.019, 1.017, 1.015, 1.013, 1.012, 1.011, 1.009, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.007, 1.007, 1.008, 1.008, 1.009, 1.011, 1.011, 1.013, 1.014, 1.016, 1.018, 1.019, 1.022, 1.024, 1.025,
+                            1.027, 1.024, 1.021, 1.019, 1.017, 1.016, 1.014, 1.012, 1.011, 1.009, 1.008, 1.008, 1.007, 1.007, 1.006, 1.006, 1.006, 1.006, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017, 1.019, 1.021, 1.023, 1.024,
+                            1.026, 1.023, 1.021, 1.019, 1.017, 1.016, 1.014, 1.012, 1.011, 1.008, 1.008, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.004, 1.005, 1.005, 1.006, 1.007, 1.009, 1.011, 1.011, 1.013, 1.015, 1.016, 1.018, 1.019, 1.022, 1.024,
+                            1.025, 1.023, 1.021, 1.018, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.014, 1.016, 1.017, 1.019, 1.022, 1.024,
+                            1.024, 1.022, 1.019, 1.018, 1.016, 1.014, 1.012, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.012, 1.014, 1.016, 1.017, 1.019, 1.021, 1.023,
+                            1.024, 1.022, 1.019, 1.017, 1.015, 1.014, 1.012, 1.009, 1.008, 1.006, 1.005, 1.005, 1.004, 1.003, 1.003, 1.002, 1.002, 1.003, 1.003, 1.004, 1.004, 1.006, 1.007, 1.009, 1.011, 1.012, 1.014, 1.015, 1.017, 1.019, 1.021, 1.023,
+                            1.024, 1.022, 1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.008, 1.007, 1.005, 1.004, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.004, 1.005, 1.007, 1.008, 1.011, 1.012, 1.014, 1.016, 1.017, 1.019, 1.021, 1.023,
+                            1.024, 1.022, 1.019, 1.017, 1.016, 1.014, 1.013, 1.011, 1.009, 1.007, 1.006, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.011, 1.013, 1.015, 1.016, 1.018, 1.019, 1.021, 1.024,
+                            1.025, 1.023, 1.019, 1.018, 1.017, 1.014, 1.012, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.013, 1.015, 1.017, 1.018, 1.021, 1.022, 1.024,
+                            1.026, 1.023, 1.021, 1.019, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.007, 1.008, 1.009, 1.011, 1.013, 1.015, 1.017, 1.018, 1.021, 1.023, 1.025,
+                            1.026, 1.024, 1.021, 1.019, 1.017, 1.016, 1.013, 1.012, 1.011, 1.008, 1.006, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.013, 1.015, 1.017, 1.019, 1.021, 1.023, 1.025,
+                            1.026, 1.024, 1.021, 1.019, 1.017, 1.016, 1.013, 1.011, 1.011, 1.008, 1.006, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.003, 1.005, 1.006, 1.008, 1.009, 1.011, 1.013, 1.015, 1.017, 1.019, 1.021, 1.022, 1.025,
+                            1.026, 1.024, 1.021, 1.019, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.006, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.006, 1.007, 1.009, 1.011, 1.013, 1.015, 1.017, 1.018, 1.021, 1.022, 1.024,
+                            1.026, 1.023, 1.021, 1.019, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.006, 1.004, 1.003, 1.002, 1.002, 1.001, 1.001, 1.002, 1.002, 1.003, 1.004, 1.006, 1.007, 1.009, 1.011, 1.012, 1.014, 1.017, 1.019, 1.019, 1.022, 1.024,
+                            1.025, 1.023, 1.021, 1.018, 1.016, 1.015, 1.013, 1.011, 1.009, 1.008, 1.006, 1.005, 1.003, 1.003, 1.002, 1.001, 1.001, 1.001, 1.002, 1.003, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.015, 1.017, 1.018, 1.021, 1.022, 1.024,
+                            1.026, 1.023, 1.021, 1.019, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.012, 1.013, 1.015, 1.017, 1.018, 1.021, 1.022, 1.024,
+                            1.026, 1.024, 1.022, 1.019, 1.018, 1.016, 1.014, 1.013, 1.012, 1.009, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.012, 1.014, 1.015, 1.018, 1.019, 1.021, 1.023, 1.025,
+                            1.027, 1.025, 1.022, 1.021, 1.019, 1.017, 1.016, 1.014, 1.013, 1.012, 1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.009, 1.009, 1.012, 1.013, 1.015, 1.017, 1.019, 1.021, 1.022, 1.024, 1.026,
+                            1.028, 1.026, 1.023, 1.021, 1.021, 1.019, 1.017, 1.015, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007, 1.007, 1.007, 1.006, 1.007, 1.007, 1.007, 1.009, 1.009, 1.011, 1.013, 1.015, 1.017, 1.019, 1.019, 1.021, 1.024, 1.025, 1.027,
+                            1.029, 1.028, 1.025, 1.023, 1.021, 1.021, 1.018, 1.017, 1.016, 1.015, 1.013, 1.012, 1.011, 1.009, 1.009, 1.008, 1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.013, 1.014, 1.016, 1.018, 1.019, 1.021, 1.023, 1.024, 1.027, 1.028,
+                            1.031, 1.029, 1.026, 1.024, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.011, 1.011, 1.011, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.016, 1.018, 1.019, 1.021, 1.022, 1.024, 1.026, 1.028, 1.029,
+                            1.032, 1.031, 1.028, 1.025, 1.024, 1.023, 1.021, 1.019, 1.019, 1.018, 1.016, 1.015, 1.014, 1.014, 1.013, 1.013, 1.012, 1.012, 1.012, 1.013, 1.013, 1.014, 1.016, 1.017, 1.019, 1.021, 1.022, 1.024, 1.025, 1.027, 1.029, 1.031,
+                            1.033, 1.031, 1.029, 1.026, 1.025, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.015, 1.016, 1.017, 1.018, 1.019, 1.022, 1.023, 1.025, 1.027, 1.028, 1.031, 1.032,
+                            1.034, 1.032, 1.029, 1.028, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.015, 1.015, 1.015, 1.015, 1.016, 1.016, 1.017, 1.018, 1.019, 1.021, 1.023, 1.024, 1.026, 1.027, 1.029, 1.031, 1.033,
+                            1.037, 1.033, 1.031, 1.029, 1.026, 1.024, 1.023, 1.022, 1.021, 1.019, 1.018, 1.018, 1.017, 1.017, 1.016, 1.016, 1.016, 1.016, 1.017, 1.017, 1.017, 1.018, 1.019, 1.021, 1.022, 1.023, 1.025, 1.027, 1.028, 1.029, 1.032, 1.034,
+                            1.038, 1.036, 1.032, 1.029, 1.028, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.017, 1.017, 1.018, 1.018, 1.018, 1.019, 1.021, 1.022, 1.023, 1.025, 1.026, 1.027, 1.029, 1.031, 1.032, 1.034,
+                            1.039, 1.038, 1.034, 1.031, 1.029, 1.027, 1.025, 1.024, 1.022, 1.021, 1.019, 1.021, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.018, 1.019, 1.019, 1.021, 1.022, 1.023, 1.024, 1.026, 1.027, 1.029, 1.029, 1.031, 1.033, 1.035,
+                            1.042, 1.039, 1.036, 1.034, 1.031, 1.028, 1.027, 1.026, 1.024, 1.023, 1.022, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.021, 1.021, 1.022, 1.023, 1.024, 1.024, 1.026, 1.027, 1.029, 1.029, 1.031, 1.032, 1.035, 1.037,
+                            1.044, 1.042, 1.039, 1.036, 1.033, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.022, 1.021, 1.022, 1.021, 1.022, 1.022, 1.024, 1.024, 1.025, 1.026, 1.028, 1.029, 1.031, 1.032, 1.033, 1.035, 1.037, 1.039,
+                            1.049, 1.045, 1.041, 1.039, 1.036, 1.034, 1.032, 1.031, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.024, 1.024, 1.024, 1.024, 1.025, 1.024, 1.025, 1.026, 1.027, 1.029, 1.031, 1.031, 1.033, 1.034, 1.036, 1.037, 1.039, 1.041,
+                            1.051, 1.051, 1.045, 1.041, 1.038, 1.035, 1.033, 1.032, 1.031, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.026, 1.026, 1.027, 1.027, 1.027, 1.027, 1.027, 1.029, 1.031, 1.031, 1.033, 1.034, 1.036, 1.037, 1.039, 1.041, 1.042
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.022, 1.021, 1.018, 1.015, 1.014, 1.012, 1.011, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.006, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.018,
+                            1.021, 1.019, 1.017, 1.015, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.007, 1.006, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017,
+                            1.021, 1.019, 1.017, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.004, 1.004, 1.005, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016,
+                            1.019, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.005, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017,
+                            1.019, 1.018, 1.016, 1.014, 1.013, 1.011, 1.009, 1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.004, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.017,
+                            1.019, 1.018, 1.015, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.007, 1.005, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.016,
+                            1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.012, 1.014, 1.016,
+                            1.019, 1.017, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.012, 1.014, 1.016,
+                            1.019, 1.017, 1.015, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.005, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.013, 1.014, 1.016,
+                            1.019, 1.018, 1.015, 1.014, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.014, 1.015, 1.017,
+                            1.021, 1.018, 1.016, 1.014, 1.013, 1.011, 1.011, 1.009, 1.008, 1.007, 1.005, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.013, 1.014, 1.016, 1.017,
+                            1.021, 1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.007, 1.006, 1.005, 1.004, 1.004, 1.003, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.016, 1.019,
+                            1.021, 1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.012, 1.013, 1.015, 1.016, 1.018,
+                            1.021, 1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.009, 1.009, 1.011, 1.012, 1.013, 1.014, 1.015, 1.016, 1.018,
+                            1.022, 1.021, 1.018, 1.016, 1.015, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.015, 1.016, 1.018,
+                            1.022, 1.019, 1.018, 1.016, 1.015, 1.014, 1.012, 1.011, 1.011, 1.009, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.005, 1.006, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.015, 1.016, 1.019,
+                            1.022, 1.021, 1.018, 1.016, 1.016, 1.014, 1.013, 1.011, 1.011, 1.009, 1.008, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.015, 1.017, 1.019,
+                            1.022, 1.021, 1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.008, 1.007, 1.006, 1.006, 1.006, 1.005, 1.005, 1.006, 1.007, 1.007, 1.008, 1.008, 1.009, 1.011, 1.011, 1.012, 1.013, 1.015, 1.015, 1.017, 1.019,
+                            1.023, 1.021, 1.019, 1.018, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.008, 1.007, 1.007, 1.007, 1.007, 1.007, 1.007, 1.007, 1.008, 1.008, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.015, 1.017, 1.018, 1.019,
+                            1.025, 1.023, 1.019, 1.018, 1.016, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.008, 1.008, 1.008, 1.008, 1.008, 1.008, 1.008, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.015, 1.016, 1.017, 1.018, 1.021,
+                            1.025, 1.024, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.013, 1.013, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.009, 1.009, 1.009, 1.011, 1.011, 1.011, 1.013, 1.013, 1.014, 1.015, 1.016, 1.017, 1.018, 1.019, 1.021,
+                            1.026, 1.025, 1.022, 1.021, 1.019, 1.019, 1.017, 1.017, 1.016, 1.015, 1.014, 1.013, 1.013, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.013, 1.014, 1.015, 1.015, 1.016, 1.017, 1.018, 1.019, 1.021, 1.023,
+                            1.027, 1.026, 1.024, 1.022, 1.021, 1.021, 1.019, 1.019, 1.017, 1.017, 1.016, 1.015, 1.014, 1.014, 1.013, 1.013, 1.013, 1.012, 1.012, 1.013, 1.013, 1.014, 1.014, 1.015, 1.016, 1.016, 1.017, 1.019, 1.019, 1.021, 1.022, 1.024,
+                            1.029, 1.027, 1.024, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.015, 1.015, 1.015, 1.014, 1.014, 1.014, 1.015, 1.015, 1.016, 1.016, 1.017, 1.018, 1.019, 1.019, 1.021, 1.021, 1.023, 1.025,
+                            1.031, 1.029, 1.026, 1.024, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.017, 1.016, 1.016, 1.016, 1.016, 1.016, 1.015, 1.016, 1.016, 1.016, 1.017, 1.018, 1.018, 1.019, 1.021, 1.021, 1.023, 1.025, 1.026,
+                            1.032, 1.031, 1.028, 1.026, 1.024, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.017, 1.018, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.018, 1.018, 1.019, 1.019, 1.021, 1.021, 1.022, 1.024, 1.026, 1.027,
+                            1.033, 1.032, 1.029, 1.027, 1.026, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.019, 1.019, 1.019, 1.021, 1.021, 1.023, 1.023, 1.024, 1.025, 1.028,
+                            1.035, 1.033, 1.031, 1.029, 1.026, 1.025, 1.024, 1.023, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.022, 1.024, 1.025, 1.025, 1.027, 1.028,
+                            1.036, 1.034, 1.033, 1.031, 1.028, 1.026, 1.026, 1.024, 1.023, 1.022, 1.022, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.021, 1.022, 1.023, 1.024, 1.025, 1.025, 1.026, 1.028, 1.029,
+                            1.038, 1.037, 1.034, 1.032, 1.029, 1.028, 1.027, 1.027, 1.026, 1.024, 1.023, 1.023, 1.023, 1.022, 1.022, 1.021, 1.021, 1.021, 1.021, 1.021, 1.022, 1.022, 1.023, 1.023, 1.024, 1.025, 1.025, 1.026, 1.027, 1.028, 1.031, 1.032,
+                            1.042, 1.039, 1.036, 1.034, 1.032, 1.029, 1.029, 1.029, 1.027, 1.027, 1.026, 1.026, 1.025, 1.024, 1.024, 1.024, 1.023, 1.024, 1.024, 1.024, 1.024, 1.024, 1.025, 1.025, 1.026, 1.027, 1.027, 1.028, 1.029, 1.031, 1.032, 1.036,
+                            1.043, 1.042, 1.039, 1.036, 1.034, 1.032, 1.031, 1.031, 1.029, 1.028, 1.028, 1.028, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.025, 1.026, 1.026, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.031, 1.032, 1.035, 1.036
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.063, 1.062, 1.055, 1.049, 1.044, 1.041, 1.037, 1.034, 1.031, 1.027, 1.025, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.024, 1.026, 1.029, 1.031, 1.034, 1.039, 1.043, 1.046, 1.051, 1.055, 1.057,
+                            1.062, 1.057, 1.052, 1.047, 1.042, 1.039, 1.035, 1.032, 1.029, 1.026, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.018, 1.018, 1.019, 1.019, 1.021, 1.023, 1.025, 1.027, 1.029, 1.032, 1.036, 1.041, 1.044, 1.048, 1.052, 1.057,
+                            1.059, 1.054, 1.049, 1.045, 1.041, 1.038, 1.034, 1.031, 1.027, 1.024, 1.022, 1.021, 1.019, 1.018, 1.018, 1.017, 1.017, 1.017, 1.017, 1.018, 1.019, 1.021, 1.024, 1.025, 1.028, 1.031, 1.034, 1.037, 1.042, 1.046, 1.051, 1.056,
+                            1.057, 1.053, 1.047, 1.043, 1.039, 1.036, 1.032, 1.029, 1.025, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.015, 1.015, 1.016, 1.017, 1.018, 1.019, 1.022, 1.024, 1.027, 1.029, 1.032, 1.037, 1.041, 1.045, 1.049, 1.054,
+                            1.057, 1.051, 1.046, 1.042, 1.038, 1.034, 1.031, 1.027, 1.024, 1.022, 1.019, 1.018, 1.016, 1.015, 1.014, 1.014, 1.014, 1.013, 1.014, 1.015, 1.016, 1.018, 1.021, 1.023, 1.026, 1.029, 1.032, 1.036, 1.039, 1.043, 1.048, 1.051,
+                            1.052, 1.049, 1.044, 1.041, 1.036, 1.032, 1.028, 1.025, 1.022, 1.019, 1.017, 1.015, 1.014, 1.012, 1.012, 1.011, 1.011, 1.012, 1.012, 1.012, 1.014, 1.016, 1.018, 1.021, 1.023, 1.027, 1.029, 1.033, 1.038, 1.041, 1.046, 1.049,
+                            1.051, 1.047, 1.042, 1.039, 1.035, 1.029, 1.027, 1.023, 1.019, 1.017, 1.015, 1.013, 1.011, 1.011, 1.009, 1.009, 1.009, 1.009, 1.009, 1.009, 1.012, 1.013, 1.016, 1.018, 1.021, 1.024, 1.028, 1.031, 1.035, 1.039, 1.043, 1.046,
+                            1.049, 1.045, 1.041, 1.036, 1.032, 1.028, 1.025, 1.021, 1.018, 1.015, 1.012, 1.011, 1.009, 1.007, 1.007, 1.006, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.016, 1.018, 1.022, 1.026, 1.031, 1.032, 1.037, 1.041, 1.045,
+                            1.049, 1.044, 1.038, 1.035, 1.031, 1.027, 1.023, 1.019, 1.016, 1.013, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.004, 1.005, 1.006, 1.006, 1.008, 1.011, 1.012, 1.014, 1.017, 1.019, 1.024, 1.028, 1.032, 1.036, 1.041, 1.044,
+                            1.048, 1.044, 1.037, 1.034, 1.031, 1.025, 1.022, 1.018, 1.015, 1.012, 1.011, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.007, 1.009, 1.012, 1.013, 1.016, 1.019, 1.023, 1.026, 1.031, 1.035, 1.039, 1.043,
+                            1.049, 1.044, 1.038, 1.034, 1.029, 1.025, 1.022, 1.018, 1.016, 1.012, 1.009, 1.007, 1.006, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.013, 1.015, 1.019, 1.023, 1.026, 1.029, 1.035, 1.039, 1.043,
+                            1.049, 1.044, 1.039, 1.034, 1.029, 1.026, 1.022, 1.019, 1.016, 1.012, 1.009, 1.007, 1.005, 1.004, 1.003, 1.003, 1.002, 1.003, 1.003, 1.005, 1.006, 1.009, 1.011, 1.012, 1.015, 1.019, 1.023, 1.025, 1.031, 1.034, 1.039, 1.043,
+                            1.051, 1.044, 1.039, 1.035, 1.031, 1.026, 1.023, 1.019, 1.016, 1.013, 1.011, 1.007, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.023, 1.027, 1.031, 1.034, 1.039, 1.044,
+                            1.051, 1.045, 1.041, 1.035, 1.031, 1.027, 1.023, 1.019, 1.016, 1.013, 1.011, 1.008, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.023, 1.027, 1.031, 1.034, 1.039, 1.044,
+                            1.051, 1.046, 1.041, 1.035, 1.031, 1.026, 1.023, 1.019, 1.017, 1.013, 1.011, 1.008, 1.006, 1.004, 1.003, 1.002, 1.002, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.024, 1.027, 1.031, 1.034, 1.039, 1.044,
+                            1.051, 1.045, 1.041, 1.036, 1.031, 1.026, 1.023, 1.019, 1.016, 1.013, 1.011, 1.008, 1.006, 1.004, 1.003, 1.003, 1.002, 1.003, 1.004, 1.004, 1.007, 1.008, 1.011, 1.014, 1.016, 1.019, 1.023, 1.027, 1.031, 1.034, 1.039, 1.043,
+                            1.051, 1.046, 1.041, 1.036, 1.031, 1.027, 1.023, 1.019, 1.017, 1.013, 1.011, 1.008, 1.006, 1.005, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.007, 1.008, 1.011, 1.014, 1.016, 1.018, 1.023, 1.025, 1.029, 1.034, 1.039, 1.043,
+                            1.051, 1.046, 1.041, 1.037, 1.032, 1.027, 1.023, 1.021, 1.017, 1.014, 1.011, 1.008, 1.007, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.007, 1.008, 1.011, 1.013, 1.016, 1.018, 1.022, 1.025, 1.031, 1.034, 1.039, 1.043,
+                            1.051, 1.047, 1.041, 1.036, 1.031, 1.028, 1.024, 1.021, 1.018, 1.014, 1.012, 1.009, 1.006, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.007, 1.008, 1.011, 1.013, 1.016, 1.019, 1.022, 1.026, 1.029, 1.033, 1.038, 1.042,
+                            1.051, 1.048, 1.042, 1.037, 1.032, 1.029, 1.025, 1.022, 1.019, 1.016, 1.013, 1.011, 1.008, 1.006, 1.005, 1.005, 1.004, 1.005, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.017, 1.019, 1.023, 1.027, 1.031, 1.034, 1.039, 1.043,
+                            1.053, 1.049, 1.043, 1.039, 1.034, 1.029, 1.027, 1.024, 1.021, 1.018, 1.015, 1.013, 1.011, 1.008, 1.007, 1.006, 1.006, 1.006, 1.006, 1.007, 1.009, 1.011, 1.012, 1.015, 1.018, 1.021, 1.024, 1.028, 1.032, 1.035, 1.041, 1.045,
+                            1.056, 1.051, 1.045, 1.039, 1.037, 1.033, 1.029, 1.025, 1.023, 1.021, 1.017, 1.015, 1.013, 1.011, 1.009, 1.009, 1.009, 1.008, 1.009, 1.009, 1.011, 1.012, 1.014, 1.017, 1.019, 1.023, 1.026, 1.029, 1.033, 1.037, 1.043, 1.046,
+                            1.057, 1.054, 1.048, 1.044, 1.039, 1.036, 1.032, 1.028, 1.026, 1.023, 1.019, 1.017, 1.016, 1.014, 1.013, 1.011, 1.011, 1.011, 1.011, 1.012, 1.013, 1.015, 1.016, 1.019, 1.022, 1.025, 1.029, 1.032, 1.036, 1.039, 1.045, 1.048,
+                            1.059, 1.057, 1.051, 1.046, 1.043, 1.038, 1.035, 1.032, 1.028, 1.026, 1.022, 1.021, 1.018, 1.016, 1.015, 1.015, 1.015, 1.015, 1.014, 1.016, 1.016, 1.018, 1.019, 1.022, 1.024, 1.029, 1.031, 1.034, 1.039, 1.043, 1.047, 1.051,
+                            1.064, 1.061, 1.054, 1.049, 1.045, 1.041, 1.038, 1.035, 1.031, 1.029, 1.025, 1.023, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.017, 1.018, 1.019, 1.021, 1.023, 1.025, 1.027, 1.031, 1.034, 1.037, 1.042, 1.044, 1.049, 1.053,
+                            1.067, 1.062, 1.057, 1.052, 1.048, 1.044, 1.041, 1.037, 1.034, 1.031, 1.028, 1.027, 1.024, 1.022, 1.022, 1.022, 1.021, 1.021, 1.021, 1.021, 1.022, 1.024, 1.025, 1.027, 1.031, 1.033, 1.036, 1.039, 1.043, 1.048, 1.053, 1.055,
+                            1.069, 1.066, 1.061, 1.055, 1.051, 1.046, 1.043, 1.039, 1.037, 1.033, 1.029, 1.028, 1.026, 1.025, 1.024, 1.023, 1.022, 1.022, 1.022, 1.023, 1.024, 1.026, 1.028, 1.029, 1.033, 1.035, 1.038, 1.042, 1.045, 1.049, 1.054, 1.056,
+                            1.071, 1.068, 1.063, 1.058, 1.052, 1.048, 1.044, 1.041, 1.038, 1.036, 1.032, 1.029, 1.029, 1.027, 1.026, 1.025, 1.024, 1.024, 1.025, 1.025, 1.026, 1.028, 1.029, 1.032, 1.034, 1.038, 1.041, 1.044, 1.046, 1.051, 1.055, 1.059,
+                            1.075, 1.071, 1.066, 1.059, 1.056, 1.051, 1.047, 1.044, 1.041, 1.038, 1.035, 1.033, 1.031, 1.029, 1.028, 1.027, 1.027, 1.026, 1.027, 1.028, 1.028, 1.029, 1.031, 1.034, 1.036, 1.039, 1.042, 1.046, 1.049, 1.053, 1.058, 1.062,
+                            1.078, 1.073, 1.068, 1.062, 1.058, 1.054, 1.051, 1.047, 1.044, 1.041, 1.038, 1.036, 1.033, 1.032, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.031, 1.032, 1.034, 1.036, 1.039, 1.042, 1.046, 1.048, 1.053, 1.056, 1.061, 1.066,
+                            1.083, 1.077, 1.071, 1.065, 1.061, 1.056, 1.053, 1.051, 1.048, 1.044, 1.041, 1.039, 1.038, 1.036, 1.034, 1.033, 1.033, 1.033, 1.033, 1.034, 1.035, 1.035, 1.037, 1.039, 1.043, 1.045, 1.048, 1.052, 1.056, 1.061, 1.065, 1.069,
+                            1.084, 1.083, 1.074, 1.069, 1.064, 1.058, 1.056, 1.052, 1.051, 1.048, 1.044, 1.041, 1.039, 1.038, 1.037, 1.035, 1.035, 1.036, 1.036, 1.036, 1.037, 1.039, 1.041, 1.043, 1.045, 1.047, 1.049, 1.054, 1.059, 1.061, 1.068, 1.069
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.046, 1.046, 1.047, 1.048, 1.053, 1.054, 1.056, 1.059, 1.061, 1.062, 1.064, 1.065, 1.066, 1.068, 1.069, 1.069, 1.069, 1.068, 1.067, 1.067, 1.064, 1.063, 1.061, 1.058, 1.056, 1.054, 1.053, 1.049, 1.049, 1.046, 1.044, 1.042,
+                            1.045, 1.046, 1.047, 1.049, 1.052, 1.054, 1.057, 1.061, 1.061, 1.064, 1.065, 1.066, 1.067, 1.069, 1.069, 1.069, 1.069, 1.069, 1.068, 1.067, 1.066, 1.063, 1.062, 1.059, 1.057, 1.055, 1.051, 1.051, 1.048, 1.044, 1.043, 1.043,
+                            1.045, 1.045, 1.048, 1.051, 1.049, 1.053, 1.057, 1.059, 1.062, 1.064, 1.067, 1.067, 1.068, 1.069, 1.071, 1.072, 1.071, 1.069, 1.069, 1.067, 1.066, 1.064, 1.063, 1.061, 1.057, 1.055, 1.052, 1.049, 1.048, 1.045, 1.044, 1.043,
+                            1.044, 1.046, 1.047, 1.048, 1.051, 1.053, 1.056, 1.059, 1.062, 1.064, 1.066, 1.068, 1.069, 1.071, 1.072, 1.072, 1.071, 1.071, 1.069, 1.068, 1.066, 1.064, 1.063, 1.061, 1.058, 1.055, 1.053, 1.051, 1.048, 1.045, 1.042, 1.043,
+                            1.045, 1.045, 1.047, 1.049, 1.051, 1.053, 1.056, 1.058, 1.062, 1.065, 1.067, 1.069, 1.071, 1.072, 1.072, 1.072, 1.072, 1.072, 1.071, 1.069, 1.067, 1.065, 1.063, 1.061, 1.059, 1.056, 1.052, 1.051, 1.048, 1.044, 1.043, 1.042,
+                            1.047, 1.046, 1.046, 1.049, 1.052, 1.054, 1.057, 1.061, 1.063, 1.065, 1.067, 1.069, 1.072, 1.072, 1.073, 1.073, 1.073, 1.072, 1.071, 1.069, 1.068, 1.066, 1.064, 1.062, 1.059, 1.056, 1.053, 1.051, 1.048, 1.044, 1.043, 1.042,
+                            1.047, 1.047, 1.047, 1.051, 1.052, 1.056, 1.058, 1.062, 1.064, 1.066, 1.067, 1.071, 1.072, 1.073, 1.074, 1.074, 1.073, 1.073, 1.072, 1.069, 1.069, 1.067, 1.065, 1.062, 1.061, 1.057, 1.054, 1.052, 1.048, 1.044, 1.044, 1.044,
+                            1.046, 1.047, 1.049, 1.051, 1.054, 1.057, 1.059, 1.062, 1.064, 1.066, 1.068, 1.069, 1.072, 1.072, 1.074, 1.074, 1.074, 1.073, 1.072, 1.071, 1.069, 1.068, 1.066, 1.063, 1.061, 1.058, 1.055, 1.053, 1.048, 1.046, 1.044, 1.043,
+                            1.047, 1.047, 1.049, 1.051, 1.054, 1.056, 1.059, 1.062, 1.065, 1.067, 1.068, 1.069, 1.071, 1.073, 1.074, 1.074, 1.074, 1.073, 1.072, 1.071, 1.069, 1.068, 1.066, 1.063, 1.061, 1.058, 1.054, 1.052, 1.048, 1.046, 1.044, 1.043,
+                            1.047, 1.046, 1.048, 1.052, 1.054, 1.057, 1.059, 1.062, 1.065, 1.067, 1.068, 1.069, 1.071, 1.072, 1.073, 1.074, 1.074, 1.073, 1.072, 1.071, 1.069, 1.067, 1.066, 1.063, 1.061, 1.057, 1.054, 1.051, 1.049, 1.045, 1.043, 1.043,
+                            1.047, 1.046, 1.049, 1.051, 1.054, 1.057, 1.061, 1.062, 1.065, 1.067, 1.069, 1.069, 1.071, 1.072, 1.073, 1.074, 1.074, 1.073, 1.071, 1.071, 1.069, 1.067, 1.065, 1.062, 1.061, 1.058, 1.054, 1.051, 1.048, 1.045, 1.042, 1.042,
+                            1.045, 1.047, 1.048, 1.051, 1.054, 1.057, 1.061, 1.063, 1.065, 1.068, 1.069, 1.069, 1.071, 1.072, 1.072, 1.072, 1.072, 1.072, 1.071, 1.069, 1.069, 1.067, 1.064, 1.061, 1.059, 1.057, 1.054, 1.051, 1.048, 1.044, 1.041, 1.039,
+                            1.045, 1.045, 1.047, 1.051, 1.053, 1.056, 1.061, 1.063, 1.065, 1.067, 1.068, 1.068, 1.071, 1.071, 1.072, 1.072, 1.071, 1.071, 1.069, 1.069, 1.067, 1.065, 1.063, 1.061, 1.058, 1.056, 1.053, 1.049, 1.046, 1.042, 1.041, 1.039,
+                            1.045, 1.044, 1.047, 1.049, 1.052, 1.056, 1.059, 1.061, 1.065, 1.066, 1.067, 1.069, 1.071, 1.071, 1.072, 1.072, 1.071, 1.069, 1.069, 1.068, 1.066, 1.064, 1.062, 1.059, 1.059, 1.055, 1.052, 1.049, 1.045, 1.042, 1.039, 1.038,
+                            1.045, 1.044, 1.047, 1.049, 1.051, 1.055, 1.058, 1.061, 1.063, 1.065, 1.067, 1.068, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.068, 1.067, 1.065, 1.064, 1.061, 1.059, 1.058, 1.055, 1.051, 1.048, 1.045, 1.041, 1.039, 1.038,
+                            1.044, 1.044, 1.047, 1.049, 1.051, 1.055, 1.057, 1.059, 1.062, 1.064, 1.066, 1.068, 1.069, 1.069, 1.071, 1.071, 1.069, 1.069, 1.068, 1.067, 1.065, 1.063, 1.061, 1.058, 1.057, 1.054, 1.051, 1.048, 1.045, 1.041, 1.038, 1.038,
+                            1.044, 1.043, 1.046, 1.049, 1.051, 1.054, 1.056, 1.059, 1.062, 1.063, 1.066, 1.067, 1.068, 1.069, 1.069, 1.071, 1.071, 1.069, 1.068, 1.066, 1.064, 1.062, 1.059, 1.058, 1.055, 1.053, 1.051, 1.047, 1.044, 1.041, 1.038, 1.036,
+                            1.043, 1.044, 1.045, 1.048, 1.051, 1.053, 1.056, 1.059, 1.061, 1.063, 1.064, 1.066, 1.068, 1.068, 1.069, 1.069, 1.069, 1.068, 1.066, 1.065, 1.063, 1.061, 1.059, 1.056, 1.054, 1.052, 1.049, 1.047, 1.043, 1.039, 1.037, 1.036,
+                            1.042, 1.044, 1.045, 1.046, 1.051, 1.051, 1.055, 1.057, 1.061, 1.062, 1.063, 1.064, 1.066, 1.067, 1.068, 1.068, 1.067, 1.066, 1.065, 1.063, 1.061, 1.059, 1.057, 1.054, 1.054, 1.049, 1.049, 1.045, 1.043, 1.039, 1.035, 1.035,
+                            1.042, 1.042, 1.044, 1.046, 1.049, 1.051, 1.054, 1.056, 1.058, 1.061, 1.062, 1.063, 1.064, 1.065, 1.066, 1.066, 1.065, 1.064, 1.063, 1.062, 1.059, 1.058, 1.055, 1.053, 1.051, 1.049, 1.047, 1.044, 1.041, 1.036, 1.034, 1.035,
+                            1.042, 1.041, 1.041, 1.044, 1.048, 1.051, 1.052, 1.055, 1.056, 1.058, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.063, 1.062, 1.061, 1.059, 1.058, 1.055, 1.053, 1.052, 1.049, 1.047, 1.045, 1.042, 1.039, 1.035, 1.034, 1.032,
+                            1.039, 1.039, 1.039, 1.043, 1.047, 1.049, 1.051, 1.053, 1.055, 1.057, 1.057, 1.059, 1.059, 1.061, 1.061, 1.061, 1.061, 1.059, 1.058, 1.057, 1.055, 1.054, 1.052, 1.049, 1.048, 1.046, 1.042, 1.039, 1.037, 1.033, 1.032, 1.032,
+                            1.038, 1.038, 1.038, 1.042, 1.045, 1.047, 1.049, 1.052, 1.052, 1.054, 1.056, 1.057, 1.057, 1.058, 1.058, 1.059, 1.058, 1.057, 1.056, 1.055, 1.054, 1.052, 1.051, 1.048, 1.046, 1.043, 1.041, 1.038, 1.034, 1.032, 1.029, 1.032,
+                            1.036, 1.035, 1.036, 1.039, 1.043, 1.045, 1.047, 1.048, 1.049, 1.052, 1.054, 1.055, 1.056, 1.056, 1.056, 1.056, 1.056, 1.056, 1.054, 1.053, 1.052, 1.051, 1.048, 1.046, 1.044, 1.041, 1.039, 1.036, 1.032, 1.031, 1.029, 1.029,
+                            1.034, 1.035, 1.035, 1.037, 1.041, 1.043, 1.045, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.054, 1.054, 1.053, 1.053, 1.052, 1.051, 1.049, 1.048, 1.046, 1.044, 1.042, 1.041, 1.037, 1.034, 1.031, 1.029, 1.028, 1.027,
+                            1.034, 1.033, 1.034, 1.036, 1.039, 1.041, 1.043, 1.045, 1.046, 1.048, 1.048, 1.049, 1.051, 1.051, 1.051, 1.052, 1.051, 1.049, 1.049, 1.048, 1.047, 1.045, 1.044, 1.042, 1.041, 1.038, 1.035, 1.031, 1.031, 1.028, 1.027, 1.026,
+                            1.032, 1.033, 1.033, 1.035, 1.036, 1.037, 1.041, 1.043, 1.045, 1.046, 1.047, 1.048, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.044, 1.044, 1.043, 1.041, 1.041, 1.037, 1.035, 1.033, 1.031, 1.028, 1.027, 1.026, 1.026,
+                            1.032, 1.032, 1.033, 1.033, 1.034, 1.036, 1.038, 1.041, 1.043, 1.044, 1.044, 1.045, 1.046, 1.046, 1.047, 1.046, 1.046, 1.044, 1.043, 1.043, 1.042, 1.041, 1.039, 1.037, 1.036, 1.034, 1.032, 1.029, 1.028, 1.027, 1.026, 1.025,
+                            1.029, 1.032, 1.032, 1.033, 1.032, 1.035, 1.036, 1.038, 1.041, 1.042, 1.044, 1.044, 1.045, 1.044, 1.044, 1.043, 1.042, 1.041, 1.041, 1.041, 1.039, 1.039, 1.036, 1.035, 1.034, 1.032, 1.031, 1.029, 1.028, 1.025, 1.025, 1.025,
+                            1.029, 1.029, 1.029, 1.031, 1.032, 1.032, 1.035, 1.036, 1.038, 1.039, 1.041, 1.041, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.038, 1.037, 1.036, 1.035, 1.033, 1.032, 1.031, 1.029, 1.029, 1.026, 1.024, 1.025, 1.026,
+                            1.028, 1.028, 1.026, 1.029, 1.031, 1.031, 1.032, 1.034, 1.036, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.037, 1.036, 1.034, 1.034, 1.032, 1.032, 1.031, 1.029, 1.029, 1.027, 1.026, 1.025, 1.026, 1.022,
+                            1.031, 1.027, 1.028, 1.028, 1.032, 1.031, 1.031, 1.033, 1.034, 1.036, 1.037, 1.038, 1.038, 1.039, 1.039, 1.037, 1.037, 1.036, 1.035, 1.034, 1.033, 1.031, 1.031, 1.031, 1.029, 1.028, 1.028, 1.025, 1.025, 1.025, 1.022, 1.024
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.031, 1.029, 1.031, 1.035, 1.039, 1.043, 1.045, 1.048, 1.049, 1.052, 1.055, 1.056, 1.057, 1.058, 1.059, 1.059, 1.059, 1.057, 1.057, 1.057, 1.054, 1.052, 1.049, 1.048, 1.046, 1.043, 1.039, 1.036, 1.033, 1.029, 1.029, 1.028,
+                            1.032, 1.033, 1.035, 1.037, 1.039, 1.044, 1.047, 1.049, 1.053, 1.055, 1.056, 1.058, 1.059, 1.061, 1.061, 1.062, 1.061, 1.061, 1.059, 1.058, 1.057, 1.054, 1.053, 1.051, 1.048, 1.044, 1.041, 1.038, 1.034, 1.032, 1.029, 1.028,
+                            1.035, 1.035, 1.037, 1.041, 1.043, 1.046, 1.049, 1.052, 1.055, 1.057, 1.059, 1.061, 1.062, 1.063, 1.063, 1.064, 1.063, 1.062, 1.062, 1.059, 1.059, 1.056, 1.055, 1.053, 1.049, 1.046, 1.043, 1.039, 1.037, 1.034, 1.031, 1.031,
+                            1.036, 1.037, 1.039, 1.042, 1.045, 1.048, 1.049, 1.053, 1.056, 1.059, 1.061, 1.062, 1.063, 1.064, 1.065, 1.065, 1.065, 1.064, 1.063, 1.062, 1.061, 1.058, 1.057, 1.054, 1.052, 1.048, 1.044, 1.041, 1.039, 1.034, 1.034, 1.032,
+                            1.037, 1.038, 1.041, 1.043, 1.046, 1.048, 1.051, 1.054, 1.058, 1.059, 1.062, 1.064, 1.065, 1.066, 1.066, 1.067, 1.067, 1.066, 1.065, 1.064, 1.062, 1.059, 1.058, 1.055, 1.052, 1.049, 1.045, 1.042, 1.039, 1.036, 1.034, 1.032,
+                            1.037, 1.038, 1.039, 1.043, 1.046, 1.049, 1.052, 1.056, 1.058, 1.059, 1.063, 1.065, 1.066, 1.068, 1.068, 1.068, 1.067, 1.067, 1.066, 1.064, 1.062, 1.061, 1.059, 1.056, 1.054, 1.051, 1.047, 1.044, 1.039, 1.036, 1.034, 1.033,
+                            1.036, 1.037, 1.039, 1.044, 1.047, 1.049, 1.053, 1.055, 1.058, 1.061, 1.062, 1.064, 1.066, 1.067, 1.068, 1.068, 1.068, 1.067, 1.066, 1.065, 1.062, 1.061, 1.059, 1.057, 1.053, 1.051, 1.047, 1.043, 1.041, 1.036, 1.033, 1.033,
+                            1.035, 1.037, 1.041, 1.043, 1.046, 1.049, 1.053, 1.056, 1.057, 1.059, 1.061, 1.063, 1.065, 1.066, 1.067, 1.068, 1.067, 1.067, 1.066, 1.065, 1.062, 1.059, 1.057, 1.056, 1.053, 1.049, 1.047, 1.043, 1.039, 1.036, 1.033, 1.032,
+                            1.034, 1.036, 1.039, 1.042, 1.046, 1.049, 1.052, 1.055, 1.057, 1.059, 1.061, 1.062, 1.063, 1.065, 1.067, 1.067, 1.067, 1.066, 1.065, 1.063, 1.062, 1.059, 1.057, 1.054, 1.051, 1.049, 1.046, 1.042, 1.038, 1.034, 1.032, 1.031,
+                            1.034, 1.036, 1.038, 1.042, 1.046, 1.049, 1.052, 1.054, 1.057, 1.059, 1.062, 1.063, 1.063, 1.065, 1.067, 1.067, 1.067, 1.066, 1.065, 1.063, 1.062, 1.059, 1.057, 1.055, 1.051, 1.048, 1.045, 1.041, 1.038, 1.034, 1.031, 1.029,
+                            1.035, 1.036, 1.039, 1.042, 1.047, 1.049, 1.053, 1.055, 1.057, 1.061, 1.062, 1.062, 1.064, 1.066, 1.067, 1.068, 1.067, 1.066, 1.065, 1.063, 1.062, 1.059, 1.057, 1.055, 1.052, 1.049, 1.046, 1.041, 1.038, 1.035, 1.031, 1.029,
+                            1.033, 1.037, 1.039, 1.044, 1.047, 1.051, 1.054, 1.057, 1.059, 1.061, 1.063, 1.064, 1.066, 1.067, 1.068, 1.068, 1.067, 1.066, 1.065, 1.064, 1.062, 1.061, 1.058, 1.055, 1.053, 1.051, 1.047, 1.043, 1.039, 1.035, 1.031, 1.031,
+                            1.036, 1.038, 1.039, 1.044, 1.047, 1.051, 1.055, 1.058, 1.061, 1.062, 1.064, 1.065, 1.066, 1.068, 1.069, 1.069, 1.069, 1.067, 1.067, 1.065, 1.063, 1.061, 1.058, 1.056, 1.053, 1.051, 1.047, 1.044, 1.041, 1.037, 1.033, 1.031,
+                            1.038, 1.038, 1.041, 1.045, 1.048, 1.051, 1.055, 1.058, 1.061, 1.063, 1.064, 1.066, 1.067, 1.069, 1.069, 1.069, 1.069, 1.068, 1.068, 1.066, 1.063, 1.062, 1.059, 1.057, 1.054, 1.052, 1.048, 1.044, 1.041, 1.037, 1.034, 1.033,
+                            1.039, 1.039, 1.043, 1.046, 1.047, 1.051, 1.055, 1.058, 1.061, 1.064, 1.065, 1.066, 1.068, 1.069, 1.071, 1.071, 1.069, 1.069, 1.068, 1.066, 1.064, 1.061, 1.059, 1.057, 1.055, 1.053, 1.049, 1.045, 1.041, 1.038, 1.034, 1.033,
+                            1.036, 1.039, 1.044, 1.045, 1.048, 1.052, 1.055, 1.058, 1.061, 1.063, 1.065, 1.067, 1.068, 1.069, 1.071, 1.071, 1.071, 1.069, 1.067, 1.065, 1.063, 1.061, 1.059, 1.057, 1.055, 1.052, 1.048, 1.045, 1.041, 1.038, 1.034, 1.032,
+                            1.036, 1.038, 1.041, 1.044, 1.047, 1.051, 1.053, 1.057, 1.059, 1.062, 1.064, 1.066, 1.067, 1.068, 1.069, 1.069, 1.069, 1.068, 1.067, 1.065, 1.062, 1.059, 1.057, 1.056, 1.053, 1.049, 1.047, 1.043, 1.039, 1.037, 1.033, 1.031,
+                            1.035, 1.036, 1.039, 1.043, 1.046, 1.049, 1.053, 1.055, 1.057, 1.059, 1.062, 1.064, 1.066, 1.067, 1.067, 1.068, 1.068, 1.066, 1.065, 1.063, 1.061, 1.058, 1.055, 1.054, 1.051, 1.048, 1.045, 1.043, 1.038, 1.035, 1.031, 1.029,
+                            1.032, 1.035, 1.037, 1.041, 1.043, 1.047, 1.051, 1.053, 1.055, 1.058, 1.059, 1.061, 1.063, 1.065, 1.065, 1.065, 1.064, 1.063, 1.062, 1.061, 1.058, 1.056, 1.054, 1.051, 1.048, 1.045, 1.043, 1.041, 1.037, 1.033, 1.028, 1.028,
+                            1.029, 1.032, 1.035, 1.039, 1.042, 1.044, 1.047, 1.051, 1.053, 1.056, 1.057, 1.058, 1.059, 1.061, 1.062, 1.062, 1.062, 1.061, 1.059, 1.058, 1.056, 1.054, 1.051, 1.049, 1.045, 1.044, 1.041, 1.037, 1.035, 1.031, 1.026, 1.024,
+                            1.028, 1.029, 1.034, 1.036, 1.039, 1.044, 1.046, 1.049, 1.051, 1.053, 1.056, 1.057, 1.058, 1.059, 1.059, 1.059, 1.059, 1.058, 1.058, 1.056, 1.054, 1.051, 1.049, 1.047, 1.045, 1.042, 1.039, 1.035, 1.032, 1.028, 1.023, 1.022,
+                            1.026, 1.029, 1.032, 1.035, 1.038, 1.041, 1.045, 1.047, 1.049, 1.051, 1.053, 1.054, 1.056, 1.057, 1.057, 1.057, 1.057, 1.056, 1.055, 1.054, 1.052, 1.049, 1.048, 1.046, 1.043, 1.041, 1.037, 1.033, 1.029, 1.025, 1.023, 1.022,
+                            1.027, 1.028, 1.031, 1.034, 1.038, 1.041, 1.043, 1.045, 1.048, 1.049, 1.052, 1.053, 1.055, 1.055, 1.055, 1.056, 1.055, 1.055, 1.054, 1.052, 1.051, 1.049, 1.047, 1.044, 1.042, 1.039, 1.035, 1.033, 1.029, 1.026, 1.023, 1.022,
+                            1.026, 1.028, 1.029, 1.034, 1.037, 1.041, 1.043, 1.044, 1.047, 1.049, 1.051, 1.053, 1.053, 1.054, 1.054, 1.055, 1.054, 1.054, 1.053, 1.051, 1.051, 1.048, 1.046, 1.044, 1.041, 1.038, 1.036, 1.032, 1.029, 1.026, 1.025, 1.023,
+                            1.026, 1.027, 1.029, 1.033, 1.036, 1.041, 1.042, 1.044, 1.046, 1.047, 1.049, 1.051, 1.052, 1.053, 1.053, 1.053, 1.053, 1.053, 1.052, 1.051, 1.049, 1.047, 1.045, 1.044, 1.041, 1.039, 1.036, 1.033, 1.029, 1.026, 1.023, 1.023,
+                            1.025, 1.028, 1.029, 1.032, 1.035, 1.037, 1.041, 1.042, 1.044, 1.046, 1.047, 1.049, 1.049, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.049, 1.047, 1.046, 1.044, 1.042, 1.039, 1.037, 1.034, 1.031, 1.027, 1.025, 1.023, 1.021,
+                            1.025, 1.026, 1.028, 1.031, 1.033, 1.035, 1.037, 1.041, 1.042, 1.044, 1.046, 1.047, 1.048, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.047, 1.045, 1.045, 1.042, 1.041, 1.037, 1.035, 1.032, 1.029, 1.026, 1.023, 1.021, 1.021,
+                            1.024, 1.025, 1.026, 1.028, 1.031, 1.032, 1.034, 1.038, 1.041, 1.041, 1.042, 1.044, 1.046, 1.047, 1.047, 1.047, 1.046, 1.045, 1.044, 1.043, 1.042, 1.041, 1.039, 1.038, 1.035, 1.032, 1.029, 1.027, 1.023, 1.022, 1.019, 1.019,
+                            1.021, 1.022, 1.023, 1.024, 1.027, 1.031, 1.032, 1.035, 1.037, 1.039, 1.039, 1.041, 1.042, 1.043, 1.043, 1.043, 1.043, 1.042, 1.041, 1.039, 1.039, 1.038, 1.036, 1.034, 1.032, 1.029, 1.026, 1.024, 1.021, 1.019, 1.017, 1.015,
+                            1.019, 1.018, 1.018, 1.021, 1.024, 1.026, 1.028, 1.031, 1.033, 1.034, 1.036, 1.037, 1.038, 1.039, 1.039, 1.038, 1.038, 1.038, 1.037, 1.036, 1.035, 1.033, 1.032, 1.029, 1.028, 1.025, 1.023, 1.021, 1.018, 1.016, 1.015, 1.013,
+                            1.016, 1.014, 1.015, 1.018, 1.019, 1.022, 1.025, 1.028, 1.029, 1.032, 1.033, 1.033, 1.034, 1.035, 1.035, 1.035, 1.035, 1.035, 1.035, 1.033, 1.031, 1.031, 1.029, 1.027, 1.025, 1.022, 1.021, 1.018, 1.014, 1.014, 1.013, 1.011,
+                            1.016, 1.012, 1.013, 1.015, 1.016, 1.019, 1.023, 1.025, 1.029, 1.029, 1.031, 1.031, 1.032, 1.033, 1.033, 1.033, 1.034, 1.034, 1.033, 1.031, 1.029, 1.029, 1.027, 1.025, 1.022, 1.021, 1.018, 1.015, 1.013, 1.011, 1.009, 1.011
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.026, 1.026, 1.027, 1.029, 1.032, 1.035, 1.038, 1.041, 1.042, 1.043, 1.045, 1.046, 1.047, 1.047, 1.048, 1.049, 1.049, 1.048, 1.047, 1.047, 1.046, 1.045, 1.043, 1.042, 1.041, 1.037, 1.036, 1.033, 1.031, 1.027, 1.025, 1.025,
+                            1.025, 1.027, 1.028, 1.029, 1.032, 1.035, 1.038, 1.041, 1.042, 1.044, 1.045, 1.046, 1.046, 1.048, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.046, 1.046, 1.044, 1.042, 1.041, 1.038, 1.036, 1.033, 1.031, 1.029, 1.026, 1.024,
+                            1.027, 1.027, 1.029, 1.031, 1.034, 1.036, 1.039, 1.041, 1.044, 1.045, 1.046, 1.046, 1.047, 1.049, 1.051, 1.051, 1.049, 1.049, 1.049, 1.048, 1.047, 1.047, 1.045, 1.043, 1.042, 1.039, 1.037, 1.034, 1.031, 1.029, 1.028, 1.025,
+                            1.026, 1.028, 1.031, 1.032, 1.035, 1.036, 1.039, 1.041, 1.044, 1.045, 1.046, 1.047, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.046, 1.043, 1.042, 1.039, 1.038, 1.035, 1.033, 1.029, 1.028, 1.027,
+                            1.028, 1.029, 1.031, 1.034, 1.035, 1.038, 1.039, 1.041, 1.044, 1.045, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.041, 1.039, 1.037, 1.034, 1.031, 1.029, 1.027,
+                            1.029, 1.031, 1.032, 1.034, 1.037, 1.039, 1.041, 1.043, 1.044, 1.046, 1.048, 1.049, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.046, 1.045, 1.042, 1.039, 1.038, 1.035, 1.032, 1.029, 1.029,
+                            1.031, 1.031, 1.033, 1.036, 1.038, 1.041, 1.042, 1.044, 1.045, 1.046, 1.048, 1.049, 1.052, 1.053, 1.053, 1.053, 1.053, 1.053, 1.053, 1.052, 1.051, 1.049, 1.049, 1.047, 1.045, 1.044, 1.042, 1.039, 1.035, 1.032, 1.031, 1.031,
+                            1.031, 1.033, 1.034, 1.037, 1.039, 1.041, 1.043, 1.045, 1.046, 1.047, 1.049, 1.051, 1.051, 1.053, 1.054, 1.054, 1.054, 1.054, 1.053, 1.053, 1.052, 1.051, 1.049, 1.047, 1.047, 1.044, 1.042, 1.041, 1.036, 1.035, 1.032, 1.029,
+                            1.032, 1.033, 1.035, 1.037, 1.039, 1.041, 1.043, 1.045, 1.047, 1.048, 1.049, 1.051, 1.051, 1.052, 1.053, 1.054, 1.054, 1.054, 1.054, 1.053, 1.051, 1.051, 1.049, 1.048, 1.046, 1.045, 1.043, 1.041, 1.037, 1.034, 1.033, 1.029,
+                            1.031, 1.032, 1.035, 1.037, 1.039, 1.041, 1.043, 1.045, 1.047, 1.048, 1.051, 1.051, 1.051, 1.052, 1.053, 1.054, 1.054, 1.054, 1.054, 1.053, 1.052, 1.051, 1.049, 1.047, 1.046, 1.045, 1.043, 1.041, 1.037, 1.035, 1.032, 1.031,
+                            1.031, 1.032, 1.035, 1.038, 1.041, 1.042, 1.044, 1.046, 1.047, 1.049, 1.049, 1.051, 1.051, 1.052, 1.053, 1.054, 1.054, 1.054, 1.053, 1.052, 1.052, 1.051, 1.049, 1.047, 1.046, 1.045, 1.042, 1.041, 1.037, 1.034, 1.031, 1.029,
+                            1.031, 1.032, 1.034, 1.037, 1.041, 1.042, 1.044, 1.046, 1.047, 1.049, 1.049, 1.051, 1.051, 1.052, 1.053, 1.053, 1.053, 1.053, 1.053, 1.052, 1.051, 1.049, 1.048, 1.047, 1.046, 1.044, 1.042, 1.039, 1.037, 1.034, 1.031, 1.029,
+                            1.031, 1.032, 1.034, 1.037, 1.038, 1.041, 1.044, 1.046, 1.047, 1.049, 1.049, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.053, 1.052, 1.052, 1.051, 1.049, 1.048, 1.047, 1.045, 1.044, 1.041, 1.039, 1.036, 1.034, 1.029, 1.028,
+                            1.029, 1.031, 1.033, 1.036, 1.039, 1.041, 1.043, 1.045, 1.047, 1.048, 1.049, 1.051, 1.052, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.042, 1.039, 1.036, 1.033, 1.031, 1.029,
+                            1.029, 1.031, 1.034, 1.036, 1.038, 1.041, 1.042, 1.045, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.054, 1.054, 1.053, 1.052, 1.052, 1.051, 1.051, 1.049, 1.047, 1.047, 1.045, 1.043, 1.041, 1.039, 1.036, 1.034, 1.029, 1.029,
+                            1.028, 1.031, 1.034, 1.036, 1.039, 1.041, 1.042, 1.045, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.054, 1.055, 1.054, 1.053, 1.052, 1.051, 1.051, 1.049, 1.047, 1.046, 1.045, 1.043, 1.041, 1.038, 1.036, 1.033, 1.031, 1.029,
+                            1.028, 1.031, 1.033, 1.036, 1.038, 1.041, 1.043, 1.044, 1.047, 1.048, 1.049, 1.051, 1.052, 1.052, 1.054, 1.055, 1.054, 1.053, 1.052, 1.051, 1.049, 1.048, 1.047, 1.046, 1.044, 1.042, 1.041, 1.038, 1.036, 1.034, 1.031, 1.029,
+                            1.029, 1.031, 1.032, 1.035, 1.038, 1.039, 1.043, 1.045, 1.046, 1.048, 1.049, 1.049, 1.051, 1.052, 1.053, 1.054, 1.054, 1.053, 1.052, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.042, 1.041, 1.038, 1.037, 1.034, 1.031, 1.029,
+                            1.028, 1.029, 1.033, 1.034, 1.037, 1.039, 1.042, 1.044, 1.045, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.053, 1.052, 1.051, 1.049, 1.049, 1.047, 1.045, 1.044, 1.043, 1.041, 1.039, 1.038, 1.035, 1.033, 1.029, 1.028,
+                            1.027, 1.031, 1.031, 1.033, 1.036, 1.038, 1.041, 1.043, 1.045, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.047, 1.046, 1.044, 1.043, 1.042, 1.041, 1.039, 1.037, 1.034, 1.031, 1.029, 1.026,
+                            1.026, 1.028, 1.029, 1.032, 1.035, 1.037, 1.039, 1.042, 1.043, 1.045, 1.046, 1.047, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.044, 1.043, 1.042, 1.041, 1.039, 1.037, 1.035, 1.032, 1.029, 1.026, 1.026,
+                            1.026, 1.027, 1.028, 1.032, 1.033, 1.036, 1.038, 1.041, 1.042, 1.043, 1.045, 1.045, 1.046, 1.047, 1.047, 1.048, 1.048, 1.047, 1.047, 1.046, 1.045, 1.043, 1.042, 1.041, 1.039, 1.038, 1.035, 1.033, 1.032, 1.028, 1.025, 1.024,
+                            1.024, 1.024, 1.027, 1.029, 1.032, 1.034, 1.036, 1.038, 1.039, 1.042, 1.043, 1.044, 1.044, 1.045, 1.045, 1.045, 1.046, 1.045, 1.045, 1.044, 1.043, 1.042, 1.041, 1.039, 1.038, 1.036, 1.033, 1.032, 1.029, 1.026, 1.023, 1.023,
+                            1.022, 1.023, 1.026, 1.027, 1.031, 1.033, 1.035, 1.036, 1.038, 1.039, 1.041, 1.042, 1.043, 1.043, 1.044, 1.044, 1.044, 1.044, 1.043, 1.043, 1.042, 1.041, 1.039, 1.038, 1.036, 1.035, 1.033, 1.031, 1.028, 1.025, 1.022, 1.022,
+                            1.021, 1.022, 1.024, 1.026, 1.029, 1.032, 1.033, 1.035, 1.036, 1.038, 1.039, 1.041, 1.041, 1.042, 1.042, 1.043, 1.043, 1.042, 1.042, 1.041, 1.039, 1.039, 1.038, 1.036, 1.035, 1.034, 1.032, 1.029, 1.026, 1.023, 1.021, 1.021,
+                            1.019, 1.021, 1.023, 1.025, 1.029, 1.031, 1.031, 1.034, 1.035, 1.037, 1.038, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.038, 1.037, 1.036, 1.034, 1.033, 1.031, 1.028, 1.025, 1.022, 1.019, 1.019,
+                            1.019, 1.021, 1.022, 1.023, 1.027, 1.028, 1.031, 1.033, 1.034, 1.036, 1.036, 1.037, 1.039, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.038, 1.038, 1.037, 1.036, 1.035, 1.032, 1.031, 1.029, 1.027, 1.023, 1.021, 1.018, 1.018,
+                            1.018, 1.018, 1.019, 1.021, 1.024, 1.027, 1.028, 1.031, 1.033, 1.035, 1.036, 1.036, 1.037, 1.038, 1.039, 1.039, 1.038, 1.038, 1.037, 1.037, 1.036, 1.036, 1.035, 1.033, 1.032, 1.029, 1.027, 1.024, 1.022, 1.019, 1.017, 1.017,
+                            1.016, 1.017, 1.019, 1.021, 1.021, 1.025, 1.027, 1.029, 1.032, 1.033, 1.034, 1.036, 1.036, 1.036, 1.037, 1.037, 1.036, 1.036, 1.036, 1.036, 1.035, 1.034, 1.033, 1.031, 1.031, 1.028, 1.026, 1.024, 1.019, 1.018, 1.016, 1.015,
+                            1.013, 1.015, 1.016, 1.019, 1.019, 1.022, 1.025, 1.027, 1.029, 1.031, 1.032, 1.034, 1.035, 1.035, 1.035, 1.036, 1.036, 1.036, 1.035, 1.035, 1.035, 1.033, 1.032, 1.029, 1.029, 1.027, 1.025, 1.022, 1.019, 1.017, 1.015, 1.016,
+                            1.015, 1.013, 1.013, 1.017, 1.019, 1.021, 1.022, 1.026, 1.027, 1.029, 1.031, 1.031, 1.032, 1.032, 1.032, 1.033, 1.034, 1.034, 1.034, 1.033, 1.032, 1.031, 1.029, 1.029, 1.027, 1.025, 1.023, 1.019, 1.018, 1.016, 1.016, 1.014,
+                            1.016, 1.013, 1.013, 1.013, 1.016, 1.019, 1.021, 1.024, 1.027, 1.028, 1.031, 1.031, 1.031, 1.032, 1.032, 1.032, 1.032, 1.033, 1.032, 1.032, 1.031, 1.031, 1.029, 1.028, 1.026, 1.024, 1.021, 1.018, 1.017, 1.016, 1.014, 1.014
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.014, 1.016, 1.018, 1.021, 1.025, 1.028, 1.029, 1.033, 1.034, 1.036, 1.038, 1.039, 1.039, 1.041, 1.042, 1.043, 1.043, 1.042, 1.042, 1.041, 1.038, 1.038, 1.036, 1.034, 1.033, 1.029, 1.028, 1.026, 1.023, 1.019, 1.016, 1.014,
+                            1.016, 1.017, 1.019, 1.021, 1.024, 1.027, 1.031, 1.033, 1.035, 1.037, 1.038, 1.039, 1.039, 1.041, 1.041, 1.043, 1.043, 1.042, 1.041, 1.041, 1.039, 1.038, 1.036, 1.035, 1.033, 1.031, 1.028, 1.025, 1.022, 1.018, 1.017, 1.016,
+                            1.015, 1.017, 1.019, 1.022, 1.025, 1.027, 1.031, 1.033, 1.035, 1.036, 1.038, 1.039, 1.041, 1.041, 1.042, 1.043, 1.042, 1.042, 1.041, 1.041, 1.039, 1.038, 1.037, 1.035, 1.032, 1.031, 1.029, 1.025, 1.023, 1.021, 1.018, 1.017,
+                            1.016, 1.017, 1.021, 1.023, 1.026, 1.028, 1.031, 1.033, 1.035, 1.037, 1.038, 1.041, 1.041, 1.042, 1.042, 1.043, 1.043, 1.043, 1.042, 1.041, 1.039, 1.039, 1.037, 1.036, 1.033, 1.031, 1.029, 1.025, 1.023, 1.019, 1.019, 1.017,
+                            1.017, 1.019, 1.021, 1.024, 1.027, 1.029, 1.031, 1.034, 1.036, 1.038, 1.039, 1.041, 1.042, 1.043, 1.043, 1.044, 1.044, 1.044, 1.043, 1.042, 1.041, 1.041, 1.039, 1.037, 1.035, 1.033, 1.029, 1.027, 1.024, 1.022, 1.019, 1.018,
+                            1.019, 1.021, 1.023, 1.026, 1.029, 1.031, 1.033, 1.035, 1.037, 1.039, 1.041, 1.042, 1.044, 1.045, 1.045, 1.046, 1.045, 1.045, 1.044, 1.043, 1.043, 1.041, 1.039, 1.038, 1.037, 1.034, 1.032, 1.029, 1.025, 1.023, 1.021, 1.019,
+                            1.022, 1.023, 1.026, 1.029, 1.032, 1.033, 1.036, 1.037, 1.039, 1.041, 1.042, 1.045, 1.046, 1.047, 1.048, 1.048, 1.048, 1.047, 1.047, 1.046, 1.045, 1.043, 1.042, 1.041, 1.039, 1.037, 1.034, 1.031, 1.028, 1.025, 1.023, 1.021,
+                            1.023, 1.025, 1.028, 1.031, 1.033, 1.036, 1.037, 1.039, 1.042, 1.043, 1.044, 1.046, 1.047, 1.048, 1.049, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.045, 1.043, 1.042, 1.041, 1.038, 1.036, 1.033, 1.031, 1.028, 1.025, 1.023,
+                            1.025, 1.027, 1.031, 1.032, 1.035, 1.037, 1.039, 1.041, 1.043, 1.044, 1.045, 1.047, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.041, 1.039, 1.038, 1.035, 1.032, 1.029, 1.025, 1.025,
+                            1.025, 1.027, 1.031, 1.033, 1.035, 1.038, 1.039, 1.042, 1.043, 1.045, 1.047, 1.048, 1.049, 1.049, 1.051, 1.052, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.046, 1.044, 1.042, 1.039, 1.038, 1.036, 1.033, 1.029, 1.027, 1.025,
+                            1.025, 1.027, 1.031, 1.033, 1.035, 1.038, 1.041, 1.041, 1.044, 1.045, 1.047, 1.048, 1.049, 1.049, 1.051, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.047, 1.046, 1.044, 1.042, 1.039, 1.037, 1.035, 1.033, 1.029, 1.027, 1.026,
+                            1.024, 1.026, 1.029, 1.032, 1.035, 1.037, 1.039, 1.042, 1.044, 1.045, 1.046, 1.047, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.044, 1.043, 1.041, 1.039, 1.037, 1.034, 1.032, 1.028, 1.026, 1.024,
+                            1.024, 1.025, 1.027, 1.031, 1.033, 1.036, 1.039, 1.041, 1.043, 1.044, 1.045, 1.046, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.045, 1.044, 1.042, 1.041, 1.038, 1.036, 1.033, 1.029, 1.027, 1.024, 1.022,
+                            1.022, 1.024, 1.026, 1.029, 1.032, 1.035, 1.038, 1.041, 1.042, 1.043, 1.045, 1.046, 1.048, 1.048, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.039, 1.038, 1.035, 1.032, 1.029, 1.026, 1.024, 1.021,
+                            1.022, 1.023, 1.026, 1.029, 1.031, 1.034, 1.037, 1.039, 1.042, 1.043, 1.045, 1.046, 1.047, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.046, 1.045, 1.044, 1.042, 1.041, 1.039, 1.037, 1.034, 1.032, 1.029, 1.026, 1.023, 1.021,
+                            1.022, 1.023, 1.026, 1.029, 1.032, 1.034, 1.037, 1.039, 1.041, 1.043, 1.044, 1.046, 1.047, 1.049, 1.049, 1.051, 1.051, 1.049, 1.048, 1.046, 1.045, 1.044, 1.042, 1.041, 1.039, 1.038, 1.034, 1.032, 1.029, 1.026, 1.023, 1.022,
+                            1.021, 1.024, 1.027, 1.029, 1.032, 1.034, 1.037, 1.039, 1.041, 1.043, 1.045, 1.046, 1.048, 1.049, 1.049, 1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.044, 1.043, 1.041, 1.039, 1.037, 1.035, 1.032, 1.031, 1.027, 1.024, 1.021,
+                            1.022, 1.024, 1.027, 1.031, 1.033, 1.035, 1.037, 1.041, 1.042, 1.044, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.046, 1.044, 1.043, 1.041, 1.039, 1.038, 1.036, 1.033, 1.031, 1.027, 1.024, 1.022,
+                            1.023, 1.025, 1.027, 1.031, 1.033, 1.035, 1.038, 1.041, 1.042, 1.044, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.046, 1.044, 1.043, 1.041, 1.039, 1.037, 1.036, 1.034, 1.031, 1.027, 1.024, 1.022,
+                            1.023, 1.025, 1.028, 1.029, 1.033, 1.035, 1.038, 1.041, 1.043, 1.044, 1.046, 1.047, 1.047, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.046, 1.045, 1.042, 1.041, 1.039, 1.037, 1.036, 1.033, 1.029, 1.027, 1.025, 1.023,
+                            1.021, 1.024, 1.026, 1.029, 1.033, 1.035, 1.036, 1.039, 1.041, 1.043, 1.044, 1.045, 1.046, 1.047, 1.049, 1.049, 1.049, 1.048, 1.048, 1.046, 1.045, 1.043, 1.041, 1.041, 1.038, 1.037, 1.035, 1.032, 1.029, 1.026, 1.024, 1.022,
+                            1.019, 1.022, 1.025, 1.027, 1.031, 1.033, 1.035, 1.038, 1.039, 1.041, 1.043, 1.044, 1.044, 1.045, 1.046, 1.047, 1.047, 1.046, 1.045, 1.044, 1.043, 1.041, 1.041, 1.039, 1.037, 1.034, 1.032, 1.031, 1.027, 1.025, 1.022, 1.021,
+                            1.018, 1.019, 1.023, 1.025, 1.028, 1.031, 1.033, 1.036, 1.037, 1.039, 1.039, 1.041, 1.042, 1.043, 1.044, 1.043, 1.043, 1.042, 1.042, 1.042, 1.041, 1.039, 1.038, 1.037, 1.035, 1.032, 1.031, 1.028, 1.025, 1.022, 1.019, 1.018,
+                            1.015, 1.017, 1.019, 1.024, 1.026, 1.028, 1.031, 1.032, 1.034, 1.036, 1.037, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.038, 1.035, 1.034, 1.032, 1.031, 1.028, 1.025, 1.023, 1.021, 1.018, 1.016,
+                            1.013, 1.015, 1.018, 1.021, 1.023, 1.026, 1.028, 1.029, 1.032, 1.033, 1.035, 1.036, 1.038, 1.038, 1.038, 1.038, 1.038, 1.038, 1.037, 1.037, 1.037, 1.035, 1.034, 1.032, 1.031, 1.029, 1.027, 1.024, 1.021, 1.018, 1.015, 1.014,
+                            1.012, 1.014, 1.016, 1.019, 1.022, 1.024, 1.026, 1.028, 1.029, 1.032, 1.033, 1.034, 1.035, 1.036, 1.037, 1.037, 1.037, 1.036, 1.036, 1.035, 1.034, 1.033, 1.032, 1.031, 1.029, 1.027, 1.025, 1.021, 1.019, 1.016, 1.014, 1.012,
+                            1.011, 1.013, 1.015, 1.018, 1.019, 1.023, 1.025, 1.027, 1.029, 1.031, 1.032, 1.033, 1.034, 1.035, 1.036, 1.036, 1.035, 1.035, 1.034, 1.033, 1.033, 1.032, 1.031, 1.029, 1.028, 1.025, 1.023, 1.021, 1.017, 1.015, 1.012, 1.011,
+                            1.009, 1.012, 1.014, 1.016, 1.019, 1.022, 1.023, 1.026, 1.028, 1.029, 1.031, 1.032, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.033, 1.033, 1.032, 1.031, 1.031, 1.028, 1.026, 1.024, 1.022, 1.019, 1.016, 1.014, 1.011, 1.009,
+                            1.009, 1.011, 1.013, 1.016, 1.017, 1.021, 1.023, 1.024, 1.027, 1.029, 1.031, 1.031, 1.033, 1.033, 1.033, 1.033, 1.033, 1.033, 1.033, 1.032, 1.031, 1.031, 1.029, 1.027, 1.026, 1.023, 1.021, 1.018, 1.016, 1.013, 1.011, 1.009,
+                            1.007, 1.009, 1.011, 1.014, 1.017, 1.019, 1.022, 1.024, 1.026, 1.028, 1.029, 1.031, 1.032, 1.032, 1.033, 1.033, 1.034, 1.033, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.025, 1.023, 1.021, 1.018, 1.015, 1.013, 1.009, 1.009,
+                            1.007, 1.007, 1.009, 1.013, 1.016, 1.018, 1.019, 1.023, 1.025, 1.026, 1.028, 1.029, 1.029, 1.031, 1.031, 1.031, 1.032, 1.032, 1.032, 1.031, 1.029, 1.029, 1.028, 1.026, 1.024, 1.022, 1.019, 1.016, 1.014, 1.012, 1.009, 1.008,
+                            1.007, 1.007, 1.009, 1.012, 1.013, 1.017, 1.019, 1.022, 1.025, 1.026, 1.026, 1.028, 1.029, 1.029, 1.028, 1.029, 1.031, 1.031, 1.031, 1.031, 1.029, 1.027, 1.027, 1.025, 1.023, 1.022, 1.019, 1.016, 1.014, 1.011, 1.008, 1.007
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.015, 1.016, 1.019, 1.022, 1.026, 1.029, 1.032, 1.035, 1.037, 1.039, 1.039, 1.041, 1.043, 1.044, 1.044, 1.045, 1.045, 1.044, 1.044, 1.043, 1.042, 1.041, 1.039, 1.038, 1.036, 1.033, 1.029, 1.027, 1.025, 1.021, 1.017, 1.016,
+                            1.016, 1.017, 1.021, 1.024, 1.026, 1.029, 1.033, 1.036, 1.038, 1.039, 1.042, 1.044, 1.044, 1.045, 1.045, 1.046, 1.046, 1.046, 1.045, 1.044, 1.043, 1.041, 1.041, 1.038, 1.036, 1.034, 1.031, 1.028, 1.026, 1.022, 1.019, 1.017,
+                            1.018, 1.021, 1.023, 1.025, 1.028, 1.031, 1.035, 1.037, 1.039, 1.042, 1.043, 1.045, 1.046, 1.047, 1.048, 1.048, 1.048, 1.047, 1.047, 1.046, 1.044, 1.043, 1.042, 1.039, 1.038, 1.035, 1.033, 1.029, 1.026, 1.024, 1.021, 1.019,
+                            1.019, 1.021, 1.024, 1.027, 1.029, 1.033, 1.036, 1.039, 1.041, 1.043, 1.045, 1.046, 1.048, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.046, 1.045, 1.044, 1.041, 1.039, 1.037, 1.035, 1.032, 1.029, 1.026, 1.023, 1.021,
+                            1.021, 1.022, 1.026, 1.029, 1.033, 1.035, 1.037, 1.041, 1.042, 1.044, 1.046, 1.047, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.047, 1.046, 1.045, 1.044, 1.041, 1.039, 1.036, 1.034, 1.031, 1.028, 1.024, 1.022,
+                            1.022, 1.025, 1.028, 1.031, 1.035, 1.036, 1.039, 1.042, 1.044, 1.046, 1.048, 1.049, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.052, 1.049, 1.049, 1.048, 1.047, 1.044, 1.043, 1.041, 1.038, 1.036, 1.031, 1.029, 1.025, 1.024,
+                            1.024, 1.027, 1.029, 1.032, 1.036, 1.038, 1.041, 1.043, 1.045, 1.046, 1.048, 1.051, 1.052, 1.053, 1.053, 1.054, 1.054, 1.054, 1.053, 1.052, 1.051, 1.049, 1.047, 1.046, 1.044, 1.042, 1.039, 1.037, 1.033, 1.031, 1.027, 1.025,
+                            1.026, 1.028, 1.031, 1.034, 1.037, 1.039, 1.042, 1.044, 1.046, 1.047, 1.049, 1.051, 1.052, 1.053, 1.054, 1.055, 1.055, 1.055, 1.054, 1.053, 1.052, 1.051, 1.048, 1.047, 1.046, 1.043, 1.041, 1.038, 1.034, 1.032, 1.028, 1.026,
+                            1.026, 1.028, 1.031, 1.034, 1.036, 1.039, 1.042, 1.044, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.054, 1.055, 1.055, 1.055, 1.055, 1.053, 1.052, 1.051, 1.049, 1.048, 1.046, 1.044, 1.041, 1.037, 1.035, 1.031, 1.029, 1.027,
+                            1.025, 1.028, 1.031, 1.034, 1.037, 1.041, 1.042, 1.044, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.055, 1.056, 1.056, 1.055, 1.055, 1.053, 1.052, 1.051, 1.049, 1.048, 1.046, 1.044, 1.041, 1.038, 1.035, 1.032, 1.029, 1.027,
+                            1.027, 1.028, 1.031, 1.035, 1.038, 1.041, 1.043, 1.045, 1.048, 1.049, 1.049, 1.051, 1.052, 1.054, 1.055, 1.056, 1.056, 1.056, 1.055, 1.053, 1.052, 1.051, 1.049, 1.048, 1.046, 1.044, 1.041, 1.039, 1.036, 1.032, 1.029, 1.027,
+                            1.026, 1.028, 1.031, 1.034, 1.038, 1.041, 1.043, 1.046, 1.048, 1.049, 1.051, 1.052, 1.053, 1.054, 1.055, 1.056, 1.056, 1.055, 1.054, 1.053, 1.052, 1.051, 1.049, 1.047, 1.046, 1.043, 1.041, 1.039, 1.035, 1.031, 1.027, 1.025,
+                            1.026, 1.027, 1.031, 1.033, 1.038, 1.041, 1.043, 1.046, 1.048, 1.049, 1.051, 1.053, 1.054, 1.055, 1.055, 1.055, 1.056, 1.055, 1.055, 1.053, 1.052, 1.051, 1.049, 1.048, 1.046, 1.043, 1.041, 1.039, 1.034, 1.032, 1.028, 1.026,
+                            1.025, 1.027, 1.031, 1.034, 1.037, 1.039, 1.043, 1.047, 1.048, 1.051, 1.051, 1.053, 1.055, 1.055, 1.057, 1.057, 1.056, 1.055, 1.055, 1.054, 1.053, 1.052, 1.049, 1.048, 1.046, 1.044, 1.042, 1.039, 1.035, 1.032, 1.029, 1.026,
+                            1.026, 1.028, 1.032, 1.035, 1.038, 1.041, 1.044, 1.046, 1.049, 1.051, 1.052, 1.054, 1.055, 1.057, 1.058, 1.058, 1.058, 1.057, 1.056, 1.055, 1.053, 1.052, 1.049, 1.048, 1.046, 1.044, 1.042, 1.039, 1.036, 1.032, 1.029, 1.027,
+                            1.026, 1.029, 1.032, 1.036, 1.038, 1.041, 1.044, 1.046, 1.048, 1.051, 1.052, 1.054, 1.056, 1.057, 1.058, 1.059, 1.058, 1.057, 1.056, 1.055, 1.054, 1.052, 1.051, 1.048, 1.046, 1.044, 1.042, 1.039, 1.036, 1.033, 1.029, 1.027,
+                            1.026, 1.028, 1.032, 1.036, 1.038, 1.041, 1.043, 1.047, 1.048, 1.051, 1.052, 1.054, 1.056, 1.057, 1.058, 1.059, 1.059, 1.057, 1.056, 1.055, 1.053, 1.052, 1.049, 1.048, 1.046, 1.044, 1.042, 1.039, 1.036, 1.033, 1.029, 1.028,
+                            1.026, 1.028, 1.031, 1.035, 1.038, 1.041, 1.044, 1.046, 1.048, 1.049, 1.052, 1.053, 1.055, 1.057, 1.057, 1.058, 1.058, 1.058, 1.056, 1.055, 1.053, 1.051, 1.049, 1.048, 1.046, 1.044, 1.041, 1.039, 1.036, 1.033, 1.029, 1.027,
+                            1.025, 1.027, 1.031, 1.033, 1.037, 1.041, 1.044, 1.046, 1.048, 1.049, 1.051, 1.052, 1.054, 1.056, 1.056, 1.057, 1.056, 1.056, 1.055, 1.054, 1.052, 1.051, 1.049, 1.046, 1.045, 1.043, 1.041, 1.039, 1.036, 1.033, 1.029, 1.026,
+                            1.024, 1.026, 1.029, 1.032, 1.036, 1.038, 1.042, 1.044, 1.046, 1.048, 1.049, 1.051, 1.053, 1.054, 1.055, 1.055, 1.055, 1.055, 1.054, 1.053, 1.051, 1.049, 1.047, 1.045, 1.043, 1.041, 1.041, 1.038, 1.034, 1.031, 1.027, 1.025,
+                            1.022, 1.024, 1.028, 1.031, 1.034, 1.037, 1.039, 1.043, 1.045, 1.047, 1.048, 1.049, 1.051, 1.051, 1.052, 1.052, 1.053, 1.053, 1.052, 1.051, 1.049, 1.047, 1.045, 1.044, 1.042, 1.041, 1.038, 1.035, 1.032, 1.028, 1.025, 1.024,
+                            1.021, 1.022, 1.024, 1.029, 1.032, 1.035, 1.038, 1.041, 1.043, 1.045, 1.046, 1.048, 1.048, 1.049, 1.051, 1.051, 1.051, 1.049, 1.049, 1.048, 1.047, 1.045, 1.044, 1.042, 1.041, 1.038, 1.036, 1.033, 1.029, 1.027, 1.024, 1.022,
+                            1.018, 1.021, 1.024, 1.027, 1.031, 1.033, 1.036, 1.039, 1.041, 1.043, 1.044, 1.046, 1.047, 1.047, 1.048, 1.048, 1.048, 1.048, 1.047, 1.046, 1.045, 1.044, 1.042, 1.041, 1.039, 1.036, 1.034, 1.032, 1.029, 1.025, 1.021, 1.021,
+                            1.016, 1.018, 1.022, 1.026, 1.028, 1.032, 1.034, 1.037, 1.039, 1.041, 1.042, 1.044, 1.045, 1.046, 1.046, 1.047, 1.046, 1.046, 1.045, 1.044, 1.044, 1.043, 1.041, 1.039, 1.037, 1.035, 1.033, 1.031, 1.027, 1.023, 1.021, 1.018,
+                            1.015, 1.017, 1.021, 1.024, 1.027, 1.029, 1.033, 1.035, 1.037, 1.039, 1.041, 1.042, 1.044, 1.044, 1.045, 1.045, 1.045, 1.045, 1.044, 1.043, 1.042, 1.041, 1.039, 1.037, 1.036, 1.035, 1.032, 1.028, 1.025, 1.022, 1.019, 1.017,
+                            1.015, 1.017, 1.019, 1.023, 1.026, 1.028, 1.031, 1.033, 1.035, 1.038, 1.039, 1.041, 1.042, 1.043, 1.043, 1.044, 1.044, 1.043, 1.042, 1.042, 1.041, 1.039, 1.038, 1.037, 1.036, 1.033, 1.031, 1.027, 1.024, 1.021, 1.018, 1.016,
+                            1.014, 1.016, 1.019, 1.021, 1.025, 1.026, 1.029, 1.033, 1.034, 1.036, 1.038, 1.039, 1.039, 1.041, 1.042, 1.042, 1.042, 1.041, 1.041, 1.041, 1.039, 1.039, 1.038, 1.036, 1.034, 1.031, 1.029, 1.026, 1.023, 1.021, 1.016, 1.015,
+                            1.012, 1.014, 1.018, 1.021, 1.023, 1.026, 1.028, 1.031, 1.033, 1.034, 1.036, 1.038, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.037, 1.034, 1.033, 1.029, 1.028, 1.024, 1.021, 1.019, 1.015, 1.013,
+                            1.011, 1.013, 1.015, 1.018, 1.021, 1.023, 1.026, 1.028, 1.031, 1.032, 1.034, 1.036, 1.037, 1.037, 1.038, 1.038, 1.038, 1.038, 1.038, 1.037, 1.037, 1.036, 1.035, 1.033, 1.031, 1.029, 1.026, 1.022, 1.019, 1.017, 1.014, 1.011,
+                            1.008, 1.011, 1.012, 1.016, 1.018, 1.021, 1.024, 1.027, 1.028, 1.031, 1.031, 1.033, 1.034, 1.035, 1.035, 1.036, 1.037, 1.037, 1.035, 1.035, 1.034, 1.033, 1.032, 1.031, 1.028, 1.026, 1.024, 1.021, 1.018, 1.014, 1.012, 1.009,
+                            1.005, 1.007, 1.011, 1.013, 1.016, 1.018, 1.021, 1.024, 1.026, 1.027, 1.029, 1.031, 1.031, 1.032, 1.033, 1.033, 1.033, 1.034, 1.033, 1.033, 1.032, 1.031, 1.029, 1.028, 1.026, 1.024, 1.021, 1.018, 1.015, 1.012, 1.009, 1.007,
+                            1.005, 1.005, 1.007, 1.011, 1.013, 1.016, 1.019, 1.022, 1.024, 1.026, 1.028, 1.031, 1.031, 1.031, 1.032, 1.032, 1.032, 1.032, 1.031, 1.031, 1.031, 1.029, 1.028, 1.026, 1.024, 1.022, 1.018, 1.016, 1.014, 1.009, 1.008, 1.006
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.006, 1.007, 1.012, 1.015, 1.019, 1.022, 1.025, 1.028, 1.031, 1.033, 1.034, 1.036, 1.038, 1.039, 1.039, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.036, 1.034, 1.032, 1.029, 1.028, 1.024, 1.021, 1.017, 1.015, 1.011, 1.011,
+                            1.006, 1.009, 1.013, 1.016, 1.019, 1.023, 1.027, 1.029, 1.032, 1.034, 1.035, 1.037, 1.038, 1.039, 1.039, 1.041, 1.041, 1.039, 1.039, 1.039, 1.038, 1.037, 1.035, 1.033, 1.031, 1.028, 1.025, 1.021, 1.018, 1.015, 1.012, 1.011,
+                            1.008, 1.011, 1.014, 1.017, 1.021, 1.024, 1.027, 1.031, 1.032, 1.035, 1.036, 1.038, 1.039, 1.041, 1.041, 1.042, 1.042, 1.041, 1.041, 1.039, 1.039, 1.037, 1.036, 1.034, 1.032, 1.029, 1.026, 1.022, 1.019, 1.016, 1.013, 1.011,
+                            1.008, 1.011, 1.014, 1.018, 1.021, 1.024, 1.027, 1.031, 1.033, 1.035, 1.037, 1.039, 1.039, 1.041, 1.043, 1.043, 1.043, 1.042, 1.042, 1.041, 1.039, 1.039, 1.037, 1.035, 1.032, 1.029, 1.027, 1.023, 1.021, 1.017, 1.014, 1.012,
+                            1.009, 1.012, 1.016, 1.019, 1.022, 1.026, 1.028, 1.031, 1.034, 1.036, 1.039, 1.041, 1.042, 1.043, 1.043, 1.044, 1.044, 1.044, 1.043, 1.043, 1.041, 1.041, 1.039, 1.036, 1.034, 1.031, 1.028, 1.025, 1.022, 1.018, 1.016, 1.013,
+                            1.012, 1.014, 1.017, 1.022, 1.025, 1.028, 1.031, 1.033, 1.036, 1.039, 1.041, 1.042, 1.044, 1.045, 1.046, 1.046, 1.046, 1.046, 1.045, 1.045, 1.044, 1.043, 1.041, 1.038, 1.036, 1.033, 1.031, 1.027, 1.024, 1.019, 1.018, 1.016,
+                            1.015, 1.017, 1.021, 1.024, 1.027, 1.031, 1.034, 1.036, 1.038, 1.041, 1.043, 1.045, 1.046, 1.048, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.043, 1.041, 1.039, 1.036, 1.033, 1.029, 1.027, 1.023, 1.019, 1.018,
+                            1.017, 1.019, 1.024, 1.027, 1.029, 1.033, 1.036, 1.039, 1.041, 1.044, 1.045, 1.046, 1.048, 1.051, 1.052, 1.052, 1.052, 1.051, 1.051, 1.051, 1.049, 1.048, 1.046, 1.044, 1.042, 1.039, 1.036, 1.032, 1.029, 1.025, 1.022, 1.021,
+                            1.018, 1.022, 1.025, 1.029, 1.032, 1.035, 1.038, 1.041, 1.043, 1.045, 1.047, 1.048, 1.051, 1.052, 1.053, 1.053, 1.054, 1.054, 1.053, 1.053, 1.051, 1.049, 1.048, 1.046, 1.044, 1.041, 1.038, 1.035, 1.031, 1.027, 1.024, 1.022,
+                            1.019, 1.022, 1.027, 1.029, 1.033, 1.036, 1.039, 1.042, 1.044, 1.047, 1.048, 1.049, 1.051, 1.053, 1.054, 1.056, 1.056, 1.055, 1.055, 1.054, 1.053, 1.051, 1.049, 1.047, 1.044, 1.042, 1.039, 1.035, 1.033, 1.029, 1.025, 1.023,
+                            1.019, 1.023, 1.027, 1.029, 1.033, 1.037, 1.041, 1.043, 1.046, 1.048, 1.049, 1.051, 1.052, 1.054, 1.055, 1.056, 1.056, 1.056, 1.055, 1.054, 1.053, 1.051, 1.049, 1.047, 1.045, 1.042, 1.039, 1.036, 1.033, 1.029, 1.025, 1.023,
+                            1.019, 1.022, 1.026, 1.029, 1.033, 1.037, 1.041, 1.043, 1.046, 1.048, 1.049, 1.051, 1.053, 1.054, 1.055, 1.056, 1.056, 1.056, 1.055, 1.054, 1.053, 1.051, 1.049, 1.047, 1.044, 1.042, 1.039, 1.035, 1.033, 1.029, 1.024, 1.022,
+                            1.019, 1.022, 1.025, 1.029, 1.032, 1.036, 1.039, 1.042, 1.045, 1.047, 1.049, 1.051, 1.053, 1.054, 1.055, 1.056, 1.056, 1.055, 1.055, 1.054, 1.052, 1.051, 1.049, 1.046, 1.044, 1.042, 1.039, 1.035, 1.032, 1.028, 1.024, 1.022,
+                            1.018, 1.021, 1.025, 1.028, 1.031, 1.035, 1.038, 1.042, 1.044, 1.047, 1.048, 1.051, 1.052, 1.054, 1.055, 1.055, 1.055, 1.055, 1.054, 1.054, 1.052, 1.049, 1.048, 1.046, 1.044, 1.041, 1.038, 1.035, 1.031, 1.027, 1.024, 1.021,
+                            1.016, 1.019, 1.024, 1.028, 1.031, 1.035, 1.037, 1.041, 1.044, 1.046, 1.048, 1.051, 1.052, 1.054, 1.055, 1.056, 1.056, 1.055, 1.054, 1.053, 1.051, 1.049, 1.048, 1.046, 1.044, 1.041, 1.038, 1.034, 1.031, 1.027, 1.024, 1.022,
+                            1.016, 1.019, 1.024, 1.028, 1.031, 1.034, 1.037, 1.041, 1.043, 1.046, 1.049, 1.051, 1.052, 1.054, 1.056, 1.057, 1.057, 1.056, 1.055, 1.053, 1.051, 1.049, 1.048, 1.046, 1.044, 1.041, 1.038, 1.034, 1.031, 1.027, 1.023, 1.021,
+                            1.017, 1.019, 1.024, 1.028, 1.031, 1.035, 1.037, 1.041, 1.043, 1.046, 1.049, 1.051, 1.053, 1.054, 1.056, 1.057, 1.057, 1.056, 1.055, 1.054, 1.052, 1.049, 1.048, 1.046, 1.044, 1.041, 1.038, 1.035, 1.031, 1.028, 1.024, 1.022,
+                            1.018, 1.021, 1.024, 1.029, 1.032, 1.035, 1.039, 1.042, 1.044, 1.047, 1.049, 1.051, 1.054, 1.055, 1.057, 1.057, 1.057, 1.057, 1.056, 1.054, 1.052, 1.051, 1.049, 1.046, 1.045, 1.042, 1.039, 1.036, 1.033, 1.029, 1.025, 1.023,
+                            1.018, 1.021, 1.025, 1.029, 1.032, 1.036, 1.039, 1.042, 1.045, 1.048, 1.049, 1.052, 1.053, 1.055, 1.057, 1.057, 1.057, 1.057, 1.056, 1.055, 1.053, 1.051, 1.049, 1.047, 1.045, 1.042, 1.039, 1.036, 1.033, 1.029, 1.026, 1.024,
+                            1.018, 1.021, 1.025, 1.029, 1.033, 1.036, 1.039, 1.042, 1.045, 1.048, 1.049, 1.051, 1.054, 1.055, 1.056, 1.057, 1.057, 1.057, 1.056, 1.055, 1.053, 1.051, 1.049, 1.048, 1.045, 1.042, 1.039, 1.036, 1.034, 1.029, 1.026, 1.024,
+                            1.018, 1.021, 1.024, 1.029, 1.032, 1.036, 1.038, 1.042, 1.044, 1.047, 1.048, 1.051, 1.052, 1.054, 1.055, 1.056, 1.056, 1.056, 1.055, 1.054, 1.052, 1.049, 1.048, 1.047, 1.044, 1.042, 1.039, 1.035, 1.033, 1.028, 1.025, 1.023,
+                            1.016, 1.019, 1.022, 1.026, 1.031, 1.033, 1.037, 1.039, 1.042, 1.045, 1.047, 1.048, 1.051, 1.052, 1.053, 1.054, 1.054, 1.054, 1.053, 1.052, 1.051, 1.049, 1.047, 1.045, 1.042, 1.041, 1.038, 1.034, 1.031, 1.026, 1.024, 1.021,
+                            1.014, 1.017, 1.021, 1.024, 1.029, 1.031, 1.034, 1.037, 1.041, 1.042, 1.044, 1.046, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.046, 1.045, 1.043, 1.041, 1.038, 1.035, 1.032, 1.028, 1.025, 1.021, 1.019,
+                            1.011, 1.014, 1.018, 1.022, 1.026, 1.029, 1.032, 1.034, 1.037, 1.039, 1.041, 1.044, 1.045, 1.047, 1.048, 1.049, 1.049, 1.049, 1.048, 1.048, 1.046, 1.044, 1.042, 1.041, 1.039, 1.036, 1.033, 1.029, 1.025, 1.022, 1.019, 1.017,
+                            1.009, 1.012, 1.015, 1.019, 1.023, 1.026, 1.029, 1.032, 1.034, 1.037, 1.039, 1.041, 1.043, 1.044, 1.045, 1.045, 1.045, 1.045, 1.045, 1.045, 1.043, 1.042, 1.041, 1.039, 1.036, 1.034, 1.031, 1.027, 1.023, 1.021, 1.016, 1.015,
+                            1.007, 1.009, 1.013, 1.017, 1.021, 1.024, 1.027, 1.029, 1.032, 1.034, 1.037, 1.038, 1.041, 1.042, 1.043, 1.043, 1.043, 1.043, 1.042, 1.042, 1.041, 1.039, 1.038, 1.036, 1.034, 1.032, 1.029, 1.025, 1.021, 1.018, 1.014, 1.013,
+                            1.005, 1.008, 1.012, 1.015, 1.018, 1.022, 1.026, 1.028, 1.031, 1.033, 1.034, 1.036, 1.038, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.038, 1.036, 1.034, 1.032, 1.029, 1.026, 1.023, 1.019, 1.016, 1.013, 1.011,
+                            1.004, 1.007, 1.011, 1.014, 1.018, 1.021, 1.024, 1.027, 1.029, 1.032, 1.033, 1.035, 1.037, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.037, 1.035, 1.033, 1.031, 1.029, 1.025, 1.022, 1.018, 1.015, 1.012, 1.009,
+                            1.003, 1.006, 1.009, 1.013, 1.016, 1.019, 1.023, 1.026, 1.029, 1.031, 1.032, 1.034, 1.036, 1.037, 1.038, 1.039, 1.039, 1.039, 1.038, 1.038, 1.037, 1.036, 1.034, 1.032, 1.031, 1.027, 1.024, 1.021, 1.017, 1.014, 1.011, 1.009,
+                            1.003, 1.005, 1.009, 1.012, 1.015, 1.018, 1.021, 1.025, 1.027, 1.029, 1.032, 1.033, 1.034, 1.035, 1.036, 1.037, 1.038, 1.038, 1.037, 1.037, 1.036, 1.034, 1.033, 1.031, 1.029, 1.026, 1.024, 1.021, 1.016, 1.014, 1.011, 1.007,
+                            1.002, 1.004, 1.007, 1.011, 1.014, 1.017, 1.021, 1.023, 1.026, 1.028, 1.031, 1.032, 1.033, 1.034, 1.035, 1.036, 1.037, 1.037, 1.036, 1.036, 1.034, 1.034, 1.032, 1.031, 1.027, 1.025, 1.022, 1.019, 1.015, 1.013, 1.009, 1.007,
+                            1.001, 1.003, 1.006, 1.011, 1.013, 1.017, 1.019, 1.021, 1.024, 1.027, 1.029, 1.031, 1.032, 1.032, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.034, 1.033, 1.031, 1.028, 1.027, 1.024, 1.021, 1.017, 1.015, 1.011, 1.007, 1.005
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    2.417, 2.338, 2.181, 2.048, 1.934, 1.836, 1.751, 1.677, 1.611, 1.555, 1.506, 1.468, 1.444, 1.429, 1.423, 1.422, 1.422, 1.423, 1.434, 1.451, 1.481, 1.523, 1.576, 1.637, 1.704, 1.781, 1.868, 1.968, 2.084, 2.219, 2.379, 2.423,
+                    2.348, 2.241, 2.091, 1.968, 1.859, 1.765, 1.688, 1.617, 1.558, 1.507, 1.465, 1.429, 1.403, 1.384, 1.372, 1.367, 1.367, 1.375, 1.391, 1.413, 1.443, 1.481, 1.526, 1.582, 1.643, 1.713, 1.797, 1.892, 2.002, 2.132, 2.284, 2.384,
+                    2.255, 2.159, 2.019, 1.898, 1.792, 1.702, 1.631, 1.561, 1.503, 1.453, 1.412, 1.378, 1.352, 1.332, 1.319, 1.315, 1.315, 1.323, 1.339, 1.362, 1.391, 1.427, 1.471, 1.524, 1.584, 1.655, 1.734, 1.826, 1.931, 2.054, 2.198, 2.288,
+                    2.181, 2.088, 1.952, 1.836, 1.734, 1.649, 1.572, 1.508, 1.454, 1.406, 1.365, 1.332, 1.307, 1.286, 1.276, 1.269, 1.271, 1.277, 1.293, 1.315, 1.343, 1.379, 1.424, 1.474, 1.532, 1.599, 1.678, 1.768, 1.869, 1.987, 2.124, 2.205,
+                    2.124, 2.025, 1.897, 1.787, 1.685, 1.601, 1.527, 1.464, 1.409, 1.364, 1.325, 1.292, 1.265, 1.246, 1.234, 1.229, 1.229, 1.237, 1.252, 1.274, 1.303, 1.339, 1.381, 1.429, 1.487, 1.553, 1.629, 1.718, 1.816, 1.929, 2.061, 2.137,
+                    2.077, 1.971, 1.851, 1.738, 1.642, 1.559, 1.488, 1.425, 1.371, 1.326, 1.288, 1.255, 1.229, 1.211, 1.197, 1.193, 1.194, 1.201, 1.216, 1.237, 1.266, 1.301, 1.342, 1.391, 1.447, 1.513, 1.587, 1.673, 1.769, 1.879, 2.014, 2.083,
+                    2.029, 1.924, 1.805, 1.693, 1.604, 1.522, 1.452, 1.391, 1.338, 1.292, 1.255, 1.222, 1.196, 1.177, 1.164, 1.159, 1.161, 1.168, 1.183, 1.205, 1.234, 1.268, 1.308, 1.357, 1.413, 1.477, 1.551, 1.635, 1.729, 1.837, 1.963, 2.039,
+                    1.988, 1.882, 1.769, 1.657, 1.569, 1.489, 1.421, 1.361, 1.308, 1.263, 1.224, 1.192, 1.167, 1.146, 1.134, 1.129, 1.129, 1.137, 1.152, 1.176, 1.203, 1.237, 1.278, 1.327, 1.382, 1.445, 1.518, 1.599, 1.692, 1.799, 1.921, 1.996,
+                    1.955, 1.848, 1.733, 1.628, 1.538, 1.462, 1.392, 1.331, 1.279, 1.235, 1.197, 1.165, 1.138, 1.119, 1.105, 1.101, 1.101, 1.109, 1.125, 1.148, 1.175, 1.209, 1.251, 1.299, 1.353, 1.416, 1.487, 1.568, 1.659, 1.764, 1.883, 1.958,
+                    1.924, 1.817, 1.703, 1.604, 1.517, 1.436, 1.367, 1.307, 1.256, 1.209, 1.171, 1.139, 1.113, 1.094, 1.081, 1.076, 1.076, 1.083, 1.099, 1.122, 1.149, 1.184, 1.226, 1.273, 1.328, 1.391, 1.461, 1.539, 1.629, 1.732, 1.849, 1.926,
+                    1.896, 1.789, 1.677, 1.576, 1.501, 1.415, 1.346, 1.287, 1.236, 1.188, 1.149, 1.117, 1.091, 1.071, 1.061, 1.056, 1.056, 1.063, 1.078, 1.099, 1.127, 1.162, 1.203, 1.251, 1.306, 1.368, 1.436, 1.515, 1.603, 1.705, 1.821, 1.899,
+                    1.873, 1.765, 1.657, 1.556, 1.479, 1.395, 1.325, 1.267, 1.216, 1.169, 1.131, 1.098, 1.074, 1.055, 1.043, 1.039, 1.039, 1.047, 1.061, 1.079, 1.107, 1.142, 1.184, 1.233, 1.287, 1.349, 1.417, 1.494, 1.582, 1.683, 1.796, 1.877,
+                    1.861, 1.747, 1.638, 1.541, 1.454, 1.379, 1.312, 1.252, 1.201, 1.155, 1.115, 1.084, 1.059, 1.042, 1.029, 1.024, 1.025, 1.034, 1.046, 1.065, 1.092, 1.127, 1.169, 1.217, 1.272, 1.334, 1.402, 1.486, 1.569, 1.665, 1.777, 1.864,
+                    1.852, 1.735, 1.628, 1.529, 1.442, 1.369, 1.303, 1.242, 1.189, 1.144, 1.105, 1.073, 1.049, 1.032, 1.022, 1.014, 1.014, 1.023, 1.037, 1.056, 1.082, 1.117, 1.159, 1.207, 1.262, 1.323, 1.391, 1.478, 1.563, 1.653, 1.764, 1.855,
+                    1.849, 1.727, 1.621, 1.522, 1.437, 1.363, 1.297, 1.237, 1.185, 1.139, 1.099, 1.068, 1.044, 1.031, 1.017, 1.011, 1.009, 1.016, 1.031, 1.051, 1.078, 1.112, 1.154, 1.202, 1.256, 1.317, 1.385, 1.466, 1.551, 1.646, 1.758, 1.853,
+                    1.848, 1.727, 1.618, 1.521, 1.436, 1.362, 1.296, 1.237, 1.185, 1.139, 1.099, 1.068, 1.043, 1.029, 1.016, 1.005, 1.005, 1.014, 1.031, 1.051, 1.077, 1.111, 1.153, 1.201, 1.255, 1.316, 1.384, 1.462, 1.548, 1.645, 1.757, 1.852,
+                    1.849, 1.733, 1.622, 1.525, 1.439, 1.366, 1.298, 1.239, 1.187, 1.141, 1.101, 1.069, 1.046, 1.031, 1.017, 1.009, 1.008, 1.018, 1.033, 1.054, 1.079, 1.114, 1.156, 1.204, 1.259, 1.321, 1.388, 1.465, 1.552, 1.649, 1.761, 1.854,
+                    1.856, 1.743, 1.631, 1.535, 1.449, 1.384, 1.309, 1.246, 1.194, 1.148, 1.109, 1.076, 1.052, 1.034, 1.022, 1.015, 1.017, 1.025, 1.041, 1.061, 1.087, 1.121, 1.163, 1.211, 1.266, 1.328, 1.396, 1.473, 1.561, 1.658, 1.771, 1.861,
+                    1.869, 1.757, 1.657, 1.551, 1.463, 1.395, 1.323, 1.261, 1.205, 1.159, 1.119, 1.087, 1.062, 1.046, 1.033, 1.027, 1.029, 1.038, 1.051, 1.071, 1.097, 1.132, 1.176, 1.229, 1.277, 1.339, 1.407, 1.485, 1.573, 1.672, 1.785, 1.871,
+                    1.885, 1.776, 1.668, 1.567, 1.477, 1.406, 1.332, 1.272, 1.218, 1.172, 1.133, 1.101, 1.076, 1.059, 1.046, 1.042, 1.043, 1.051, 1.064, 1.084, 1.111, 1.146, 1.191, 1.246, 1.291, 1.352, 1.421, 1.499, 1.587, 1.688, 1.802, 1.886,
+                    1.909, 1.796, 1.681, 1.586, 1.496, 1.418, 1.349, 1.289, 1.234, 1.189, 1.149, 1.117, 1.092, 1.074, 1.062, 1.058, 1.059, 1.065, 1.079, 1.099, 1.128, 1.163, 1.204, 1.253, 1.307, 1.369, 1.438, 1.516, 1.605, 1.707, 1.822, 1.905,
+                    1.929, 1.823, 1.708, 1.609, 1.519, 1.438, 1.371, 1.309, 1.255, 1.209, 1.171, 1.137, 1.112, 1.093, 1.079, 1.076, 1.077, 1.084, 1.099, 1.119, 1.148, 1.182, 1.224, 1.274, 1.327, 1.389, 1.458, 1.537, 1.627, 1.729, 1.848, 1.929,
+                    1.958, 1.852, 1.738, 1.635, 1.543, 1.464, 1.394, 1.335, 1.279, 1.233, 1.194, 1.163, 1.137, 1.118, 1.111, 1.101, 1.101, 1.107, 1.122, 1.144, 1.172, 1.207, 1.263, 1.294, 1.351, 1.412, 1.482, 1.562, 1.653, 1.756, 1.875, 1.959,
+                    1.993, 1.889, 1.777, 1.671, 1.575, 1.497, 1.423, 1.362, 1.307, 1.262, 1.224, 1.191, 1.164, 1.144, 1.135, 1.128, 1.127, 1.135, 1.151, 1.173, 1.201, 1.236, 1.282, 1.322, 1.378, 1.439, 1.511, 1.591, 1.683, 1.789, 1.909, 1.989,
+                    2.026, 1.934, 1.807, 1.705, 1.609, 1.531, 1.457, 1.393, 1.339, 1.295, 1.254, 1.224, 1.199, 1.176, 1.162, 1.158, 1.159, 1.166, 1.182, 1.203, 1.232, 1.267, 1.306, 1.355, 1.411, 1.473, 1.546, 1.627, 1.721, 1.829, 1.955, 2.025,
+                    2.079, 1.981, 1.851, 1.746, 1.648, 1.566, 1.496, 1.429, 1.376, 1.332, 1.293, 1.257, 1.231, 1.211, 1.198, 1.193, 1.194, 1.201, 1.216, 1.237, 1.267, 1.302, 1.342, 1.391, 1.447, 1.512, 1.585, 1.668, 1.764, 1.874, 2.001, 2.078,
+                    2.133, 2.039, 1.905, 1.798, 1.696, 1.611, 1.542, 1.473, 1.421, 1.372, 1.331, 1.299, 1.269, 1.251, 1.238, 1.234, 1.235, 1.242, 1.257, 1.278, 1.305, 1.341, 1.384, 1.432, 1.489, 1.555, 1.629, 1.715, 1.814, 1.927, 2.059, 2.133,
+                    2.199, 2.105, 1.968, 1.855, 1.751, 1.665, 1.589, 1.522, 1.467, 1.419, 1.376, 1.343, 1.315, 1.295, 1.282, 1.279, 1.279, 1.288, 1.301, 1.322, 1.349, 1.386, 1.428, 1.477, 1.536, 1.603, 1.679, 1.767, 1.871, 1.989, 2.133, 2.207,
+                    2.286, 2.181, 2.038, 1.917, 1.812, 1.724, 1.644, 1.576, 1.518, 1.468, 1.426, 1.391, 1.365, 1.344, 1.331, 1.326, 1.327, 1.335, 1.349, 1.371, 1.399, 1.434, 1.477, 1.529, 1.588, 1.657, 1.735, 1.828, 1.939, 2.107, 2.202, 2.292,
+                    2.371, 2.277, 2.119, 1.991, 1.886, 1.788, 1.706, 1.635, 1.575, 1.523, 1.479, 1.444, 1.417, 1.397, 1.388, 1.379, 1.379, 1.387, 1.402, 1.423, 1.452, 1.487, 1.533, 1.586, 1.646, 1.716, 1.798, 1.896, 2.008, 2.147, 2.288, 2.382,
+                    2.445, 2.359, 2.214, 2.072, 1.961, 1.867, 1.776, 1.697, 1.632, 1.581, 1.538, 1.502, 1.475, 1.453, 1.441, 1.435, 1.435, 1.442, 1.458, 1.479, 1.508, 1.545, 1.591, 1.643, 1.707, 1.782, 1.871, 1.971, 2.084, 2.221, 2.379, 2.461,
+                    2.547, 2.424, 2.265, 2.146, 2.027, 1.909, 1.829, 1.745, 1.682, 1.626, 1.579, 1.537, 1.502, 1.481, 1.473, 1.472, 1.472, 1.475, 1.485, 1.508, 1.543, 1.585, 1.633, 1.691, 1.756, 1.833, 1.921, 2.023, 2.144, 2.288, 2.456, 2.531
+                ],
+                "sigma": 0.00173,
+                "sigma_Cb": 0.00101
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 2300,
+                        "ccm":
+                        [
+                            1.68006, -0.27691, -0.40316,
+                            -0.47307, 1.79604, -0.32297,
+                            0.05726, -1.19189, 2.13463
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "ccm":
+                        [
+                            1.67003, -0.35103, -0.31901,
+                            -0.40968, 1.76185, -0.35217,
+                            0.08881, -1.03205, 1.94324
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.68624, -0.43345, -0.25279,
+                            -0.47172, 1.73761, -0.26589,
+                            0.03957, -0.74365, 1.70408
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "ccm":
+                        [
+                            1.69271, -0.47764, -0.21507,
+                            -0.37316, 1.65241, -0.27924,
+                            0.00556, -0.54736, 1.54181
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "ccm":
+                        [
+                            2.04845, -0.88498, -0.16347,
+                            -0.39306, 1.58125, -0.18819,
+                            0.03097, -0.55042, 1.51945
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            1.66545, -0.43544, -0.23001,
+                            -0.27893, 1.68964, -0.41072,
+                            0.00809, -0.54202, 1.53392
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.cac": { }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.25,
+                "limit": 1.0,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx378.json 0.6.0-2/src/ipa/rpi/pisp/data/imx378.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx378.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx378.json	2025-11-27 11:55:28.000000000 +0000
@@ -25,7 +25,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.641
+                "reference_slope": 3.7
             }
         },
         {
@@ -42,11 +42,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -55,7 +55,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -63,11 +63,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -76,19 +76,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -97,8 +97,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -531,37 +531,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx415.json 0.6.0-2/src/ipa/rpi/pisp/data/imx415.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx415.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx415.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 17,
-                "reference_slope": 3.439
+                "reference_slope": 4.8
             }
         },
         {
@@ -45,11 +45,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -58,7 +58,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,11 +66,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -79,19 +79,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -100,8 +100,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -999,37 +999,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1092,8 +1110,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx415_b0569.json 0.6.0-2/src/ipa/rpi/pisp/data/imx415_b0569.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx415_b0569.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx415_b0569.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,1475 @@
+{
+    "version": 2.0,
+    "target": "pisp",
+    "vendor": "Arducam",
+    "sku": "B0569",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 3200
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 9990,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 875,
+                "reference_Y": 15940
+            }
+        },
+        {
+            "rpi.dpc":
+            {
+                "strength": 1
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 3.44
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 221,
+                "slope": 0.00645
+            }
+        },
+        {
+            "rpi.denoise":
+            {
+                "normal":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 0.8,
+                        "threshold": 0.05
+                    }
+                },
+                "hdr":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                },
+                "night":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                }
+            }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 7700
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8000
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    2300.0, 0.9197, 0.3071,
+                    2856.0, 0.7489, 0.3158,
+                    3000.0, 0.7206, 0.3229,
+                    4000.0, 0.5709, 0.4095,
+                    4100.0, 0.5465, 0.4349,
+                    6500.0, 0.4564, 0.5728
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.02416,
+                "transverse_neg": 0.04263
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.049, 1.049, 1.044, 1.041, 1.037, 1.034, 1.029, 1.028, 1.024, 1.021, 1.018, 1.016, 1.015, 1.013, 1.012, 1.011, 1.011, 1.011, 1.012, 1.014, 1.015, 1.017, 1.019, 1.022, 1.026, 1.027, 1.029, 1.032, 1.034, 1.039, 1.042, 1.042,
+                            1.059, 1.056, 1.052, 1.048, 1.044, 1.042, 1.038, 1.034, 1.031, 1.029, 1.026, 1.025, 1.023, 1.023, 1.022, 1.022, 1.022, 1.022, 1.023, 1.024, 1.025, 1.026, 1.028, 1.031, 1.033, 1.036, 1.039, 1.042, 1.045, 1.047, 1.049, 1.053,
+                            1.061, 1.058, 1.055, 1.051, 1.047, 1.043, 1.039, 1.036, 1.033, 1.029, 1.028, 1.025, 1.024, 1.023, 1.022, 1.022, 1.022, 1.022, 1.023, 1.024, 1.025, 1.027, 1.029, 1.032, 1.035, 1.038, 1.041, 1.043, 1.046, 1.049, 1.052, 1.054,
+                            1.061, 1.058, 1.054, 1.051, 1.046, 1.043, 1.038, 1.034, 1.031, 1.028, 1.025, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.021, 1.022, 1.024, 1.025, 1.028, 1.029, 1.033, 1.037, 1.039, 1.042, 1.045, 1.049, 1.052, 1.053,
+                            1.059, 1.056, 1.052, 1.048, 1.045, 1.041, 1.037, 1.033, 1.029, 1.025, 1.024, 1.022, 1.019, 1.018, 1.017, 1.017, 1.017, 1.018, 1.018, 1.021, 1.022, 1.023, 1.026, 1.029, 1.032, 1.035, 1.038, 1.041, 1.044, 1.048, 1.051, 1.053,
+                            1.058, 1.055, 1.052, 1.048, 1.044, 1.039, 1.036, 1.032, 1.028, 1.024, 1.022, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.016, 1.017, 1.018, 1.021, 1.022, 1.024, 1.028, 1.031, 1.034, 1.037, 1.041, 1.044, 1.047, 1.051, 1.052,
+                            1.057, 1.054, 1.051, 1.047, 1.043, 1.038, 1.035, 1.031, 1.027, 1.023, 1.021, 1.018, 1.016, 1.015, 1.014, 1.013, 1.013, 1.014, 1.015, 1.016, 1.018, 1.021, 1.022, 1.026, 1.029, 1.033, 1.036, 1.039, 1.042, 1.046, 1.049, 1.051,
+                            1.056, 1.054, 1.049, 1.046, 1.042, 1.038, 1.033, 1.029, 1.025, 1.022, 1.019, 1.016, 1.014, 1.012, 1.011, 1.011, 1.011, 1.012, 1.013, 1.014, 1.016, 1.018, 1.021, 1.025, 1.028, 1.032, 1.035, 1.039, 1.042, 1.045, 1.049, 1.051,
+                            1.056, 1.052, 1.048, 1.045, 1.041, 1.037, 1.032, 1.028, 1.023, 1.021, 1.017, 1.015, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.011, 1.013, 1.014, 1.017, 1.019, 1.023, 1.027, 1.031, 1.034, 1.037, 1.041, 1.044, 1.048, 1.049,
+                            1.056, 1.052, 1.047, 1.043, 1.039, 1.035, 1.031, 1.026, 1.022, 1.019, 1.016, 1.013, 1.011, 1.009, 1.008, 1.007, 1.007, 1.008, 1.009, 1.011, 1.013, 1.015, 1.018, 1.021, 1.025, 1.029, 1.033, 1.036, 1.039, 1.044, 1.047, 1.049,
+                            1.055, 1.051, 1.046, 1.043, 1.038, 1.034, 1.029, 1.026, 1.022, 1.018, 1.015, 1.012, 1.011, 1.008, 1.007, 1.007, 1.006, 1.007, 1.008, 1.009, 1.012, 1.015, 1.017, 1.021, 1.024, 1.029, 1.032, 1.035, 1.039, 1.043, 1.047, 1.048,
+                            1.054, 1.051, 1.046, 1.042, 1.038, 1.034, 1.029, 1.025, 1.021, 1.018, 1.014, 1.011, 1.009, 1.007, 1.006, 1.006, 1.006, 1.006, 1.007, 1.009, 1.012, 1.014, 1.017, 1.021, 1.024, 1.028, 1.032, 1.035, 1.039, 1.042, 1.046, 1.048,
+                            1.054, 1.051, 1.046, 1.041, 1.038, 1.033, 1.029, 1.024, 1.021, 1.017, 1.013, 1.011, 1.008, 1.007, 1.006, 1.006, 1.006, 1.006, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.023, 1.027, 1.031, 1.035, 1.038, 1.042, 1.045, 1.047,
+                            1.053, 1.051, 1.045, 1.041, 1.036, 1.033, 1.028, 1.024, 1.019, 1.016, 1.012, 1.009, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.006, 1.008, 1.009, 1.013, 1.016, 1.019, 1.022, 1.027, 1.031, 1.034, 1.038, 1.041, 1.045, 1.047,
+                            1.053, 1.049, 1.044, 1.041, 1.036, 1.033, 1.028, 1.024, 1.019, 1.015, 1.012, 1.009, 1.007, 1.005, 1.005, 1.005, 1.005, 1.005, 1.006, 1.007, 1.011, 1.013, 1.015, 1.019, 1.022, 1.027, 1.031, 1.034, 1.038, 1.041, 1.045, 1.046,
+                            1.053, 1.049, 1.044, 1.041, 1.037, 1.033, 1.027, 1.024, 1.019, 1.016, 1.012, 1.009, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.006, 1.007, 1.009, 1.013, 1.015, 1.019, 1.022, 1.026, 1.031, 1.034, 1.038, 1.041, 1.045, 1.047,
+                            1.052, 1.049, 1.045, 1.042, 1.037, 1.033, 1.028, 1.024, 1.019, 1.016, 1.013, 1.009, 1.007, 1.006, 1.006, 1.006, 1.006, 1.005, 1.006, 1.008, 1.009, 1.013, 1.015, 1.019, 1.023, 1.027, 1.031, 1.034, 1.038, 1.041, 1.045, 1.047,
+                            1.052, 1.049, 1.045, 1.042, 1.037, 1.033, 1.028, 1.024, 1.019, 1.015, 1.013, 1.009, 1.007, 1.006, 1.006, 1.005, 1.006, 1.005, 1.006, 1.008, 1.009, 1.013, 1.015, 1.018, 1.022, 1.027, 1.031, 1.034, 1.038, 1.041, 1.045, 1.047,
+                            1.052, 1.049, 1.045, 1.041, 1.037, 1.033, 1.028, 1.023, 1.019, 1.016, 1.012, 1.009, 1.007, 1.006, 1.005, 1.006, 1.005, 1.005, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.022, 1.027, 1.031, 1.034, 1.038, 1.041, 1.044, 1.046,
+                            1.052, 1.049, 1.045, 1.041, 1.037, 1.033, 1.028, 1.024, 1.019, 1.016, 1.012, 1.009, 1.007, 1.006, 1.006, 1.005, 1.006, 1.006, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.023, 1.027, 1.031, 1.033, 1.037, 1.041, 1.045, 1.046,
+                            1.052, 1.049, 1.044, 1.041, 1.038, 1.033, 1.029, 1.024, 1.021, 1.016, 1.013, 1.009, 1.008, 1.007, 1.006, 1.006, 1.006, 1.006, 1.007, 1.009, 1.011, 1.014, 1.016, 1.019, 1.023, 1.027, 1.031, 1.034, 1.037, 1.041, 1.045, 1.046,
+                            1.053, 1.049, 1.044, 1.041, 1.038, 1.033, 1.029, 1.025, 1.021, 1.017, 1.014, 1.011, 1.009, 1.007, 1.007, 1.006, 1.006, 1.007, 1.008, 1.009, 1.012, 1.014, 1.016, 1.019, 1.023, 1.028, 1.032, 1.035, 1.038, 1.041, 1.045, 1.046,
+                            1.053, 1.049, 1.044, 1.041, 1.038, 1.033, 1.029, 1.024, 1.021, 1.017, 1.014, 1.011, 1.009, 1.008, 1.008, 1.008, 1.008, 1.008, 1.009, 1.011, 1.012, 1.015, 1.018, 1.021, 1.024, 1.028, 1.032, 1.034, 1.038, 1.041, 1.045, 1.047,
+                            1.053, 1.049, 1.044, 1.041, 1.038, 1.034, 1.029, 1.025, 1.021, 1.018, 1.015, 1.012, 1.011, 1.009, 1.008, 1.008, 1.008, 1.008, 1.009, 1.011, 1.013, 1.016, 1.018, 1.021, 1.025, 1.028, 1.031, 1.035, 1.038, 1.041, 1.045, 1.047,
+                            1.054, 1.051, 1.046, 1.042, 1.038, 1.034, 1.031, 1.026, 1.022, 1.019, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.011, 1.011, 1.011, 1.013, 1.014, 1.017, 1.019, 1.022, 1.025, 1.029, 1.032, 1.035, 1.038, 1.042, 1.046, 1.048,
+                            1.054, 1.052, 1.047, 1.043, 1.039, 1.036, 1.031, 1.027, 1.023, 1.019, 1.017, 1.015, 1.013, 1.012, 1.011, 1.011, 1.012, 1.012, 1.013, 1.014, 1.016, 1.018, 1.021, 1.023, 1.026, 1.029, 1.033, 1.036, 1.039, 1.043, 1.047, 1.048,
+                            1.055, 1.053, 1.048, 1.044, 1.041, 1.037, 1.032, 1.029, 1.025, 1.021, 1.019, 1.016, 1.015, 1.013, 1.013, 1.013, 1.013, 1.014, 1.014, 1.016, 1.017, 1.019, 1.022, 1.024, 1.027, 1.031, 1.033, 1.037, 1.039, 1.044, 1.048, 1.049,
+                            1.056, 1.054, 1.049, 1.045, 1.042, 1.038, 1.034, 1.029, 1.027, 1.023, 1.021, 1.018, 1.016, 1.015, 1.014, 1.014, 1.015, 1.015, 1.016, 1.017, 1.018, 1.021, 1.023, 1.025, 1.028, 1.032, 1.034, 1.038, 1.041, 1.045, 1.048, 1.051,
+                            1.058, 1.054, 1.049, 1.046, 1.042, 1.038, 1.034, 1.031, 1.027, 1.024, 1.022, 1.019, 1.018, 1.016, 1.015, 1.016, 1.016, 1.016, 1.017, 1.018, 1.019, 1.021, 1.024, 1.026, 1.028, 1.032, 1.035, 1.038, 1.042, 1.046, 1.049, 1.051,
+                            1.058, 1.054, 1.051, 1.046, 1.042, 1.039, 1.035, 1.032, 1.028, 1.025, 1.023, 1.021, 1.019, 1.018, 1.017, 1.017, 1.017, 1.018, 1.018, 1.019, 1.021, 1.023, 1.024, 1.027, 1.029, 1.033, 1.036, 1.039, 1.043, 1.047, 1.051, 1.053,
+                            1.058, 1.056, 1.051, 1.047, 1.043, 1.039, 1.036, 1.033, 1.029, 1.027, 1.025, 1.023, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.022, 1.024, 1.026, 1.028, 1.029, 1.034, 1.036, 1.039, 1.043, 1.048, 1.051, 1.053,
+                            1.061, 1.056, 1.052, 1.048, 1.044, 1.041, 1.037, 1.033, 1.029, 1.028, 1.026, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.023, 1.025, 1.027, 1.029, 1.031, 1.035, 1.037, 1.041, 1.044, 1.048, 1.052, 1.054
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.057, 1.057, 1.053, 1.048, 1.043, 1.039, 1.036, 1.033, 1.029, 1.024, 1.022, 1.019, 1.017, 1.016, 1.014, 1.014, 1.014, 1.014, 1.015, 1.016, 1.019, 1.019, 1.022, 1.025, 1.028, 1.031, 1.033, 1.037, 1.039, 1.043, 1.045, 1.045,
+                            1.065, 1.061, 1.057, 1.053, 1.049, 1.044, 1.039, 1.036, 1.032, 1.031, 1.028, 1.026, 1.024, 1.023, 1.023, 1.022, 1.022, 1.023, 1.023, 1.024, 1.026, 1.027, 1.029, 1.031, 1.034, 1.037, 1.041, 1.043, 1.047, 1.049, 1.053, 1.056,
+                            1.069, 1.065, 1.061, 1.057, 1.053, 1.049, 1.044, 1.039, 1.036, 1.033, 1.031, 1.028, 1.026, 1.025, 1.024, 1.023, 1.024, 1.024, 1.025, 1.025, 1.027, 1.029, 1.031, 1.034, 1.037, 1.041, 1.044, 1.047, 1.049, 1.053, 1.056, 1.058,
+                            1.069, 1.067, 1.063, 1.059, 1.054, 1.049, 1.044, 1.041, 1.037, 1.034, 1.031, 1.028, 1.026, 1.025, 1.024, 1.024, 1.024, 1.024, 1.025, 1.026, 1.028, 1.029, 1.031, 1.035, 1.038, 1.042, 1.045, 1.048, 1.051, 1.055, 1.057, 1.061,
+                            1.069, 1.065, 1.063, 1.058, 1.053, 1.049, 1.044, 1.039, 1.035, 1.032, 1.029, 1.027, 1.026, 1.024, 1.023, 1.023, 1.023, 1.023, 1.023, 1.025, 1.026, 1.029, 1.031, 1.034, 1.037, 1.041, 1.044, 1.047, 1.051, 1.054, 1.057, 1.061,
+                            1.066, 1.064, 1.059, 1.055, 1.051, 1.045, 1.041, 1.036, 1.031, 1.029, 1.025, 1.023, 1.021, 1.019, 1.018, 1.017, 1.017, 1.018, 1.019, 1.021, 1.022, 1.024, 1.027, 1.031, 1.034, 1.037, 1.041, 1.045, 1.048, 1.052, 1.055, 1.057,
+                            1.064, 1.061, 1.056, 1.052, 1.046, 1.042, 1.037, 1.032, 1.028, 1.025, 1.021, 1.019, 1.017, 1.015, 1.013, 1.013, 1.012, 1.013, 1.014, 1.016, 1.018, 1.021, 1.023, 1.026, 1.031, 1.034, 1.038, 1.042, 1.046, 1.049, 1.053, 1.054,
+                            1.063, 1.061, 1.055, 1.051, 1.046, 1.041, 1.036, 1.031, 1.027, 1.023, 1.019, 1.017, 1.015, 1.013, 1.012, 1.011, 1.011, 1.012, 1.013, 1.015, 1.017, 1.019, 1.022, 1.025, 1.029, 1.034, 1.037, 1.041, 1.045, 1.048, 1.053, 1.054,
+                            1.064, 1.062, 1.057, 1.052, 1.047, 1.043, 1.038, 1.032, 1.028, 1.024, 1.021, 1.017, 1.015, 1.013, 1.012, 1.011, 1.011, 1.012, 1.013, 1.015, 1.017, 1.019, 1.022, 1.026, 1.031, 1.034, 1.038, 1.041, 1.046, 1.049, 1.054, 1.055,
+                            1.065, 1.062, 1.056, 1.053, 1.047, 1.043, 1.038, 1.032, 1.028, 1.023, 1.019, 1.017, 1.014, 1.012, 1.011, 1.011, 1.011, 1.011, 1.012, 1.014, 1.016, 1.019, 1.022, 1.026, 1.031, 1.034, 1.038, 1.042, 1.046, 1.051, 1.053, 1.055,
+                            1.062, 1.059, 1.055, 1.049, 1.044, 1.039, 1.035, 1.031, 1.026, 1.021, 1.017, 1.014, 1.011, 1.009, 1.008, 1.008, 1.007, 1.008, 1.009, 1.011, 1.013, 1.016, 1.019, 1.023, 1.028, 1.032, 1.036, 1.039, 1.043, 1.048, 1.052, 1.054,
+                            1.059, 1.056, 1.051, 1.047, 1.042, 1.037, 1.032, 1.027, 1.022, 1.018, 1.014, 1.011, 1.008, 1.006, 1.006, 1.005, 1.005, 1.005, 1.006, 1.008, 1.011, 1.014, 1.017, 1.021, 1.024, 1.029, 1.033, 1.037, 1.041, 1.045, 1.049, 1.051,
+                            1.059, 1.056, 1.051, 1.046, 1.041, 1.037, 1.031, 1.027, 1.022, 1.017, 1.013, 1.009, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.024, 1.029, 1.033, 1.036, 1.041, 1.044, 1.049, 1.051,
+                            1.061, 1.058, 1.053, 1.049, 1.043, 1.039, 1.034, 1.029, 1.024, 1.019, 1.015, 1.012, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.007, 1.009, 1.012, 1.015, 1.018, 1.022, 1.026, 1.031, 1.035, 1.039, 1.042, 1.047, 1.051, 1.053,
+                            1.061, 1.058, 1.054, 1.049, 1.044, 1.039, 1.034, 1.029, 1.025, 1.019, 1.016, 1.012, 1.009, 1.008, 1.008, 1.008, 1.007, 1.008, 1.008, 1.009, 1.012, 1.015, 1.019, 1.023, 1.026, 1.032, 1.036, 1.039, 1.043, 1.048, 1.052, 1.054,
+                            1.061, 1.056, 1.052, 1.048, 1.043, 1.038, 1.033, 1.027, 1.024, 1.018, 1.014, 1.011, 1.009, 1.007, 1.006, 1.006, 1.006, 1.006, 1.007, 1.008, 1.011, 1.014, 1.017, 1.021, 1.025, 1.029, 1.034, 1.038, 1.042, 1.046, 1.049, 1.053,
+                            1.058, 1.054, 1.049, 1.045, 1.041, 1.036, 1.031, 1.026, 1.021, 1.016, 1.012, 1.009, 1.007, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.007, 1.009, 1.012, 1.016, 1.019, 1.023, 1.028, 1.032, 1.036, 1.039, 1.043, 1.048, 1.049,
+                            1.059, 1.054, 1.051, 1.046, 1.041, 1.036, 1.031, 1.026, 1.021, 1.016, 1.012, 1.009, 1.007, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.007, 1.009, 1.012, 1.016, 1.019, 1.023, 1.028, 1.032, 1.036, 1.041, 1.044, 1.047, 1.051,
+                            1.061, 1.057, 1.052, 1.048, 1.043, 1.039, 1.034, 1.027, 1.023, 1.019, 1.016, 1.012, 1.009, 1.008, 1.007, 1.007, 1.006, 1.006, 1.007, 1.009, 1.011, 1.015, 1.018, 1.022, 1.026, 1.031, 1.035, 1.038, 1.042, 1.046, 1.049, 1.052,
+                            1.061, 1.059, 1.053, 1.049, 1.043, 1.041, 1.035, 1.029, 1.025, 1.021, 1.016, 1.013, 1.011, 1.009, 1.008, 1.008, 1.008, 1.008, 1.008, 1.011, 1.013, 1.017, 1.019, 1.023, 1.027, 1.032, 1.036, 1.039, 1.043, 1.047, 1.051, 1.052,
+                            1.061, 1.057, 1.052, 1.048, 1.043, 1.038, 1.033, 1.029, 1.023, 1.019, 1.015, 1.013, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.008, 1.011, 1.013, 1.015, 1.019, 1.022, 1.026, 1.031, 1.035, 1.039, 1.042, 1.046, 1.049, 1.052,
+                            1.058, 1.054, 1.049, 1.045, 1.041, 1.036, 1.031, 1.026, 1.021, 1.017, 1.014, 1.011, 1.008, 1.007, 1.006, 1.006, 1.006, 1.006, 1.007, 1.009, 1.012, 1.014, 1.017, 1.021, 1.025, 1.029, 1.033, 1.036, 1.041, 1.044, 1.048, 1.049,
+                            1.058, 1.055, 1.049, 1.046, 1.041, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.012, 1.009, 1.008, 1.007, 1.006, 1.007, 1.007, 1.008, 1.009, 1.012, 1.015, 1.018, 1.021, 1.025, 1.029, 1.033, 1.036, 1.041, 1.044, 1.048, 1.049,
+                            1.061, 1.057, 1.052, 1.049, 1.044, 1.039, 1.034, 1.029, 1.025, 1.021, 1.017, 1.015, 1.013, 1.009, 1.009, 1.009, 1.009, 1.011, 1.011, 1.013, 1.016, 1.018, 1.021, 1.024, 1.027, 1.032, 1.035, 1.039, 1.043, 1.047, 1.049, 1.052,
+                            1.062, 1.059, 1.054, 1.051, 1.046, 1.042, 1.036, 1.031, 1.027, 1.023, 1.021, 1.017, 1.015, 1.014, 1.013, 1.013, 1.013, 1.014, 1.015, 1.016, 1.018, 1.021, 1.023, 1.026, 1.029, 1.033, 1.037, 1.041, 1.045, 1.049, 1.051, 1.054,
+                            1.062, 1.059, 1.054, 1.051, 1.046, 1.042, 1.036, 1.032, 1.027, 1.023, 1.021, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014, 1.015, 1.016, 1.018, 1.021, 1.023, 1.026, 1.029, 1.033, 1.037, 1.041, 1.045, 1.049, 1.052, 1.054,
+                            1.062, 1.058, 1.053, 1.049, 1.044, 1.041, 1.035, 1.031, 1.027, 1.023, 1.021, 1.017, 1.016, 1.014, 1.014, 1.013, 1.013, 1.014, 1.014, 1.016, 1.018, 1.021, 1.022, 1.025, 1.027, 1.031, 1.036, 1.041, 1.043, 1.048, 1.052, 1.053,
+                            1.063, 1.058, 1.054, 1.051, 1.045, 1.041, 1.037, 1.032, 1.028, 1.024, 1.021, 1.018, 1.017, 1.015, 1.015, 1.015, 1.015, 1.015, 1.015, 1.017, 1.019, 1.021, 1.023, 1.026, 1.029, 1.033, 1.037, 1.041, 1.045, 1.048, 1.052, 1.054,
+                            1.065, 1.063, 1.057, 1.053, 1.048, 1.044, 1.039, 1.035, 1.031, 1.028, 1.025, 1.023, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.023, 1.025, 1.027, 1.029, 1.032, 1.035, 1.039, 1.043, 1.047, 1.051, 1.056, 1.057,
+                            1.067, 1.065, 1.059, 1.055, 1.051, 1.046, 1.042, 1.038, 1.035, 1.031, 1.028, 1.026, 1.025, 1.024, 1.023, 1.023, 1.023, 1.023, 1.023, 1.024, 1.026, 1.028, 1.029, 1.032, 1.034, 1.038, 1.042, 1.046, 1.049, 1.054, 1.057, 1.059,
+                            1.068, 1.065, 1.059, 1.055, 1.051, 1.046, 1.042, 1.038, 1.035, 1.031, 1.029, 1.027, 1.025, 1.024, 1.023, 1.023, 1.023, 1.023, 1.024, 1.025, 1.026, 1.029, 1.031, 1.032, 1.035, 1.038, 1.043, 1.046, 1.049, 1.054, 1.058, 1.061,
+                            1.068, 1.064, 1.059, 1.055, 1.049, 1.045, 1.041, 1.037, 1.033, 1.029, 1.029, 1.027, 1.025, 1.024, 1.023, 1.023, 1.023, 1.023, 1.023, 1.024, 1.025, 1.028, 1.029, 1.031, 1.034, 1.037, 1.041, 1.045, 1.049, 1.053, 1.056, 1.059
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.036, 1.036, 1.031, 1.028, 1.026, 1.024, 1.021, 1.018, 1.014, 1.012, 1.009, 1.008, 1.006, 1.005, 1.004, 1.004, 1.004, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.012, 1.014, 1.015, 1.018, 1.019, 1.022, 1.024, 1.024,
+                            1.047, 1.044, 1.041, 1.039, 1.036, 1.032, 1.029, 1.026, 1.024, 1.021, 1.019, 1.019, 1.017, 1.016, 1.016, 1.016, 1.016, 1.015, 1.015, 1.016, 1.017, 1.017, 1.018, 1.019, 1.022, 1.025, 1.027, 1.028, 1.031, 1.033, 1.035, 1.035,
+                            1.049, 1.047, 1.044, 1.041, 1.038, 1.035, 1.031, 1.028, 1.026, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.016, 1.017, 1.017, 1.018, 1.019, 1.022, 1.024, 1.026, 1.028, 1.031, 1.033, 1.035, 1.036, 1.037,
+                            1.049, 1.046, 1.044, 1.041, 1.038, 1.034, 1.031, 1.028, 1.025, 1.023, 1.021, 1.018, 1.017, 1.016, 1.015, 1.015, 1.014, 1.014, 1.015, 1.015, 1.016, 1.017, 1.018, 1.021, 1.024, 1.026, 1.028, 1.029, 1.033, 1.035, 1.037, 1.038,
+                            1.047, 1.046, 1.043, 1.041, 1.037, 1.033, 1.031, 1.027, 1.024, 1.021, 1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.012, 1.012, 1.013, 1.014, 1.015, 1.016, 1.018, 1.019, 1.023, 1.025, 1.027, 1.029, 1.032, 1.034, 1.036, 1.038,
+                            1.047, 1.044, 1.042, 1.039, 1.036, 1.032, 1.029, 1.026, 1.022, 1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.009, 1.011, 1.011, 1.013, 1.015, 1.016, 1.018, 1.021, 1.023, 1.026, 1.028, 1.031, 1.033, 1.035, 1.037,
+                            1.045, 1.044, 1.041, 1.039, 1.035, 1.031, 1.028, 1.024, 1.021, 1.018, 1.016, 1.014, 1.012, 1.011, 1.009, 1.008, 1.008, 1.008, 1.009, 1.009, 1.011, 1.013, 1.014, 1.017, 1.019, 1.022, 1.025, 1.027, 1.029, 1.032, 1.035, 1.036,
+                            1.045, 1.044, 1.041, 1.037, 1.034, 1.031, 1.027, 1.024, 1.021, 1.018, 1.015, 1.012, 1.011, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.009, 1.009, 1.011, 1.013, 1.016, 1.018, 1.022, 1.024, 1.027, 1.029, 1.032, 1.034, 1.035,
+                            1.045, 1.043, 1.041, 1.036, 1.034, 1.031, 1.027, 1.023, 1.019, 1.016, 1.013, 1.011, 1.009, 1.007, 1.006, 1.005, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.012, 1.015, 1.018, 1.021, 1.024, 1.025, 1.028, 1.032, 1.033, 1.035,
+                            1.044, 1.043, 1.039, 1.036, 1.032, 1.029, 1.026, 1.022, 1.019, 1.015, 1.013, 1.009, 1.008, 1.006, 1.005, 1.005, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.017, 1.021, 1.023, 1.025, 1.028, 1.031, 1.033, 1.034,
+                            1.044, 1.042, 1.039, 1.035, 1.032, 1.029, 1.025, 1.021, 1.018, 1.015, 1.011, 1.009, 1.007, 1.005, 1.004, 1.004, 1.003, 1.003, 1.004, 1.005, 1.007, 1.008, 1.011, 1.013, 1.016, 1.021, 1.022, 1.025, 1.027, 1.029, 1.033, 1.034,
+                            1.043, 1.041, 1.038, 1.034, 1.032, 1.029, 1.024, 1.021, 1.017, 1.014, 1.011, 1.008, 1.005, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.013, 1.015, 1.019, 1.022, 1.024, 1.026, 1.029, 1.032, 1.033,
+                            1.043, 1.041, 1.038, 1.035, 1.032, 1.029, 1.025, 1.021, 1.017, 1.014, 1.011, 1.008, 1.005, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.005, 1.006, 1.008, 1.009, 1.013, 1.015, 1.019, 1.022, 1.024, 1.026, 1.029, 1.032, 1.033,
+                            1.043, 1.041, 1.039, 1.034, 1.032, 1.029, 1.024, 1.021, 1.018, 1.014, 1.011, 1.008, 1.006, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013, 1.015, 1.019, 1.022, 1.024, 1.026, 1.029, 1.031, 1.034,
+                            1.043, 1.041, 1.038, 1.035, 1.032, 1.029, 1.025, 1.021, 1.018, 1.014, 1.011, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.006, 1.008, 1.009, 1.012, 1.016, 1.019, 1.022, 1.024, 1.027, 1.029, 1.032, 1.032,
+                            1.043, 1.041, 1.038, 1.035, 1.032, 1.029, 1.025, 1.021, 1.017, 1.013, 1.011, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.006, 1.008, 1.009, 1.012, 1.016, 1.019, 1.022, 1.024, 1.026, 1.028, 1.032, 1.033,
+                            1.044, 1.041, 1.039, 1.035, 1.032, 1.029, 1.025, 1.022, 1.017, 1.014, 1.011, 1.008, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.008, 1.009, 1.012, 1.015, 1.019, 1.022, 1.024, 1.026, 1.028, 1.031, 1.033,
+                            1.044, 1.041, 1.038, 1.035, 1.032, 1.029, 1.025, 1.022, 1.018, 1.014, 1.011, 1.008, 1.007, 1.005, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.007, 1.008, 1.011, 1.012, 1.016, 1.019, 1.022, 1.025, 1.027, 1.029, 1.032, 1.033,
+                            1.044, 1.041, 1.039, 1.035, 1.033, 1.029, 1.026, 1.022, 1.019, 1.015, 1.012, 1.008, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.016, 1.019, 1.023, 1.025, 1.027, 1.029, 1.032, 1.033,
+                            1.044, 1.041, 1.039, 1.035, 1.032, 1.029, 1.026, 1.022, 1.019, 1.015, 1.012, 1.009, 1.008, 1.006, 1.006, 1.005, 1.005, 1.005, 1.005, 1.006, 1.008, 1.009, 1.011, 1.014, 1.017, 1.021, 1.023, 1.025, 1.028, 1.029, 1.032, 1.034,
+                            1.044, 1.041, 1.038, 1.035, 1.032, 1.029, 1.025, 1.022, 1.018, 1.015, 1.012, 1.009, 1.008, 1.006, 1.005, 1.005, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.012, 1.014, 1.017, 1.021, 1.023, 1.025, 1.027, 1.029, 1.032, 1.033,
+                            1.044, 1.041, 1.038, 1.035, 1.032, 1.029, 1.025, 1.022, 1.018, 1.015, 1.012, 1.009, 1.009, 1.007, 1.006, 1.006, 1.006, 1.006, 1.006, 1.007, 1.009, 1.011, 1.012, 1.015, 1.017, 1.021, 1.023, 1.025, 1.027, 1.031, 1.032, 1.033,
+                            1.044, 1.042, 1.039, 1.036, 1.033, 1.029, 1.026, 1.022, 1.019, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.007, 1.009, 1.009, 1.011, 1.013, 1.015, 1.018, 1.021, 1.024, 1.025, 1.028, 1.031, 1.032, 1.033,
+                            1.045, 1.043, 1.039, 1.036, 1.033, 1.029, 1.027, 1.023, 1.019, 1.016, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.008, 1.009, 1.009, 1.011, 1.013, 1.014, 1.016, 1.018, 1.022, 1.024, 1.026, 1.029, 1.031, 1.033, 1.034,
+                            1.046, 1.043, 1.041, 1.037, 1.034, 1.031, 1.028, 1.024, 1.021, 1.018, 1.016, 1.013, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.013, 1.014, 1.015, 1.017, 1.019, 1.022, 1.024, 1.027, 1.031, 1.032, 1.034, 1.035,
+                            1.046, 1.044, 1.041, 1.038, 1.035, 1.031, 1.028, 1.025, 1.021, 1.018, 1.016, 1.015, 1.013, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.014, 1.014, 1.016, 1.018, 1.019, 1.023, 1.025, 1.027, 1.031, 1.032, 1.034, 1.036,
+                            1.047, 1.044, 1.042, 1.039, 1.036, 1.032, 1.029, 1.026, 1.023, 1.019, 1.017, 1.016, 1.015, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.014, 1.016, 1.017, 1.019, 1.021, 1.023, 1.025, 1.028, 1.031, 1.033, 1.035, 1.037,
+                            1.048, 1.046, 1.043, 1.041, 1.037, 1.033, 1.029, 1.027, 1.024, 1.021, 1.019, 1.017, 1.016, 1.015, 1.015, 1.015, 1.014, 1.015, 1.015, 1.015, 1.016, 1.017, 1.019, 1.019, 1.022, 1.023, 1.026, 1.029, 1.032, 1.034, 1.036, 1.037,
+                            1.049, 1.047, 1.043, 1.041, 1.037, 1.034, 1.029, 1.028, 1.025, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.016, 1.017, 1.018, 1.018, 1.019, 1.021, 1.022, 1.024, 1.027, 1.029, 1.033, 1.035, 1.037, 1.037,
+                            1.049, 1.048, 1.044, 1.041, 1.038, 1.034, 1.031, 1.028, 1.026, 1.023, 1.021, 1.021, 1.019, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.019, 1.019, 1.021, 1.022, 1.023, 1.025, 1.028, 1.031, 1.033, 1.036, 1.037, 1.038,
+                            1.051, 1.047, 1.044, 1.041, 1.038, 1.034, 1.031, 1.028, 1.026, 1.024, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.022, 1.022, 1.024, 1.026, 1.029, 1.031, 1.034, 1.036, 1.038, 1.039,
+                            1.051, 1.048, 1.045, 1.042, 1.038, 1.034, 1.032, 1.028, 1.026, 1.025, 1.023, 1.022, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.022, 1.025, 1.027, 1.029, 1.032, 1.034, 1.036, 1.039, 1.039
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.048, 1.048, 1.042, 1.038, 1.035, 1.033, 1.028, 1.025, 1.022, 1.019, 1.016, 1.015, 1.012, 1.009, 1.008, 1.008, 1.007, 1.007, 1.007, 1.008, 1.011, 1.011, 1.012, 1.015, 1.017, 1.018, 1.021, 1.021, 1.023, 1.028, 1.029, 1.029,
+                            1.059, 1.054, 1.052, 1.048, 1.044, 1.039, 1.036, 1.033, 1.031, 1.028, 1.025, 1.024, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.023, 1.024, 1.027, 1.029, 1.032, 1.033, 1.036, 1.038, 1.041, 1.043,
+                            1.061, 1.057, 1.053, 1.051, 1.047, 1.043, 1.039, 1.035, 1.032, 1.029, 1.026, 1.024, 1.023, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.023, 1.026, 1.028, 1.031, 1.032, 1.035, 1.037, 1.039, 1.043, 1.044,
+                            1.059, 1.055, 1.052, 1.051, 1.046, 1.042, 1.038, 1.035, 1.031, 1.028, 1.025, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.017, 1.017, 1.018, 1.018, 1.019, 1.021, 1.024, 1.027, 1.029, 1.031, 1.033, 1.036, 1.039, 1.041, 1.043,
+                            1.057, 1.055, 1.052, 1.049, 1.045, 1.041, 1.036, 1.033, 1.029, 1.026, 1.023, 1.021, 1.019, 1.017, 1.016, 1.015, 1.014, 1.014, 1.015, 1.016, 1.016, 1.017, 1.019, 1.022, 1.025, 1.028, 1.029, 1.032, 1.036, 1.038, 1.039, 1.041,
+                            1.057, 1.054, 1.051, 1.048, 1.044, 1.039, 1.035, 1.032, 1.028, 1.024, 1.021, 1.019, 1.017, 1.015, 1.014, 1.013, 1.013, 1.013, 1.014, 1.014, 1.015, 1.016, 1.018, 1.021, 1.024, 1.027, 1.029, 1.032, 1.034, 1.038, 1.039, 1.041,
+                            1.056, 1.054, 1.051, 1.048, 1.044, 1.039, 1.034, 1.031, 1.027, 1.023, 1.021, 1.018, 1.016, 1.014, 1.012, 1.011, 1.011, 1.011, 1.012, 1.013, 1.014, 1.015, 1.017, 1.019, 1.023, 1.026, 1.029, 1.032, 1.034, 1.037, 1.039, 1.041,
+                            1.056, 1.053, 1.051, 1.046, 1.043, 1.038, 1.034, 1.029, 1.025, 1.022, 1.019, 1.016, 1.014, 1.011, 1.011, 1.009, 1.009, 1.009, 1.009, 1.011, 1.012, 1.014, 1.015, 1.018, 1.021, 1.026, 1.027, 1.031, 1.034, 1.037, 1.038, 1.039,
+                            1.055, 1.053, 1.049, 1.045, 1.041, 1.037, 1.032, 1.028, 1.023, 1.021, 1.017, 1.014, 1.011, 1.009, 1.008, 1.007, 1.006, 1.007, 1.007, 1.008, 1.011, 1.012, 1.014, 1.016, 1.019, 1.024, 1.026, 1.029, 1.032, 1.036, 1.038, 1.039,
+                            1.054, 1.052, 1.048, 1.044, 1.039, 1.035, 1.031, 1.027, 1.022, 1.019, 1.015, 1.012, 1.009, 1.008, 1.006, 1.005, 1.004, 1.005, 1.005, 1.006, 1.008, 1.011, 1.012, 1.015, 1.018, 1.022, 1.025, 1.028, 1.031, 1.034, 1.037, 1.038,
+                            1.054, 1.051, 1.048, 1.043, 1.039, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.008, 1.006, 1.005, 1.004, 1.004, 1.003, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.017, 1.022, 1.025, 1.027, 1.031, 1.034, 1.037, 1.037,
+                            1.053, 1.052, 1.047, 1.043, 1.039, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.008, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.018, 1.022, 1.025, 1.027, 1.031, 1.033, 1.037, 1.037,
+                            1.054, 1.051, 1.047, 1.043, 1.039, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.008, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.018, 1.022, 1.025, 1.028, 1.029, 1.033, 1.036, 1.038,
+                            1.053, 1.051, 1.046, 1.041, 1.038, 1.035, 1.029, 1.024, 1.021, 1.017, 1.013, 1.009, 1.007, 1.005, 1.005, 1.004, 1.004, 1.003, 1.003, 1.005, 1.006, 1.009, 1.011, 1.013, 1.016, 1.021, 1.025, 1.027, 1.029, 1.033, 1.035, 1.037,
+                            1.052, 1.049, 1.046, 1.042, 1.038, 1.034, 1.029, 1.024, 1.021, 1.016, 1.012, 1.009, 1.006, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013, 1.016, 1.021, 1.024, 1.027, 1.029, 1.033, 1.035, 1.037,
+                            1.052, 1.049, 1.046, 1.042, 1.038, 1.034, 1.029, 1.025, 1.021, 1.017, 1.013, 1.009, 1.007, 1.006, 1.005, 1.004, 1.004, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013, 1.017, 1.021, 1.024, 1.027, 1.029, 1.032, 1.035, 1.037,
+                            1.053, 1.051, 1.047, 1.044, 1.039, 1.035, 1.031, 1.026, 1.021, 1.018, 1.013, 1.011, 1.008, 1.006, 1.006, 1.005, 1.005, 1.004, 1.004, 1.005, 1.007, 1.009, 1.012, 1.014, 1.017, 1.022, 1.025, 1.028, 1.031, 1.033, 1.036, 1.038,
+                            1.053, 1.051, 1.047, 1.044, 1.039, 1.036, 1.031, 1.026, 1.021, 1.018, 1.014, 1.011, 1.008, 1.007, 1.006, 1.006, 1.005, 1.004, 1.005, 1.006, 1.008, 1.011, 1.012, 1.014, 1.017, 1.022, 1.025, 1.029, 1.031, 1.033, 1.036, 1.037,
+                            1.053, 1.051, 1.047, 1.043, 1.039, 1.036, 1.031, 1.026, 1.021, 1.017, 1.014, 1.011, 1.008, 1.006, 1.006, 1.005, 1.005, 1.004, 1.005, 1.005, 1.008, 1.009, 1.012, 1.015, 1.017, 1.022, 1.025, 1.028, 1.031, 1.033, 1.035, 1.037,
+                            1.053, 1.051, 1.046, 1.042, 1.039, 1.035, 1.031, 1.025, 1.021, 1.017, 1.014, 1.011, 1.008, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.006, 1.008, 1.011, 1.012, 1.014, 1.017, 1.022, 1.024, 1.027, 1.031, 1.033, 1.035, 1.036,
+                            1.053, 1.049, 1.046, 1.042, 1.039, 1.035, 1.031, 1.026, 1.021, 1.017, 1.015, 1.011, 1.009, 1.007, 1.006, 1.005, 1.005, 1.004, 1.005, 1.007, 1.009, 1.011, 1.013, 1.015, 1.017, 1.022, 1.025, 1.028, 1.031, 1.033, 1.035, 1.036,
+                            1.053, 1.049, 1.047, 1.043, 1.039, 1.036, 1.031, 1.026, 1.022, 1.019, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.007, 1.007, 1.008, 1.011, 1.012, 1.014, 1.016, 1.019, 1.023, 1.026, 1.028, 1.032, 1.034, 1.036, 1.037,
+                            1.054, 1.049, 1.047, 1.044, 1.039, 1.036, 1.032, 1.027, 1.023, 1.019, 1.016, 1.014, 1.011, 1.009, 1.009, 1.009, 1.008, 1.008, 1.009, 1.009, 1.011, 1.013, 1.015, 1.017, 1.019, 1.024, 1.027, 1.029, 1.032, 1.035, 1.036, 1.038,
+                            1.054, 1.051, 1.047, 1.044, 1.041, 1.036, 1.032, 1.027, 1.024, 1.021, 1.017, 1.014, 1.013, 1.011, 1.009, 1.009, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.018, 1.021, 1.024, 1.027, 1.029, 1.031, 1.035, 1.037, 1.037,
+                            1.055, 1.052, 1.048, 1.045, 1.041, 1.036, 1.032, 1.028, 1.024, 1.021, 1.017, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.013, 1.014, 1.016, 1.018, 1.021, 1.024, 1.027, 1.029, 1.032, 1.034, 1.036, 1.037,
+                            1.056, 1.053, 1.049, 1.046, 1.041, 1.036, 1.034, 1.029, 1.025, 1.022, 1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.012, 1.013, 1.013, 1.013, 1.014, 1.016, 1.017, 1.019, 1.022, 1.025, 1.028, 1.029, 1.033, 1.036, 1.037, 1.038,
+                            1.058, 1.055, 1.051, 1.048, 1.044, 1.039, 1.035, 1.031, 1.027, 1.024, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.016, 1.016, 1.017, 1.018, 1.019, 1.021, 1.023, 1.027, 1.029, 1.032, 1.035, 1.037, 1.038, 1.041,
+                            1.059, 1.055, 1.051, 1.049, 1.045, 1.041, 1.036, 1.032, 1.029, 1.026, 1.023, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.018, 1.017, 1.018, 1.018, 1.019, 1.021, 1.023, 1.025, 1.028, 1.029, 1.033, 1.036, 1.038, 1.041, 1.042,
+                            1.059, 1.056, 1.052, 1.049, 1.046, 1.041, 1.036, 1.033, 1.031, 1.027, 1.025, 1.022, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.024, 1.026, 1.028, 1.032, 1.034, 1.037, 1.039, 1.041, 1.044,
+                            1.061, 1.056, 1.051, 1.049, 1.045, 1.041, 1.036, 1.033, 1.031, 1.027, 1.026, 1.023, 1.022, 1.021, 1.019, 1.021, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.024, 1.025, 1.026, 1.029, 1.032, 1.035, 1.037, 1.039, 1.043, 1.045,
+                            1.061, 1.057, 1.052, 1.048, 1.045, 1.042, 1.037, 1.034, 1.031, 1.028, 1.026, 1.025, 1.023, 1.022, 1.022, 1.022, 1.021, 1.021, 1.021, 1.021, 1.022, 1.023, 1.025, 1.026, 1.028, 1.029, 1.033, 1.035, 1.038, 1.041, 1.044, 1.046,
+                            1.061, 1.059, 1.053, 1.048, 1.046, 1.043, 1.037, 1.035, 1.031, 1.029, 1.027, 1.027, 1.025, 1.024, 1.023, 1.023, 1.023, 1.022, 1.023, 1.024, 1.024, 1.024, 1.026, 1.027, 1.029, 1.032, 1.033, 1.035, 1.037, 1.042, 1.044, 1.046
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.044, 1.044, 1.039, 1.034, 1.033, 1.029, 1.027, 1.023, 1.021, 1.018, 1.016, 1.013, 1.012, 1.009, 1.008, 1.008, 1.007, 1.007, 1.007, 1.008, 1.009, 1.009, 1.011, 1.012, 1.013, 1.014, 1.017, 1.018, 1.019, 1.022, 1.024, 1.024,
+                            1.056, 1.052, 1.048, 1.046, 1.043, 1.039, 1.036, 1.033, 1.029, 1.028, 1.025, 1.024, 1.022, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.022, 1.023, 1.025, 1.027, 1.029, 1.031, 1.032, 1.033, 1.035, 1.037,
+                            1.057, 1.055, 1.051, 1.049, 1.046, 1.043, 1.038, 1.035, 1.032, 1.029, 1.027, 1.025, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.023, 1.025, 1.027, 1.029, 1.031, 1.032, 1.034, 1.035, 1.038, 1.038,
+                            1.057, 1.055, 1.052, 1.049, 1.047, 1.042, 1.038, 1.035, 1.032, 1.029, 1.027, 1.024, 1.023, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.023, 1.025, 1.027, 1.029, 1.031, 1.033, 1.035, 1.036, 1.038, 1.039,
+                            1.057, 1.054, 1.051, 1.049, 1.045, 1.041, 1.037, 1.033, 1.031, 1.027, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.017, 1.017, 1.017, 1.018, 1.019, 1.021, 1.023, 1.025, 1.028, 1.029, 1.032, 1.034, 1.036, 1.037, 1.039,
+                            1.056, 1.053, 1.051, 1.048, 1.043, 1.039, 1.035, 1.032, 1.028, 1.025, 1.022, 1.021, 1.018, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014, 1.015, 1.016, 1.017, 1.019, 1.021, 1.023, 1.026, 1.028, 1.031, 1.033, 1.035, 1.036, 1.036,
+                            1.054, 1.052, 1.049, 1.046, 1.042, 1.038, 1.033, 1.029, 1.027, 1.024, 1.021, 1.018, 1.016, 1.014, 1.013, 1.012, 1.012, 1.011, 1.012, 1.013, 1.015, 1.016, 1.017, 1.019, 1.022, 1.025, 1.027, 1.029, 1.032, 1.034, 1.035, 1.036,
+                            1.054, 1.052, 1.049, 1.046, 1.042, 1.038, 1.033, 1.029, 1.026, 1.023, 1.019, 1.017, 1.015, 1.012, 1.011, 1.011, 1.011, 1.009, 1.011, 1.012, 1.014, 1.014, 1.016, 1.018, 1.022, 1.024, 1.027, 1.029, 1.032, 1.035, 1.036, 1.037,
+                            1.054, 1.052, 1.049, 1.045, 1.042, 1.038, 1.033, 1.029, 1.025, 1.021, 1.019, 1.016, 1.013, 1.011, 1.011, 1.009, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.018, 1.021, 1.024, 1.026, 1.029, 1.032, 1.034, 1.036, 1.037,
+                            1.054, 1.051, 1.048, 1.045, 1.041, 1.037, 1.032, 1.029, 1.024, 1.021, 1.017, 1.014, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.007, 1.008, 1.011, 1.012, 1.014, 1.017, 1.019, 1.023, 1.025, 1.027, 1.031, 1.033, 1.035, 1.037,
+                            1.052, 1.051, 1.047, 1.044, 1.039, 1.035, 1.032, 1.027, 1.023, 1.019, 1.015, 1.012, 1.009, 1.008, 1.006, 1.005, 1.005, 1.004, 1.005, 1.007, 1.008, 1.011, 1.013, 1.015, 1.018, 1.021, 1.024, 1.027, 1.029, 1.032, 1.033, 1.035,
+                            1.052, 1.049, 1.046, 1.043, 1.038, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.009, 1.006, 1.006, 1.005, 1.004, 1.003, 1.004, 1.006, 1.008, 1.009, 1.012, 1.014, 1.017, 1.021, 1.024, 1.026, 1.028, 1.031, 1.033, 1.034,
+                            1.052, 1.049, 1.047, 1.042, 1.038, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.009, 1.007, 1.006, 1.006, 1.005, 1.004, 1.004, 1.006, 1.008, 1.011, 1.012, 1.014, 1.018, 1.022, 1.024, 1.026, 1.029, 1.032, 1.034, 1.034,
+                            1.052, 1.051, 1.047, 1.043, 1.039, 1.035, 1.031, 1.026, 1.022, 1.018, 1.015, 1.011, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.004, 1.006, 1.008, 1.011, 1.012, 1.015, 1.018, 1.022, 1.024, 1.027, 1.029, 1.032, 1.034, 1.034,
+                            1.052, 1.049, 1.045, 1.043, 1.039, 1.035, 1.031, 1.026, 1.023, 1.018, 1.014, 1.011, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.005, 1.006, 1.008, 1.009, 1.012, 1.015, 1.018, 1.022, 1.024, 1.027, 1.029, 1.031, 1.033, 1.034,
+                            1.051, 1.049, 1.045, 1.042, 1.038, 1.034, 1.031, 1.025, 1.022, 1.017, 1.013, 1.011, 1.007, 1.006, 1.006, 1.005, 1.005, 1.004, 1.004, 1.005, 1.008, 1.009, 1.011, 1.014, 1.017, 1.021, 1.024, 1.026, 1.029, 1.031, 1.032, 1.033,
+                            1.051, 1.049, 1.045, 1.042, 1.039, 1.035, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.008, 1.007, 1.006, 1.006, 1.005, 1.004, 1.004, 1.006, 1.008, 1.009, 1.011, 1.014, 1.017, 1.021, 1.024, 1.026, 1.029, 1.031, 1.033, 1.033,
+                            1.052, 1.049, 1.046, 1.042, 1.041, 1.035, 1.031, 1.026, 1.022, 1.019, 1.015, 1.012, 1.009, 1.008, 1.007, 1.007, 1.006, 1.005, 1.005, 1.007, 1.008, 1.011, 1.012, 1.015, 1.018, 1.021, 1.025, 1.027, 1.029, 1.032, 1.033, 1.034,
+                            1.053, 1.049, 1.047, 1.043, 1.041, 1.036, 1.032, 1.027, 1.023, 1.019, 1.016, 1.013, 1.009, 1.009, 1.008, 1.008, 1.007, 1.006, 1.006, 1.007, 1.009, 1.012, 1.014, 1.017, 1.019, 1.022, 1.026, 1.028, 1.031, 1.033, 1.034, 1.035,
+                            1.052, 1.051, 1.046, 1.043, 1.039, 1.036, 1.032, 1.027, 1.022, 1.019, 1.016, 1.012, 1.011, 1.008, 1.007, 1.007, 1.007, 1.006, 1.006, 1.008, 1.011, 1.012, 1.014, 1.016, 1.019, 1.023, 1.025, 1.028, 1.031, 1.032, 1.034, 1.034,
+                            1.051, 1.048, 1.045, 1.042, 1.038, 1.035, 1.031, 1.026, 1.022, 1.018, 1.015, 1.012, 1.011, 1.008, 1.007, 1.006, 1.006, 1.006, 1.006, 1.008, 1.011, 1.012, 1.013, 1.015, 1.019, 1.022, 1.024, 1.027, 1.029, 1.031, 1.033, 1.034,
+                            1.051, 1.048, 1.045, 1.041, 1.038, 1.034, 1.031, 1.026, 1.022, 1.018, 1.015, 1.012, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.007, 1.009, 1.011, 1.012, 1.014, 1.016, 1.019, 1.023, 1.025, 1.027, 1.028, 1.031, 1.032, 1.033,
+                            1.051, 1.049, 1.046, 1.042, 1.038, 1.035, 1.031, 1.027, 1.023, 1.019, 1.016, 1.014, 1.012, 1.011, 1.009, 1.009, 1.008, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017, 1.021, 1.024, 1.025, 1.028, 1.029, 1.032, 1.033, 1.034,
+                            1.052, 1.049, 1.047, 1.043, 1.041, 1.036, 1.033, 1.028, 1.024, 1.021, 1.018, 1.016, 1.014, 1.013, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.014, 1.015, 1.017, 1.019, 1.021, 1.024, 1.026, 1.029, 1.031, 1.033, 1.034, 1.035,
+                            1.054, 1.051, 1.048, 1.044, 1.041, 1.037, 1.033, 1.029, 1.025, 1.022, 1.019, 1.017, 1.015, 1.014, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.015, 1.016, 1.017, 1.019, 1.022, 1.025, 1.027, 1.028, 1.031, 1.034, 1.034, 1.036,
+                            1.053, 1.051, 1.048, 1.044, 1.041, 1.037, 1.033, 1.029, 1.025, 1.022, 1.019, 1.018, 1.017, 1.015, 1.015, 1.014, 1.014, 1.014, 1.014, 1.015, 1.015, 1.017, 1.018, 1.021, 1.022, 1.025, 1.027, 1.029, 1.031, 1.033, 1.035, 1.036,
+                            1.055, 1.051, 1.049, 1.046, 1.042, 1.038, 1.034, 1.031, 1.027, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.015, 1.015, 1.016, 1.017, 1.017, 1.018, 1.021, 1.023, 1.025, 1.027, 1.029, 1.032, 1.033, 1.036, 1.037,
+                            1.056, 1.053, 1.049, 1.047, 1.043, 1.039, 1.036, 1.033, 1.029, 1.026, 1.023, 1.022, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.019, 1.021, 1.022, 1.025, 1.027, 1.029, 1.031, 1.033, 1.035, 1.037, 1.039,
+                            1.057, 1.054, 1.049, 1.048, 1.044, 1.041, 1.037, 1.034, 1.031, 1.029, 1.026, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.022, 1.023, 1.024, 1.026, 1.028, 1.031, 1.033, 1.034, 1.036, 1.039, 1.041,
+                            1.057, 1.054, 1.051, 1.048, 1.044, 1.041, 1.037, 1.033, 1.031, 1.029, 1.027, 1.025, 1.024, 1.022, 1.022, 1.021, 1.021, 1.021, 1.021, 1.021, 1.023, 1.023, 1.024, 1.025, 1.027, 1.029, 1.031, 1.033, 1.035, 1.037, 1.039, 1.042,
+                            1.057, 1.053, 1.049, 1.047, 1.044, 1.041, 1.037, 1.034, 1.031, 1.029, 1.027, 1.025, 1.024, 1.023, 1.022, 1.022, 1.022, 1.022, 1.022, 1.022, 1.023, 1.024, 1.025, 1.025, 1.026, 1.029, 1.031, 1.033, 1.035, 1.038, 1.041, 1.042,
+                            1.057, 1.053, 1.049, 1.046, 1.044, 1.041, 1.036, 1.034, 1.031, 1.029, 1.027, 1.025, 1.024, 1.023, 1.023, 1.023, 1.022, 1.022, 1.022, 1.022, 1.024, 1.024, 1.025, 1.025, 1.027, 1.029, 1.031, 1.032, 1.035, 1.039, 1.041, 1.042
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.067, 1.066, 1.061, 1.055, 1.051, 1.046, 1.038, 1.034, 1.029, 1.026, 1.023, 1.019, 1.017, 1.014, 1.013, 1.011, 1.011, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.016, 1.021, 1.021, 1.024, 1.027, 1.029, 1.034, 1.036, 1.036,
+                            1.075, 1.071, 1.065, 1.061, 1.055, 1.049, 1.044, 1.041, 1.037, 1.034, 1.029, 1.027, 1.025, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.021, 1.022, 1.023, 1.024, 1.026, 1.029, 1.033, 1.035, 1.036, 1.039, 1.043, 1.046, 1.047,
+                            1.078, 1.074, 1.071, 1.065, 1.061, 1.053, 1.048, 1.043, 1.039, 1.036, 1.032, 1.029, 1.027, 1.024, 1.022, 1.022, 1.021, 1.021, 1.021, 1.021, 1.022, 1.023, 1.025, 1.028, 1.031, 1.034, 1.036, 1.038, 1.043, 1.046, 1.048, 1.049,
+                            1.078, 1.074, 1.071, 1.065, 1.059, 1.053, 1.048, 1.042, 1.038, 1.035, 1.031, 1.028, 1.025, 1.023, 1.021, 1.021, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.024, 1.026, 1.031, 1.034, 1.035, 1.038, 1.043, 1.045, 1.048, 1.049,
+                            1.077, 1.073, 1.068, 1.063, 1.057, 1.052, 1.045, 1.039, 1.036, 1.033, 1.029, 1.025, 1.023, 1.021, 1.019, 1.017, 1.016, 1.015, 1.016, 1.017, 1.018, 1.021, 1.022, 1.025, 1.028, 1.032, 1.033, 1.037, 1.041, 1.045, 1.047, 1.048,
+                            1.075, 1.072, 1.067, 1.062, 1.056, 1.049, 1.043, 1.038, 1.035, 1.031, 1.027, 1.023, 1.021, 1.017, 1.016, 1.014, 1.014, 1.013, 1.013, 1.014, 1.016, 1.017, 1.019, 1.023, 1.025, 1.031, 1.033, 1.035, 1.039, 1.044, 1.046, 1.047,
+                            1.075, 1.071, 1.066, 1.061, 1.055, 1.049, 1.043, 1.038, 1.033, 1.028, 1.024, 1.021, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.011, 1.013, 1.014, 1.016, 1.018, 1.021, 1.025, 1.029, 1.032, 1.035, 1.039, 1.043, 1.045, 1.047,
+                            1.074, 1.071, 1.065, 1.059, 1.052, 1.049, 1.042, 1.037, 1.031, 1.026, 1.023, 1.019, 1.017, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009, 1.011, 1.013, 1.014, 1.016, 1.019, 1.024, 1.028, 1.032, 1.034, 1.039, 1.042, 1.046, 1.047,
+                            1.073, 1.071, 1.065, 1.059, 1.053, 1.047, 1.041, 1.036, 1.031, 1.026, 1.021, 1.018, 1.015, 1.012, 1.011, 1.009, 1.008, 1.008, 1.009, 1.009, 1.011, 1.013, 1.015, 1.019, 1.023, 1.027, 1.031, 1.034, 1.038, 1.041, 1.045, 1.047,
+                            1.073, 1.069, 1.063, 1.056, 1.051, 1.045, 1.041, 1.035, 1.029, 1.023, 1.019, 1.016, 1.013, 1.009, 1.008, 1.006, 1.005, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.017, 1.021, 1.026, 1.029, 1.032, 1.036, 1.041, 1.043, 1.045,
+                            1.071, 1.068, 1.062, 1.056, 1.049, 1.044, 1.039, 1.034, 1.028, 1.022, 1.018, 1.014, 1.011, 1.008, 1.006, 1.005, 1.004, 1.003, 1.004, 1.005, 1.007, 1.009, 1.012, 1.016, 1.019, 1.024, 1.028, 1.031, 1.034, 1.039, 1.042, 1.044,
+                            1.071, 1.067, 1.061, 1.055, 1.049, 1.044, 1.038, 1.034, 1.027, 1.022, 1.017, 1.013, 1.011, 1.008, 1.005, 1.005, 1.003, 1.002, 1.003, 1.004, 1.006, 1.008, 1.011, 1.015, 1.019, 1.024, 1.027, 1.031, 1.034, 1.038, 1.042, 1.043,
+                            1.069, 1.067, 1.061, 1.054, 1.049, 1.044, 1.038, 1.033, 1.027, 1.022, 1.017, 1.013, 1.009, 1.008, 1.006, 1.005, 1.004, 1.002, 1.003, 1.004, 1.007, 1.009, 1.011, 1.015, 1.019, 1.024, 1.027, 1.031, 1.035, 1.038, 1.042, 1.044,
+                            1.069, 1.067, 1.059, 1.054, 1.049, 1.045, 1.039, 1.033, 1.027, 1.022, 1.017, 1.014, 1.011, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.004, 1.007, 1.009, 1.012, 1.015, 1.019, 1.024, 1.028, 1.031, 1.035, 1.038, 1.042, 1.044,
+                            1.069, 1.066, 1.059, 1.054, 1.049, 1.043, 1.038, 1.033, 1.027, 1.022, 1.017, 1.013, 1.009, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.004, 1.007, 1.009, 1.011, 1.015, 1.019, 1.024, 1.027, 1.031, 1.035, 1.038, 1.041, 1.043,
+                            1.069, 1.065, 1.059, 1.054, 1.049, 1.044, 1.038, 1.032, 1.027, 1.021, 1.017, 1.014, 1.009, 1.008, 1.006, 1.006, 1.005, 1.004, 1.003, 1.004, 1.007, 1.009, 1.011, 1.015, 1.019, 1.024, 1.027, 1.031, 1.034, 1.038, 1.042, 1.043,
+                            1.069, 1.066, 1.061, 1.055, 1.049, 1.045, 1.039, 1.033, 1.027, 1.022, 1.017, 1.014, 1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.004, 1.005, 1.007, 1.009, 1.012, 1.015, 1.019, 1.024, 1.028, 1.031, 1.034, 1.038, 1.042, 1.044,
+                            1.069, 1.067, 1.062, 1.055, 1.051, 1.046, 1.039, 1.034, 1.029, 1.022, 1.019, 1.016, 1.012, 1.009, 1.008, 1.007, 1.006, 1.006, 1.005, 1.006, 1.008, 1.011, 1.013, 1.017, 1.021, 1.025, 1.029, 1.033, 1.036, 1.039, 1.043, 1.045,
+                            1.069, 1.068, 1.062, 1.056, 1.051, 1.046, 1.041, 1.035, 1.029, 1.024, 1.019, 1.016, 1.013, 1.011, 1.009, 1.008, 1.007, 1.007, 1.007, 1.008, 1.009, 1.012, 1.015, 1.017, 1.021, 1.027, 1.031, 1.033, 1.037, 1.039, 1.043, 1.045,
+                            1.071, 1.067, 1.061, 1.056, 1.051, 1.046, 1.041, 1.035, 1.029, 1.023, 1.019, 1.017, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.007, 1.009, 1.011, 1.013, 1.015, 1.018, 1.022, 1.027, 1.031, 1.033, 1.036, 1.041, 1.043, 1.044,
+                            1.069, 1.066, 1.061, 1.055, 1.049, 1.045, 1.041, 1.034, 1.029, 1.024, 1.021, 1.016, 1.014, 1.011, 1.009, 1.009, 1.007, 1.007, 1.008, 1.009, 1.011, 1.013, 1.016, 1.019, 1.022, 1.027, 1.029, 1.033, 1.036, 1.039, 1.043, 1.044,
+                            1.069, 1.066, 1.061, 1.055, 1.049, 1.045, 1.041, 1.034, 1.029, 1.024, 1.022, 1.017, 1.015, 1.012, 1.011, 1.009, 1.008, 1.008, 1.009, 1.009, 1.012, 1.014, 1.017, 1.019, 1.023, 1.027, 1.031, 1.033, 1.037, 1.041, 1.044, 1.045,
+                            1.071, 1.067, 1.061, 1.056, 1.051, 1.046, 1.041, 1.035, 1.031, 1.026, 1.022, 1.019, 1.017, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.013, 1.014, 1.016, 1.018, 1.022, 1.025, 1.029, 1.032, 1.034, 1.038, 1.041, 1.044, 1.046,
+                            1.072, 1.069, 1.063, 1.058, 1.053, 1.047, 1.042, 1.037, 1.033, 1.028, 1.023, 1.021, 1.019, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.016, 1.017, 1.019, 1.021, 1.023, 1.026, 1.031, 1.033, 1.036, 1.039, 1.043, 1.045, 1.047,
+                            1.073, 1.069, 1.064, 1.059, 1.054, 1.048, 1.044, 1.039, 1.035, 1.029, 1.026, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.017, 1.019, 1.021, 1.022, 1.025, 1.028, 1.031, 1.033, 1.037, 1.039, 1.044, 1.046, 1.047,
+                            1.075, 1.071, 1.065, 1.061, 1.055, 1.049, 1.044, 1.041, 1.036, 1.031, 1.028, 1.026, 1.023, 1.022, 1.019, 1.019, 1.018, 1.018, 1.018, 1.019, 1.021, 1.022, 1.024, 1.026, 1.028, 1.032, 1.035, 1.037, 1.041, 1.044, 1.047, 1.049,
+                            1.076, 1.071, 1.066, 1.062, 1.057, 1.051, 1.047, 1.042, 1.038, 1.034, 1.031, 1.027, 1.026, 1.023, 1.022, 1.022, 1.021, 1.021, 1.021, 1.022, 1.023, 1.024, 1.026, 1.028, 1.029, 1.033, 1.036, 1.039, 1.043, 1.046, 1.048, 1.049,
+                            1.078, 1.073, 1.069, 1.064, 1.059, 1.054, 1.049, 1.044, 1.041, 1.036, 1.033, 1.031, 1.028, 1.027, 1.026, 1.026, 1.024, 1.024, 1.024, 1.025, 1.026, 1.028, 1.029, 1.031, 1.033, 1.035, 1.039, 1.041, 1.045, 1.049, 1.051, 1.054,
+                            1.081, 1.076, 1.071, 1.066, 1.061, 1.056, 1.051, 1.046, 1.043, 1.039, 1.037, 1.034, 1.031, 1.029, 1.029, 1.029, 1.028, 1.027, 1.028, 1.029, 1.029, 1.031, 1.032, 1.033, 1.034, 1.037, 1.041, 1.044, 1.047, 1.051, 1.054, 1.056,
+                            1.081, 1.077, 1.072, 1.067, 1.062, 1.057, 1.052, 1.048, 1.044, 1.041, 1.038, 1.036, 1.034, 1.033, 1.032, 1.031, 1.031, 1.029, 1.029, 1.031, 1.031, 1.033, 1.034, 1.035, 1.036, 1.039, 1.042, 1.045, 1.049, 1.052, 1.056, 1.057,
+                            1.082, 1.077, 1.072, 1.067, 1.062, 1.057, 1.052, 1.048, 1.044, 1.043, 1.041, 1.038, 1.037, 1.035, 1.033, 1.032, 1.032, 1.031, 1.031, 1.032, 1.033, 1.034, 1.035, 1.036, 1.038, 1.041, 1.043, 1.046, 1.051, 1.053, 1.056, 1.058,
+                            1.083, 1.078, 1.072, 1.066, 1.061, 1.056, 1.052, 1.049, 1.044, 1.043, 1.041, 1.039, 1.038, 1.036, 1.035, 1.033, 1.033, 1.032, 1.032, 1.033, 1.033, 1.034, 1.035, 1.036, 1.038, 1.042, 1.044, 1.047, 1.052, 1.054, 1.056, 1.058
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.061, 1.061, 1.063, 1.061, 1.059, 1.059, 1.058, 1.056, 1.054, 1.054, 1.053, 1.053, 1.053, 1.051, 1.047, 1.047, 1.046, 1.045, 1.045, 1.044, 1.042, 1.042, 1.041, 1.039, 1.036, 1.034, 1.032, 1.029, 1.025, 1.024, 1.021, 1.019,
+                            1.058, 1.057, 1.057, 1.057, 1.057, 1.055, 1.054, 1.052, 1.051, 1.049, 1.048, 1.047, 1.047, 1.046, 1.044, 1.042, 1.041, 1.039, 1.039, 1.039, 1.037, 1.036, 1.035, 1.035, 1.033, 1.032, 1.031, 1.027, 1.025, 1.023, 1.018, 1.016,
+                            1.058, 1.057, 1.057, 1.057, 1.056, 1.056, 1.053, 1.051, 1.049, 1.048, 1.046, 1.045, 1.045, 1.044, 1.042, 1.041, 1.039, 1.038, 1.038, 1.037, 1.036, 1.035, 1.034, 1.032, 1.032, 1.031, 1.028, 1.027, 1.025, 1.019, 1.017, 1.016,
+                            1.059, 1.058, 1.057, 1.056, 1.056, 1.056, 1.054, 1.052, 1.049, 1.046, 1.045, 1.044, 1.043, 1.042, 1.041, 1.039, 1.038, 1.037, 1.037, 1.035, 1.035, 1.033, 1.032, 1.032, 1.031, 1.031, 1.028, 1.026, 1.025, 1.021, 1.018, 1.016,
+                            1.059, 1.058, 1.056, 1.055, 1.055, 1.055, 1.053, 1.051, 1.048, 1.046, 1.044, 1.043, 1.042, 1.041, 1.039, 1.037, 1.036, 1.035, 1.035, 1.034, 1.033, 1.031, 1.031, 1.031, 1.031, 1.029, 1.027, 1.026, 1.024, 1.021, 1.017, 1.016,
+                            1.059, 1.058, 1.056, 1.054, 1.053, 1.053, 1.051, 1.049, 1.047, 1.045, 1.042, 1.041, 1.041, 1.038, 1.037, 1.036, 1.034, 1.033, 1.033, 1.032, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.027, 1.025, 1.023, 1.021, 1.017, 1.016,
+                            1.058, 1.057, 1.055, 1.053, 1.052, 1.051, 1.049, 1.048, 1.046, 1.042, 1.041, 1.039, 1.038, 1.037, 1.035, 1.033, 1.032, 1.031, 1.031, 1.031, 1.029, 1.028, 1.028, 1.029, 1.029, 1.028, 1.026, 1.024, 1.022, 1.021, 1.016, 1.015,
+                            1.058, 1.057, 1.056, 1.053, 1.052, 1.051, 1.048, 1.047, 1.044, 1.041, 1.041, 1.039, 1.037, 1.035, 1.034, 1.032, 1.029, 1.029, 1.029, 1.029, 1.027, 1.026, 1.027, 1.028, 1.028, 1.028, 1.025, 1.024, 1.022, 1.019, 1.016, 1.014,
+                            1.057, 1.057, 1.056, 1.054, 1.052, 1.049, 1.048, 1.045, 1.043, 1.041, 1.039, 1.038, 1.035, 1.034, 1.032, 1.029, 1.028, 1.028, 1.028, 1.027, 1.026, 1.025, 1.025, 1.026, 1.027, 1.028, 1.025, 1.024, 1.022, 1.019, 1.016, 1.014,
+                            1.056, 1.055, 1.056, 1.054, 1.052, 1.049, 1.046, 1.044, 1.042, 1.039, 1.038, 1.036, 1.034, 1.033, 1.031, 1.028, 1.027, 1.027, 1.026, 1.025, 1.024, 1.024, 1.023, 1.025, 1.027, 1.027, 1.024, 1.023, 1.021, 1.019, 1.017, 1.012,
+                            1.055, 1.054, 1.054, 1.053, 1.052, 1.049, 1.046, 1.043, 1.041, 1.038, 1.036, 1.035, 1.033, 1.031, 1.029, 1.027, 1.026, 1.024, 1.024, 1.024, 1.023, 1.022, 1.022, 1.023, 1.025, 1.025, 1.024, 1.022, 1.021, 1.019, 1.014, 1.012,
+                            1.054, 1.052, 1.052, 1.052, 1.051, 1.049, 1.046, 1.043, 1.039, 1.036, 1.035, 1.033, 1.031, 1.029, 1.027, 1.026, 1.024, 1.023, 1.022, 1.022, 1.022, 1.021, 1.021, 1.021, 1.023, 1.024, 1.024, 1.022, 1.021, 1.019, 1.014, 1.011,
+                            1.053, 1.052, 1.052, 1.051, 1.049, 1.048, 1.046, 1.043, 1.038, 1.036, 1.034, 1.032, 1.031, 1.029, 1.027, 1.025, 1.024, 1.022, 1.022, 1.022, 1.022, 1.021, 1.021, 1.021, 1.022, 1.023, 1.023, 1.022, 1.021, 1.018, 1.012, 1.011,
+                            1.053, 1.052, 1.052, 1.049, 1.049, 1.047, 1.045, 1.042, 1.038, 1.035, 1.033, 1.031, 1.029, 1.028, 1.026, 1.025, 1.023, 1.022, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.022, 1.023, 1.023, 1.021, 1.021, 1.019, 1.013, 1.011,
+                            1.053, 1.052, 1.051, 1.049, 1.048, 1.047, 1.044, 1.042, 1.039, 1.035, 1.033, 1.031, 1.028, 1.027, 1.026, 1.025, 1.023, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.023, 1.023, 1.022, 1.021, 1.019, 1.018, 1.013, 1.011,
+                            1.052, 1.052, 1.051, 1.049, 1.048, 1.046, 1.043, 1.041, 1.038, 1.035, 1.032, 1.029, 1.028, 1.027, 1.026, 1.025, 1.022, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.022, 1.022, 1.022, 1.021, 1.019, 1.019, 1.013, 1.011,
+                            1.051, 1.051, 1.051, 1.049, 1.048, 1.045, 1.043, 1.041, 1.037, 1.034, 1.032, 1.029, 1.028, 1.027, 1.026, 1.025, 1.022, 1.021, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.022, 1.022, 1.022, 1.021, 1.019, 1.018, 1.013, 1.009,
+                            1.051, 1.051, 1.051, 1.049, 1.048, 1.046, 1.043, 1.039, 1.037, 1.034, 1.031, 1.029, 1.028, 1.027, 1.025, 1.024, 1.023, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.023, 1.023, 1.022, 1.019, 1.019, 1.017, 1.012, 1.009,
+                            1.051, 1.051, 1.049, 1.049, 1.048, 1.046, 1.043, 1.039, 1.037, 1.034, 1.032, 1.029, 1.028, 1.026, 1.025, 1.024, 1.022, 1.019, 1.019, 1.021, 1.022, 1.022, 1.022, 1.022, 1.023, 1.023, 1.022, 1.019, 1.019, 1.017, 1.013, 1.009,
+                            1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.039, 1.037, 1.033, 1.031, 1.029, 1.028, 1.026, 1.025, 1.024, 1.022, 1.021, 1.021, 1.021, 1.022, 1.022, 1.022, 1.022, 1.023, 1.023, 1.022, 1.019, 1.018, 1.016, 1.013, 1.008,
+                            1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.042, 1.039, 1.036, 1.034, 1.032, 1.029, 1.028, 1.027, 1.025, 1.024, 1.022, 1.021, 1.021, 1.022, 1.022, 1.022, 1.022, 1.022, 1.023, 1.023, 1.023, 1.019, 1.018, 1.016, 1.013, 1.008,
+                            1.048, 1.047, 1.047, 1.046, 1.045, 1.044, 1.041, 1.039, 1.036, 1.034, 1.032, 1.031, 1.029, 1.027, 1.026, 1.024, 1.023, 1.022, 1.022, 1.022, 1.023, 1.023, 1.021, 1.021, 1.022, 1.023, 1.023, 1.019, 1.017, 1.015, 1.011, 1.008,
+                            1.046, 1.045, 1.045, 1.045, 1.044, 1.042, 1.041, 1.038, 1.036, 1.034, 1.032, 1.031, 1.029, 1.028, 1.027, 1.025, 1.024, 1.022, 1.022, 1.023, 1.024, 1.023, 1.022, 1.021, 1.022, 1.023, 1.023, 1.018, 1.016, 1.014, 1.011, 1.007,
+                            1.044, 1.044, 1.044, 1.044, 1.043, 1.042, 1.041, 1.038, 1.036, 1.035, 1.033, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.023, 1.024, 1.024, 1.024, 1.022, 1.022, 1.022, 1.023, 1.023, 1.018, 1.015, 1.014, 1.011, 1.007,
+                            1.044, 1.044, 1.044, 1.043, 1.043, 1.042, 1.041, 1.038, 1.037, 1.035, 1.033, 1.032, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.024, 1.025, 1.025, 1.024, 1.023, 1.022, 1.022, 1.023, 1.022, 1.017, 1.015, 1.013, 1.011, 1.007,
+                            1.043, 1.043, 1.043, 1.042, 1.043, 1.042, 1.041, 1.039, 1.037, 1.036, 1.034, 1.032, 1.031, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.025, 1.026, 1.025, 1.023, 1.022, 1.022, 1.023, 1.022, 1.017, 1.015, 1.013, 1.011, 1.007,
+                            1.042, 1.042, 1.042, 1.042, 1.043, 1.042, 1.041, 1.039, 1.038, 1.036, 1.035, 1.033, 1.032, 1.031, 1.029, 1.029, 1.028, 1.027, 1.026, 1.026, 1.026, 1.025, 1.024, 1.023, 1.023, 1.023, 1.022, 1.018, 1.015, 1.013, 1.009, 1.007,
+                            1.042, 1.042, 1.042, 1.041, 1.042, 1.042, 1.041, 1.039, 1.038, 1.037, 1.035, 1.034, 1.033, 1.032, 1.031, 1.029, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.024, 1.023, 1.024, 1.023, 1.022, 1.017, 1.016, 1.013, 1.011, 1.005,
+                            1.043, 1.042, 1.042, 1.042, 1.042, 1.041, 1.041, 1.039, 1.038, 1.037, 1.036, 1.035, 1.034, 1.033, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.024, 1.024, 1.023, 1.022, 1.018, 1.016, 1.013, 1.011, 1.006,
+                            1.042, 1.041, 1.041, 1.041, 1.042, 1.041, 1.041, 1.039, 1.039, 1.038, 1.037, 1.036, 1.035, 1.034, 1.033, 1.032, 1.031, 1.029, 1.028, 1.028, 1.028, 1.027, 1.026, 1.024, 1.024, 1.023, 1.022, 1.018, 1.016, 1.014, 1.011, 1.005,
+                            1.042, 1.041, 1.041, 1.041, 1.042, 1.041, 1.041, 1.039, 1.039, 1.039, 1.037, 1.036, 1.036, 1.034, 1.034, 1.033, 1.032, 1.031, 1.029, 1.029, 1.029, 1.028, 1.027, 1.024, 1.024, 1.022, 1.021, 1.017, 1.016, 1.014, 1.011, 1.005,
+                            1.041, 1.041, 1.041, 1.042, 1.042, 1.042, 1.041, 1.039, 1.039, 1.038, 1.037, 1.036, 1.036, 1.036, 1.035, 1.034, 1.032, 1.031, 1.029, 1.029, 1.029, 1.029, 1.027, 1.024, 1.023, 1.022, 1.021, 1.018, 1.016, 1.013, 1.009, 1.004
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.032, 1.032, 1.032, 1.031, 1.031, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.026, 1.024, 1.023, 1.022, 1.021, 1.021, 1.019, 1.018, 1.015, 1.014, 1.013, 1.012, 1.009, 1.007, 1.007, 1.005, 1.001, 1.001,
+                            1.048, 1.048, 1.048, 1.047, 1.049, 1.049, 1.046, 1.045, 1.044, 1.043, 1.043, 1.043, 1.044, 1.043, 1.041, 1.039, 1.039, 1.038, 1.037, 1.036, 1.034, 1.032, 1.032, 1.029, 1.029, 1.026, 1.025, 1.023, 1.019, 1.018, 1.017, 1.017,
+                            1.049, 1.048, 1.048, 1.048, 1.049, 1.049, 1.047, 1.045, 1.044, 1.043, 1.043, 1.043, 1.044, 1.043, 1.041, 1.041, 1.039, 1.038, 1.037, 1.036, 1.034, 1.032, 1.032, 1.029, 1.029, 1.026, 1.025, 1.023, 1.021, 1.019, 1.017, 1.017,
+                            1.045, 1.044, 1.044, 1.046, 1.046, 1.046, 1.045, 1.043, 1.042, 1.041, 1.039, 1.039, 1.039, 1.039, 1.039, 1.037, 1.035, 1.033, 1.033, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.021, 1.019, 1.016, 1.014, 1.014,
+                            1.045, 1.044, 1.044, 1.044, 1.045, 1.045, 1.044, 1.043, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.037, 1.035, 1.034, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.021, 1.019, 1.019, 1.016, 1.014, 1.012,
+                            1.049, 1.046, 1.046, 1.046, 1.046, 1.046, 1.045, 1.044, 1.043, 1.042, 1.041, 1.041, 1.039, 1.038, 1.037, 1.036, 1.035, 1.034, 1.034, 1.032, 1.031, 1.029, 1.029, 1.027, 1.026, 1.025, 1.023, 1.021, 1.019, 1.018, 1.015, 1.013,
+                            1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.044, 1.043, 1.043, 1.042, 1.041, 1.039, 1.039, 1.037, 1.036, 1.035, 1.034, 1.033, 1.032, 1.031, 1.029, 1.029, 1.028, 1.027, 1.024, 1.024, 1.023, 1.019, 1.017, 1.014,
+                            1.049, 1.049, 1.049, 1.049, 1.048, 1.046, 1.046, 1.044, 1.044, 1.043, 1.042, 1.041, 1.039, 1.039, 1.038, 1.035, 1.034, 1.034, 1.034, 1.032, 1.031, 1.031, 1.029, 1.028, 1.028, 1.026, 1.024, 1.024, 1.021, 1.018, 1.016, 1.014,
+                            1.044, 1.047, 1.047, 1.047, 1.044, 1.043, 1.042, 1.041, 1.041, 1.039, 1.038, 1.037, 1.035, 1.034, 1.034, 1.031, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.025, 1.025, 1.023, 1.022, 1.019, 1.018, 1.016, 1.014, 1.012,
+                            1.043, 1.044, 1.046, 1.046, 1.043, 1.042, 1.041, 1.039, 1.039, 1.038, 1.037, 1.035, 1.034, 1.033, 1.031, 1.029, 1.028, 1.027, 1.027, 1.026, 1.025, 1.023, 1.023, 1.023, 1.024, 1.023, 1.021, 1.018, 1.017, 1.016, 1.013, 1.009,
+                            1.044, 1.046, 1.047, 1.047, 1.046, 1.044, 1.042, 1.041, 1.039, 1.038, 1.037, 1.036, 1.035, 1.033, 1.032, 1.029, 1.028, 1.028, 1.028, 1.027, 1.025, 1.024, 1.024, 1.024, 1.024, 1.024, 1.022, 1.019, 1.019, 1.017, 1.013, 1.012,
+                            1.046, 1.047, 1.048, 1.048, 1.047, 1.045, 1.044, 1.043, 1.041, 1.039, 1.038, 1.038, 1.036, 1.035, 1.033, 1.032, 1.031, 1.029, 1.029, 1.029, 1.027, 1.026, 1.025, 1.025, 1.026, 1.026, 1.023, 1.022, 1.021, 1.019, 1.015, 1.012,
+                            1.046, 1.047, 1.047, 1.047, 1.046, 1.045, 1.044, 1.043, 1.041, 1.039, 1.037, 1.037, 1.035, 1.034, 1.033, 1.032, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.025, 1.026, 1.025, 1.023, 1.022, 1.021, 1.019, 1.015, 1.011,
+                            1.042, 1.043, 1.043, 1.042, 1.041, 1.041, 1.041, 1.039, 1.038, 1.036, 1.034, 1.032, 1.031, 1.031, 1.029, 1.028, 1.026, 1.025, 1.024, 1.024, 1.024, 1.023, 1.022, 1.022, 1.023, 1.022, 1.021, 1.018, 1.017, 1.016, 1.012, 1.011,
+                            1.042, 1.042, 1.042, 1.042, 1.041, 1.041, 1.039, 1.039, 1.038, 1.035, 1.033, 1.031, 1.031, 1.029, 1.029, 1.027, 1.025, 1.024, 1.023, 1.023, 1.023, 1.022, 1.021, 1.021, 1.022, 1.021, 1.019, 1.018, 1.017, 1.015, 1.011, 1.009,
+                            1.042, 1.043, 1.044, 1.044, 1.043, 1.042, 1.041, 1.039, 1.039, 1.036, 1.035, 1.034, 1.032, 1.031, 1.031, 1.029, 1.027, 1.025, 1.025, 1.025, 1.024, 1.023, 1.022, 1.022, 1.022, 1.022, 1.021, 1.019, 1.019, 1.016, 1.013, 1.009,
+                            1.046, 1.046, 1.047, 1.046, 1.046, 1.045, 1.043, 1.042, 1.039, 1.038, 1.037, 1.035, 1.034, 1.033, 1.033, 1.032, 1.029, 1.027, 1.026, 1.027, 1.027, 1.027, 1.025, 1.025, 1.026, 1.025, 1.023, 1.021, 1.021, 1.019, 1.015, 1.012,
+                            1.046, 1.046, 1.047, 1.046, 1.046, 1.045, 1.043, 1.042, 1.041, 1.039, 1.036, 1.035, 1.034, 1.033, 1.033, 1.031, 1.029, 1.027, 1.026, 1.026, 1.027, 1.027, 1.026, 1.026, 1.026, 1.024, 1.023, 1.021, 1.021, 1.019, 1.015, 1.012,
+                            1.044, 1.043, 1.043, 1.043, 1.042, 1.041, 1.039, 1.039, 1.038, 1.036, 1.034, 1.032, 1.031, 1.029, 1.029, 1.028, 1.026, 1.025, 1.024, 1.024, 1.024, 1.024, 1.023, 1.023, 1.023, 1.023, 1.021, 1.019, 1.018, 1.016, 1.012, 1.009,
+                            1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.037, 1.035, 1.033, 1.031, 1.031, 1.029, 1.029, 1.027, 1.025, 1.024, 1.023, 1.023, 1.023, 1.023, 1.022, 1.022, 1.023, 1.022, 1.019, 1.017, 1.015, 1.015, 1.011, 1.008,
+                            1.043, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.039, 1.038, 1.036, 1.034, 1.033, 1.031, 1.031, 1.029, 1.028, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.023, 1.023, 1.023, 1.023, 1.021, 1.018, 1.016, 1.015, 1.012, 1.009,
+                            1.044, 1.044, 1.044, 1.043, 1.043, 1.043, 1.042, 1.041, 1.041, 1.039, 1.037, 1.036, 1.034, 1.033, 1.033, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.026, 1.025, 1.025, 1.024, 1.024, 1.019, 1.019, 1.017, 1.013, 1.009,
+                            1.042, 1.044, 1.044, 1.044, 1.043, 1.042, 1.041, 1.041, 1.041, 1.039, 1.038, 1.036, 1.034, 1.034, 1.033, 1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.026, 1.025, 1.025, 1.024, 1.023, 1.019, 1.019, 1.016, 1.013, 1.009,
+                            1.039, 1.039, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.037, 1.036, 1.035, 1.033, 1.032, 1.031, 1.031, 1.029, 1.028, 1.027, 1.027, 1.027, 1.026, 1.025, 1.023, 1.022, 1.022, 1.022, 1.019, 1.017, 1.015, 1.013, 1.011, 1.008,
+                            1.037, 1.038, 1.039, 1.039, 1.038, 1.037, 1.037, 1.037, 1.036, 1.035, 1.034, 1.033, 1.031, 1.031, 1.029, 1.029, 1.028, 1.026, 1.026, 1.025, 1.025, 1.024, 1.023, 1.022, 1.021, 1.021, 1.018, 1.016, 1.014, 1.012, 1.009, 1.007,
+                            1.037, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.037, 1.036, 1.035, 1.034, 1.033, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.026, 1.026, 1.024, 1.023, 1.022, 1.021, 1.019, 1.017, 1.015, 1.014, 1.011, 1.009,
+                            1.041, 1.041, 1.041, 1.041, 1.042, 1.041, 1.041, 1.041, 1.039, 1.039, 1.039, 1.038, 1.037, 1.036, 1.034, 1.034, 1.033, 1.032, 1.032, 1.032, 1.031, 1.028, 1.027, 1.025, 1.025, 1.025, 1.022, 1.021, 1.018, 1.016, 1.013, 1.009,
+                            1.042, 1.041, 1.041, 1.042, 1.042, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.039, 1.038, 1.037, 1.035, 1.035, 1.034, 1.033, 1.033, 1.032, 1.032, 1.029, 1.027, 1.025, 1.025, 1.025, 1.023, 1.021, 1.018, 1.016, 1.012, 1.009,
+                            1.038, 1.038, 1.038, 1.038, 1.039, 1.038, 1.037, 1.036, 1.036, 1.036, 1.037, 1.036, 1.036, 1.035, 1.034, 1.033, 1.031, 1.031, 1.031, 1.031, 1.029, 1.027, 1.025, 1.023, 1.023, 1.022, 1.021, 1.019, 1.015, 1.013, 1.009, 1.009,
+                            1.036, 1.036, 1.036, 1.036, 1.037, 1.036, 1.035, 1.035, 1.035, 1.035, 1.036, 1.035, 1.034, 1.034, 1.033, 1.032, 1.031, 1.029, 1.029, 1.028, 1.028, 1.027, 1.024, 1.022, 1.021, 1.021, 1.019, 1.017, 1.014, 1.011, 1.009, 1.007,
+                            1.037, 1.036, 1.036, 1.037, 1.037, 1.037, 1.036, 1.036, 1.036, 1.036, 1.036, 1.036, 1.035, 1.035, 1.034, 1.034, 1.033, 1.029, 1.029, 1.029, 1.028, 1.027, 1.025, 1.022, 1.022, 1.021, 1.019, 1.017, 1.015, 1.012, 1.009, 1.008,
+                            1.038, 1.037, 1.038, 1.038, 1.039, 1.039, 1.038, 1.037, 1.038, 1.038, 1.038, 1.038, 1.038, 1.037, 1.037, 1.036, 1.035, 1.033, 1.032, 1.032, 1.031, 1.029, 1.027, 1.024, 1.023, 1.022, 1.022, 1.019, 1.016, 1.013, 1.011, 1.007
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.049, 1.049, 1.047, 1.048, 1.046, 1.046, 1.044, 1.042, 1.041, 1.039, 1.038, 1.038, 1.038, 1.037, 1.034, 1.033, 1.033, 1.033, 1.033, 1.031, 1.029, 1.028, 1.028, 1.027, 1.026, 1.024, 1.023, 1.022, 1.021, 1.017, 1.017, 1.016,
+                            1.043, 1.043, 1.043, 1.043, 1.043, 1.042, 1.041, 1.038, 1.035, 1.034, 1.033, 1.033, 1.032, 1.031, 1.031, 1.028, 1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.017, 1.015, 1.011, 1.009,
+                            1.043, 1.042, 1.042, 1.042, 1.042, 1.041, 1.039, 1.037, 1.035, 1.033, 1.032, 1.031, 1.031, 1.031, 1.028, 1.027, 1.026, 1.025, 1.024, 1.024, 1.023, 1.022, 1.022, 1.021, 1.019, 1.019, 1.018, 1.017, 1.016, 1.014, 1.012, 1.011,
+                            1.043, 1.042, 1.042, 1.042, 1.042, 1.041, 1.038, 1.036, 1.034, 1.032, 1.031, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.023, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.019, 1.017, 1.016, 1.015, 1.013, 1.011, 1.011,
+                            1.043, 1.042, 1.041, 1.041, 1.041, 1.039, 1.037, 1.036, 1.033, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.024, 1.023, 1.022, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.018, 1.016, 1.015, 1.015, 1.013, 1.011, 1.011,
+                            1.043, 1.042, 1.041, 1.041, 1.039, 1.038, 1.036, 1.034, 1.032, 1.031, 1.029, 1.028, 1.027, 1.025, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.011, 1.009,
+                            1.043, 1.043, 1.041, 1.041, 1.039, 1.037, 1.036, 1.033, 1.032, 1.031, 1.029, 1.027, 1.025, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.018, 1.018, 1.017, 1.018, 1.018, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.011, 1.011,
+                            1.043, 1.043, 1.042, 1.041, 1.039, 1.037, 1.035, 1.033, 1.031, 1.029, 1.027, 1.026, 1.024, 1.022, 1.021, 1.019, 1.018, 1.018, 1.018, 1.018, 1.017, 1.016, 1.016, 1.017, 1.018, 1.017, 1.015, 1.014, 1.014, 1.013, 1.011, 1.009,
+                            1.042, 1.043, 1.042, 1.041, 1.038, 1.036, 1.034, 1.032, 1.029, 1.028, 1.026, 1.024, 1.022, 1.021, 1.019, 1.017, 1.015, 1.015, 1.016, 1.015, 1.014, 1.014, 1.015, 1.016, 1.017, 1.016, 1.014, 1.013, 1.013, 1.012, 1.011, 1.009,
+                            1.041, 1.042, 1.041, 1.041, 1.038, 1.035, 1.032, 1.031, 1.029, 1.026, 1.025, 1.022, 1.021, 1.019, 1.017, 1.015, 1.014, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.015, 1.016, 1.015, 1.014, 1.013, 1.012, 1.012, 1.009, 1.008,
+                            1.041, 1.041, 1.041, 1.039, 1.038, 1.035, 1.032, 1.029, 1.027, 1.025, 1.023, 1.022, 1.019, 1.017, 1.016, 1.014, 1.012, 1.012, 1.012, 1.012, 1.011, 1.011, 1.011, 1.013, 1.015, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.007,
+                            1.041, 1.041, 1.039, 1.039, 1.038, 1.035, 1.033, 1.029, 1.027, 1.025, 1.023, 1.021, 1.018, 1.017, 1.015, 1.013, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.014, 1.014, 1.014, 1.014, 1.012, 1.012, 1.009, 1.008,
+                            1.039, 1.039, 1.039, 1.038, 1.037, 1.034, 1.033, 1.029, 1.027, 1.024, 1.022, 1.019, 1.017, 1.016, 1.014, 1.013, 1.011, 1.009, 1.009, 1.011, 1.011, 1.011, 1.011, 1.011, 1.013, 1.014, 1.014, 1.013, 1.013, 1.011, 1.009, 1.007,
+                            1.039, 1.039, 1.039, 1.037, 1.035, 1.034, 1.031, 1.029, 1.027, 1.023, 1.021, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.009, 1.011, 1.009, 1.011, 1.011, 1.013, 1.014, 1.013, 1.013, 1.013, 1.011, 1.008, 1.007,
+                            1.039, 1.039, 1.038, 1.036, 1.034, 1.033, 1.031, 1.028, 1.027, 1.023, 1.019, 1.017, 1.015, 1.014, 1.013, 1.011, 1.009, 1.009, 1.008, 1.009, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.012, 1.012, 1.012, 1.011, 1.008, 1.006,
+                            1.039, 1.039, 1.038, 1.037, 1.034, 1.032, 1.031, 1.028, 1.025, 1.022, 1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.009, 1.008, 1.008, 1.009, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.012, 1.011, 1.011, 1.009, 1.007, 1.006,
+                            1.039, 1.039, 1.038, 1.036, 1.035, 1.032, 1.031, 1.028, 1.026, 1.023, 1.019, 1.018, 1.015, 1.014, 1.012, 1.011, 1.009, 1.008, 1.008, 1.009, 1.011, 1.011, 1.011, 1.011, 1.013, 1.013, 1.013, 1.012, 1.012, 1.011, 1.009, 1.007,
+                            1.039, 1.038, 1.037, 1.036, 1.035, 1.033, 1.031, 1.028, 1.026, 1.023, 1.021, 1.018, 1.016, 1.014, 1.012, 1.011, 1.009, 1.008, 1.008, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.013, 1.013, 1.012, 1.012, 1.011, 1.009, 1.007,
+                            1.039, 1.038, 1.037, 1.036, 1.034, 1.032, 1.031, 1.029, 1.026, 1.022, 1.019, 1.018, 1.015, 1.014, 1.013, 1.011, 1.009, 1.008, 1.008, 1.009, 1.011, 1.011, 1.011, 1.012, 1.013, 1.013, 1.013, 1.012, 1.012, 1.011, 1.009, 1.007,
+                            1.039, 1.038, 1.037, 1.035, 1.034, 1.032, 1.031, 1.028, 1.026, 1.022, 1.019, 1.017, 1.015, 1.014, 1.013, 1.011, 1.009, 1.008, 1.008, 1.009, 1.011, 1.011, 1.011, 1.012, 1.013, 1.013, 1.012, 1.011, 1.011, 1.011, 1.009, 1.006,
+                            1.039, 1.038, 1.037, 1.035, 1.033, 1.032, 1.029, 1.028, 1.025, 1.022, 1.021, 1.017, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.011, 1.011, 1.011, 1.012, 1.013, 1.013, 1.012, 1.011, 1.011, 1.011, 1.008, 1.007,
+                            1.037, 1.037, 1.036, 1.035, 1.033, 1.031, 1.029, 1.028, 1.025, 1.023, 1.021, 1.019, 1.017, 1.015, 1.013, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.013, 1.013, 1.013, 1.012, 1.011, 1.011, 1.009, 1.006,
+                            1.037, 1.037, 1.036, 1.034, 1.033, 1.031, 1.029, 1.028, 1.025, 1.023, 1.021, 1.019, 1.017, 1.016, 1.014, 1.013, 1.012, 1.011, 1.011, 1.012, 1.013, 1.012, 1.012, 1.012, 1.013, 1.013, 1.013, 1.012, 1.011, 1.011, 1.008, 1.005,
+                            1.036, 1.036, 1.035, 1.034, 1.032, 1.031, 1.029, 1.027, 1.026, 1.024, 1.022, 1.019, 1.018, 1.016, 1.015, 1.014, 1.013, 1.012, 1.012, 1.013, 1.013, 1.013, 1.013, 1.012, 1.013, 1.013, 1.013, 1.011, 1.011, 1.009, 1.007, 1.005,
+                            1.036, 1.036, 1.035, 1.034, 1.032, 1.031, 1.029, 1.028, 1.025, 1.024, 1.022, 1.019, 1.018, 1.017, 1.016, 1.015, 1.013, 1.012, 1.012, 1.013, 1.014, 1.013, 1.013, 1.012, 1.012, 1.013, 1.012, 1.011, 1.009, 1.009, 1.007, 1.005,
+                            1.035, 1.035, 1.035, 1.034, 1.033, 1.031, 1.029, 1.027, 1.026, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.015, 1.014, 1.013, 1.013, 1.014, 1.014, 1.014, 1.013, 1.012, 1.013, 1.013, 1.012, 1.011, 1.009, 1.009, 1.006, 1.004,
+                            1.036, 1.036, 1.036, 1.034, 1.032, 1.031, 1.029, 1.028, 1.026, 1.025, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.015, 1.015, 1.015, 1.014, 1.013, 1.013, 1.013, 1.013, 1.011, 1.011, 1.009, 1.007, 1.005,
+                            1.037, 1.036, 1.035, 1.034, 1.032, 1.031, 1.029, 1.028, 1.026, 1.026, 1.025, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.015, 1.014, 1.013, 1.013, 1.014, 1.014, 1.012, 1.011, 1.009, 1.007, 1.004,
+                            1.037, 1.036, 1.035, 1.034, 1.033, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.024, 1.023, 1.021, 1.021, 1.019, 1.018, 1.018, 1.017, 1.017, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014, 1.012, 1.011, 1.011, 1.008, 1.005,
+                            1.036, 1.036, 1.035, 1.034, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.026, 1.025, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.018, 1.018, 1.017, 1.016, 1.014, 1.014, 1.014, 1.014, 1.013, 1.011, 1.011, 1.008, 1.005,
+                            1.035, 1.035, 1.035, 1.034, 1.033, 1.031, 1.029, 1.029, 1.028, 1.026, 1.026, 1.026, 1.025, 1.023, 1.022, 1.022, 1.021, 1.019, 1.018, 1.018, 1.018, 1.017, 1.015, 1.014, 1.014, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.006,
+                            1.036, 1.036, 1.035, 1.034, 1.033, 1.031, 1.031, 1.029, 1.027, 1.026, 1.026, 1.026, 1.024, 1.024, 1.023, 1.023, 1.021, 1.019, 1.019, 1.018, 1.019, 1.018, 1.016, 1.014, 1.014, 1.014, 1.013, 1.011, 1.009, 1.009, 1.008, 1.007
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.045, 1.044, 1.044, 1.044, 1.043, 1.043, 1.042, 1.043, 1.042, 1.042, 1.042, 1.042, 1.042, 1.041, 1.038, 1.038, 1.038, 1.038, 1.037, 1.036, 1.034, 1.033, 1.032, 1.032, 1.029, 1.027, 1.026, 1.024, 1.022, 1.022, 1.021, 1.021,
+                            1.033, 1.034, 1.033, 1.034, 1.034, 1.033, 1.033, 1.032, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.023, 1.022, 1.021, 1.019, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.011,
+                            1.031, 1.031, 1.031, 1.031, 1.032, 1.032, 1.031, 1.031, 1.029, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.025, 1.024, 1.023, 1.023, 1.022, 1.021, 1.021, 1.019, 1.017, 1.017, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.029, 1.029, 1.029, 1.029, 1.031, 1.031, 1.029, 1.029, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.024, 1.024, 1.022, 1.021, 1.021, 1.021, 1.019, 1.018, 1.017, 1.017, 1.015, 1.014, 1.013, 1.011, 1.009, 1.008, 1.007, 1.007,
+                            1.031, 1.031, 1.029, 1.029, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.026, 1.026, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.021, 1.021, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007, 1.007,
+                            1.032, 1.032, 1.031, 1.031, 1.032, 1.032, 1.032, 1.031, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.025, 1.024, 1.023, 1.022, 1.022, 1.021, 1.021, 1.019, 1.018, 1.018, 1.017, 1.016, 1.014, 1.013, 1.012, 1.011, 1.008, 1.007,
+                            1.032, 1.032, 1.032, 1.031, 1.031, 1.032, 1.032, 1.031, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.022, 1.022, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.016, 1.015, 1.013, 1.012, 1.011, 1.008, 1.007,
+                            1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.027, 1.026, 1.024, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.017, 1.016, 1.015, 1.013, 1.012, 1.011, 1.009, 1.007, 1.005,
+                            1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.024, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.017, 1.016, 1.016, 1.015, 1.015, 1.015, 1.015, 1.014, 1.012, 1.011, 1.009, 1.008, 1.006, 1.005,
+                            1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.018, 1.016, 1.016, 1.016, 1.016, 1.015, 1.014, 1.014, 1.015, 1.015, 1.014, 1.013, 1.011, 1.009, 1.008, 1.006, 1.005,
+                            1.031, 1.031, 1.031, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.017, 1.016, 1.015, 1.015, 1.014, 1.015, 1.016, 1.016, 1.014, 1.013, 1.011, 1.009, 1.007, 1.006,
+                            1.031, 1.031, 1.031, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.022, 1.021, 1.019, 1.018, 1.016, 1.016, 1.016, 1.016, 1.015, 1.014, 1.014, 1.014, 1.016, 1.016, 1.014, 1.013, 1.011, 1.009, 1.007, 1.006,
+                            1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.025, 1.024, 1.022, 1.021, 1.019, 1.019, 1.018, 1.016, 1.015, 1.015, 1.014, 1.014, 1.014, 1.013, 1.013, 1.013, 1.014, 1.014, 1.013, 1.012, 1.011, 1.009, 1.006, 1.005,
+                            1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.025, 1.024, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.013, 1.012, 1.012, 1.012, 1.012, 1.012, 1.012, 1.012, 1.011, 1.011, 1.009, 1.008, 1.004, 1.004,
+                            1.027, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.015, 1.014, 1.014, 1.013, 1.012, 1.012, 1.012, 1.011, 1.011, 1.011, 1.012, 1.012, 1.011, 1.011, 1.009, 1.007, 1.005, 1.004,
+                            1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.014, 1.014, 1.013, 1.013, 1.014, 1.013, 1.013, 1.014, 1.014, 1.014, 1.012, 1.011, 1.011, 1.009, 1.006, 1.004,
+                            1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.026, 1.024, 1.022, 1.021, 1.019, 1.019, 1.017, 1.016, 1.015, 1.014, 1.013, 1.014, 1.015, 1.014, 1.014, 1.014, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.007, 1.005,
+                            1.029, 1.028, 1.028, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.012, 1.012, 1.013, 1.014, 1.013, 1.014, 1.014, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.006, 1.004,
+                            1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.022, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.012, 1.011, 1.011, 1.012, 1.012, 1.012, 1.012, 1.012, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.005, 1.003,
+                            1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.025, 1.024, 1.021, 1.019, 1.018, 1.016, 1.016, 1.014, 1.013, 1.012, 1.012, 1.012, 1.011, 1.012, 1.012, 1.012, 1.012, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.005, 1.003,
+                            1.028, 1.029, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.025, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.014, 1.014, 1.014, 1.014, 1.014, 1.013, 1.014, 1.014, 1.013, 1.012, 1.011, 1.008, 1.008, 1.006, 1.005,
+                            1.029, 1.029, 1.028, 1.028, 1.029, 1.028, 1.028, 1.027, 1.025, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.015, 1.015, 1.015, 1.015, 1.015, 1.014, 1.014, 1.014, 1.014, 1.012, 1.011, 1.009, 1.007, 1.006, 1.004,
+                            1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.014, 1.015, 1.015, 1.014, 1.014, 1.013, 1.013, 1.013, 1.012, 1.009, 1.007, 1.007, 1.005, 1.003,
+                            1.026, 1.025, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.013, 1.014, 1.014, 1.013, 1.012, 1.012, 1.012, 1.011, 1.009, 1.007, 1.007, 1.006, 1.005, 1.001,
+                            1.026, 1.025, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.013, 1.013, 1.014, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.011, 1.008, 1.006, 1.005, 1.003, 1.001,
+                            1.026, 1.027, 1.027, 1.026, 1.027, 1.026, 1.025, 1.025, 1.024, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.015, 1.014, 1.013, 1.013, 1.013, 1.011, 1.009, 1.007, 1.006, 1.004, 1.002,
+                            1.027, 1.027, 1.027, 1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.017, 1.017, 1.017, 1.017, 1.015, 1.014, 1.013, 1.012, 1.012, 1.011, 1.009, 1.007, 1.007, 1.005, 1.002,
+                            1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.026, 1.025, 1.024, 1.024, 1.023, 1.023, 1.021, 1.021, 1.019, 1.019, 1.018, 1.017, 1.017, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.012, 1.011, 1.009, 1.007, 1.005, 1.004, 1.002,
+                            1.026, 1.025, 1.024, 1.024, 1.024, 1.023, 1.023, 1.023, 1.023, 1.022, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.017, 1.016, 1.016, 1.015, 1.015, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.007, 1.005, 1.005, 1.003, 1.002,
+                            1.025, 1.024, 1.024, 1.024, 1.023, 1.023, 1.023, 1.022, 1.022, 1.022, 1.022, 1.022, 1.021, 1.019, 1.019, 1.019, 1.017, 1.016, 1.016, 1.016, 1.015, 1.014, 1.013, 1.011, 1.011, 1.011, 1.009, 1.008, 1.006, 1.005, 1.004, 1.002,
+                            1.026, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.024, 1.024, 1.024, 1.023, 1.023, 1.022, 1.022, 1.022, 1.021, 1.021, 1.019, 1.017, 1.017, 1.017, 1.016, 1.014, 1.013, 1.013, 1.012, 1.011, 1.008, 1.008, 1.007, 1.005, 1.005,
+                            1.027, 1.027, 1.026, 1.027, 1.026, 1.025, 1.025, 1.025, 1.025, 1.024, 1.024, 1.024, 1.023, 1.023, 1.023, 1.023, 1.021, 1.019, 1.018, 1.018, 1.018, 1.017, 1.016, 1.014, 1.013, 1.012, 1.012, 1.009, 1.009, 1.008, 1.006, 1.005
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.038, 1.038, 1.038, 1.038, 1.038, 1.039, 1.037, 1.037, 1.036, 1.036, 1.036, 1.036, 1.036, 1.034, 1.033, 1.032, 1.032, 1.031, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.024, 1.022, 1.021, 1.019, 1.018, 1.016, 1.016, 1.016,
+                            1.032, 1.032, 1.031, 1.032, 1.032, 1.032, 1.032, 1.031, 1.029, 1.028, 1.028, 1.028, 1.027, 1.026, 1.026, 1.025, 1.024, 1.024, 1.024, 1.023, 1.021, 1.021, 1.018, 1.018, 1.017, 1.016, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008,
+                            1.031, 1.031, 1.029, 1.031, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.027, 1.026, 1.026, 1.025, 1.024, 1.023, 1.023, 1.022, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.016, 1.014, 1.013, 1.011, 1.011, 1.009, 1.007, 1.008,
+                            1.031, 1.029, 1.029, 1.029, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.019, 1.019, 1.017, 1.017, 1.016, 1.016, 1.014, 1.013, 1.011, 1.011, 1.008, 1.007, 1.008,
+                            1.033, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.028, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007,
+                            1.033, 1.032, 1.032, 1.032, 1.032, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.021, 1.021, 1.019, 1.019, 1.018, 1.018, 1.018, 1.017, 1.016, 1.014, 1.013, 1.012, 1.009, 1.009, 1.008,
+                            1.033, 1.032, 1.032, 1.032, 1.032, 1.032, 1.031, 1.029, 1.029, 1.028, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.018, 1.017, 1.016, 1.014, 1.013, 1.012, 1.009, 1.009, 1.008,
+                            1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.027, 1.026, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.017, 1.017, 1.017, 1.017, 1.016, 1.015, 1.015, 1.016, 1.016, 1.015, 1.013, 1.012, 1.011, 1.009, 1.007, 1.007,
+                            1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.024, 1.022, 1.021, 1.019, 1.019, 1.017, 1.017, 1.016, 1.016, 1.016, 1.015, 1.014, 1.014, 1.015, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.007, 1.006,
+                            1.031, 1.031, 1.032, 1.031, 1.031, 1.029, 1.028, 1.027, 1.026, 1.025, 1.023, 1.022, 1.019, 1.019, 1.018, 1.016, 1.016, 1.015, 1.015, 1.015, 1.014, 1.013, 1.013, 1.014, 1.015, 1.014, 1.013, 1.011, 1.011, 1.009, 1.006, 1.006,
+                            1.032, 1.032, 1.033, 1.033, 1.032, 1.031, 1.029, 1.028, 1.027, 1.026, 1.024, 1.023, 1.021, 1.019, 1.019, 1.017, 1.016, 1.016, 1.016, 1.016, 1.015, 1.014, 1.014, 1.015, 1.016, 1.016, 1.015, 1.013, 1.012, 1.011, 1.008, 1.007,
+                            1.031, 1.031, 1.032, 1.033, 1.032, 1.031, 1.029, 1.028, 1.027, 1.025, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.015, 1.015, 1.015, 1.015, 1.015, 1.013, 1.013, 1.014, 1.015, 1.015, 1.014, 1.013, 1.011, 1.011, 1.008, 1.006,
+                            1.029, 1.029, 1.029, 1.031, 1.031, 1.029, 1.029, 1.026, 1.026, 1.023, 1.021, 1.021, 1.018, 1.017, 1.016, 1.015, 1.013, 1.013, 1.013, 1.013, 1.012, 1.012, 1.012, 1.012, 1.013, 1.013, 1.013, 1.011, 1.011, 1.009, 1.007, 1.005,
+                            1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.027, 1.026, 1.025, 1.022, 1.021, 1.019, 1.017, 1.016, 1.015, 1.014, 1.012, 1.012, 1.012, 1.011, 1.011, 1.011, 1.011, 1.012, 1.013, 1.013, 1.012, 1.011, 1.009, 1.008, 1.006, 1.004,
+                            1.028, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.022, 1.021, 1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.012, 1.011, 1.011, 1.012, 1.013, 1.013, 1.012, 1.011, 1.009, 1.008, 1.006, 1.005,
+                            1.029, 1.031, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.026, 1.023, 1.021, 1.019, 1.018, 1.017, 1.015, 1.015, 1.013, 1.012, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.014, 1.014, 1.013, 1.012, 1.011, 1.009, 1.007, 1.005,
+                            1.029, 1.031, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.025, 1.024, 1.021, 1.019, 1.018, 1.017, 1.015, 1.015, 1.013, 1.012, 1.012, 1.013, 1.013, 1.013, 1.013, 1.014, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.007, 1.005,
+                            1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.026, 1.025, 1.022, 1.019, 1.018, 1.017, 1.015, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.012, 1.012, 1.012, 1.013, 1.013, 1.013, 1.012, 1.011, 1.009, 1.008, 1.006, 1.003,
+                            1.028, 1.029, 1.028, 1.028, 1.028, 1.027, 1.026, 1.025, 1.024, 1.022, 1.019, 1.018, 1.017, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.012, 1.013, 1.013, 1.012, 1.011, 1.009, 1.009, 1.008, 1.005, 1.003,
+                            1.028, 1.028, 1.028, 1.029, 1.028, 1.028, 1.027, 1.026, 1.024, 1.022, 1.021, 1.018, 1.017, 1.015, 1.014, 1.013, 1.011, 1.011, 1.011, 1.012, 1.012, 1.012, 1.012, 1.013, 1.013, 1.013, 1.012, 1.011, 1.009, 1.008, 1.005, 1.004,
+                            1.031, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.026, 1.023, 1.022, 1.019, 1.019, 1.017, 1.015, 1.015, 1.014, 1.013, 1.013, 1.014, 1.014, 1.014, 1.013, 1.014, 1.014, 1.014, 1.013, 1.011, 1.009, 1.009, 1.007, 1.005,
+                            1.029, 1.029, 1.028, 1.029, 1.029, 1.029, 1.028, 1.027, 1.026, 1.023, 1.022, 1.021, 1.019, 1.017, 1.016, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014, 1.014, 1.013, 1.013, 1.014, 1.014, 1.013, 1.011, 1.009, 1.008, 1.006, 1.005,
+                            1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.026, 1.025, 1.024, 1.023, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.013, 1.014, 1.014, 1.014, 1.013, 1.013, 1.013, 1.013, 1.012, 1.009, 1.008, 1.007, 1.006, 1.003,
+                            1.026, 1.027, 1.027, 1.027, 1.026, 1.026, 1.025, 1.024, 1.023, 1.021, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.013, 1.013, 1.013, 1.013, 1.012, 1.012, 1.012, 1.011, 1.011, 1.009, 1.007, 1.006, 1.004, 1.003,
+                            1.026, 1.026, 1.026, 1.026, 1.026, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.014, 1.013, 1.013, 1.013, 1.013, 1.013, 1.012, 1.012, 1.012, 1.011, 1.008, 1.007, 1.006, 1.004, 1.002,
+                            1.028, 1.028, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.025, 1.024, 1.023, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.015, 1.014, 1.013, 1.013, 1.013, 1.012, 1.011, 1.008, 1.007, 1.005, 1.004,
+                            1.027, 1.027, 1.027, 1.027, 1.028, 1.027, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.016, 1.016, 1.016, 1.015, 1.014, 1.013, 1.013, 1.013, 1.012, 1.011, 1.008, 1.007, 1.005, 1.004,
+                            1.026, 1.027, 1.027, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.017, 1.017, 1.017, 1.016, 1.016, 1.015, 1.014, 1.012, 1.012, 1.012, 1.011, 1.008, 1.007, 1.006, 1.005, 1.003,
+                            1.025, 1.025, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.023, 1.023, 1.022, 1.022, 1.021, 1.019, 1.019, 1.017, 1.017, 1.017, 1.016, 1.016, 1.016, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.008, 1.006, 1.005, 1.004, 1.002,
+                            1.026, 1.025, 1.025, 1.025, 1.025, 1.024, 1.024, 1.023, 1.023, 1.023, 1.022, 1.022, 1.021, 1.021, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.016, 1.016, 1.014, 1.013, 1.012, 1.012, 1.011, 1.009, 1.006, 1.005, 1.004, 1.003,
+                            1.027, 1.027, 1.027, 1.027, 1.027, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.024, 1.023, 1.022, 1.022, 1.022, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.015, 1.014, 1.014, 1.013, 1.012, 1.009, 1.008, 1.008, 1.005, 1.005,
+                            1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.023, 1.023, 1.023, 1.022, 1.019, 1.019, 1.019, 1.019, 1.018, 1.016, 1.015, 1.015, 1.013, 1.012, 1.011, 1.009, 1.009, 1.008, 1.005
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.012, 1.014, 1.015, 1.016, 1.017, 1.017, 1.018, 1.018, 1.019, 1.019, 1.021, 1.021, 1.021, 1.022, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.017, 1.015, 1.014, 1.013, 1.011, 1.009, 1.007, 1.007, 1.005, 1.002, 1.001,
+                            1.021, 1.024, 1.025, 1.028, 1.029, 1.031, 1.031, 1.031, 1.032, 1.032, 1.032, 1.033, 1.033, 1.034, 1.034, 1.033, 1.033, 1.033, 1.032, 1.031, 1.029, 1.028, 1.026, 1.025, 1.024, 1.022, 1.021, 1.018, 1.016, 1.013, 1.012, 1.011,
+                            1.024, 1.025, 1.027, 1.029, 1.031, 1.032, 1.033, 1.033, 1.033, 1.033, 1.033, 1.034, 1.034, 1.035, 1.035, 1.035, 1.034, 1.033, 1.033, 1.033, 1.031, 1.029, 1.028, 1.026, 1.025, 1.023, 1.021, 1.019, 1.018, 1.016, 1.013, 1.012,
+                            1.024, 1.025, 1.027, 1.028, 1.029, 1.031, 1.032, 1.032, 1.032, 1.033, 1.033, 1.033, 1.034, 1.034, 1.034, 1.034, 1.033, 1.032, 1.032, 1.031, 1.031, 1.028, 1.028, 1.026, 1.025, 1.023, 1.021, 1.019, 1.018, 1.016, 1.013, 1.011,
+                            1.026, 1.027, 1.027, 1.028, 1.031, 1.032, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.035, 1.035, 1.035, 1.035, 1.034, 1.034, 1.033, 1.032, 1.031, 1.029, 1.028, 1.027, 1.025, 1.023, 1.022, 1.019, 1.018, 1.016, 1.014, 1.013,
+                            1.027, 1.028, 1.029, 1.029, 1.031, 1.032, 1.033, 1.034, 1.035, 1.035, 1.036, 1.036, 1.036, 1.036, 1.036, 1.035, 1.035, 1.034, 1.034, 1.033, 1.032, 1.031, 1.029, 1.028, 1.027, 1.024, 1.022, 1.021, 1.019, 1.017, 1.014, 1.013,
+                            1.027, 1.027, 1.028, 1.029, 1.031, 1.031, 1.033, 1.034, 1.035, 1.035, 1.035, 1.036, 1.035, 1.035, 1.035, 1.035, 1.034, 1.034, 1.034, 1.033, 1.031, 1.031, 1.029, 1.029, 1.027, 1.024, 1.023, 1.021, 1.018, 1.017, 1.015, 1.012,
+                            1.026, 1.028, 1.029, 1.029, 1.031, 1.031, 1.032, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.035, 1.034, 1.033, 1.033, 1.032, 1.032, 1.031, 1.031, 1.029, 1.028, 1.027, 1.027, 1.024, 1.022, 1.019, 1.018, 1.016, 1.014, 1.012,
+                            1.026, 1.027, 1.028, 1.029, 1.029, 1.031, 1.032, 1.032, 1.033, 1.033, 1.033, 1.033, 1.034, 1.034, 1.033, 1.033, 1.032, 1.032, 1.031, 1.031, 1.029, 1.028, 1.027, 1.027, 1.026, 1.024, 1.021, 1.019, 1.018, 1.016, 1.014, 1.012,
+                            1.026, 1.027, 1.029, 1.031, 1.031, 1.032, 1.032, 1.032, 1.033, 1.033, 1.034, 1.034, 1.034, 1.033, 1.033, 1.033, 1.032, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.027, 1.026, 1.025, 1.022, 1.019, 1.018, 1.017, 1.014, 1.012,
+                            1.027, 1.027, 1.029, 1.031, 1.032, 1.033, 1.033, 1.033, 1.033, 1.034, 1.034, 1.034, 1.034, 1.034, 1.033, 1.033, 1.032, 1.032, 1.032, 1.031, 1.029, 1.028, 1.027, 1.027, 1.027, 1.025, 1.023, 1.021, 1.019, 1.018, 1.014, 1.012,
+                            1.025, 1.027, 1.029, 1.031, 1.032, 1.033, 1.033, 1.033, 1.033, 1.033, 1.033, 1.033, 1.034, 1.033, 1.032, 1.032, 1.031, 1.031, 1.031, 1.031, 1.029, 1.028, 1.027, 1.026, 1.026, 1.025, 1.022, 1.021, 1.019, 1.017, 1.014, 1.011,
+                            1.025, 1.026, 1.027, 1.029, 1.031, 1.031, 1.032, 1.032, 1.032, 1.032, 1.032, 1.032, 1.032, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.026, 1.025, 1.025, 1.023, 1.021, 1.019, 1.018, 1.016, 1.012, 1.011,
+                            1.025, 1.026, 1.026, 1.028, 1.029, 1.031, 1.031, 1.032, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.028, 1.028, 1.027, 1.026, 1.025, 1.024, 1.024, 1.022, 1.021, 1.019, 1.017, 1.016, 1.011, 1.009,
+                            1.024, 1.026, 1.027, 1.028, 1.028, 1.031, 1.031, 1.031, 1.032, 1.031, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.025, 1.024, 1.024, 1.022, 1.021, 1.018, 1.017, 1.015, 1.013, 1.009,
+                            1.025, 1.026, 1.027, 1.029, 1.029, 1.029, 1.031, 1.031, 1.032, 1.032, 1.031, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.025, 1.024, 1.023, 1.021, 1.019, 1.017, 1.016, 1.012, 1.011,
+                            1.024, 1.025, 1.027, 1.028, 1.028, 1.029, 1.031, 1.031, 1.032, 1.031, 1.031, 1.031, 1.029, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.027, 1.027, 1.027, 1.025, 1.024, 1.024, 1.023, 1.021, 1.019, 1.017, 1.015, 1.013, 1.011,
+                            1.023, 1.024, 1.025, 1.027, 1.027, 1.028, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.028, 1.027, 1.026, 1.026, 1.026, 1.025, 1.025, 1.024, 1.023, 1.023, 1.022, 1.019, 1.017, 1.016, 1.015, 1.011, 1.009,
+                            1.022, 1.023, 1.024, 1.025, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.027, 1.027, 1.027, 1.025, 1.025, 1.025, 1.025, 1.024, 1.023, 1.022, 1.022, 1.022, 1.021, 1.018, 1.016, 1.015, 1.013, 1.011, 1.009,
+                            1.022, 1.023, 1.024, 1.026, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.024, 1.023, 1.022, 1.022, 1.021, 1.019, 1.016, 1.015, 1.013, 1.011, 1.009,
+                            1.023, 1.023, 1.025, 1.026, 1.027, 1.027, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.028, 1.027, 1.027, 1.026, 1.026, 1.025, 1.026, 1.025, 1.025, 1.024, 1.024, 1.022, 1.022, 1.021, 1.019, 1.016, 1.015, 1.013, 1.011, 1.009,
+                            1.022, 1.023, 1.024, 1.025, 1.026, 1.027, 1.028, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.027, 1.027, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.024, 1.022, 1.021, 1.021, 1.021, 1.018, 1.016, 1.015, 1.012, 1.011, 1.008,
+                            1.019, 1.021, 1.023, 1.024, 1.024, 1.025, 1.026, 1.027, 1.028, 1.027, 1.027, 1.026, 1.026, 1.026, 1.026, 1.025, 1.024, 1.024, 1.024, 1.024, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.017, 1.014, 1.012, 1.011, 1.009, 1.007,
+                            1.019, 1.019, 1.022, 1.022, 1.023, 1.023, 1.024, 1.025, 1.026, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.023, 1.023, 1.023, 1.023, 1.022, 1.021, 1.019, 1.019, 1.018, 1.017, 1.015, 1.013, 1.012, 1.011, 1.008, 1.005,
+                            1.018, 1.019, 1.022, 1.022, 1.023, 1.023, 1.024, 1.025, 1.025, 1.026, 1.026, 1.026, 1.025, 1.025, 1.024, 1.024, 1.024, 1.023, 1.023, 1.023, 1.023, 1.021, 1.019, 1.019, 1.018, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.006,
+                            1.019, 1.019, 1.021, 1.022, 1.023, 1.024, 1.024, 1.025, 1.025, 1.026, 1.026, 1.026, 1.025, 1.025, 1.025, 1.024, 1.024, 1.023, 1.023, 1.023, 1.022, 1.021, 1.019, 1.018, 1.018, 1.017, 1.015, 1.013, 1.011, 1.011, 1.008, 1.005,
+                            1.018, 1.019, 1.021, 1.022, 1.023, 1.023, 1.024, 1.025, 1.025, 1.026, 1.026, 1.025, 1.025, 1.025, 1.025, 1.025, 1.024, 1.024, 1.023, 1.023, 1.022, 1.021, 1.019, 1.018, 1.018, 1.016, 1.015, 1.013, 1.011, 1.009, 1.006, 1.004,
+                            1.017, 1.018, 1.019, 1.019, 1.021, 1.021, 1.022, 1.023, 1.023, 1.023, 1.024, 1.024, 1.024, 1.024, 1.023, 1.023, 1.022, 1.022, 1.022, 1.021, 1.021, 1.019, 1.018, 1.016, 1.015, 1.015, 1.014, 1.012, 1.009, 1.007, 1.005, 1.004,
+                            1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.021, 1.021, 1.022, 1.022, 1.022, 1.023, 1.023, 1.022, 1.022, 1.022, 1.021, 1.021, 1.021, 1.019, 1.019, 1.018, 1.016, 1.015, 1.014, 1.014, 1.012, 1.011, 1.009, 1.007, 1.004, 1.003,
+                            1.015, 1.017, 1.018, 1.018, 1.019, 1.021, 1.021, 1.021, 1.022, 1.022, 1.022, 1.023, 1.023, 1.022, 1.022, 1.022, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.017, 1.015, 1.014, 1.014, 1.012, 1.009, 1.009, 1.007, 1.005, 1.003,
+                            1.016, 1.017, 1.018, 1.019, 1.019, 1.021, 1.021, 1.022, 1.022, 1.022, 1.023, 1.023, 1.023, 1.023, 1.023, 1.022, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.016, 1.015, 1.014, 1.013, 1.012, 1.009, 1.009, 1.007, 1.005, 1.004,
+                            1.016, 1.017, 1.018, 1.019, 1.021, 1.021, 1.022, 1.022, 1.022, 1.023, 1.023, 1.023, 1.023, 1.023, 1.023, 1.022, 1.022, 1.021, 1.021, 1.021, 1.019, 1.019, 1.015, 1.014, 1.014, 1.014, 1.013, 1.011, 1.008, 1.007, 1.006, 1.004
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    2.357, 2.251, 2.084, 1.944, 1.824, 1.721, 1.632, 1.555, 1.488, 1.431, 1.382, 1.341, 1.311, 1.296, 1.288, 1.288, 1.288, 1.291, 1.305, 1.327, 1.362, 1.407, 1.462, 1.524, 1.595, 1.677, 1.772, 1.883, 2.017, 2.172, 2.352, 2.439,
+                    2.296, 2.169, 2.012, 1.877, 1.761, 1.662, 1.578, 1.505, 1.443, 1.391, 1.347, 1.309, 1.281, 1.261, 1.247, 1.242, 1.244, 1.253, 1.271, 1.296, 1.329, 1.371, 1.419, 1.476, 1.544, 1.622, 1.713, 1.819, 1.946, 2.095, 2.268, 2.382,
+                    2.231, 2.109, 1.957, 1.826, 1.713, 1.616, 1.532, 1.461, 1.401, 1.349, 1.307, 1.272, 1.245, 1.223, 1.211, 1.206, 1.207, 1.216, 1.234, 1.259, 1.291, 1.329, 1.378, 1.434, 1.499, 1.577, 1.666, 1.771, 1.891, 2.035, 2.204, 2.312,
+                    2.177, 2.049, 1.901, 1.774, 1.666, 1.573, 1.493, 1.424, 1.364, 1.312, 1.269, 1.235, 1.207, 1.187, 1.174, 1.169, 1.171, 1.181, 1.198, 1.222, 1.254, 1.293, 1.341, 1.397, 1.462, 1.536, 1.622, 1.722, 1.838, 1.976, 2.139, 2.254,
+                    2.137, 2.008, 1.864, 1.741, 1.634, 1.541, 1.462, 1.393, 1.335, 1.284, 1.242, 1.208, 1.181, 1.161, 1.148, 1.144, 1.145, 1.154, 1.171, 1.196, 1.227, 1.265, 1.312, 1.367, 1.431, 1.505, 1.591, 1.689, 1.803, 1.937, 2.096, 2.211,
+                    2.106, 1.979, 1.839, 1.717, 1.611, 1.519, 1.441, 1.372, 1.314, 1.263, 1.222, 1.188, 1.162, 1.142, 1.129, 1.124, 1.127, 1.137, 1.154, 1.176, 1.206, 1.245, 1.291, 1.346, 1.411, 1.484, 1.568, 1.667, 1.779, 1.909, 2.064, 2.178,
+                    2.073, 1.953, 1.815, 1.695, 1.589, 1.499, 1.421, 1.353, 1.295, 1.245, 1.203, 1.168, 1.141, 1.123, 1.111, 1.106, 1.108, 1.117, 1.134, 1.156, 1.188, 1.227, 1.274, 1.328, 1.392, 1.465, 1.549, 1.645, 1.756, 1.884, 2.036, 2.146,
+                    2.036, 1.919, 1.784, 1.665, 1.562, 1.472, 1.395, 1.327, 1.271, 1.222, 1.181, 1.146, 1.121, 1.101, 1.088, 1.083, 1.085, 1.095, 1.113, 1.136, 1.167, 1.204, 1.251, 1.305, 1.367, 1.439, 1.522, 1.617, 1.727, 1.852, 1.999, 2.107,
+                    2.005, 1.881, 1.749, 1.634, 1.532, 1.444, 1.369, 1.304, 1.248, 1.199, 1.158, 1.124, 1.097, 1.077, 1.063, 1.059, 1.061, 1.072, 1.089, 1.113, 1.145, 1.183, 1.229, 1.282, 1.343, 1.413, 1.494, 1.587, 1.695, 1.818, 1.961, 2.075,
+                    1.986, 1.861, 1.729, 1.615, 1.514, 1.427, 1.352, 1.287, 1.231, 1.183, 1.142, 1.108, 1.081, 1.062, 1.048, 1.043, 1.045, 1.057, 1.074, 1.098, 1.129, 1.167, 1.213, 1.266, 1.326, 1.397, 1.478, 1.571, 1.676, 1.798, 1.938, 2.054,
+                    1.974, 1.849, 1.719, 1.606, 1.506, 1.419, 1.344, 1.279, 1.223, 1.175, 1.133, 1.099, 1.072, 1.052, 1.039, 1.035, 1.037, 1.047, 1.064, 1.088, 1.119, 1.159, 1.205, 1.258, 1.319, 1.389, 1.471, 1.563, 1.669, 1.791, 1.929, 2.042,
+                    1.965, 1.839, 1.711, 1.597, 1.498, 1.412, 1.337, 1.272, 1.216, 1.167, 1.125, 1.091, 1.063, 1.044, 1.033, 1.028, 1.031, 1.039, 1.056, 1.081, 1.112, 1.152, 1.198, 1.252, 1.313, 1.383, 1.463, 1.555, 1.662, 1.782, 1.921, 2.033,
+                    1.948, 1.826, 1.698, 1.585, 1.487, 1.401, 1.327, 1.262, 1.206, 1.157, 1.115, 1.081, 1.053, 1.034, 1.024, 1.021, 1.022, 1.031, 1.046, 1.071, 1.103, 1.141, 1.188, 1.242, 1.303, 1.373, 1.453, 1.545, 1.651, 1.771, 1.909, 2.018,
+                    1.936, 1.807, 1.681, 1.569, 1.471, 1.386, 1.313, 1.249, 1.194, 1.146, 1.105, 1.071, 1.043, 1.023, 1.014, 1.009, 1.011, 1.021, 1.036, 1.061, 1.092, 1.131, 1.176, 1.228, 1.289, 1.358, 1.438, 1.529, 1.634, 1.753, 1.889, 2.005,
+                    1.932, 1.802, 1.675, 1.563, 1.466, 1.381, 1.308, 1.245, 1.189, 1.141, 1.099, 1.065, 1.039, 1.019, 1.009, 1.005, 1.008, 1.016, 1.032, 1.055, 1.087, 1.125, 1.171, 1.224, 1.284, 1.354, 1.433, 1.524, 1.629, 1.748, 1.884, 2.001,
+                    1.936, 1.808, 1.681, 1.569, 1.471, 1.385, 1.312, 1.249, 1.194, 1.145, 1.102, 1.067, 1.039, 1.022, 1.012, 1.009, 1.011, 1.019, 1.033, 1.057, 1.089, 1.128, 1.174, 1.228, 1.289, 1.358, 1.438, 1.529, 1.634, 1.754, 1.891, 2.005,
+                    1.944, 1.818, 1.689, 1.576, 1.478, 1.392, 1.319, 1.256, 1.199, 1.151, 1.107, 1.072, 1.044, 1.026, 1.017, 1.013, 1.015, 1.023, 1.037, 1.062, 1.094, 1.134, 1.181, 1.234, 1.295, 1.366, 1.446, 1.538, 1.643, 1.764, 1.902, 2.014,
+                    1.948, 1.822, 1.693, 1.579, 1.481, 1.395, 1.321, 1.258, 1.202, 1.153, 1.109, 1.074, 1.046, 1.028, 1.019, 1.015, 1.017, 1.025, 1.039, 1.064, 1.097, 1.137, 1.183, 1.237, 1.298, 1.368, 1.449, 1.541, 1.647, 1.768, 1.906, 2.018,
+                    1.951, 1.817, 1.689, 1.576, 1.477, 1.392, 1.319, 1.256, 1.199, 1.151, 1.108, 1.074, 1.048, 1.029, 1.017, 1.013, 1.015, 1.024, 1.042, 1.066, 1.097, 1.135, 1.181, 1.234, 1.295, 1.365, 1.446, 1.538, 1.643, 1.764, 1.902, 2.021,
+                    1.956, 1.828, 1.698, 1.584, 1.486, 1.401, 1.326, 1.263, 1.207, 1.159, 1.117, 1.084, 1.056, 1.036, 1.023, 1.019, 1.021, 1.031, 1.049, 1.074, 1.105, 1.143, 1.188, 1.241, 1.303, 1.373, 1.454, 1.546, 1.652, 1.773, 1.913, 2.026,
+                    1.974, 1.851, 1.719, 1.605, 1.505, 1.419, 1.344, 1.279, 1.223, 1.174, 1.133, 1.099, 1.072, 1.051, 1.038, 1.033, 1.035, 1.046, 1.064, 1.089, 1.121, 1.159, 1.204, 1.258, 1.319, 1.391, 1.472, 1.566, 1.672, 1.796, 1.937, 2.046,
+                    1.998, 1.879, 1.746, 1.629, 1.529, 1.441, 1.366, 1.299, 1.242, 1.193, 1.151, 1.116, 1.089, 1.069, 1.057, 1.052, 1.054, 1.065, 1.082, 1.106, 1.138, 1.177, 1.223, 1.278, 1.341, 1.412, 1.495, 1.591, 1.698, 1.824, 1.968, 2.069,
+                    2.025, 1.901, 1.764, 1.647, 1.545, 1.457, 1.381, 1.314, 1.257, 1.207, 1.165, 1.131, 1.105, 1.085, 1.072, 1.067, 1.069, 1.081, 1.097, 1.121, 1.152, 1.191, 1.237, 1.292, 1.355, 1.428, 1.511, 1.607, 1.716, 1.842, 1.988, 2.095,
+                    2.044, 1.915, 1.779, 1.659, 1.557, 1.468, 1.391, 1.325, 1.267, 1.219, 1.178, 1.145, 1.118, 1.098, 1.085, 1.081, 1.082, 1.093, 1.111, 1.135, 1.166, 1.204, 1.249, 1.303, 1.367, 1.439, 1.523, 1.619, 1.728, 1.855, 2.002, 2.115,
+                    2.067, 1.941, 1.802, 1.681, 1.578, 1.488, 1.411, 1.344, 1.288, 1.239, 1.197, 1.164, 1.137, 1.117, 1.103, 1.098, 1.099, 1.111, 1.129, 1.154, 1.185, 1.223, 1.268, 1.322, 1.385, 1.458, 1.543, 1.638, 1.749, 1.878, 2.027, 2.138,
+                    2.107, 1.984, 1.842, 1.719, 1.613, 1.521, 1.442, 1.374, 1.316, 1.267, 1.224, 1.191, 1.163, 1.143, 1.131, 1.126, 1.127, 1.138, 1.156, 1.181, 1.211, 1.249, 1.296, 1.352, 1.417, 1.492, 1.577, 1.674, 1.787, 1.919, 2.072, 2.181,
+                    2.151, 2.034, 1.888, 1.763, 1.653, 1.559, 1.477, 1.408, 1.349, 1.297, 1.254, 1.221, 1.194, 1.174, 1.162, 1.158, 1.159, 1.169, 1.186, 1.211, 1.241, 1.281, 1.328, 1.385, 1.451, 1.528, 1.616, 1.715, 1.831, 1.966, 2.124, 2.226,
+                    2.204, 2.074, 1.925, 1.797, 1.685, 1.589, 1.506, 1.436, 1.376, 1.324, 1.281, 1.247, 1.219, 1.201, 1.189, 1.184, 1.185, 1.196, 1.213, 1.237, 1.268, 1.308, 1.356, 1.413, 1.481, 1.558, 1.647, 1.748, 1.866, 2.004, 2.166, 2.278,
+                    2.246, 2.111, 1.959, 1.829, 1.715, 1.617, 1.534, 1.463, 1.403, 1.352, 1.308, 1.272, 1.244, 1.224, 1.212, 1.208, 1.209, 1.219, 1.236, 1.261, 1.294, 1.335, 1.383, 1.439, 1.507, 1.585, 1.674, 1.777, 1.898, 2.039, 2.204, 2.321,
+                    2.291, 2.158, 2.001, 1.868, 1.752, 1.653, 1.569, 1.498, 1.437, 1.385, 1.341, 1.305, 1.275, 1.253, 1.241, 1.236, 1.237, 1.248, 1.266, 1.293, 1.327, 1.367, 1.416, 1.473, 1.541, 1.619, 1.709, 1.814, 1.938, 2.082, 2.251, 2.371,
+                    2.354, 2.227, 2.063, 1.925, 1.807, 1.703, 1.614, 1.539, 1.476, 1.423, 1.379, 1.343, 1.315, 1.294, 1.281, 1.276, 1.277, 1.288, 1.305, 1.329, 1.362, 1.404, 1.454, 1.514, 1.584, 1.666, 1.759, 1.869, 1.996, 2.146, 2.321, 2.431,
+                    2.424, 2.283, 2.113, 1.972, 1.851, 1.745, 1.653, 1.577, 1.511, 1.455, 1.409, 1.371, 1.342, 1.319, 1.307, 1.305, 1.306, 1.311, 1.331, 1.357, 1.392, 1.436, 1.489, 1.549, 1.622, 1.705, 1.801, 1.913, 2.042, 2.197, 2.379, 2.499
+                ],
+                "sigma": 0.00123,
+                "sigma_Cb": 0.00146
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 2300,
+                        "ccm":
+                        [
+                            2.01119, -0.36191, -0.64928,
+                            -0.78032, 2.37784, -0.59752,
+                            -0.03773, -1.95327, 2.99099
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "ccm":
+                        [
+                            1.98369, -0.55358, -0.43011,
+                            -0.66848, 2.25457, -0.58609,
+                            0.07611, -1.54904, 2.47293
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.94265, -0.60043, -0.34222,
+                            -0.72163, 2.15558, -0.43395,
+                            0.01301, -1.21862, 2.20561
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "ccm":
+                        [
+                            1.93565, -0.67509, -0.26056,
+                            -0.58313, 2.01866, -0.43553,
+                            -0.02356, -0.83611, 1.85967
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "ccm":
+                        [
+                            2.47351, -1.29971, -0.17379,
+                            -0.58113, 1.90309, -0.32197,
+                            0.05889, -0.84751, 1.78862
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            2.01179, -0.81594, -0.19586,
+                            -0.42897, 2.04658, -0.61762,
+                            0.03994, -0.81735, 1.77741
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.cac": { }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.25,
+                "limit": 1.0,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx462.json 0.6.0-2/src/ipa/rpi/pisp/data/imx462.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx462.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx462.json	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,8 @@
 {
     "version": 2.0,
     "target": "pisp",
-    "description": "This is an interim tuning only. Please consider doing a more formal tuning for your application.",
+    "vendor": "Innomaker",
+    "sku": "CAM-MIPI462RAW",
     "algorithms": [
         {
             "rpi.black_level":
@@ -10,30 +11,33 @@
             }
         },
         {
-            "rpi.dpc": { }
-        },
-        {
             "rpi.lux":
             {
-                "reference_shutter_speed": 6813,
+                "reference_shutter_speed": 5437,
                 "reference_gain": 1.0,
                 "reference_aperture": 1.0,
-                "reference_lux": 890,
-                "reference_Y": 12900
+                "reference_lux": 972,
+                "reference_Y": 12728
+            }
+        },
+        {
+            "rpi.dpc":
+            {
+                "strength": 1
             }
         },
         {
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.67
+                "reference_slope": 3.849
             }
         },
         {
             "rpi.geq":
             {
-                "offset": 187,
-                "slope": 0.00842
+                "offset": 194,
+                "slope": 0.01041
             }
         },
         {
@@ -43,11 +47,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -56,7 +60,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -64,11 +68,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -77,19 +81,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -98,8 +102,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -107,128 +111,691 @@
         {
             "rpi.awb":
             {
-                "bayes": 0
-            }
-        },
-        {
-            "rpi.agc":
-            {
-                "speed": 0.2,
-                "metering_modes":
-                {
-                    "matrix":
+                "priors": [
                     {
-                        "weights":
+                        "lux": 0,
+                        "prior":
                         [
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
-                        ]
-                    },
-                    "centre-weighted":
-                    {
-                        "weights":
-                        [
-                            0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
-                            0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
-                            1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
-                            1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
-                            1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
-                            1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
-                            1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
-                            1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
-                            1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
-                            1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
-                            1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
-                            1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
-                            1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
-                            0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
-                            0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
-                        ]
-                    },
-                    "spot":
-                    {
-                        "weights":
-                        [
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-                            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
                         ]
                     }
-                },
-                "exposure_modes":
+                ],
+                "modes":
                 {
-                    "normal":
+                    "auto":
+                    {
+                        "lo": 2800,
+                        "hi": 6700
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2800,
+                        "hi": 3000
+                    },
+                    "tungsten":
                     {
-                        "shutter": [ 10, 30000, 60000 ],
-                        "gain": [ 1.0, 2.0, 8.0 ]
+                        "lo": 3000,
+                        "hi": 3500
                     },
-                    "short":
+                    "fluorescent":
                     {
-                        "shutter": [ 10, 5000, 10000, 20000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                        "lo": 4000,
+                        "hi": 4700
                     },
-                    "long":
+                    "indoor":
                     {
-                        "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
                     }
                 },
-                "constraint_modes":
-                {
-                    "normal": [  ],
-                    "highlight": [
+                "bayes": 1,
+                "ct_curve":
+                [
+                    2820.0, 0.8649, 0.3772,
+                    2865.0, 0.8521, 0.3881,
+                    2895.0, 0.8514, 0.3885,
+                    2906.0, 0.8486, 0.3909,
+                    2918.0, 0.8331, 0.4038,
+                    3587.0, 0.7423, 0.4781,
+                    3615.0, 0.7419, 0.4784,
+                    3620.0, 0.7382, 0.4814,
+                    4330.0, 0.6425, 0.5575,
+                    4490.0, 0.6296, 0.5676,
+                    4535.0, 0.6232, 0.5726,
+                    4580.0, 0.6181, 0.5766,
+                    5640.0, 0.5629, 0.6192,
+                    5675.0, 0.5614, 0.6203,
+                    5750.0, 0.5593, 0.6219,
+                    6737.0, 0.4925, 0.6724
+                ],
+                "sensitivity_r": 1.05,
+                "sensitivity_b": 1.05,
+                "transverse_pos": 0.04613,
+                "transverse_neg": 0.02808
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
                         {
-                            "bound": "LOWER",
-                            "q_lo": 0.98,
-                            "q_hi": 1.0,
-                            "y_target":
-                            [
-                                0, 0.5,
-                                1000, 0.5
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
                             ]
                         },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
                         {
-                            "bound": "UPPER",
-                            "q_lo": 0.98,
-                            "q_hi": 1.0,
-                            "y_target":
-                            [
-                                0, 0.8,
-                                1000, 0.8
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
                             ]
-                        }
-                    ]
-                },
-                "y_target":
-                [
-                    0, 0.16,
-                    1000, 0.16,
-                    10000, 0.16
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
                 ]
             }
         },
@@ -237,44 +804,276 @@
             {
                 "omega": 1.3,
                 "n_iter": 100,
-                "luminance_strength": 0.7,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2900,
+                        "table":
+                        [
+                            1.063, 1.058, 1.049, 1.046, 1.039, 1.034, 1.032, 1.027, 1.024, 1.022, 1.019, 1.017, 1.015, 1.014, 1.014, 1.014, 1.013, 1.013, 1.014, 1.014, 1.014, 1.015, 1.017, 1.019, 1.021, 1.022, 1.025, 1.028, 1.031, 1.035, 1.039, 1.043,
+                            1.061, 1.055, 1.049, 1.042, 1.039, 1.034, 1.031, 1.027, 1.023, 1.021, 1.019, 1.017, 1.015, 1.014, 1.014, 1.013, 1.013, 1.012, 1.013, 1.013, 1.014, 1.014, 1.016, 1.017, 1.019, 1.021, 1.024, 1.027, 1.029, 1.034, 1.037, 1.041,
+                            1.059, 1.053, 1.046, 1.041, 1.036, 1.032, 1.028, 1.025, 1.022, 1.019, 1.017, 1.015, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.012, 1.012, 1.012, 1.013, 1.014, 1.015, 1.017, 1.019, 1.022, 1.026, 1.029, 1.032, 1.036, 1.038,
+                            1.056, 1.052, 1.045, 1.039, 1.035, 1.031, 1.027, 1.024, 1.021, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.009, 1.009, 1.011, 1.011, 1.012, 1.014, 1.014, 1.016, 1.018, 1.021, 1.024, 1.027, 1.031, 1.034, 1.037,
+                            1.055, 1.049, 1.043, 1.038, 1.033, 1.029, 1.025, 1.022, 1.019, 1.017, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.008, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017, 1.019, 1.023, 1.026, 1.029, 1.033, 1.035,
+                            1.053, 1.048, 1.042, 1.037, 1.032, 1.027, 1.023, 1.021, 1.018, 1.016, 1.014, 1.012, 1.011, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.008, 1.008, 1.009, 1.011, 1.013, 1.014, 1.017, 1.019, 1.022, 1.025, 1.028, 1.032, 1.034,
+                            1.052, 1.046, 1.041, 1.035, 1.029, 1.026, 1.022, 1.019, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.006, 1.007, 1.006, 1.008, 1.009, 1.011, 1.011, 1.013, 1.016, 1.017, 1.021, 1.024, 1.027, 1.031, 1.033,
+                            1.051, 1.045, 1.039, 1.034, 1.029, 1.024, 1.021, 1.019, 1.016, 1.013, 1.012, 1.009, 1.007, 1.007, 1.006, 1.006, 1.006, 1.006, 1.006, 1.006, 1.007, 1.008, 1.009, 1.009, 1.012, 1.014, 1.017, 1.019, 1.023, 1.026, 1.029, 1.033,
+                            1.048, 1.044, 1.038, 1.032, 1.027, 1.023, 1.021, 1.018, 1.015, 1.013, 1.011, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.005, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.016, 1.018, 1.021, 1.025, 1.029, 1.032,
+                            1.047, 1.042, 1.037, 1.031, 1.027, 1.023, 1.019, 1.017, 1.014, 1.012, 1.009, 1.007, 1.006, 1.005, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.006, 1.007, 1.008, 1.009, 1.012, 1.014, 1.017, 1.021, 1.024, 1.028, 1.031,
+                            1.047, 1.042, 1.037, 1.031, 1.026, 1.023, 1.019, 1.016, 1.013, 1.011, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.015, 1.019, 1.023, 1.027, 1.031,
+                            1.046, 1.042, 1.036, 1.031, 1.025, 1.022, 1.019, 1.016, 1.013, 1.011, 1.008, 1.006, 1.005, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.002, 1.003, 1.005, 1.006, 1.008, 1.009, 1.011, 1.013, 1.014, 1.018, 1.023, 1.027, 1.031,
+                            1.045, 1.042, 1.035, 1.031, 1.025, 1.021, 1.018, 1.015, 1.012, 1.009, 1.008, 1.007, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.006, 1.007, 1.008, 1.011, 1.012, 1.014, 1.018, 1.022, 1.027, 1.029,
+                            1.044, 1.042, 1.034, 1.029, 1.025, 1.021, 1.018, 1.015, 1.012, 1.008, 1.007, 1.006, 1.005, 1.003, 1.002, 1.002, 1.002, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.007, 1.008, 1.011, 1.012, 1.014, 1.017, 1.021, 1.026, 1.028,
+                            1.044, 1.039, 1.034, 1.029, 1.024, 1.021, 1.017, 1.013, 1.011, 1.008, 1.007, 1.005, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.003, 1.002, 1.003, 1.004, 1.005, 1.007, 1.008, 1.009, 1.012, 1.014, 1.016, 1.021, 1.025, 1.027,
+                            1.044, 1.039, 1.034, 1.029, 1.024, 1.019, 1.017, 1.013, 1.011, 1.008, 1.006, 1.005, 1.003, 1.003, 1.002, 1.001, 1.001, 1.001, 1.001, 1.002, 1.002, 1.003, 1.004, 1.006, 1.008, 1.009, 1.012, 1.014, 1.016, 1.021, 1.025, 1.027,
+                            1.044, 1.039, 1.034, 1.028, 1.023, 1.018, 1.016, 1.013, 1.011, 1.008, 1.006, 1.005, 1.004, 1.003, 1.002, 1.001, 1.001, 1.001, 1.001, 1.002, 1.002, 1.002, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.016, 1.021, 1.026, 1.027,
+                            1.044, 1.039, 1.034, 1.027, 1.023, 1.019, 1.016, 1.014, 1.011, 1.008, 1.007, 1.005, 1.003, 1.002, 1.001, 1.001, 1.001, 1.001, 1.001, 1.002, 1.002, 1.003, 1.003, 1.005, 1.007, 1.009, 1.011, 1.014, 1.017, 1.021, 1.025, 1.028,
+                            1.044, 1.039, 1.034, 1.027, 1.023, 1.019, 1.016, 1.013, 1.011, 1.009, 1.007, 1.005, 1.004, 1.003, 1.001, 1.001, 1.001, 1.001, 1.001, 1.002, 1.003, 1.003, 1.003, 1.005, 1.007, 1.009, 1.011, 1.014, 1.016, 1.021, 1.025, 1.027,
+                            1.045, 1.039, 1.034, 1.028, 1.023, 1.021, 1.016, 1.014, 1.011, 1.008, 1.007, 1.005, 1.004, 1.003, 1.002, 1.001, 1.001, 1.001, 1.002, 1.002, 1.002, 1.003, 1.004, 1.006, 1.007, 1.009, 1.012, 1.014, 1.017, 1.021, 1.025, 1.027,
+                            1.045, 1.039, 1.034, 1.028, 1.023, 1.019, 1.016, 1.014, 1.011, 1.008, 1.007, 1.005, 1.004, 1.003, 1.002, 1.001, 1.001, 1.001, 1.001, 1.002, 1.002, 1.003, 1.004, 1.005, 1.008, 1.009, 1.012, 1.014, 1.017, 1.021, 1.024, 1.027,
+                            1.045, 1.038, 1.033, 1.028, 1.023, 1.021, 1.016, 1.014, 1.011, 1.008, 1.007, 1.005, 1.004, 1.003, 1.003, 1.001, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.004, 1.006, 1.008, 1.009, 1.012, 1.014, 1.017, 1.021, 1.025, 1.027,
+                            1.045, 1.039, 1.034, 1.028, 1.023, 1.021, 1.016, 1.014, 1.012, 1.009, 1.007, 1.006, 1.005, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.004, 1.007, 1.008, 1.011, 1.012, 1.014, 1.017, 1.021, 1.025, 1.027,
+                            1.045, 1.039, 1.035, 1.029, 1.025, 1.021, 1.017, 1.015, 1.012, 1.009, 1.008, 1.006, 1.005, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.008, 1.009, 1.011, 1.012, 1.014, 1.017, 1.021, 1.026, 1.028,
+                            1.045, 1.042, 1.036, 1.029, 1.026, 1.021, 1.018, 1.015, 1.013, 1.011, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.008, 1.009, 1.011, 1.012, 1.015, 1.017, 1.021, 1.026, 1.029,
+                            1.046, 1.042, 1.036, 1.031, 1.026, 1.021, 1.019, 1.016, 1.013, 1.011, 1.009, 1.007, 1.005, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.007, 1.009, 1.009, 1.011, 1.013, 1.016, 1.019, 1.023, 1.028, 1.029,
+                            1.048, 1.043, 1.037, 1.032, 1.027, 1.022, 1.019, 1.016, 1.014, 1.012, 1.009, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.012, 1.014, 1.017, 1.021, 1.024, 1.028, 1.029,
+                            1.049, 1.045, 1.039, 1.033, 1.029, 1.024, 1.021, 1.018, 1.015, 1.012, 1.011, 1.008, 1.007, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.006, 1.007, 1.009, 1.011, 1.011, 1.013, 1.015, 1.018, 1.021, 1.025, 1.028, 1.031,
+                            1.049, 1.046, 1.039, 1.035, 1.031, 1.025, 1.021, 1.019, 1.016, 1.013, 1.012, 1.011, 1.008, 1.007, 1.007, 1.006, 1.006, 1.006, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.014, 1.017, 1.019, 1.022, 1.026, 1.029, 1.032,
+                            1.052, 1.046, 1.041, 1.035, 1.031, 1.027, 1.023, 1.019, 1.016, 1.015, 1.012, 1.011, 1.009, 1.008, 1.007, 1.007, 1.006, 1.006, 1.006, 1.007, 1.008, 1.008, 1.009, 1.012, 1.013, 1.015, 1.017, 1.021, 1.023, 1.026, 1.031, 1.033,
+                            1.053, 1.047, 1.041, 1.036, 1.031, 1.027, 1.024, 1.019, 1.017, 1.016, 1.013, 1.011, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.016, 1.018, 1.021, 1.025, 1.028, 1.031, 1.036,
+                            1.054, 1.048, 1.042, 1.037, 1.032, 1.027, 1.024, 1.019, 1.017, 1.016, 1.014, 1.012, 1.009, 1.009, 1.008, 1.007, 1.008, 1.007, 1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.015, 1.016, 1.019, 1.021, 1.026, 1.029, 1.032, 1.036
+                        ]
+                    },
+                    {
+                        "ct": 4250,
+                        "table":
+                        [
+                            1.069, 1.063, 1.057, 1.049, 1.045, 1.039, 1.035, 1.031, 1.027, 1.025, 1.022, 1.021, 1.019, 1.017, 1.017, 1.016, 1.015, 1.015, 1.014, 1.015, 1.016, 1.018, 1.019, 1.021, 1.023, 1.024, 1.028, 1.032, 1.034, 1.039, 1.048, 1.049,
+                            1.066, 1.063, 1.055, 1.048, 1.044, 1.037, 1.033, 1.029, 1.026, 1.023, 1.021, 1.019, 1.017, 1.017, 1.015, 1.014, 1.013, 1.013, 1.013, 1.014, 1.015, 1.017, 1.018, 1.019, 1.021, 1.023, 1.026, 1.031, 1.034, 1.038, 1.044, 1.048,
+                            1.065, 1.061, 1.053, 1.046, 1.039, 1.035, 1.031, 1.027, 1.024, 1.022, 1.019, 1.017, 1.016, 1.014, 1.013, 1.012, 1.012, 1.012, 1.012, 1.013, 1.013, 1.015, 1.017, 1.018, 1.019, 1.021, 1.024, 1.028, 1.031, 1.038, 1.043, 1.046,
+                            1.064, 1.057, 1.051, 1.044, 1.038, 1.033, 1.028, 1.026, 1.022, 1.021, 1.018, 1.015, 1.014, 1.014, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.013, 1.013, 1.015, 1.016, 1.018, 1.021, 1.023, 1.026, 1.031, 1.035, 1.041, 1.044,
+                            1.062, 1.056, 1.048, 1.041, 1.037, 1.031, 1.027, 1.024, 1.021, 1.019, 1.016, 1.015, 1.013, 1.011, 1.011, 1.009, 1.009, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.015, 1.017, 1.019, 1.022, 1.025, 1.029, 1.033, 1.039, 1.042,
+                            1.061, 1.055, 1.047, 1.039, 1.036, 1.029, 1.027, 1.023, 1.021, 1.018, 1.016, 1.014, 1.012, 1.009, 1.009, 1.008, 1.008, 1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.014, 1.016, 1.018, 1.021, 1.024, 1.028, 1.032, 1.037, 1.041,
+                            1.059, 1.052, 1.044, 1.039, 1.034, 1.029, 1.025, 1.022, 1.019, 1.016, 1.014, 1.013, 1.009, 1.009, 1.008, 1.007, 1.007, 1.006, 1.007, 1.008, 1.008, 1.009, 1.011, 1.012, 1.014, 1.016, 1.019, 1.023, 1.026, 1.031, 1.035, 1.039,
+                            1.056, 1.051, 1.043, 1.037, 1.031, 1.029, 1.024, 1.021, 1.018, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.006, 1.006, 1.006, 1.008, 1.008, 1.009, 1.011, 1.013, 1.016, 1.019, 1.021, 1.024, 1.031, 1.035, 1.039,
+                            1.055, 1.049, 1.041, 1.036, 1.031, 1.027, 1.022, 1.019, 1.016, 1.014, 1.012, 1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.006, 1.007, 1.007, 1.009, 1.009, 1.012, 1.015, 1.017, 1.021, 1.023, 1.029, 1.033, 1.037,
+                            1.055, 1.049, 1.041, 1.035, 1.029, 1.026, 1.021, 1.018, 1.015, 1.013, 1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.004, 1.005, 1.006, 1.006, 1.008, 1.009, 1.011, 1.015, 1.016, 1.019, 1.023, 1.028, 1.032, 1.036,
+                            1.054, 1.046, 1.041, 1.034, 1.029, 1.024, 1.021, 1.017, 1.015, 1.011, 1.009, 1.007, 1.007, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.006, 1.007, 1.009, 1.011, 1.013, 1.016, 1.019, 1.023, 1.027, 1.029, 1.034,
+                            1.051, 1.046, 1.038, 1.033, 1.028, 1.024, 1.019, 1.017, 1.014, 1.011, 1.009, 1.007, 1.007, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.009, 1.011, 1.012, 1.015, 1.018, 1.021, 1.025, 1.029, 1.033,
+                            1.051, 1.045, 1.038, 1.032, 1.028, 1.023, 1.019, 1.016, 1.013, 1.011, 1.008, 1.007, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.012, 1.014, 1.017, 1.021, 1.024, 1.029, 1.033,
+                            1.051, 1.045, 1.037, 1.031, 1.028, 1.023, 1.019, 1.016, 1.012, 1.011, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.017, 1.021, 1.023, 1.028, 1.032,
+                            1.049, 1.042, 1.037, 1.029, 1.026, 1.022, 1.018, 1.015, 1.012, 1.009, 1.006, 1.005, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.007, 1.008, 1.011, 1.014, 1.016, 1.019, 1.023, 1.027, 1.031,
+                            1.049, 1.042, 1.036, 1.031, 1.025, 1.021, 1.018, 1.014, 1.011, 1.009, 1.007, 1.005, 1.004, 1.002, 1.002, 1.002, 1.001, 1.001, 1.002, 1.002, 1.003, 1.003, 1.005, 1.006, 1.009, 1.011, 1.013, 1.016, 1.019, 1.023, 1.027, 1.031,
+                            1.048, 1.042, 1.036, 1.031, 1.024, 1.022, 1.018, 1.014, 1.011, 1.009, 1.007, 1.005, 1.004, 1.002, 1.002, 1.001, 1.001, 1.001, 1.001, 1.002, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.012, 1.016, 1.018, 1.023, 1.026, 1.031,
+                            1.048, 1.041, 1.034, 1.029, 1.024, 1.021, 1.018, 1.014, 1.011, 1.009, 1.006, 1.006, 1.004, 1.002, 1.001, 1.001, 1.001, 1.001, 1.001, 1.001, 1.002, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013, 1.015, 1.019, 1.024, 1.027, 1.031,
+                            1.048, 1.041, 1.034, 1.031, 1.025, 1.021, 1.018, 1.014, 1.011, 1.009, 1.007, 1.006, 1.004, 1.003, 1.002, 1.001, 1.001, 1.001, 1.001, 1.002, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013, 1.016, 1.019, 1.023, 1.027, 1.031,
+                            1.048, 1.041, 1.034, 1.031, 1.025, 1.021, 1.017, 1.014, 1.011, 1.008, 1.007, 1.006, 1.005, 1.003, 1.002, 1.001, 1.001, 1.001, 1.002, 1.002, 1.003, 1.003, 1.004, 1.006, 1.009, 1.011, 1.013, 1.017, 1.019, 1.023, 1.028, 1.032,
+                            1.048, 1.041, 1.035, 1.029, 1.025, 1.021, 1.018, 1.014, 1.011, 1.008, 1.007, 1.005, 1.004, 1.004, 1.002, 1.002, 1.001, 1.001, 1.002, 1.002, 1.003, 1.003, 1.005, 1.007, 1.009, 1.011, 1.014, 1.017, 1.019, 1.023, 1.027, 1.031,
+                            1.049, 1.042, 1.037, 1.031, 1.026, 1.022, 1.018, 1.014, 1.011, 1.009, 1.007, 1.005, 1.005, 1.004, 1.002, 1.002, 1.001, 1.001, 1.002, 1.003, 1.003, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.017, 1.019, 1.024, 1.028, 1.031,
+                            1.048, 1.043, 1.036, 1.031, 1.025, 1.021, 1.018, 1.014, 1.012, 1.009, 1.007, 1.005, 1.004, 1.004, 1.003, 1.002, 1.001, 1.001, 1.002, 1.003, 1.003, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.017, 1.019, 1.023, 1.028, 1.031,
+                            1.048, 1.043, 1.037, 1.032, 1.026, 1.022, 1.018, 1.015, 1.012, 1.009, 1.008, 1.005, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.004, 1.006, 1.008, 1.009, 1.012, 1.014, 1.017, 1.021, 1.024, 1.028, 1.032,
+                            1.049, 1.045, 1.038, 1.032, 1.026, 1.021, 1.019, 1.015, 1.013, 1.011, 1.008, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.008, 1.011, 1.012, 1.015, 1.017, 1.021, 1.025, 1.029, 1.032,
+                            1.052, 1.046, 1.039, 1.032, 1.027, 1.022, 1.019, 1.016, 1.014, 1.011, 1.009, 1.007, 1.005, 1.004, 1.004, 1.003, 1.004, 1.003, 1.003, 1.004, 1.004, 1.006, 1.008, 1.009, 1.011, 1.014, 1.016, 1.019, 1.023, 1.026, 1.031, 1.032,
+                            1.054, 1.046, 1.039, 1.033, 1.028, 1.023, 1.019, 1.017, 1.014, 1.012, 1.009, 1.008, 1.007, 1.005, 1.005, 1.004, 1.005, 1.004, 1.004, 1.005, 1.005, 1.007, 1.008, 1.009, 1.012, 1.014, 1.016, 1.019, 1.023, 1.027, 1.031, 1.034,
+                            1.053, 1.047, 1.041, 1.034, 1.029, 1.024, 1.022, 1.018, 1.015, 1.013, 1.011, 1.009, 1.007, 1.006, 1.005, 1.005, 1.005, 1.004, 1.004, 1.006, 1.006, 1.008, 1.009, 1.011, 1.012, 1.015, 1.017, 1.019, 1.024, 1.028, 1.032, 1.035,
+                            1.054, 1.047, 1.041, 1.036, 1.031, 1.026, 1.022, 1.019, 1.016, 1.014, 1.011, 1.009, 1.008, 1.007, 1.006, 1.006, 1.006, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.015, 1.018, 1.019, 1.025, 1.029, 1.033, 1.036,
+                            1.057, 1.048, 1.042, 1.036, 1.031, 1.027, 1.023, 1.021, 1.017, 1.014, 1.013, 1.011, 1.009, 1.007, 1.007, 1.007, 1.006, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.013, 1.016, 1.019, 1.021, 1.025, 1.029, 1.034, 1.038,
+                            1.058, 1.051, 1.043, 1.038, 1.033, 1.027, 1.024, 1.021, 1.018, 1.015, 1.013, 1.012, 1.009, 1.008, 1.008, 1.007, 1.007, 1.007, 1.007, 1.008, 1.009, 1.009, 1.011, 1.012, 1.014, 1.016, 1.019, 1.023, 1.026, 1.031, 1.034, 1.039,
+                            1.059, 1.052, 1.046, 1.038, 1.034, 1.028, 1.024, 1.022, 1.018, 1.015, 1.013, 1.012, 1.009, 1.009, 1.008, 1.007, 1.007, 1.008, 1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.015, 1.017, 1.021, 1.023, 1.027, 1.031, 1.034, 1.039
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.067, 1.061, 1.054, 1.048, 1.046, 1.039, 1.035, 1.031, 1.028, 1.026, 1.023, 1.021, 1.019, 1.018, 1.016, 1.015, 1.016, 1.016, 1.016, 1.017, 1.018, 1.018, 1.021, 1.021, 1.023, 1.026, 1.031, 1.033, 1.039, 1.041, 1.047, 1.049,
+                            1.064, 1.059, 1.053, 1.046, 1.043, 1.037, 1.032, 1.028, 1.026, 1.024, 1.021, 1.021, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.015, 1.016, 1.016, 1.018, 1.019, 1.021, 1.022, 1.025, 1.028, 1.032, 1.036, 1.041, 1.044, 1.047,
+                            1.061, 1.057, 1.051, 1.046, 1.039, 1.034, 1.029, 1.027, 1.024, 1.022, 1.019, 1.018, 1.015, 1.015, 1.014, 1.013, 1.013, 1.013, 1.013, 1.014, 1.015, 1.016, 1.017, 1.019, 1.021, 1.023, 1.026, 1.029, 1.034, 1.039, 1.042, 1.046,
+                            1.061, 1.056, 1.049, 1.043, 1.038, 1.032, 1.028, 1.025, 1.022, 1.021, 1.018, 1.016, 1.015, 1.013, 1.013, 1.012, 1.011, 1.011, 1.012, 1.012, 1.013, 1.014, 1.015, 1.017, 1.019, 1.022, 1.025, 1.028, 1.032, 1.036, 1.041, 1.044,
+                            1.059, 1.053, 1.048, 1.042, 1.036, 1.032, 1.027, 1.025, 1.021, 1.019, 1.016, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.016, 1.018, 1.019, 1.023, 1.026, 1.031, 1.035, 1.041, 1.043,
+                            1.055, 1.052, 1.045, 1.039, 1.035, 1.029, 1.026, 1.022, 1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009, 1.008, 1.008, 1.009, 1.011, 1.011, 1.012, 1.014, 1.016, 1.019, 1.022, 1.024, 1.029, 1.032, 1.039, 1.042,
+                            1.055, 1.051, 1.044, 1.038, 1.033, 1.028, 1.026, 1.021, 1.018, 1.016, 1.015, 1.013, 1.011, 1.008, 1.008, 1.008, 1.008, 1.007, 1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.015, 1.018, 1.021, 1.024, 1.028, 1.032, 1.037, 1.041,
+                            1.054, 1.049, 1.043, 1.035, 1.031, 1.027, 1.023, 1.019, 1.017, 1.015, 1.013, 1.011, 1.009, 1.007, 1.007, 1.007, 1.007, 1.006, 1.007, 1.007, 1.008, 1.008, 1.011, 1.012, 1.014, 1.016, 1.019, 1.023, 1.026, 1.031, 1.036, 1.038,
+                            1.052, 1.049, 1.042, 1.035, 1.031, 1.027, 1.021, 1.019, 1.017, 1.014, 1.012, 1.009, 1.008, 1.007, 1.007, 1.007, 1.006, 1.006, 1.006, 1.007, 1.008, 1.008, 1.009, 1.011, 1.013, 1.015, 1.018, 1.021, 1.025, 1.031, 1.035, 1.037,
+                            1.052, 1.048, 1.041, 1.034, 1.029, 1.025, 1.021, 1.018, 1.015, 1.013, 1.011, 1.009, 1.007, 1.007, 1.006, 1.006, 1.005, 1.005, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.012, 1.015, 1.018, 1.021, 1.024, 1.029, 1.035, 1.037,
+                            1.051, 1.047, 1.041, 1.033, 1.029, 1.023, 1.019, 1.017, 1.015, 1.012, 1.011, 1.008, 1.006, 1.006, 1.006, 1.005, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.008, 1.009, 1.012, 1.014, 1.017, 1.019, 1.022, 1.027, 1.034, 1.036,
+                            1.051, 1.047, 1.039, 1.032, 1.028, 1.023, 1.019, 1.016, 1.014, 1.012, 1.009, 1.007, 1.006, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.014, 1.016, 1.019, 1.022, 1.026, 1.033, 1.036,
+                            1.051, 1.045, 1.038, 1.032, 1.026, 1.021, 1.018, 1.016, 1.014, 1.011, 1.009, 1.007, 1.006, 1.005, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.005, 1.006, 1.008, 1.009, 1.011, 1.013, 1.016, 1.019, 1.021, 1.025, 1.031, 1.035,
+                            1.049, 1.044, 1.037, 1.031, 1.026, 1.021, 1.017, 1.015, 1.013, 1.009, 1.008, 1.006, 1.006, 1.005, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.005, 1.006, 1.007, 1.009, 1.009, 1.013, 1.015, 1.018, 1.021, 1.026, 1.031, 1.034,
+                            1.048, 1.043, 1.036, 1.031, 1.025, 1.021, 1.018, 1.014, 1.011, 1.009, 1.008, 1.007, 1.006, 1.004, 1.003, 1.002, 1.002, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.008, 1.009, 1.012, 1.014, 1.017, 1.021, 1.026, 1.031, 1.034,
+                            1.048, 1.042, 1.037, 1.031, 1.025, 1.021, 1.017, 1.013, 1.011, 1.009, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.004, 1.006, 1.007, 1.009, 1.011, 1.014, 1.017, 1.019, 1.025, 1.029, 1.033,
+                            1.047, 1.042, 1.036, 1.031, 1.024, 1.021, 1.017, 1.013, 1.009, 1.008, 1.007, 1.006, 1.005, 1.003, 1.002, 1.002, 1.001, 1.001, 1.002, 1.003, 1.003, 1.004, 1.005, 1.007, 1.009, 1.012, 1.014, 1.017, 1.019, 1.024, 1.031, 1.033,
+                            1.047, 1.042, 1.037, 1.031, 1.024, 1.021, 1.017, 1.014, 1.011, 1.008, 1.007, 1.005, 1.004, 1.003, 1.002, 1.001, 1.001, 1.001, 1.002, 1.003, 1.003, 1.004, 1.005, 1.007, 1.009, 1.012, 1.014, 1.016, 1.019, 1.024, 1.028, 1.033,
+                            1.047, 1.042, 1.035, 1.029, 1.024, 1.021, 1.017, 1.015, 1.011, 1.009, 1.007, 1.005, 1.004, 1.002, 1.002, 1.002, 1.001, 1.001, 1.001, 1.002, 1.003, 1.004, 1.005, 1.007, 1.009, 1.012, 1.013, 1.016, 1.019, 1.023, 1.028, 1.034,
+                            1.046, 1.041, 1.034, 1.031, 1.025, 1.021, 1.017, 1.014, 1.011, 1.009, 1.007, 1.005, 1.003, 1.002, 1.002, 1.001, 1.001, 1.001, 1.002, 1.002, 1.003, 1.004, 1.005, 1.007, 1.009, 1.011, 1.013, 1.016, 1.019, 1.024, 1.029, 1.033,
+                            1.048, 1.042, 1.035, 1.031, 1.025, 1.021, 1.017, 1.014, 1.011, 1.009, 1.007, 1.005, 1.003, 1.003, 1.002, 1.002, 1.001, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.007, 1.009, 1.011, 1.014, 1.017, 1.019, 1.024, 1.029, 1.033,
+                            1.049, 1.042, 1.036, 1.029, 1.024, 1.021, 1.015, 1.014, 1.011, 1.009, 1.007, 1.005, 1.004, 1.003, 1.002, 1.001, 1.001, 1.001, 1.002, 1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.014, 1.016, 1.021, 1.024, 1.029, 1.033,
+                            1.048, 1.042, 1.038, 1.031, 1.024, 1.021, 1.016, 1.014, 1.012, 1.009, 1.007, 1.005, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.015, 1.018, 1.021, 1.024, 1.029, 1.033,
+                            1.048, 1.042, 1.038, 1.031, 1.025, 1.021, 1.017, 1.014, 1.012, 1.009, 1.007, 1.006, 1.004, 1.004, 1.003, 1.002, 1.002, 1.003, 1.004, 1.004, 1.004, 1.005, 1.006, 1.008, 1.009, 1.012, 1.015, 1.017, 1.021, 1.025, 1.029, 1.033,
+                            1.048, 1.043, 1.038, 1.031, 1.025, 1.021, 1.018, 1.015, 1.012, 1.009, 1.008, 1.006, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.004, 1.006, 1.008, 1.008, 1.011, 1.013, 1.015, 1.019, 1.022, 1.025, 1.029, 1.034,
+                            1.049, 1.044, 1.039, 1.032, 1.026, 1.021, 1.019, 1.015, 1.013, 1.011, 1.008, 1.007, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.006, 1.007, 1.009, 1.009, 1.012, 1.014, 1.016, 1.019, 1.023, 1.027, 1.031, 1.034,
+                            1.051, 1.045, 1.039, 1.033, 1.029, 1.022, 1.021, 1.016, 1.014, 1.011, 1.009, 1.008, 1.007, 1.005, 1.004, 1.004, 1.003, 1.004, 1.004, 1.006, 1.006, 1.008, 1.009, 1.011, 1.012, 1.014, 1.016, 1.021, 1.024, 1.029, 1.031, 1.035,
+                            1.051, 1.046, 1.041, 1.034, 1.029, 1.024, 1.019, 1.017, 1.015, 1.012, 1.011, 1.008, 1.008, 1.006, 1.004, 1.004, 1.003, 1.003, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.015, 1.018, 1.021, 1.025, 1.029, 1.033, 1.036,
+                            1.051, 1.046, 1.041, 1.037, 1.031, 1.026, 1.019, 1.017, 1.015, 1.014, 1.011, 1.009, 1.008, 1.007, 1.006, 1.004, 1.004, 1.004, 1.006, 1.006, 1.007, 1.009, 1.009, 1.011, 1.012, 1.015, 1.019, 1.021, 1.026, 1.031, 1.035, 1.037,
+                            1.052, 1.047, 1.041, 1.037, 1.031, 1.025, 1.021, 1.018, 1.016, 1.013, 1.011, 1.009, 1.007, 1.006, 1.006, 1.005, 1.004, 1.005, 1.006, 1.006, 1.007, 1.009, 1.011, 1.012, 1.014, 1.016, 1.019, 1.022, 1.027, 1.032, 1.035, 1.037,
+                            1.053, 1.047, 1.043, 1.037, 1.031, 1.025, 1.021, 1.018, 1.016, 1.013, 1.011, 1.009, 1.007, 1.007, 1.006, 1.005, 1.005, 1.005, 1.006, 1.007, 1.007, 1.009, 1.011, 1.012, 1.014, 1.017, 1.019, 1.023, 1.028, 1.032, 1.035, 1.038,
+                            1.054, 1.047, 1.043, 1.037, 1.032, 1.027, 1.022, 1.018, 1.016, 1.014, 1.012, 1.009, 1.007, 1.006, 1.006, 1.005, 1.004, 1.005, 1.006, 1.006, 1.007, 1.008, 1.011, 1.012, 1.014, 1.018, 1.021, 1.023, 1.029, 1.032, 1.035, 1.038
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2900,
+                        "table":
+                        [
+                            1.009, 1.009, 1.009, 1.009, 1.008, 1.006, 1.006, 1.005, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.005, 1.004, 1.003, 1.003, 1.002, 1.003, 1.004, 1.005, 1.006, 1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016,
+                            1.011, 1.011, 1.009, 1.009, 1.009, 1.008, 1.006, 1.006, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017,
+                            1.009, 1.011, 1.011, 1.009, 1.009, 1.008, 1.007, 1.006, 1.007, 1.007, 1.006, 1.004, 1.004, 1.004, 1.004, 1.003, 1.002, 1.002, 1.003, 1.004, 1.004, 1.005, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.012, 1.014, 1.016, 1.017,
+                            1.009, 1.009, 1.009, 1.009, 1.008, 1.008, 1.007, 1.007, 1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.003, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.006, 1.005, 1.006, 1.009, 1.011, 1.013, 1.015, 1.016,
+                            1.008, 1.008, 1.009, 1.008, 1.008, 1.007, 1.007, 1.007, 1.006, 1.006, 1.004, 1.004, 1.004, 1.004, 1.004, 1.002, 1.003, 1.003, 1.003, 1.004, 1.004, 1.004, 1.005, 1.005, 1.005, 1.005, 1.006, 1.008, 1.009, 1.012, 1.014, 1.015,
+                            1.009, 1.008, 1.008, 1.008, 1.008, 1.007, 1.007, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.006, 1.006, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.014,
+                            1.008, 1.008, 1.007, 1.007, 1.007, 1.006, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.006, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.013, 1.014,
+                            1.009, 1.008, 1.007, 1.006, 1.006, 1.005, 1.005, 1.004, 1.003, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.004, 1.004, 1.005, 1.004, 1.004, 1.004, 1.005, 1.005, 1.006, 1.007, 1.007, 1.008, 1.008, 1.011, 1.012, 1.015,
+                            1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.005, 1.004, 1.004, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.009, 1.012, 1.013,
+                            1.011, 1.009, 1.008, 1.006, 1.005, 1.004, 1.004, 1.004, 1.003, 1.003, 1.004, 1.004, 1.004, 1.003, 1.004, 1.003, 1.004, 1.004, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.012,
+                            1.011, 1.009, 1.008, 1.006, 1.005, 1.005, 1.004, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.005, 1.005, 1.005, 1.007, 1.007, 1.007, 1.008, 1.009, 1.009, 1.011, 1.013,
+                            1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.002, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.005, 1.007, 1.007, 1.007, 1.007, 1.008, 1.009, 1.012, 1.013,
+                            1.007, 1.006, 1.006, 1.005, 1.004, 1.005, 1.005, 1.005, 1.005, 1.004, 1.004, 1.003, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.005, 1.006, 1.007, 1.007, 1.007, 1.007, 1.008, 1.009, 1.012, 1.013,
+                            1.007, 1.006, 1.005, 1.003, 1.003, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.004, 1.003, 1.004, 1.004, 1.005, 1.005, 1.006, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.013,
+                            1.005, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.004, 1.004, 1.003, 1.003, 1.004, 1.003, 1.004, 1.005, 1.005, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012,
+                            1.007, 1.006, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.003, 1.003, 1.004, 1.004, 1.005, 1.004, 1.005, 1.006, 1.006, 1.007, 1.007, 1.009, 1.011, 1.012,
+                            1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.002, 1.003, 1.002, 1.002, 1.002, 1.001, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.004, 1.004, 1.005, 1.005, 1.006, 1.007, 1.007, 1.007, 1.008, 1.009, 1.012,
+                            1.007, 1.006, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.003, 1.002, 1.002, 1.002, 1.001, 1.002, 1.002, 1.002, 1.003, 1.003, 1.003, 1.004, 1.003, 1.004, 1.006, 1.007, 1.008, 1.008, 1.009, 1.009, 1.011, 1.013,
+                            1.006, 1.006, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.002, 1.002, 1.003, 1.003, 1.004, 1.004, 1.005, 1.006, 1.006, 1.008, 1.009, 1.009, 1.009, 1.009, 1.013,
+                            1.006, 1.006, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.002, 1.002, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.014,
+                            1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.005, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.005, 1.007, 1.007, 1.008, 1.009, 1.012, 1.013,
+                            1.008, 1.007, 1.005, 1.005, 1.004, 1.004, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.004, 1.004, 1.003, 1.004, 1.004, 1.004, 1.005, 1.006, 1.006, 1.006, 1.006, 1.008, 1.011, 1.013,
+                            1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.004, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.005, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.006, 1.007, 1.007, 1.011, 1.012,
+                            1.008, 1.006, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.003, 1.004, 1.005, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.006, 1.006, 1.006, 1.006, 1.007, 1.007, 1.007, 1.006, 1.008, 1.008, 1.011, 1.013,
+                            1.007, 1.006, 1.005, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.004, 1.003, 1.004, 1.005, 1.005, 1.003, 1.003, 1.003, 1.003, 1.004, 1.006, 1.006, 1.006, 1.007, 1.006, 1.007, 1.007, 1.007, 1.008, 1.009, 1.009, 1.012, 1.014,
+                            1.008, 1.008, 1.006, 1.005, 1.004, 1.005, 1.004, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.005, 1.004, 1.004, 1.004, 1.005, 1.006, 1.007, 1.007, 1.006, 1.006, 1.005, 1.006, 1.007, 1.008, 1.009, 1.009, 1.011, 1.012, 1.014,
+                            1.009, 1.008, 1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.004, 1.003, 1.004, 1.004, 1.005, 1.005, 1.005, 1.006, 1.007, 1.007, 1.007, 1.007, 1.007, 1.006, 1.006, 1.007, 1.008, 1.009, 1.009, 1.011, 1.012, 1.014, 1.015,
+                            1.008, 1.007, 1.007, 1.006, 1.006, 1.006, 1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.003, 1.003, 1.003, 1.005, 1.005, 1.006, 1.006, 1.007, 1.007, 1.007, 1.007, 1.007, 1.008, 1.008, 1.008, 1.009, 1.011, 1.012, 1.014, 1.015,
+                            1.007, 1.006, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.005, 1.004, 1.004, 1.003, 1.003, 1.002, 1.004, 1.004, 1.005, 1.005, 1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.009, 1.009, 1.009, 1.011, 1.014, 1.016, 1.017,
+                            1.006, 1.005, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.006, 1.008, 1.009, 1.009, 1.009, 1.011, 1.011, 1.013, 1.015, 1.017, 1.018,
+                            1.006, 1.006, 1.004, 1.004, 1.004, 1.003, 1.002, 1.003, 1.002, 1.004, 1.004, 1.004, 1.004, 1.005, 1.005, 1.006, 1.005, 1.004, 1.004, 1.005, 1.005, 1.005, 1.007, 1.008, 1.009, 1.008, 1.011, 1.012, 1.014, 1.016, 1.017, 1.019,
+                            1.007, 1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.001, 1.001, 1.001, 1.002, 1.002, 1.003, 1.004, 1.006, 1.006, 1.007, 1.005, 1.005, 1.005, 1.005, 1.006, 1.006, 1.007, 1.007, 1.006, 1.008, 1.011, 1.015, 1.016, 1.017, 1.018
+                        ]
+                    },
+                    {
+                        "ct": 4250,
+                        "table":
+                        [
+                            1.001, 1.004, 1.006, 1.008, 1.009, 1.009, 1.011, 1.011, 1.011, 1.012, 1.012, 1.012, 1.013, 1.014, 1.015, 1.014, 1.014, 1.012, 1.012, 1.013, 1.013, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.013, 1.012, 1.012, 1.012, 1.011,
+                            1.002, 1.005, 1.008, 1.009, 1.011, 1.012, 1.011, 1.011, 1.012, 1.013, 1.013, 1.014, 1.014, 1.014, 1.015, 1.014, 1.014, 1.014, 1.014, 1.013, 1.014, 1.014, 1.014, 1.014, 1.014, 1.013, 1.013, 1.013, 1.013, 1.012, 1.012, 1.011,
+                            1.004, 1.006, 1.009, 1.011, 1.012, 1.012, 1.012, 1.012, 1.013, 1.014, 1.014, 1.014, 1.015, 1.015, 1.015, 1.015, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.014, 1.013, 1.014, 1.013, 1.013, 1.012, 1.012,
+                            1.005, 1.007, 1.009, 1.011, 1.012, 1.012, 1.012, 1.013, 1.014, 1.014, 1.014, 1.014, 1.015, 1.016, 1.016, 1.017, 1.016, 1.016, 1.015, 1.015, 1.015, 1.014, 1.014, 1.013, 1.014, 1.013, 1.012, 1.013, 1.013, 1.013, 1.013, 1.012,
+                            1.005, 1.008, 1.009, 1.011, 1.012, 1.012, 1.013, 1.013, 1.014, 1.015, 1.015, 1.015, 1.017, 1.017, 1.017, 1.018, 1.017, 1.017, 1.017, 1.016, 1.015, 1.015, 1.014, 1.013, 1.013, 1.013, 1.012, 1.013, 1.013, 1.013, 1.013, 1.012,
+                            1.006, 1.008, 1.009, 1.011, 1.011, 1.012, 1.013, 1.013, 1.014, 1.015, 1.015, 1.016, 1.017, 1.018, 1.018, 1.019, 1.019, 1.018, 1.018, 1.017, 1.016, 1.016, 1.015, 1.014, 1.014, 1.012, 1.012, 1.013, 1.013, 1.013, 1.012, 1.012,
+                            1.007, 1.008, 1.009, 1.011, 1.011, 1.012, 1.012, 1.013, 1.014, 1.015, 1.016, 1.017, 1.018, 1.019, 1.019, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.016, 1.015, 1.014, 1.013, 1.013, 1.014, 1.014, 1.014, 1.012, 1.012,
+                            1.007, 1.009, 1.011, 1.011, 1.011, 1.012, 1.012, 1.013, 1.014, 1.015, 1.016, 1.018, 1.019, 1.019, 1.019, 1.021, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.016, 1.014, 1.014, 1.014, 1.014, 1.014, 1.013, 1.013, 1.012,
+                            1.008, 1.009, 1.011, 1.011, 1.011, 1.011, 1.011, 1.012, 1.014, 1.016, 1.017, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014, 1.013, 1.014, 1.014,
+                            1.009, 1.009, 1.011, 1.011, 1.011, 1.011, 1.012, 1.012, 1.014, 1.016, 1.017, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.019, 1.019, 1.019, 1.019, 1.018, 1.018, 1.017, 1.016, 1.015, 1.015, 1.013, 1.013, 1.013, 1.013, 1.013,
+                            1.008, 1.009, 1.009, 1.011, 1.011, 1.012, 1.012, 1.014, 1.016, 1.016, 1.017, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.017, 1.015, 1.015, 1.014, 1.014, 1.013, 1.013, 1.012,
+                            1.008, 1.009, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.017, 1.016, 1.015, 1.014, 1.014, 1.013, 1.014, 1.013,
+                            1.007, 1.008, 1.009, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017, 1.018, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014,
+                            1.008, 1.008, 1.008, 1.009, 1.009, 1.012, 1.014, 1.015, 1.017, 1.018, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.015,
+                            1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.014, 1.014, 1.016, 1.018, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.021, 1.019, 1.018, 1.018, 1.017, 1.015, 1.014, 1.014, 1.014, 1.014, 1.015,
+                            1.008, 1.009, 1.009, 1.009, 1.011, 1.013, 1.014, 1.014, 1.016, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.019, 1.021, 1.021, 1.021, 1.021, 1.018, 1.017, 1.017, 1.015, 1.014, 1.014, 1.014, 1.015, 1.015,
+                            1.008, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.019, 1.019, 1.017, 1.016, 1.015, 1.014, 1.013, 1.014, 1.014, 1.014,
+                            1.009, 1.009, 1.009, 1.011, 1.011, 1.012, 1.014, 1.016, 1.017, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.021, 1.019, 1.019, 1.018, 1.016, 1.015, 1.015, 1.013, 1.014, 1.014, 1.014,
+                            1.009, 1.009, 1.011, 1.011, 1.011, 1.013, 1.014, 1.016, 1.017, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.015, 1.014, 1.013, 1.013,
+                            1.009, 1.009, 1.011, 1.011, 1.012, 1.014, 1.014, 1.015, 1.017, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.014, 1.014, 1.013, 1.014,
+                            1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.015, 1.017, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.016, 1.016, 1.015, 1.014, 1.014, 1.014, 1.013, 1.013,
+                            1.009, 1.009, 1.011, 1.011, 1.012, 1.012, 1.014, 1.016, 1.018, 1.019, 1.019, 1.019, 1.019, 1.021, 1.021, 1.021, 1.019, 1.019, 1.021, 1.021, 1.021, 1.019, 1.019, 1.018, 1.016, 1.016, 1.015, 1.015, 1.014, 1.014, 1.014, 1.013,
+                            1.009, 1.009, 1.011, 1.011, 1.012, 1.012, 1.014, 1.015, 1.017, 1.019, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014, 1.014,
+                            1.009, 1.009, 1.011, 1.011, 1.012, 1.012, 1.013, 1.015, 1.018, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.017, 1.016, 1.015, 1.015, 1.014, 1.014, 1.014, 1.014,
+                            1.009, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.014, 1.017, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.015, 1.014, 1.014, 1.014, 1.014,
+                            1.008, 1.009, 1.011, 1.011, 1.012, 1.012, 1.013, 1.015, 1.016, 1.017, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.022, 1.022, 1.022, 1.021, 1.021, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.015, 1.015, 1.014, 1.013,
+                            1.008, 1.009, 1.011, 1.012, 1.012, 1.012, 1.013, 1.015, 1.016, 1.017, 1.018, 1.019, 1.019, 1.021, 1.021, 1.022, 1.022, 1.022, 1.022, 1.022, 1.021, 1.021, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.015, 1.015, 1.015,
+                            1.008, 1.009, 1.011, 1.012, 1.012, 1.012, 1.014, 1.015, 1.016, 1.017, 1.017, 1.018, 1.019, 1.019, 1.021, 1.021, 1.022, 1.022, 1.022, 1.021, 1.021, 1.021, 1.019, 1.018, 1.018, 1.017, 1.016, 1.016, 1.016, 1.015, 1.016, 1.015,
+                            1.007, 1.008, 1.009, 1.011, 1.011, 1.012, 1.014, 1.015, 1.016, 1.017, 1.017, 1.018, 1.019, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.018, 1.018, 1.017, 1.016, 1.016, 1.017, 1.016, 1.016, 1.015,
+                            1.006, 1.007, 1.009, 1.009, 1.011, 1.011, 1.013, 1.013, 1.015, 1.016, 1.018, 1.018, 1.018, 1.019, 1.019, 1.021, 1.021, 1.019, 1.019, 1.018, 1.018, 1.018, 1.017, 1.017, 1.017, 1.016, 1.016, 1.017, 1.016, 1.016, 1.016, 1.016,
+                            1.006, 1.006, 1.008, 1.009, 1.009, 1.009, 1.011, 1.012, 1.012, 1.014, 1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.016, 1.016, 1.016, 1.015, 1.016, 1.017, 1.017, 1.017, 1.017, 1.016,
+                            1.006, 1.007, 1.009, 1.009, 1.009, 1.009, 1.011, 1.011, 1.012, 1.014, 1.015, 1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.014, 1.014, 1.017, 1.017, 1.017, 1.018, 1.017, 1.016
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.001, 1.003, 1.003, 1.004, 1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.009, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.009, 1.009, 1.009, 1.009, 1.009, 1.008, 1.009, 1.009, 1.009, 1.008, 1.007, 1.007, 1.007, 1.006, 1.004,
+                            1.001, 1.003, 1.004, 1.004, 1.006, 1.006, 1.007, 1.008, 1.009, 1.009, 1.011, 1.011, 1.011, 1.012, 1.012, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011, 1.011, 1.009, 1.009, 1.009, 1.008, 1.008, 1.007, 1.007, 1.007, 1.006, 1.005,
+                            1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.012, 1.012, 1.013, 1.013, 1.013, 1.012, 1.012, 1.012, 1.012, 1.012, 1.012, 1.011, 1.011, 1.009, 1.009, 1.008, 1.008, 1.008, 1.007, 1.007, 1.007, 1.006,
+                            1.005, 1.005, 1.005, 1.007, 1.008, 1.008, 1.009, 1.011, 1.011, 1.012, 1.012, 1.012, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.013, 1.012, 1.012, 1.011, 1.011, 1.009, 1.009, 1.008, 1.008, 1.008, 1.008, 1.007, 1.007, 1.008,
+                            1.005, 1.004, 1.005, 1.007, 1.008, 1.009, 1.009, 1.011, 1.012, 1.012, 1.013, 1.013, 1.014, 1.014, 1.014, 1.015, 1.014, 1.014, 1.014, 1.013, 1.012, 1.011, 1.011, 1.011, 1.009, 1.009, 1.009, 1.008, 1.008, 1.008, 1.008, 1.008,
+                            1.004, 1.004, 1.006, 1.007, 1.008, 1.009, 1.009, 1.011, 1.011, 1.012, 1.013, 1.013, 1.016, 1.015, 1.016, 1.017, 1.016, 1.016, 1.014, 1.014, 1.014, 1.012, 1.012, 1.011, 1.011, 1.009, 1.009, 1.009, 1.009, 1.008, 1.008, 1.008,
+                            1.004, 1.004, 1.006, 1.006, 1.008, 1.009, 1.011, 1.011, 1.011, 1.012, 1.014, 1.015, 1.016, 1.017, 1.018, 1.018, 1.017, 1.016, 1.016, 1.015, 1.014, 1.013, 1.012, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.009, 1.008, 1.008,
+                            1.004, 1.005, 1.006, 1.006, 1.008, 1.009, 1.011, 1.011, 1.011, 1.013, 1.015, 1.016, 1.017, 1.017, 1.018, 1.018, 1.018, 1.018, 1.017, 1.017, 1.016, 1.014, 1.013, 1.013, 1.012, 1.011, 1.009, 1.011, 1.009, 1.009, 1.008, 1.008,
+                            1.005, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.011, 1.012, 1.014, 1.015, 1.016, 1.017, 1.017, 1.017, 1.018, 1.018, 1.017, 1.017, 1.017, 1.017, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.008, 1.008,
+                            1.005, 1.006, 1.007, 1.007, 1.008, 1.009, 1.011, 1.012, 1.014, 1.015, 1.017, 1.017, 1.017, 1.017, 1.018, 1.018, 1.019, 1.017, 1.017, 1.017, 1.017, 1.016, 1.015, 1.013, 1.013, 1.012, 1.011, 1.011, 1.009, 1.009, 1.009, 1.008,
+                            1.005, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.014, 1.015, 1.017, 1.017, 1.017, 1.017, 1.017, 1.018, 1.018, 1.017, 1.017, 1.017, 1.017, 1.016, 1.016, 1.015, 1.014, 1.012, 1.012, 1.011, 1.011, 1.009, 1.009, 1.009,
+                            1.005, 1.006, 1.005, 1.006, 1.008, 1.009, 1.012, 1.014, 1.015, 1.016, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.018, 1.018, 1.017, 1.017, 1.017, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.012, 1.013, 1.015, 1.016, 1.017, 1.017, 1.018, 1.018, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.016, 1.014, 1.013, 1.012, 1.011, 1.011, 1.009, 1.009, 1.008,
+                            1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.013, 1.014, 1.015, 1.016, 1.017, 1.018, 1.019, 1.019, 1.018, 1.018, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.015, 1.014, 1.013, 1.013, 1.011, 1.011, 1.009, 1.009, 1.008,
+                            1.004, 1.004, 1.005, 1.006, 1.008, 1.011, 1.013, 1.014, 1.015, 1.017, 1.018, 1.018, 1.019, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.017, 1.017, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.011, 1.009, 1.009, 1.008,
+                            1.004, 1.004, 1.006, 1.008, 1.009, 1.011, 1.013, 1.013, 1.015, 1.017, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.019, 1.018, 1.018, 1.018, 1.017, 1.015, 1.015, 1.014, 1.012, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.005, 1.005, 1.007, 1.008, 1.009, 1.011, 1.012, 1.014, 1.015, 1.017, 1.018, 1.018, 1.018, 1.018, 1.017, 1.017, 1.018, 1.019, 1.019, 1.018, 1.018, 1.018, 1.017, 1.016, 1.015, 1.014, 1.012, 1.011, 1.011, 1.009, 1.009, 1.011,
+                            1.005, 1.006, 1.008, 1.008, 1.009, 1.011, 1.012, 1.014, 1.016, 1.018, 1.017, 1.018, 1.018, 1.018, 1.017, 1.017, 1.018, 1.019, 1.018, 1.018, 1.018, 1.018, 1.018, 1.016, 1.015, 1.014, 1.013, 1.011, 1.011, 1.011, 1.009, 1.009,
+                            1.006, 1.006, 1.008, 1.008, 1.011, 1.012, 1.013, 1.015, 1.016, 1.017, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.017, 1.018, 1.017, 1.016, 1.015, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.009,
+                            1.005, 1.006, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017, 1.018, 1.018, 1.018, 1.018, 1.018, 1.018, 1.019, 1.019, 1.018, 1.018, 1.018, 1.017, 1.017, 1.016, 1.016, 1.015, 1.014, 1.014, 1.012, 1.011, 1.011, 1.009, 1.009,
+                            1.006, 1.006, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016, 1.018, 1.018, 1.018, 1.019, 1.018, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.017, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.011, 1.009, 1.009,
+                            1.006, 1.006, 1.007, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016, 1.018, 1.018, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.019, 1.018, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.005, 1.006, 1.007, 1.008, 1.011, 1.012, 1.013, 1.015, 1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.021, 1.019, 1.019, 1.018, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.015, 1.014, 1.013, 1.011, 1.011, 1.009, 1.009, 1.011,
+                            1.004, 1.005, 1.007, 1.008, 1.009, 1.011, 1.012, 1.015, 1.016, 1.018, 1.018, 1.019, 1.019, 1.021, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.014, 1.013, 1.011, 1.011, 1.009, 1.009, 1.009,
+                            1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.012, 1.014, 1.016, 1.017, 1.018, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.014, 1.013, 1.012, 1.011, 1.011, 1.009, 1.009,
+                            1.004, 1.004, 1.006, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016, 1.018, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.019, 1.018, 1.016, 1.016, 1.014, 1.013, 1.012, 1.012, 1.011, 1.011, 1.009,
+                            1.004, 1.005, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.021, 1.021, 1.021, 1.021, 1.021, 1.019, 1.018, 1.017, 1.016, 1.016, 1.014, 1.012, 1.012, 1.011, 1.011, 1.011, 1.011,
+                            1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.012, 1.013, 1.014, 1.016, 1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.015, 1.015, 1.013, 1.013, 1.012, 1.012, 1.011, 1.011, 1.011,
+                            1.003, 1.004, 1.005, 1.006, 1.008, 1.009, 1.011, 1.014, 1.014, 1.016, 1.016, 1.017, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.017, 1.015, 1.015, 1.014, 1.013, 1.012, 1.012, 1.011, 1.012, 1.013,
+                            1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.011, 1.013, 1.014, 1.015, 1.016, 1.017, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.017, 1.017, 1.016, 1.016, 1.015, 1.014, 1.013, 1.012, 1.012, 1.012, 1.013, 1.014,
+                            1.004, 1.004, 1.005, 1.006, 1.007, 1.008, 1.009, 1.011, 1.012, 1.013, 1.015, 1.017, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.017, 1.017, 1.016, 1.015, 1.015, 1.015, 1.014, 1.013, 1.013, 1.012, 1.013, 1.013, 1.013, 1.014,
+                            1.004, 1.004, 1.005, 1.006, 1.008, 1.008, 1.009, 1.009, 1.011, 1.012, 1.015, 1.016, 1.016, 1.017, 1.018, 1.019, 1.019, 1.019, 1.017, 1.016, 1.015, 1.015, 1.014, 1.014, 1.013, 1.012, 1.012, 1.012, 1.014, 1.014, 1.013, 1.013
+                        ]
+                    }
+                ],
                 "luminance_lut":
                 [
-                    2.844, 2.604, 2.365, 2.2, 2.039, 1.916, 1.799, 1.707, 1.622, 1.552, 1.487, 1.435, 1.389, 1.356, 1.332, 1.317, 1.31, 1.308, 1.313, 1.324, 1.344, 1.37, 1.41, 1.454, 1.508, 1.567, 1.641, 1.719, 1.82, 1.925, 2.073, 2.221,
-                    2.749, 2.521, 2.294, 2.134, 1.979, 1.861, 1.749, 1.661, 1.578, 1.511, 1.448, 1.398, 1.354, 1.322, 1.3, 1.285, 1.278, 1.277, 1.281, 1.292, 1.311, 1.336, 1.374, 1.416, 1.469, 1.526, 1.596, 1.671, 1.77, 1.872, 2.019, 2.166,
-                    2.654, 2.438, 2.223, 2.069, 1.919, 1.807, 1.7, 1.614, 1.534, 1.469, 1.409, 1.361, 1.318, 1.288, 1.267, 1.254, 1.247, 1.245, 1.25, 1.259, 1.277, 1.302, 1.338, 1.379, 1.43, 1.485, 1.552, 1.623, 1.719, 1.819, 1.965, 2.112,
-                    2.563, 2.359, 2.155, 2.007, 1.863, 1.755, 1.653, 1.571, 1.493, 1.43, 1.372, 1.325, 1.284, 1.256, 1.236, 1.223, 1.217, 1.216, 1.219, 1.229, 1.246, 1.269, 1.305, 1.344, 1.393, 1.446, 1.51, 1.578, 1.672, 1.77, 1.914, 2.059,
-                    2.494, 2.299, 2.103, 1.961, 1.822, 1.718, 1.619, 1.538, 1.461, 1.399, 1.343, 1.298, 1.259, 1.232, 1.213, 1.2, 1.194, 1.193, 1.196, 1.205, 1.222, 1.245, 1.279, 1.318, 1.365, 1.416, 1.481, 1.549, 1.641, 1.735, 1.875, 2.015,
-                    2.425, 2.238, 2.05, 1.914, 1.782, 1.681, 1.585, 1.505, 1.429, 1.369, 1.314, 1.271, 1.234, 1.208, 1.189, 1.177, 1.171, 1.169, 1.173, 1.182, 1.198, 1.221, 1.254, 1.292, 1.338, 1.387, 1.452, 1.519, 1.609, 1.701, 1.836, 1.971,
-                    2.363, 2.183, 2.003, 1.873, 1.746, 1.648, 1.555, 1.477, 1.401, 1.342, 1.289, 1.247, 1.212, 1.187, 1.168, 1.156, 1.149, 1.148, 1.152, 1.16, 1.177, 1.198, 1.231, 1.267, 1.312, 1.36, 1.425, 1.492, 1.58, 1.671, 1.802, 1.932,
-                    2.314, 2.14, 1.965, 1.839, 1.716, 1.622, 1.532, 1.454, 1.38, 1.322, 1.27, 1.229, 1.195, 1.169, 1.149, 1.137, 1.129, 1.128, 1.132, 1.142, 1.158, 1.18, 1.21, 1.245, 1.289, 1.336, 1.401, 1.469, 1.557, 1.649, 1.776, 1.903,
-                    2.264, 2.096, 1.927, 1.805, 1.687, 1.596, 1.509, 1.432, 1.358, 1.301, 1.251, 1.211, 1.177, 1.151, 1.131, 1.117, 1.109, 1.108, 1.113, 1.123, 1.14, 1.161, 1.19, 1.222, 1.265, 1.313, 1.378, 1.445, 1.534, 1.626, 1.75, 1.874,
-                    2.225, 2.061, 1.897, 1.778, 1.663, 1.574, 1.489, 1.414, 1.341, 1.285, 1.235, 1.196, 1.163, 1.136, 1.115, 1.1, 1.091, 1.089, 1.095, 1.106, 1.124, 1.145, 1.174, 1.205, 1.248, 1.294, 1.359, 1.427, 1.516, 1.606, 1.728, 1.849,
-                    2.193, 2.033, 1.872, 1.756, 1.642, 1.556, 1.473, 1.399, 1.327, 1.272, 1.224, 1.185, 1.15, 1.123, 1.1, 1.084, 1.074, 1.072, 1.078, 1.09, 1.11, 1.133, 1.161, 1.193, 1.234, 1.28, 1.345, 1.413, 1.501, 1.59, 1.709, 1.828,
-                    2.161, 2.004, 1.848, 1.734, 1.622, 1.537, 1.457, 1.384, 1.313, 1.26, 1.212, 1.173, 1.138, 1.11, 1.085, 1.068, 1.057, 1.055, 1.062, 1.075, 1.096, 1.12, 1.148, 1.18, 1.221, 1.266, 1.331, 1.399, 1.486, 1.574, 1.69, 1.807,
-                    2.14, 1.986, 1.832, 1.719, 1.609, 1.525, 1.445, 1.373, 1.304, 1.251, 1.204, 1.165, 1.129, 1.1, 1.074, 1.055, 1.043, 1.041, 1.049, 1.063, 1.086, 1.11, 1.14, 1.172, 1.212, 1.258, 1.323, 1.39, 1.477, 1.566, 1.679, 1.792,
-                    2.123, 1.971, 1.819, 1.707, 1.598, 1.514, 1.434, 1.364, 1.296, 1.243, 1.197, 1.158, 1.122, 1.091, 1.064, 1.044, 1.031, 1.027, 1.036, 1.052, 1.076, 1.102, 1.132, 1.165, 1.206, 1.251, 1.316, 1.383, 1.471, 1.56, 1.67, 1.78,
-                    2.106, 1.956, 1.806, 1.695, 1.587, 1.504, 1.424, 1.354, 1.288, 1.236, 1.19, 1.15, 1.114, 1.083, 1.055, 1.033, 1.018, 1.014, 1.024, 1.04, 1.066, 1.094, 1.124, 1.158, 1.199, 1.245, 1.309, 1.376, 1.465, 1.555, 1.661, 1.767,
-                    2.104, 1.955, 1.805, 1.694, 1.586, 1.502, 1.422, 1.352, 1.285, 1.234, 1.188, 1.149, 1.113, 1.081, 1.053, 1.031, 1.014, 1.011, 1.021, 1.038, 1.064, 1.091, 1.122, 1.156, 1.198, 1.244, 1.308, 1.376, 1.465, 1.555, 1.66, 1.766,
-                    2.104, 1.955, 1.806, 1.695, 1.586, 1.502, 1.421, 1.351, 1.284, 1.232, 1.187, 1.148, 1.112, 1.08, 1.051, 1.029, 1.012, 1.008, 1.02, 1.036, 1.062, 1.089, 1.12, 1.155, 1.197, 1.244, 1.308, 1.375, 1.465, 1.555, 1.661, 1.766,
-                    2.105, 1.956, 1.807, 1.696, 1.587, 1.502, 1.42, 1.35, 1.282, 1.231, 1.186, 1.148, 1.112, 1.08, 1.051, 1.028, 1.011, 1.007, 1.019, 1.036, 1.061, 1.088, 1.119, 1.154, 1.197, 1.244, 1.308, 1.376, 1.466, 1.557, 1.662, 1.767,
-                    2.121, 1.97, 1.818, 1.705, 1.595, 1.508, 1.424, 1.353, 1.286, 1.236, 1.191, 1.153, 1.118, 1.087, 1.059, 1.038, 1.022, 1.018, 1.028, 1.044, 1.067, 1.093, 1.124, 1.158, 1.201, 1.248, 1.314, 1.383, 1.474, 1.567, 1.672, 1.777,
-                    2.137, 1.983, 1.829, 1.715, 1.603, 1.514, 1.428, 1.357, 1.291, 1.24, 1.196, 1.158, 1.123, 1.094, 1.068, 1.047, 1.033, 1.029, 1.038, 1.052, 1.074, 1.098, 1.128, 1.162, 1.205, 1.253, 1.32, 1.39, 1.483, 1.577, 1.682, 1.788,
-                    2.154, 1.998, 1.843, 1.726, 1.613, 1.522, 1.435, 1.364, 1.297, 1.246, 1.202, 1.164, 1.131, 1.102, 1.078, 1.059, 1.045, 1.041, 1.048, 1.061, 1.082, 1.105, 1.134, 1.167, 1.211, 1.259, 1.327, 1.399, 1.494, 1.588, 1.694, 1.8,
-                    2.176, 2.019, 1.862, 1.744, 1.628, 1.537, 1.449, 1.377, 1.309, 1.258, 1.213, 1.176, 1.143, 1.116, 1.092, 1.074, 1.061, 1.057, 1.063, 1.075, 1.094, 1.117, 1.146, 1.178, 1.222, 1.27, 1.34, 1.414, 1.509, 1.604, 1.711, 1.818,
-                    2.199, 2.04, 1.881, 1.761, 1.644, 1.552, 1.464, 1.391, 1.321, 1.269, 1.223, 1.187, 1.155, 1.129, 1.106, 1.09, 1.078, 1.074, 1.078, 1.088, 1.107, 1.128, 1.157, 1.189, 1.233, 1.281, 1.353, 1.428, 1.524, 1.62, 1.728, 1.836,
-                    2.228, 2.066, 1.904, 1.782, 1.662, 1.57, 1.482, 1.408, 1.337, 1.284, 1.237, 1.201, 1.17, 1.145, 1.123, 1.107, 1.096, 1.092, 1.095, 1.104, 1.121, 1.142, 1.17, 1.203, 1.247, 1.297, 1.37, 1.446, 1.542, 1.639, 1.75, 1.86,
-                    2.267, 2.099, 1.932, 1.807, 1.684, 1.592, 1.504, 1.428, 1.356, 1.302, 1.255, 1.219, 1.189, 1.164, 1.141, 1.125, 1.115, 1.111, 1.114, 1.123, 1.138, 1.158, 1.186, 1.22, 1.266, 1.318, 1.391, 1.467, 1.563, 1.661, 1.776, 1.891,
-                    2.305, 2.132, 1.96, 1.832, 1.707, 1.614, 1.526, 1.449, 1.375, 1.32, 1.272, 1.237, 1.208, 1.182, 1.16, 1.144, 1.135, 1.131, 1.134, 1.141, 1.155, 1.174, 1.203, 1.236, 1.285, 1.338, 1.412, 1.489, 1.585, 1.682, 1.802, 1.922,
-                    2.351, 2.173, 1.996, 1.864, 1.736, 1.641, 1.552, 1.474, 1.4, 1.344, 1.294, 1.258, 1.228, 1.203, 1.181, 1.165, 1.156, 1.152, 1.155, 1.162, 1.176, 1.195, 1.224, 1.259, 1.309, 1.365, 1.439, 1.516, 1.613, 1.711, 1.835, 1.96,
-                    2.4, 2.218, 2.036, 1.901, 1.768, 1.671, 1.58, 1.502, 1.428, 1.37, 1.319, 1.281, 1.249, 1.224, 1.203, 1.188, 1.178, 1.174, 1.177, 1.184, 1.197, 1.217, 1.248, 1.285, 1.337, 1.394, 1.469, 1.547, 1.644, 1.743, 1.873, 2.002,
-                    2.45, 2.264, 2.077, 1.938, 1.801, 1.702, 1.608, 1.53, 1.456, 1.397, 1.344, 1.304, 1.271, 1.245, 1.224, 1.21, 1.2, 1.196, 1.199, 1.206, 1.219, 1.239, 1.272, 1.311, 1.365, 1.424, 1.5, 1.578, 1.676, 1.776, 1.91, 2.044,
-                    2.513, 2.318, 2.124, 1.984, 1.848, 1.747, 1.652, 1.572, 1.496, 1.436, 1.383, 1.341, 1.303, 1.274, 1.253, 1.238, 1.228, 1.225, 1.228, 1.235, 1.248, 1.269, 1.303, 1.343, 1.4, 1.46, 1.537, 1.617, 1.718, 1.82, 1.962, 2.103,
-                    2.579, 2.376, 2.172, 2.032, 1.897, 1.796, 1.7, 1.617, 1.538, 1.479, 1.426, 1.38, 1.337, 1.306, 1.283, 1.267, 1.258, 1.254, 1.257, 1.265, 1.279, 1.3, 1.336, 1.377, 1.435, 1.497, 1.576, 1.658, 1.761, 1.867, 2.016, 2.165,
-                    2.645, 2.433, 2.22, 2.08, 1.946, 1.844, 1.747, 1.663, 1.581, 1.521, 1.468, 1.419, 1.371, 1.337, 1.313, 1.296, 1.287, 1.284, 1.287, 1.295, 1.309, 1.331, 1.368, 1.411, 1.471, 1.535, 1.615, 1.699, 1.805, 1.914, 2.071, 2.227
+                    2.453, 2.231, 1.984, 1.798, 1.655, 1.541, 1.449, 1.373, 1.311, 1.261, 1.221, 1.185, 1.155, 1.133, 1.125, 1.124, 1.124, 1.124, 1.129, 1.149, 1.179, 1.213, 1.251, 1.299, 1.357, 1.427, 1.512, 1.613, 1.741, 1.901, 2.116, 2.292,
+                    2.331, 2.129, 1.904, 1.731, 1.597, 1.489, 1.404, 1.332, 1.273, 1.224, 1.188, 1.156, 1.131, 1.114, 1.102, 1.096, 1.096, 1.099, 1.109, 1.126, 1.149, 1.181, 1.216, 1.261, 1.316, 1.382, 1.463, 1.562, 1.679, 1.829, 2.022, 2.188,
+                    2.233, 2.044, 1.834, 1.674, 1.549, 1.448, 1.365, 1.296, 1.241, 1.192, 1.156, 1.129, 1.105, 1.088, 1.077, 1.072, 1.071, 1.074, 1.083, 1.099, 1.123, 1.149, 1.186, 1.228, 1.279, 1.344, 1.421, 1.513, 1.629, 1.766, 1.943, 2.101,
+                    2.147, 1.971, 1.775, 1.624, 1.506, 1.409, 1.329, 1.265, 1.209, 1.164, 1.129, 1.104, 1.082, 1.066, 1.056, 1.051, 1.051, 1.053, 1.061, 1.076, 1.098, 1.123, 1.158, 1.199, 1.249, 1.311, 1.384, 1.472, 1.585, 1.715, 1.879, 2.024,
+                    2.078, 1.905, 1.722, 1.581, 1.468, 1.376, 1.299, 1.236, 1.183, 1.139, 1.106, 1.082, 1.062, 1.047, 1.038, 1.033, 1.032, 1.035, 1.042, 1.056, 1.075, 1.099, 1.133, 1.172, 1.221, 1.279, 1.349, 1.434, 1.542, 1.671, 1.823, 1.964,
+                    2.015, 1.847, 1.677, 1.543, 1.434, 1.345, 1.271, 1.209, 1.158, 1.117, 1.086, 1.062, 1.046, 1.032, 1.025, 1.022, 1.021, 1.022, 1.027, 1.039, 1.056, 1.081, 1.111, 1.149, 1.196, 1.253, 1.321, 1.402, 1.501, 1.628, 1.777, 1.911,
+                    1.962, 1.801, 1.639, 1.508, 1.404, 1.318, 1.247, 1.186, 1.137, 1.098, 1.069, 1.047, 1.032, 1.023, 1.019, 1.018, 1.017, 1.017, 1.018, 1.026, 1.041, 1.062, 1.092, 1.128, 1.174, 1.229, 1.297, 1.375, 1.469, 1.589, 1.735, 1.868,
+                    1.917, 1.757, 1.602, 1.479, 1.377, 1.293, 1.223, 1.166, 1.119, 1.081, 1.054, 1.035, 1.024, 1.019, 1.017, 1.015, 1.014, 1.013, 1.014, 1.017, 1.028, 1.048, 1.075, 1.111, 1.155, 1.209, 1.274, 1.349, 1.441, 1.555, 1.697, 1.829,
+                    1.878, 1.722, 1.573, 1.452, 1.354, 1.273, 1.205, 1.149, 1.103, 1.067, 1.042, 1.026, 1.021, 1.018, 1.015, 1.013, 1.012, 1.011, 1.012, 1.014, 1.019, 1.036, 1.062, 1.095, 1.137, 1.189, 1.252, 1.328, 1.418, 1.529, 1.663, 1.798,
+                    1.843, 1.691, 1.547, 1.429, 1.333, 1.254, 1.188, 1.133, 1.088, 1.055, 1.033, 1.023, 1.019, 1.016, 1.013, 1.011, 1.011, 1.009, 1.011, 1.013, 1.015, 1.026, 1.049, 1.081, 1.123, 1.173, 1.236, 1.309, 1.397, 1.505, 1.636, 1.771,
+                    1.816, 1.664, 1.525, 1.411, 1.317, 1.239, 1.174, 1.119, 1.077, 1.045, 1.026, 1.021, 1.017, 1.014, 1.011, 1.009, 1.008, 1.008, 1.009, 1.011, 1.014, 1.019, 1.041, 1.069, 1.109, 1.159, 1.219, 1.292, 1.379, 1.484, 1.611, 1.748,
+                    1.794, 1.642, 1.505, 1.394, 1.302, 1.225, 1.162, 1.109, 1.067, 1.038, 1.024, 1.019, 1.015, 1.012, 1.009, 1.007, 1.006, 1.006, 1.008, 1.009, 1.012, 1.017, 1.031, 1.059, 1.099, 1.147, 1.207, 1.278, 1.364, 1.466, 1.591, 1.729,
+                    1.774, 1.622, 1.489, 1.379, 1.291, 1.215, 1.152, 1.099, 1.059, 1.031, 1.022, 1.018, 1.013, 1.011, 1.007, 1.005, 1.004, 1.005, 1.006, 1.009, 1.011, 1.015, 1.027, 1.053, 1.091, 1.138, 1.197, 1.267, 1.351, 1.453, 1.574, 1.715,
+                    1.759, 1.608, 1.477, 1.369, 1.282, 1.207, 1.144, 1.093, 1.053, 1.028, 1.021, 1.017, 1.013, 1.009, 1.005, 1.004, 1.003, 1.004, 1.006, 1.008, 1.011, 1.014, 1.022, 1.046, 1.083, 1.131, 1.187, 1.257, 1.342, 1.441, 1.562, 1.702,
+                    1.751, 1.597, 1.466, 1.361, 1.274, 1.199, 1.138, 1.087, 1.049, 1.026, 1.019, 1.015, 1.011, 1.007, 1.004, 1.002, 1.002, 1.003, 1.005, 1.007, 1.009, 1.014, 1.019, 1.042, 1.078, 1.125, 1.181, 1.249, 1.335, 1.434, 1.552, 1.694,
+                    1.743, 1.589, 1.461, 1.355, 1.269, 1.195, 1.134, 1.084, 1.046, 1.025, 1.019, 1.015, 1.011, 1.007, 1.003, 1.001, 1.001, 1.002, 1.004, 1.006, 1.009, 1.013, 1.019, 1.039, 1.073, 1.121, 1.176, 1.245, 1.329, 1.428, 1.544, 1.691,
+                    1.741, 1.585, 1.458, 1.353, 1.266, 1.192, 1.132, 1.081, 1.045, 1.024, 1.019, 1.014, 1.009, 1.007, 1.003, 1.001, 1.001, 1.002, 1.004, 1.006, 1.009, 1.012, 1.017, 1.036, 1.071, 1.117, 1.174, 1.243, 1.326, 1.424, 1.541, 1.689,
+                    1.741, 1.584, 1.457, 1.352, 1.266, 1.191, 1.131, 1.081, 1.045, 1.024, 1.019, 1.014, 1.011, 1.006, 1.003, 1.001, 1.001, 1.002, 1.004, 1.006, 1.009, 1.012, 1.017, 1.036, 1.071, 1.117, 1.173, 1.243, 1.326, 1.425, 1.541, 1.688,
+                    1.742, 1.585, 1.458, 1.353, 1.267, 1.192, 1.132, 1.081, 1.045, 1.025, 1.018, 1.014, 1.011, 1.007, 1.003, 1.002, 1.002, 1.002, 1.004, 1.007, 1.009, 1.013, 1.018, 1.036, 1.072, 1.118, 1.175, 1.243, 1.328, 1.427, 1.544, 1.689,
+                    1.744, 1.589, 1.462, 1.356, 1.269, 1.195, 1.134, 1.084, 1.047, 1.026, 1.019, 1.015, 1.011, 1.007, 1.004, 1.003, 1.002, 1.003, 1.005, 1.008, 1.011, 1.013, 1.019, 1.039, 1.074, 1.121, 1.178, 1.246, 1.333, 1.431, 1.549, 1.691,
+                    1.751, 1.599, 1.467, 1.362, 1.276, 1.201, 1.139, 1.089, 1.051, 1.027, 1.021, 1.015, 1.012, 1.009, 1.006, 1.004, 1.004, 1.005, 1.006, 1.009, 1.011, 1.015, 1.021, 1.042, 1.078, 1.126, 1.183, 1.253, 1.339, 1.438, 1.557, 1.697,
+                    1.763, 1.609, 1.477, 1.371, 1.284, 1.208, 1.146, 1.094, 1.057, 1.031, 1.022, 1.017, 1.013, 1.009, 1.008, 1.006, 1.006, 1.007, 1.008, 1.011, 1.013, 1.016, 1.024, 1.047, 1.084, 1.133, 1.189, 1.261, 1.349, 1.452, 1.571, 1.707,
+                    1.779, 1.627, 1.489, 1.381, 1.293, 1.218, 1.155, 1.104, 1.063, 1.035, 1.023, 1.019, 1.015, 1.012, 1.009, 1.008, 1.007, 1.008, 1.009, 1.012, 1.015, 1.017, 1.028, 1.053, 1.093, 1.142, 1.199, 1.272, 1.361, 1.463, 1.585, 1.718,
+                    1.797, 1.647, 1.507, 1.395, 1.306, 1.229, 1.165, 1.114, 1.073, 1.041, 1.025, 1.021, 1.016, 1.013, 1.011, 1.009, 1.009, 1.009, 1.012, 1.014, 1.016, 1.021, 1.035, 1.063, 1.102, 1.151, 1.211, 1.286, 1.374, 1.479, 1.604, 1.736,
+                    1.823, 1.671, 1.528, 1.412, 1.322, 1.243, 1.179, 1.126, 1.083, 1.051, 1.029, 1.022, 1.018, 1.015, 1.013, 1.011, 1.011, 1.012, 1.013, 1.016, 1.019, 1.023, 1.043, 1.073, 1.114, 1.163, 1.226, 1.302, 1.391, 1.497, 1.624, 1.759,
+                    1.853, 1.699, 1.553, 1.435, 1.339, 1.259, 1.194, 1.139, 1.095, 1.061, 1.037, 1.025, 1.021, 1.017, 1.015, 1.013, 1.013, 1.014, 1.016, 1.018, 1.021, 1.031, 1.054, 1.085, 1.127, 1.179, 1.243, 1.319, 1.412, 1.519, 1.649, 1.783,
+                    1.889, 1.732, 1.583, 1.459, 1.361, 1.279, 1.212, 1.156, 1.111, 1.075, 1.048, 1.031, 1.023, 1.019, 1.017, 1.016, 1.016, 1.016, 1.018, 1.021, 1.024, 1.041, 1.067, 1.099, 1.143, 1.196, 1.263, 1.341, 1.434, 1.545, 1.678, 1.808,
+                    1.929, 1.769, 1.612, 1.488, 1.386, 1.301, 1.231, 1.175, 1.128, 1.089, 1.061, 1.039, 1.028, 1.022, 1.019, 1.018, 1.018, 1.019, 1.021, 1.024, 1.033, 1.053, 1.081, 1.117, 1.161, 1.217, 1.286, 1.365, 1.459, 1.573, 1.711, 1.846,
+                    1.977, 1.811, 1.648, 1.519, 1.414, 1.325, 1.254, 1.195, 1.147, 1.107, 1.076, 1.053, 1.038, 1.028, 1.022, 1.021, 1.021, 1.021, 1.024, 1.033, 1.047, 1.068, 1.099, 1.137, 1.183, 1.239, 1.309, 1.391, 1.487, 1.607, 1.751, 1.884,
+                    2.029, 1.861, 1.689, 1.554, 1.445, 1.355, 1.281, 1.218, 1.169, 1.128, 1.095, 1.071, 1.053, 1.038, 1.029, 1.026, 1.026, 1.028, 1.035, 1.047, 1.065, 1.087, 1.119, 1.157, 1.206, 1.265, 1.336, 1.419, 1.521, 1.643, 1.793, 1.932,
+                    2.091, 1.919, 1.737, 1.594, 1.481, 1.387, 1.309, 1.246, 1.194, 1.152, 1.118, 1.091, 1.071, 1.055, 1.046, 1.041, 1.039, 1.042, 1.051, 1.064, 1.084, 1.109, 1.142, 1.182, 1.233, 1.292, 1.366, 1.453, 1.558, 1.687, 1.841, 1.983,
+                    2.161, 1.978, 1.783, 1.633, 1.515, 1.418, 1.339, 1.272, 1.219, 1.175, 1.139, 1.111, 1.089, 1.071, 1.058, 1.055, 1.055, 1.056, 1.064, 1.082, 1.103, 1.129, 1.165, 1.207, 1.259, 1.319, 1.395, 1.489, 1.595, 1.729, 1.887, 2.048
                 ],
-                "sigma": 0.005,
-                "sigma_Cb": 0.005
+                "sigma": 0.00073,
+                "sigma_Cb": 0.00094
             }
         },
         {
@@ -284,59 +1083,296 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
         },
         {
-            "rpi.sharpen": { }
-        },
-        {
             "rpi.ccm":
             {
                 "ccms": [
                     {
-                        "ct": 3900,
+                        "ct": 2820,
                         "ccm":
                         [
-                            1.54659, -0.17707, -0.36953,
-                            -0.51471, 1.72733, -0.21262,
-                            0.06667, -0.92279, 1.85612
+                            1.93931, -0.47781, -0.46149,
+                            -0.80685, 2.51162, -0.70477,
+                            -0.09454, -1.45358, 2.54812
+                        ]
+                    },
+                    {
+                        "ct": 2865,
+                        "ccm":
+                        [
+                            1.94246, -0.55124, -0.39122,
+                            -0.78361, 2.40473, -0.62111,
+                            -0.11531, -1.27787, 2.39318
+                        ]
+                    },
+                    {
+                        "ct": 2895,
+                        "ccm":
+                        [
+                            1.94327, -0.54456, -0.39871,
+                            -0.79328, 2.40105, -0.60778,
+                            -0.10876, -1.29604, 2.40479
+                        ]
+                    },
+                    {
+                        "ct": 2906,
+                        "ccm":
+                        [
+                            1.97118, -0.59105, -0.38013,
+                            -0.75994, 2.31847, -0.55853,
+                            -0.09992, -1.35216, 2.45208
+                        ]
+                    },
+                    {
+                        "ct": 2918,
+                        "ccm":
+                        [
+                            2.06216, -0.63222, -0.42995,
+                            -0.60242, 2.06677, -0.46435,
+                            -0.03346, -1.75896, 2.79242
+                        ]
+                    },
+                    {
+                        "ct": 3587,
+                        "ccm":
+                        [
+                            1.94068, -0.63318, -0.30749,
+                            -0.66311, 2.20775, -0.54464,
+                            -0.08091, -1.06356, 2.14446
+                        ]
+                    },
+                    {
+                        "ct": 3615,
+                        "ccm":
+                        [
+                            1.96948, -0.66674, -0.30274,
+                            -0.66175, 2.15942, -0.49767,
+                            -0.07734, -1.02936, 2.10669
+                        ]
+                    },
+                    {
+                        "ct": 3620,
+                        "ccm":
+                        [
+                            1.96032, -0.64845, -0.31187,
+                            -0.66439, 2.19693, -0.53254,
+                            -0.07931, -0.99342, 2.07273
+                        ]
+                    },
+                    {
+                        "ct": 3631,
+                        "ccm":
+                        [
+                            1.95335, -0.64176, -0.31159,
+                            -0.67046, 2.21381, -0.54335,
+                            -0.07752, -1.00559, 2.08311
+                        ]
+                    },
+                    {
+                        "ct": 4330,
+                        "ccm":
+                        [
+                            1.93342, -0.68988, -0.24354,
+                            -0.58033, 2.22555, -0.64522,
+                            -0.02843, -0.98497, 2.01341
+                        ]
+                    },
+                    {
+                        "ct": 4490,
+                        "ccm":
+                        [
+                            1.91993, -0.66289, -0.25703,
+                            -0.59626, 2.26099, -0.66474,
+                            -0.03311, -0.88565, 1.91876
+                        ]
+                    },
+                    {
+                        "ct": 4535,
+                        "ccm":
+                        [
+                            1.94301, -0.70807, -0.23493,
+                            -0.58322, 2.22932, -0.64611,
+                            -0.02783, -0.90947, 1.93731
+                        ]
+                    },
+                    {
+                        "ct": 4580,
+                        "ccm":
+                        [
+                            1.95379, -0.71008, -0.24371,
+                            -0.57399, 2.21945, -0.64546,
+                            -0.04161, -0.88852, 1.93014
+                        ]
+                    },
+                    {
+                        "ct": 5640,
+                        "ccm":
+                        [
+                            1.94452, -0.67353, -0.27099,
+                            -0.54171, 2.11661, -0.57489,
+                            -0.07599, -0.72696, 1.80296
+                        ]
+                    },
+                    {
+                        "ct": 5675,
+                        "ccm":
+                        [
+                            1.94622, -0.68276, -0.26347,
+                            -0.53484, 2.10948, -0.57464,
+                            -0.07245, -0.72609, 1.79855
+                        ]
+                    },
+                    {
+                        "ct": 5700,
+                        "ccm":
+                        [
+                            1.93628, -0.66435, -0.27193,
+                            -0.52401, 2.10331, -0.57931,
+                            -0.06978, -0.74412, 1.81389
+                        ]
+                    },
+                    {
+                        "ct": 5750,
+                        "ccm":
+                        [
+                            1.93116, -0.66993, -0.26123,
+                            -0.53618, 2.12508, -0.58891,
+                            -0.07301, -0.71671, 1.78971
+                        ]
+                    },
+                    {
+                        "ct": 6737,
+                        "ccm":
+                        [
+                            1.97225, -0.45644, -0.51582,
+                            -0.56034, 2.58211, -1.02177,
+                            -0.15077, -0.89189, 2.04267
                         ]
                     }
                 ]
             }
+        },
+        {
+            "rpi.cac": { }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
         }
     ]
 }
\ No newline at end of file
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx477.json 0.6.0-2/src/ipa/rpi/pisp/data/imx477.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx477.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx477.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.809
+                "reference_slope": 3.9
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -271,18 +271,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1020,37 +1020,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1119,8 +1137,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx477_16mm.json 0.6.0-2/src/ipa/rpi/pisp/data/imx477_16mm.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx477_16mm.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx477_16mm.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.809
+                "reference_slope": 3.9
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -271,18 +271,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1020,37 +1020,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1119,8 +1137,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx477_6mm.json 0.6.0-2/src/ipa/rpi/pisp/data/imx477_6mm.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx477_6mm.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx477_6mm.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.809
+                "reference_slope": 3.9
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -271,18 +271,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1020,37 +1020,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1119,8 +1137,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx477_noir.json 0.6.0-2/src/ipa/rpi/pisp/data/imx477_noir.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx477_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx477_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.809
+                "reference_slope": 3.9
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -188,18 +188,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -937,37 +937,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1081,8 +1099,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx477_scientific.json 0.6.0-2/src/ipa/rpi/pisp/data/imx477_scientific.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx477_scientific.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx477_scientific.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.809
+                "reference_slope": 3.9
             }
         },
         {
@@ -43,20 +43,20 @@
             {
                 "sdn":
                 {
-                    "deviation": 1.6,
-                    "strength": 0.5,
+                    "deviation": 0.6,
+                    "strength": 0.95,
                     "deviation2": 3.2,
                     "deviation_no_tdn": 3.2,
-                    "strength_no_tdn": 0.75
+                    "strength_no_tdn": 0.95
                 },
                 "cdn":
                 {
-                    "deviation": 200,
+                    "deviation": 100,
                     "strength": 0.3
                 },
                 "tdn":
                 {
-                    "deviation": 0.8,
+                    "deviation": 1.0,
                     "threshold": 0.05
                 }
             }
@@ -537,8 +537,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx519.json 0.6.0-2/src/ipa/rpi/pisp/data/imx519.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx519.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx519.json	2025-11-27 11:55:28.000000000 +0000
@@ -25,7 +25,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.776
+                "reference_slope": 3.8
             }
         },
         {
@@ -42,11 +42,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -55,7 +55,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -63,11 +63,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -76,19 +76,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -97,8 +97,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -531,37 +531,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx708.json 0.6.0-2/src/ipa/rpi/pisp/data/imx708.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx708.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx708.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 1.856
+                "reference_slope": 2.856
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 3.2,
-                        "strength": 0.75,
+                        "deviation": 0.2,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -270,18 +270,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1019,37 +1019,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1109,8 +1127,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
@@ -1139,11 +1157,27 @@
                         "step_coarse": 1.0,
                         "step_fine": 0.25,
                         "contrast_ratio": 0.75,
-                        "pdaf_gain": -0.02,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 10,
+                        "pdaf_gain": -0.016,
                         "pdaf_squelch": 0.125,
-                        "max_slew": 2.0,
+                        "max_slew": 1.5,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
+                        "step_frames": 5
+                    },
+                    "fast":
+                    {
+                        "step_coarse": 1.25,
+                        "step_fine": 0.0,
+                        "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 8,
+                        "pdaf_gain": -0.02,
+                        "pdaf_squelch": 0.125,
+                        "max_slew": 2.0,
+                        "pdaf_frames": 16,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -1151,6 +1185,7 @@
                 "conf_thresh": 16,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": false,
                 "map": [ 0.0, 445, 15.0, 925 ]
             }
         },
@@ -1267,4 +1302,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx708_noir.json 0.6.0-2/src/ipa/rpi/pisp/data/imx708_noir.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx708_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx708_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 1.856
+                "reference_slope": 2.856
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -188,18 +188,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -937,37 +937,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1126,8 +1144,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
@@ -1156,11 +1174,27 @@
                         "step_coarse": 1.0,
                         "step_fine": 0.25,
                         "contrast_ratio": 0.75,
-                        "pdaf_gain": -0.02,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 10,
+                        "pdaf_gain": -0.016,
                         "pdaf_squelch": 0.125,
-                        "max_slew": 2.0,
+                        "max_slew": 1.5,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
+                        "step_frames": 5
+                    },
+                    "fast":
+                    {
+                        "step_coarse": 1.25,
+                        "step_fine": 0.0,
+                        "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 8,
+                        "pdaf_gain": -0.02,
+                        "pdaf_squelch": 0.125,
+                        "max_slew": 2.0,
+                        "pdaf_frames": 16,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -1168,6 +1202,7 @@
                 "conf_thresh": 16,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": true,
                 "map": [ 0.0, 445, 15.0, 925 ]
             }
         },
@@ -1230,4 +1265,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx708_wide.json 0.6.0-2/src/ipa/rpi/pisp/data/imx708_wide.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx708_wide.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx708_wide.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.9
+                "reference_slope": 2.856
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -270,18 +270,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1019,37 +1019,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1118,8 +1136,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
@@ -1148,23 +1166,27 @@
                         "step_coarse": 2.0,
                         "step_fine": 0.5,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio" : 0.8,
+                        "retrigger_delay" : 10,
                         "pdaf_gain": -0.03,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 4.0,
+                        "max_slew": 3.0,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
-                        "step_frames": 4
+                        "step_frames": 5
                     },
                     "fast":
                     {
-                        "step_coarse": 2.0,
-                        "step_fine": 0.5,
+                        "step_coarse": 2.5,
+                        "step_fine": 0.0,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio" : 0.8,
+                        "retrigger_delay" : 8,
                         "pdaf_gain": -0.05,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 5.0,
+                        "max_slew": 4.0,
                         "pdaf_frames": 16,
-                        "dropout_frames": 6,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -1172,6 +1194,7 @@
                 "conf_thresh": 12,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": false,
                 "map": [ 0.0, 420, 35.0, 920 ]
             }
         },
@@ -1290,4 +1313,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/imx708_wide_noir.json 0.6.0-2/src/ipa/rpi/pisp/data/imx708_wide_noir.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/imx708_wide_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/imx708_wide_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.9
+                "reference_slope": 2.856
             }
         },
         {
@@ -45,20 +45,20 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,42 +66,42 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
-                        "deviation": 200,
+                        "deviation": 100,
                         "strength": 0.3
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -188,18 +188,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
                                 "shutter": [ 100, 5000, 10000, 20000, 60000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -937,37 +937,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1027,8 +1045,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
@@ -1057,23 +1075,27 @@
                         "step_coarse": 2.0,
                         "step_fine": 0.5,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio" : 0.8,
+                        "retrigger_delay" : 10,
                         "pdaf_gain": -0.03,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 4.0,
+                        "max_slew": 3.0,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
-                        "step_frames": 4
+                        "step_frames": 5
                     },
                     "fast":
                     {
-                        "step_coarse": 2.0,
-                        "step_fine": 0.5,
+                        "step_coarse": 2.5,
+                        "step_fine": 0.0,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio" : 0.8,
+                        "retrigger_delay" : 8,
                         "pdaf_gain": -0.05,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 5.0,
+                        "max_slew": 4.0,
                         "pdaf_frames": 16,
-                        "dropout_frames": 6,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -1081,6 +1103,7 @@
                 "conf_thresh": 12,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": true,
                 "map": [ 0.0, 420, 35.0, 920 ]
             }
         },
@@ -1145,4 +1168,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/meson.build 0.6.0-2/src/ipa/rpi/pisp/data/meson.build
--- 0.5.0-1/src/ipa/rpi/pisp/data/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -3,11 +3,14 @@
 conf_files = files([
     'imx219.json',
     'imx219_noir.json',
+    'imx283.json',
     'imx290.json',
     'imx296.json',
     'imx296_mono.json',
+    'imx335.json',
     'imx378.json',
     'imx415.json',
+    'imx415_b0569.json',
     'imx462.json',
     'imx477.json',
     'imx477_noir.json',
@@ -23,6 +26,10 @@ conf_files = files([
     'ov9281_mono.json',
     'se327m12.json',
     'uncalibrated.json',
+    'vd55g1.json',
+    'vd55g1_mono.json',
+    'vd56g3.json',
+    'vd56g3_mono.json',
 ])
 
 install_data(conf_files,
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/ov5647.json 0.6.0-2/src/ipa/rpi/pisp/data/ov5647.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/ov5647.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/ov5647.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 4.371
+                "reference_slope": 5.871
             }
         },
         {
@@ -45,11 +45,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -58,7 +58,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,11 +66,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -79,19 +79,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -100,8 +100,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -271,7 +271,7 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
                                 "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
                             },
                             "short":
@@ -282,7 +282,7 @@
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 8.0 ]
                             }
                         },
                         "constraint_modes":
@@ -1020,37 +1020,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1119,8 +1137,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/ov5647_noir.json 0.6.0-2/src/ipa/rpi/pisp/data/ov5647_noir.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/ov5647_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/ov5647_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 4.371
+                "reference_slope": 5.871
             }
         },
         {
@@ -45,11 +45,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -58,7 +58,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,11 +66,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -79,19 +79,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -100,8 +100,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -188,7 +188,7 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "shutter": [ 100, 10000, 30000, 50000, 66666 ],
                                 "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
                             },
                             "short":
@@ -199,7 +199,7 @@
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 8.0 ]
                             }
                         },
                         "constraint_modes":
@@ -937,37 +937,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1054,8 +1072,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/ov64a40.json 0.6.0-2/src/ipa/rpi/pisp/data/ov64a40.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/ov64a40.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/ov64a40.json	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.984
+                "reference_slope": 4.1
             }
         },
         {
@@ -45,11 +45,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -58,7 +58,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -66,11 +66,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -79,19 +79,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -100,8 +100,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -924,37 +924,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
@@ -1026,8 +1044,8 @@
         {
             "rpi.sharpen":
             {
-                "threshold": 0.25,
-                "limit": 1.0,
+                "threshold": 0.75,
+                "limit": 0.5,
                 "strength": 1.0
             }
         },
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/ov9281_mono.json 0.6.0-2/src/ipa/rpi/pisp/data/ov9281_mono.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/ov9281_mono.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/ov9281_mono.json	2025-11-27 11:55:28.000000000 +0000
@@ -22,7 +22,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.5
+                "reference_slope": 3.5
             }
         },
         {
@@ -32,11 +32,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -45,7 +45,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -53,11 +53,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -66,19 +66,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -87,8 +87,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -176,37 +176,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/se327m12.json 0.6.0-2/src/ipa/rpi/pisp/data/se327m12.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/se327m12.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/se327m12.json	2025-11-27 11:55:28.000000000 +0000
@@ -25,7 +25,7 @@
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 1.986
+                "reference_slope": 2.7
             }
         },
         {
@@ -42,11 +42,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -55,7 +55,7 @@
                     },
                     "tdn":
                     {
-                        "deviation": 0.8,
+                        "deviation": 1.0,
                         "threshold": 0.05
                     }
                 },
@@ -63,11 +63,11 @@
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -76,19 +76,19 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 },
                 "night":
                 {
                     "sdn":
                     {
-                        "deviation": 1.6,
-                        "strength": 0.5,
+                        "deviation": 0.6,
+                        "strength": 0.95,
                         "deviation2": 3.2,
                         "deviation_no_tdn": 3.2,
-                        "strength_no_tdn": 0.75
+                        "strength_no_tdn": 0.95
                     },
                     "cdn":
                     {
@@ -97,8 +97,8 @@
                     },
                     "tdn":
                     {
-                        "deviation": 1.3,
-                        "threshold": 0.1
+                        "deviation": 1.0,
+                        "threshold": 0.05
                     }
                 }
             }
@@ -531,37 +531,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/uncalibrated.json 0.6.0-2/src/ipa/rpi/pisp/data/uncalibrated.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/uncalibrated.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/uncalibrated.json	2025-11-27 11:55:28.000000000 +0000
@@ -96,37 +96,55 @@
                 "gamma_curve":
                 [
                     0, 0,
-                    1024, 5040,
-                    2048, 9338,
-                    3072, 12356,
-                    4096, 15312,
-                    5120, 18051,
-                    6144, 20790,
-                    7168, 23193,
-                    8192, 25744,
-                    9216, 27942,
-                    10240, 30035,
-                    11264, 32005,
-                    12288, 33975,
-                    13312, 35815,
-                    14336, 37600,
-                    15360, 39168,
-                    16384, 40642,
-                    18432, 43379,
-                    20480, 45749,
-                    22528, 47753,
-                    24576, 49621,
-                    26624, 51253,
-                    28672, 52698,
-                    30720, 53796,
-                    32768, 54876,
-                    36864, 57012,
-                    40960, 58656,
-                    45056, 59954,
-                    49152, 61183,
-                    53248, 62355,
-                    57344, 63419,
-                    61440, 64476,
+                    512, 2518,
+                    1024, 5033,
+                    1536, 7175,
+                    2048, 9309,
+                    2560, 10814,
+                    3072, 12312,
+                    3584, 13773,
+                    4096, 15225,
+                    4608, 16566,
+                    5120, 17899,
+                    5632, 19221,
+                    6144, 20534,
+                    6656, 21684,
+                    7168, 22826,
+                    7680, 24024,
+                    8192, 25212,
+                    9216, 27251,
+                    10240, 29167,
+                    11264, 30947,
+                    12288, 32696,
+                    13312, 34309,
+                    14336, 35849,
+                    15360, 37194,
+                    16384, 38445,
+                    17408, 39598,
+                    18432, 40732,
+                    19456, 41717,
+                    20480, 42687,
+                    22528, 44343,
+                    24576, 45871,
+                    26624, 47222,
+                    28672, 48441,
+                    30720, 49460,
+                    32768, 50470,
+                    34816, 51476,
+                    36864, 52480,
+                    38912, 53382,
+                    40960, 54294,
+                    43008, 55155,
+                    45056, 56035,
+                    47104, 56920,
+                    49152, 57824,
+                    51200, 58737,
+                    53248, 59666,
+                    55296, 60604,
+                    57344, 61558,
+                    59392, 62529,
+                    61440, 63516,
+                    63488, 64519,
                     65535, 65535
                 ]
             }
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/vd55g1.json 0.6.0-2/src/ipa/rpi/pisp/data/vd55g1.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/vd55g1.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/vd55g1.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,1209 @@
+{
+    "version": 2.0,
+    "target": "pisp",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 32138,
+                "reference_gain": 1.23,
+                "reference_aperture": 1.0,
+                "reference_lux": 1060,
+                "reference_Y": 21540
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 20,
+                "reference_slope": 6.825
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 81,
+                "slope": 0.05471
+            }
+        },
+        {
+            "rpi.denoise":
+            {
+                "normal":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 0.8,
+                        "threshold": 0.05
+                    }
+                },
+                "hdr":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                },
+                "night":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                }
+            }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 7700
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8000
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    3000.0, 1.1369, 0.3947,
+                    4100.0, 0.9224, 0.5046,
+                    6500.0, 0.6719, 0.7064
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.01,
+                "transverse_neg": 0.01
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.001, 1.009, 1.016, 1.022, 1.025, 1.029, 1.034, 1.035, 1.037, 1.038, 1.038, 1.039, 1.041, 1.043, 1.043, 1.043, 1.042, 1.043, 1.045, 1.046, 1.046, 1.045, 1.048, 1.049, 1.051, 1.052, 1.051, 1.051, 1.051, 1.052, 1.053, 1.053,
+                            1.008, 1.012, 1.021, 1.024, 1.029, 1.035, 1.041, 1.042, 1.046, 1.042, 1.043, 1.044, 1.047, 1.048, 1.049, 1.047, 1.049, 1.049, 1.049, 1.052, 1.053, 1.052, 1.054, 1.054, 1.055, 1.055, 1.057, 1.056, 1.057, 1.054, 1.054, 1.053,
+                            1.011, 1.016, 1.024, 1.031, 1.036, 1.043, 1.047, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.052, 1.053, 1.053, 1.056, 1.056, 1.056, 1.055, 1.056, 1.057, 1.059, 1.059, 1.061, 1.061, 1.061, 1.059, 1.056, 1.054,
+                            1.011, 1.017, 1.031, 1.036, 1.043, 1.047, 1.049, 1.051, 1.052, 1.055, 1.055, 1.055, 1.056, 1.056, 1.056, 1.056, 1.056, 1.057, 1.058, 1.059, 1.061, 1.058, 1.059, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.061, 1.059, 1.056,
+                            1.015, 1.026, 1.035, 1.039, 1.046, 1.048, 1.052, 1.054, 1.058, 1.058, 1.058, 1.058, 1.059, 1.059, 1.059, 1.059, 1.059, 1.061, 1.062, 1.061, 1.061, 1.061, 1.061, 1.061, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.059, 1.056,
+                            1.019, 1.027, 1.035, 1.042, 1.047, 1.051, 1.054, 1.058, 1.059, 1.059, 1.061, 1.061, 1.061, 1.062, 1.061, 1.062, 1.063, 1.063, 1.064, 1.064, 1.066, 1.062, 1.062, 1.062, 1.063, 1.064, 1.063, 1.063, 1.063, 1.063, 1.061, 1.056,
+                            1.019, 1.031, 1.038, 1.043, 1.048, 1.053, 1.055, 1.058, 1.061, 1.062, 1.064, 1.065, 1.065, 1.063, 1.063, 1.064, 1.064, 1.064, 1.065, 1.066, 1.067, 1.065, 1.065, 1.063, 1.064, 1.066, 1.065, 1.066, 1.064, 1.064, 1.058, 1.057,
+                            1.023, 1.034, 1.039, 1.045, 1.053, 1.055, 1.058, 1.059, 1.062, 1.063, 1.065, 1.066, 1.066, 1.065, 1.064, 1.065, 1.065, 1.065, 1.066, 1.066, 1.069, 1.068, 1.067, 1.065, 1.066, 1.066, 1.067, 1.067, 1.066, 1.065, 1.061, 1.057,
+                            1.024, 1.036, 1.042, 1.046, 1.053, 1.055, 1.059, 1.061, 1.064, 1.064, 1.066, 1.068, 1.069, 1.067, 1.066, 1.066, 1.067, 1.066, 1.067, 1.068, 1.069, 1.069, 1.068, 1.067, 1.067, 1.066, 1.067, 1.067, 1.066, 1.064, 1.059, 1.057,
+                            1.024, 1.036, 1.044, 1.049, 1.054, 1.058, 1.061, 1.063, 1.065, 1.066, 1.068, 1.068, 1.069, 1.068, 1.068, 1.067, 1.068, 1.068, 1.069, 1.068, 1.069, 1.071, 1.069, 1.069, 1.067, 1.067, 1.067, 1.067, 1.065, 1.064, 1.059, 1.057,
+                            1.026, 1.039, 1.044, 1.049, 1.054, 1.059, 1.062, 1.065, 1.066, 1.068, 1.068, 1.068, 1.069, 1.068, 1.067, 1.068, 1.068, 1.069, 1.069, 1.068, 1.069, 1.069, 1.069, 1.069, 1.068, 1.067, 1.067, 1.067, 1.066, 1.063, 1.061, 1.058,
+                            1.027, 1.041, 1.047, 1.051, 1.055, 1.059, 1.062, 1.066, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.069, 1.069, 1.069, 1.069, 1.069, 1.069, 1.069, 1.068, 1.067, 1.067, 1.065, 1.064, 1.063, 1.056,
+                            1.028, 1.039, 1.047, 1.052, 1.056, 1.059, 1.062, 1.066, 1.068, 1.068, 1.068, 1.068, 1.069, 1.069, 1.069, 1.071, 1.069, 1.069, 1.069, 1.068, 1.068, 1.068, 1.069, 1.069, 1.069, 1.068, 1.067, 1.067, 1.066, 1.065, 1.064, 1.056,
+                            1.033, 1.042, 1.049, 1.055, 1.057, 1.061, 1.063, 1.066, 1.067, 1.068, 1.068, 1.068, 1.069, 1.071, 1.071, 1.071, 1.069, 1.069, 1.071, 1.071, 1.071, 1.069, 1.069, 1.069, 1.069, 1.069, 1.068, 1.066, 1.066, 1.066, 1.065, 1.055,
+                            1.033, 1.046, 1.049, 1.055, 1.058, 1.061, 1.063, 1.065, 1.067, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.069, 1.071, 1.069, 1.069, 1.068, 1.068, 1.067, 1.065, 1.058,
+                            1.034, 1.047, 1.052, 1.055, 1.057, 1.061, 1.063, 1.066, 1.068, 1.069, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.071, 1.072, 1.073, 1.073, 1.072, 1.071, 1.071, 1.071, 1.071, 1.069, 1.068, 1.068, 1.065, 1.058,
+                            1.037, 1.048, 1.053, 1.055, 1.058, 1.061, 1.064, 1.067, 1.069, 1.069, 1.068, 1.069, 1.069, 1.071, 1.071, 1.073, 1.072, 1.072, 1.071, 1.073, 1.073, 1.073, 1.073, 1.073, 1.072, 1.071, 1.071, 1.071, 1.069, 1.067, 1.066, 1.058,
+                            1.038, 1.049, 1.053, 1.056, 1.058, 1.061, 1.066, 1.068, 1.069, 1.069, 1.068, 1.068, 1.069, 1.071, 1.072, 1.072, 1.072, 1.071, 1.073, 1.073, 1.074, 1.073, 1.074, 1.073, 1.073, 1.072, 1.072, 1.071, 1.069, 1.067, 1.066, 1.056,
+                            1.038, 1.049, 1.052, 1.057, 1.059, 1.062, 1.066, 1.068, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.072, 1.072, 1.072, 1.073, 1.074, 1.074, 1.075, 1.074, 1.075, 1.075, 1.074, 1.072, 1.072, 1.072, 1.072, 1.068, 1.066, 1.058,
+                            1.039, 1.049, 1.053, 1.058, 1.061, 1.064, 1.066, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.073, 1.075, 1.075, 1.075, 1.074, 1.075, 1.074, 1.074, 1.073, 1.074, 1.074, 1.073, 1.071, 1.066, 1.058,
+                            1.041, 1.049, 1.055, 1.059, 1.061, 1.064, 1.066, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.072, 1.073, 1.074, 1.074, 1.074, 1.074, 1.075, 1.075, 1.075, 1.075, 1.075, 1.075, 1.073, 1.071, 1.067, 1.058,
+                            1.043, 1.052, 1.057, 1.059, 1.062, 1.065, 1.067, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.073, 1.074, 1.074, 1.073, 1.074, 1.075, 1.075, 1.075, 1.076, 1.076, 1.075, 1.074, 1.071, 1.067, 1.057,
+                            1.048, 1.054, 1.058, 1.061, 1.063, 1.065, 1.066, 1.069, 1.069, 1.071, 1.071, 1.072, 1.073, 1.072, 1.072, 1.072, 1.072, 1.073, 1.073, 1.073, 1.073, 1.074, 1.076, 1.076, 1.076, 1.077, 1.077, 1.076, 1.073, 1.072, 1.067, 1.059,
+                            1.048, 1.055, 1.059, 1.063, 1.063, 1.066, 1.067, 1.069, 1.071, 1.071, 1.072, 1.073, 1.073, 1.071, 1.071, 1.071, 1.072, 1.073, 1.073, 1.073, 1.073, 1.074, 1.075, 1.075, 1.076, 1.077, 1.079, 1.076, 1.075, 1.074, 1.068, 1.063,
+                            1.048, 1.058, 1.063, 1.064, 1.065, 1.066, 1.067, 1.069, 1.069, 1.071, 1.071, 1.073, 1.073, 1.072, 1.072, 1.072, 1.072, 1.072, 1.073, 1.073, 1.075, 1.075, 1.076, 1.076, 1.078, 1.078, 1.079, 1.078, 1.075, 1.072, 1.068, 1.063,
+                            1.049, 1.059, 1.064, 1.066, 1.066, 1.068, 1.069, 1.071, 1.069, 1.071, 1.072, 1.072, 1.072, 1.072, 1.071, 1.072, 1.072, 1.072, 1.072, 1.074, 1.076, 1.075, 1.077, 1.077, 1.079, 1.079, 1.081, 1.078, 1.076, 1.073, 1.068, 1.063,
+                            1.053, 1.059, 1.065, 1.068, 1.068, 1.069, 1.071, 1.071, 1.069, 1.073, 1.072, 1.073, 1.072, 1.072, 1.071, 1.072, 1.074, 1.072, 1.072, 1.074, 1.075, 1.074, 1.076, 1.076, 1.079, 1.079, 1.079, 1.079, 1.077, 1.073, 1.068, 1.061,
+                            1.054, 1.062, 1.066, 1.069, 1.069, 1.071, 1.071, 1.072, 1.069, 1.072, 1.072, 1.073, 1.072, 1.072, 1.069, 1.069, 1.071, 1.071, 1.072, 1.074, 1.073, 1.073, 1.074, 1.076, 1.079, 1.079, 1.081, 1.079, 1.078, 1.074, 1.071, 1.063,
+                            1.055, 1.062, 1.066, 1.069, 1.069, 1.069, 1.069, 1.071, 1.071, 1.072, 1.072, 1.073, 1.073, 1.071, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.078, 1.081, 1.082, 1.079, 1.076, 1.074, 1.069, 1.063,
+                            1.055, 1.064, 1.066, 1.068, 1.068, 1.069, 1.069, 1.069, 1.069, 1.071, 1.071, 1.072, 1.072, 1.071, 1.068, 1.067, 1.068, 1.067, 1.067, 1.067, 1.067, 1.068, 1.068, 1.071, 1.075, 1.078, 1.082, 1.077, 1.076, 1.071, 1.065, 1.061,
+                            1.055, 1.059, 1.064, 1.067, 1.068, 1.067, 1.068, 1.067, 1.066, 1.066, 1.067, 1.069, 1.068, 1.067, 1.064, 1.064, 1.061, 1.063, 1.062, 1.062, 1.062, 1.061, 1.063, 1.063, 1.066, 1.071, 1.075, 1.073, 1.069, 1.065, 1.061, 1.055,
+                            1.052, 1.057, 1.063, 1.063, 1.063, 1.059, 1.061, 1.061, 1.061, 1.061, 1.061, 1.063, 1.063, 1.059, 1.057, 1.057, 1.054, 1.055, 1.055, 1.055, 1.055, 1.057, 1.057, 1.057, 1.061, 1.066, 1.066, 1.066, 1.059, 1.057, 1.054, 1.054
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.001, 1.008, 1.019, 1.024, 1.035, 1.044, 1.046, 1.053, 1.059, 1.061, 1.063, 1.063, 1.063, 1.069, 1.069, 1.071, 1.069, 1.072, 1.075, 1.076, 1.079, 1.081, 1.081, 1.083, 1.085, 1.086, 1.086, 1.086, 1.085, 1.085, 1.085, 1.084,
+                            1.005, 1.015, 1.024, 1.035, 1.042, 1.048, 1.053, 1.061, 1.064, 1.066, 1.067, 1.069, 1.071, 1.073, 1.074, 1.076, 1.079, 1.077, 1.079, 1.081, 1.082, 1.084, 1.084, 1.089, 1.091, 1.091, 1.093, 1.092, 1.093, 1.091, 1.089, 1.089,
+                            1.012, 1.022, 1.035, 1.042, 1.049, 1.055, 1.062, 1.071, 1.071, 1.074, 1.074, 1.076, 1.078, 1.079, 1.082, 1.083, 1.083, 1.084, 1.085, 1.088, 1.089, 1.091, 1.092, 1.092, 1.095, 1.095, 1.095, 1.097, 1.095, 1.095, 1.091, 1.089,
+                            1.015, 1.028, 1.041, 1.048, 1.054, 1.061, 1.069, 1.071, 1.074, 1.077, 1.079, 1.081, 1.082, 1.084, 1.086, 1.086, 1.087, 1.088, 1.089, 1.091, 1.093, 1.093, 1.094, 1.094, 1.096, 1.097, 1.096, 1.097, 1.095, 1.095, 1.092, 1.089,
+                            1.018, 1.032, 1.042, 1.053, 1.058, 1.068, 1.073, 1.076, 1.079, 1.081, 1.084, 1.084, 1.087, 1.089, 1.089, 1.091, 1.091, 1.091, 1.092, 1.093, 1.096, 1.095, 1.094, 1.094, 1.097, 1.099, 1.099, 1.099, 1.097, 1.096, 1.093, 1.089,
+                            1.027, 1.036, 1.047, 1.055, 1.067, 1.071, 1.075, 1.079, 1.082, 1.085, 1.087, 1.088, 1.089, 1.091, 1.091, 1.094, 1.095, 1.095, 1.096, 1.097, 1.097, 1.096, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.099, 1.098, 1.094, 1.089,
+                            1.028, 1.041, 1.051, 1.058, 1.071, 1.074, 1.077, 1.081, 1.087, 1.088, 1.089, 1.092, 1.092, 1.093, 1.093, 1.095, 1.094, 1.097, 1.099, 1.099, 1.099, 1.098, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.101, 1.095, 1.089,
+                            1.033, 1.046, 1.056, 1.065, 1.071, 1.075, 1.081, 1.084, 1.087, 1.091, 1.092, 1.095, 1.096, 1.096, 1.095, 1.096, 1.097, 1.098, 1.099, 1.101, 1.101, 1.101, 1.101, 1.099, 1.099, 1.101, 1.101, 1.099, 1.099, 1.098, 1.094, 1.089,
+                            1.037, 1.049, 1.059, 1.066, 1.073, 1.077, 1.084, 1.089, 1.089, 1.092, 1.095, 1.096, 1.096, 1.096, 1.096, 1.096, 1.097, 1.098, 1.099, 1.099, 1.101, 1.102, 1.101, 1.101, 1.101, 1.102, 1.101, 1.101, 1.099, 1.098, 1.094, 1.088,
+                            1.037, 1.049, 1.062, 1.066, 1.075, 1.082, 1.086, 1.089, 1.092, 1.095, 1.096, 1.097, 1.097, 1.096, 1.096, 1.097, 1.098, 1.099, 1.101, 1.101, 1.102, 1.102, 1.102, 1.103, 1.103, 1.103, 1.102, 1.101, 1.099, 1.098, 1.093, 1.087,
+                            1.048, 1.056, 1.063, 1.069, 1.077, 1.083, 1.089, 1.091, 1.093, 1.096, 1.097, 1.097, 1.097, 1.098, 1.098, 1.099, 1.101, 1.101, 1.102, 1.103, 1.102, 1.103, 1.102, 1.104, 1.104, 1.101, 1.101, 1.099, 1.099, 1.096, 1.092, 1.087,
+                            1.048, 1.058, 1.068, 1.073, 1.081, 1.085, 1.089, 1.091, 1.094, 1.097, 1.097, 1.099, 1.097, 1.099, 1.099, 1.099, 1.101, 1.101, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.102, 1.101, 1.101, 1.099, 1.097, 1.095, 1.092, 1.085,
+                            1.048, 1.059, 1.068, 1.075, 1.083, 1.085, 1.091, 1.093, 1.095, 1.098, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.102, 1.101, 1.103, 1.103, 1.103, 1.103, 1.102, 1.102, 1.102, 1.101, 1.101, 1.099, 1.098, 1.094, 1.091, 1.085,
+                            1.048, 1.061, 1.071, 1.078, 1.084, 1.085, 1.088, 1.094, 1.097, 1.099, 1.099, 1.099, 1.101, 1.101, 1.101, 1.101, 1.102, 1.101, 1.103, 1.103, 1.103, 1.103, 1.101, 1.102, 1.102, 1.102, 1.101, 1.098, 1.096, 1.094, 1.091, 1.082,
+                            1.059, 1.067, 1.075, 1.078, 1.084, 1.087, 1.092, 1.094, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.101, 1.103, 1.103, 1.102, 1.103, 1.103, 1.102, 1.101, 1.101, 1.102, 1.103, 1.103, 1.101, 1.099, 1.097, 1.095, 1.091, 1.082,
+                            1.061, 1.071, 1.076, 1.082, 1.086, 1.089, 1.092, 1.096, 1.098, 1.099, 1.101, 1.101, 1.102, 1.102, 1.103, 1.102, 1.102, 1.102, 1.103, 1.103, 1.103, 1.103, 1.102, 1.102, 1.103, 1.103, 1.102, 1.099, 1.097, 1.094, 1.091, 1.079,
+                            1.061, 1.071, 1.078, 1.082, 1.087, 1.091, 1.093, 1.097, 1.099, 1.099, 1.099, 1.101, 1.103, 1.103, 1.103, 1.103, 1.102, 1.102, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.099, 1.099, 1.093, 1.091, 1.079,
+                            1.064, 1.074, 1.079, 1.085, 1.088, 1.093, 1.095, 1.098, 1.099, 1.099, 1.101, 1.099, 1.101, 1.103, 1.103, 1.103, 1.103, 1.102, 1.103, 1.103, 1.104, 1.104, 1.105, 1.104, 1.104, 1.103, 1.102, 1.101, 1.099, 1.093, 1.091, 1.078,
+                            1.066, 1.074, 1.076, 1.086, 1.091, 1.094, 1.097, 1.099, 1.099, 1.099, 1.101, 1.102, 1.103, 1.103, 1.104, 1.102, 1.103, 1.103, 1.104, 1.104, 1.105, 1.105, 1.105, 1.105, 1.105, 1.103, 1.102, 1.101, 1.098, 1.094, 1.088, 1.077,
+                            1.066, 1.074, 1.081, 1.087, 1.091, 1.095, 1.097, 1.099, 1.101, 1.102, 1.104, 1.104, 1.104, 1.103, 1.102, 1.102, 1.103, 1.105, 1.105, 1.105, 1.105, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.101, 1.099, 1.096, 1.088, 1.074,
+                            1.067, 1.076, 1.082, 1.088, 1.092, 1.095, 1.101, 1.101, 1.102, 1.103, 1.103, 1.104, 1.104, 1.104, 1.103, 1.103, 1.103, 1.105, 1.105, 1.106, 1.106, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.101, 1.099, 1.094, 1.087, 1.073,
+                            1.071, 1.079, 1.083, 1.089, 1.092, 1.096, 1.099, 1.102, 1.103, 1.103, 1.102, 1.104, 1.104, 1.104, 1.103, 1.103, 1.105, 1.105, 1.106, 1.106, 1.107, 1.105, 1.105, 1.104, 1.103, 1.103, 1.102, 1.101, 1.098, 1.094, 1.087, 1.072,
+                            1.076, 1.082, 1.086, 1.091, 1.093, 1.098, 1.101, 1.101, 1.102, 1.102, 1.102, 1.104, 1.104, 1.104, 1.104, 1.105, 1.105, 1.105, 1.106, 1.106, 1.107, 1.105, 1.105, 1.105, 1.103, 1.102, 1.102, 1.099, 1.097, 1.094, 1.085, 1.073,
+                            1.076, 1.083, 1.089, 1.092, 1.095, 1.097, 1.099, 1.101, 1.101, 1.102, 1.103, 1.104, 1.105, 1.104, 1.103, 1.104, 1.104, 1.105, 1.105, 1.105, 1.105, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.099, 1.097, 1.094, 1.084, 1.074,
+                            1.079, 1.084, 1.091, 1.094, 1.096, 1.098, 1.101, 1.101, 1.102, 1.102, 1.103, 1.105, 1.107, 1.105, 1.105, 1.105, 1.104, 1.104, 1.104, 1.104, 1.104, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.099, 1.096, 1.092, 1.084, 1.074,
+                            1.078, 1.088, 1.092, 1.096, 1.097, 1.101, 1.101, 1.101, 1.103, 1.103, 1.103, 1.106, 1.106, 1.105, 1.103, 1.103, 1.103, 1.104, 1.104, 1.104, 1.104, 1.104, 1.105, 1.105, 1.104, 1.103, 1.102, 1.098, 1.095, 1.092, 1.082, 1.071,
+                            1.082, 1.091, 1.092, 1.097, 1.099, 1.101, 1.102, 1.102, 1.103, 1.103, 1.104, 1.104, 1.104, 1.104, 1.102, 1.101, 1.101, 1.102, 1.103, 1.103, 1.103, 1.103, 1.104, 1.104, 1.102, 1.102, 1.101, 1.098, 1.095, 1.089, 1.082, 1.068,
+                            1.084, 1.091, 1.094, 1.098, 1.101, 1.102, 1.103, 1.103, 1.103, 1.103, 1.101, 1.103, 1.101, 1.102, 1.101, 1.101, 1.101, 1.099, 1.102, 1.101, 1.101, 1.101, 1.102, 1.103, 1.102, 1.099, 1.098, 1.096, 1.092, 1.086, 1.079, 1.067,
+                            1.084, 1.091, 1.095, 1.099, 1.101, 1.102, 1.103, 1.103, 1.103, 1.102, 1.101, 1.102, 1.101, 1.099, 1.099, 1.099, 1.098, 1.097, 1.097, 1.095, 1.095, 1.094, 1.094, 1.096, 1.096, 1.096, 1.095, 1.092, 1.087, 1.083, 1.076, 1.067,
+                            1.084, 1.092, 1.096, 1.099, 1.099, 1.101, 1.101, 1.102, 1.101, 1.099, 1.098, 1.098, 1.098, 1.097, 1.097, 1.097, 1.097, 1.095, 1.091, 1.091, 1.091, 1.089, 1.089, 1.091, 1.092, 1.091, 1.091, 1.087, 1.083, 1.076, 1.069, 1.061,
+                            1.084, 1.091, 1.094, 1.095, 1.098, 1.099, 1.099, 1.099, 1.099, 1.096, 1.095, 1.095, 1.094, 1.093, 1.093, 1.091, 1.087, 1.088, 1.086, 1.086, 1.084, 1.079, 1.079, 1.082, 1.085, 1.085, 1.081, 1.078, 1.076, 1.069, 1.059, 1.054,
+                            1.087, 1.087, 1.094, 1.095, 1.094, 1.094, 1.096, 1.095, 1.095, 1.092, 1.089, 1.089, 1.088, 1.087, 1.085, 1.081, 1.082, 1.082, 1.081, 1.077, 1.074, 1.073, 1.071, 1.074, 1.077, 1.077, 1.074, 1.074, 1.069, 1.062, 1.054, 1.048
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.001, 1.002, 1.016, 1.027, 1.033, 1.045, 1.052, 1.054, 1.061, 1.065, 1.068, 1.067, 1.069, 1.073, 1.073, 1.077, 1.078, 1.081, 1.087, 1.092, 1.092, 1.095, 1.097, 1.099, 1.101, 1.105, 1.111, 1.112, 1.114, 1.115, 1.121, 1.124,
+                            1.001, 1.014, 1.027, 1.033, 1.043, 1.053, 1.057, 1.061, 1.068, 1.071, 1.071, 1.075, 1.075, 1.076, 1.079, 1.082, 1.084, 1.086, 1.089, 1.092, 1.092, 1.094, 1.097, 1.101, 1.104, 1.108, 1.112, 1.112, 1.115, 1.117, 1.119, 1.122,
+                            1.004, 1.021, 1.031, 1.041, 1.053, 1.058, 1.062, 1.071, 1.073, 1.077, 1.079, 1.082, 1.081, 1.084, 1.084, 1.085, 1.086, 1.089, 1.091, 1.092, 1.093, 1.096, 1.099, 1.102, 1.106, 1.109, 1.112, 1.114, 1.116, 1.118, 1.121, 1.121,
+                            1.013, 1.021, 1.036, 1.045, 1.058, 1.064, 1.071, 1.074, 1.078, 1.082, 1.082, 1.084, 1.084, 1.085, 1.087, 1.087, 1.089, 1.091, 1.093, 1.095, 1.095, 1.097, 1.099, 1.104, 1.105, 1.108, 1.111, 1.115, 1.116, 1.117, 1.119, 1.121,
+                            1.015, 1.028, 1.041, 1.052, 1.061, 1.068, 1.074, 1.078, 1.081, 1.084, 1.083, 1.085, 1.085, 1.086, 1.088, 1.089, 1.091, 1.091, 1.094, 1.096, 1.096, 1.098, 1.099, 1.099, 1.104, 1.107, 1.109, 1.112, 1.116, 1.117, 1.117, 1.119,
+                            1.024, 1.029, 1.047, 1.053, 1.064, 1.071, 1.076, 1.081, 1.083, 1.086, 1.086, 1.087, 1.086, 1.089, 1.089, 1.091, 1.092, 1.092, 1.095, 1.096, 1.097, 1.098, 1.099, 1.099, 1.101, 1.105, 1.108, 1.111, 1.115, 1.116, 1.116, 1.114,
+                            1.024, 1.034, 1.051, 1.057, 1.066, 1.075, 1.078, 1.081, 1.085, 1.087, 1.087, 1.088, 1.089, 1.091, 1.091, 1.091, 1.089, 1.091, 1.091, 1.094, 1.096, 1.097, 1.098, 1.099, 1.103, 1.104, 1.107, 1.108, 1.112, 1.113, 1.114, 1.113,
+                            1.029, 1.042, 1.053, 1.059, 1.071, 1.076, 1.078, 1.082, 1.087, 1.087, 1.088, 1.089, 1.089, 1.089, 1.088, 1.088, 1.089, 1.089, 1.093, 1.094, 1.096, 1.097, 1.098, 1.098, 1.103, 1.103, 1.106, 1.108, 1.109, 1.111, 1.111, 1.108,
+                            1.033, 1.046, 1.057, 1.066, 1.074, 1.077, 1.079, 1.083, 1.087, 1.088, 1.089, 1.089, 1.089, 1.088, 1.086, 1.086, 1.088, 1.089, 1.091, 1.094, 1.095, 1.095, 1.098, 1.099, 1.103, 1.103, 1.103, 1.104, 1.108, 1.107, 1.107, 1.106,
+                            1.037, 1.051, 1.061, 1.071, 1.076, 1.081, 1.084, 1.085, 1.087, 1.086, 1.089, 1.088, 1.089, 1.087, 1.086, 1.087, 1.089, 1.091, 1.092, 1.093, 1.095, 1.096, 1.097, 1.098, 1.099, 1.101, 1.103, 1.105, 1.106, 1.107, 1.106, 1.105,
+                            1.043, 1.054, 1.065, 1.071, 1.076, 1.083, 1.085, 1.086, 1.087, 1.088, 1.088, 1.088, 1.088, 1.087, 1.087, 1.085, 1.086, 1.089, 1.092, 1.093, 1.093, 1.094, 1.097, 1.097, 1.098, 1.099, 1.102, 1.103, 1.103, 1.104, 1.104, 1.101,
+                            1.047, 1.059, 1.067, 1.072, 1.079, 1.084, 1.085, 1.087, 1.087, 1.087, 1.086, 1.088, 1.087, 1.087, 1.086, 1.086, 1.086, 1.089, 1.089, 1.091, 1.091, 1.093, 1.094, 1.095, 1.095, 1.097, 1.099, 1.102, 1.102, 1.103, 1.101, 1.098,
+                            1.049, 1.062, 1.069, 1.074, 1.079, 1.083, 1.086, 1.088, 1.088, 1.089, 1.088, 1.088, 1.087, 1.088, 1.087, 1.087, 1.086, 1.087, 1.088, 1.089, 1.089, 1.091, 1.093, 1.095, 1.097, 1.096, 1.098, 1.098, 1.101, 1.101, 1.099, 1.096,
+                            1.051, 1.062, 1.069, 1.077, 1.082, 1.084, 1.086, 1.087, 1.089, 1.088, 1.088, 1.088, 1.087, 1.088, 1.087, 1.086, 1.086, 1.086, 1.087, 1.088, 1.089, 1.091, 1.093, 1.094, 1.095, 1.096, 1.096, 1.098, 1.101, 1.101, 1.097, 1.094,
+                            1.057, 1.064, 1.076, 1.082, 1.084, 1.086, 1.086, 1.087, 1.089, 1.088, 1.088, 1.088, 1.088, 1.088, 1.088, 1.087, 1.086, 1.086, 1.086, 1.087, 1.088, 1.089, 1.092, 1.095, 1.097, 1.097, 1.097, 1.097, 1.099, 1.098, 1.095, 1.089,
+                            1.063, 1.072, 1.079, 1.083, 1.086, 1.087, 1.089, 1.089, 1.089, 1.089, 1.088, 1.089, 1.087, 1.087, 1.087, 1.087, 1.086, 1.086, 1.087, 1.087, 1.089, 1.089, 1.092, 1.094, 1.094, 1.097, 1.097, 1.097, 1.097, 1.097, 1.094, 1.088,
+                            1.066, 1.079, 1.084, 1.085, 1.086, 1.088, 1.089, 1.089, 1.089, 1.091, 1.089, 1.089, 1.088, 1.088, 1.087, 1.087, 1.086, 1.087, 1.088, 1.089, 1.089, 1.089, 1.092, 1.095, 1.096, 1.098, 1.097, 1.097, 1.097, 1.097, 1.093, 1.087,
+                            1.075, 1.079, 1.085, 1.087, 1.088, 1.089, 1.091, 1.091, 1.092, 1.092, 1.092, 1.089, 1.088, 1.089, 1.087, 1.087, 1.086, 1.087, 1.089, 1.089, 1.089, 1.091, 1.093, 1.097, 1.097, 1.097, 1.097, 1.098, 1.097, 1.097, 1.092, 1.085,
+                            1.076, 1.082, 1.086, 1.089, 1.091, 1.093, 1.095, 1.094, 1.092, 1.092, 1.092, 1.091, 1.091, 1.089, 1.089, 1.088, 1.088, 1.089, 1.089, 1.091, 1.092, 1.093, 1.093, 1.097, 1.097, 1.097, 1.097, 1.098, 1.098, 1.096, 1.089, 1.081,
+                            1.077, 1.085, 1.089, 1.092, 1.094, 1.095, 1.096, 1.096, 1.096, 1.095, 1.094, 1.092, 1.092, 1.089, 1.088, 1.089, 1.091, 1.089, 1.091, 1.091, 1.093, 1.093, 1.095, 1.096, 1.098, 1.098, 1.097, 1.098, 1.098, 1.093, 1.089, 1.081,
+                            1.082, 1.086, 1.092, 1.095, 1.097, 1.097, 1.098, 1.096, 1.097, 1.096, 1.094, 1.093, 1.093, 1.092, 1.089, 1.091, 1.091, 1.092, 1.092, 1.093, 1.094, 1.094, 1.095, 1.096, 1.097, 1.098, 1.099, 1.097, 1.096, 1.094, 1.089, 1.079,
+                            1.087, 1.091, 1.096, 1.097, 1.099, 1.098, 1.101, 1.099, 1.099, 1.097, 1.096, 1.095, 1.095, 1.095, 1.091, 1.093, 1.092, 1.093, 1.093, 1.093, 1.094, 1.095, 1.095, 1.097, 1.098, 1.101, 1.101, 1.099, 1.097, 1.094, 1.091, 1.077,
+                            1.092, 1.094, 1.099, 1.099, 1.102, 1.102, 1.103, 1.103, 1.101, 1.098, 1.097, 1.097, 1.097, 1.097, 1.096, 1.096, 1.095, 1.094, 1.094, 1.094, 1.094, 1.094, 1.095, 1.097, 1.098, 1.101, 1.101, 1.099, 1.098, 1.094, 1.088, 1.076,
+                            1.097, 1.101, 1.103, 1.105, 1.106, 1.106, 1.105, 1.104, 1.103, 1.101, 1.099, 1.099, 1.099, 1.098, 1.097, 1.097, 1.097, 1.097, 1.096, 1.094, 1.095, 1.095, 1.096, 1.097, 1.098, 1.101, 1.101, 1.099, 1.096, 1.094, 1.087, 1.078,
+                            1.101, 1.106, 1.107, 1.108, 1.109, 1.106, 1.106, 1.105, 1.105, 1.102, 1.103, 1.103, 1.102, 1.099, 1.099, 1.098, 1.098, 1.096, 1.096, 1.095, 1.096, 1.095, 1.095, 1.097, 1.098, 1.101, 1.101, 1.098, 1.095, 1.092, 1.084, 1.079,
+                            1.108, 1.109, 1.114, 1.114, 1.112, 1.112, 1.111, 1.112, 1.108, 1.106, 1.105, 1.106, 1.104, 1.101, 1.098, 1.098, 1.098, 1.098, 1.097, 1.096, 1.096, 1.096, 1.097, 1.098, 1.099, 1.099, 1.099, 1.096, 1.095, 1.091, 1.084, 1.079,
+                            1.111, 1.115, 1.116, 1.117, 1.116, 1.113, 1.113, 1.113, 1.111, 1.108, 1.107, 1.107, 1.105, 1.103, 1.099, 1.098, 1.098, 1.098, 1.097, 1.096, 1.096, 1.096, 1.097, 1.097, 1.098, 1.098, 1.097, 1.096, 1.093, 1.091, 1.084, 1.074,
+                            1.115, 1.119, 1.123, 1.122, 1.118, 1.117, 1.114, 1.115, 1.113, 1.108, 1.107, 1.106, 1.106, 1.102, 1.098, 1.098, 1.097, 1.097, 1.096, 1.096, 1.096, 1.093, 1.096, 1.096, 1.097, 1.097, 1.095, 1.094, 1.093, 1.091, 1.084, 1.071,
+                            1.123, 1.126, 1.127, 1.127, 1.124, 1.119, 1.117, 1.115, 1.116, 1.112, 1.107, 1.106, 1.106, 1.101, 1.098, 1.097, 1.097, 1.096, 1.095, 1.094, 1.093, 1.093, 1.092, 1.093, 1.093, 1.092, 1.092, 1.091, 1.091, 1.085, 1.076, 1.069,
+                            1.126, 1.128, 1.129, 1.129, 1.128, 1.124, 1.119, 1.117, 1.117, 1.116, 1.107, 1.106, 1.106, 1.103, 1.098, 1.097, 1.096, 1.095, 1.093, 1.089, 1.089, 1.086, 1.086, 1.085, 1.085, 1.085, 1.084, 1.081, 1.081, 1.078, 1.072, 1.065,
+                            1.127, 1.129, 1.131, 1.131, 1.128, 1.126, 1.123, 1.117, 1.117, 1.114, 1.113, 1.107, 1.105, 1.101, 1.097, 1.094, 1.092, 1.088, 1.086, 1.084, 1.081, 1.078, 1.079, 1.081, 1.082, 1.081, 1.079, 1.078, 1.076, 1.071, 1.062, 1.053,
+                            1.128, 1.131, 1.131, 1.131, 1.127, 1.126, 1.118, 1.118, 1.116, 1.114, 1.114, 1.106, 1.103, 1.101, 1.094, 1.092, 1.086, 1.084, 1.083, 1.079, 1.077, 1.076, 1.071, 1.069, 1.072, 1.072, 1.074, 1.073, 1.071, 1.064, 1.053, 1.052
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.001, 1.019, 1.033, 1.061, 1.077, 1.092, 1.113, 1.124, 1.133, 1.144, 1.145, 1.153, 1.162, 1.167, 1.181, 1.181, 1.191, 1.194, 1.201, 1.212, 1.214, 1.215, 1.222, 1.227, 1.233, 1.234, 1.236, 1.237, 1.241, 1.239, 1.233, 1.232,
+                            1.008, 1.027, 1.052, 1.069, 1.084, 1.102, 1.118, 1.133, 1.138, 1.148, 1.151, 1.163, 1.167, 1.179, 1.182, 1.189, 1.193, 1.198, 1.209, 1.214, 1.217, 1.221, 1.226, 1.231, 1.234, 1.236, 1.236, 1.239, 1.238, 1.239, 1.235, 1.232,
+                            1.021, 1.034, 1.064, 1.079, 1.101, 1.114, 1.129, 1.137, 1.149, 1.158, 1.165, 1.172, 1.181, 1.183, 1.191, 1.194, 1.199, 1.204, 1.212, 1.222, 1.222, 1.225, 1.229, 1.232, 1.239, 1.241, 1.241, 1.241, 1.242, 1.239, 1.235, 1.232,
+                            1.027, 1.043, 1.072, 1.084, 1.114, 1.123, 1.136, 1.149, 1.161, 1.167, 1.174, 1.181, 1.188, 1.191, 1.197, 1.202, 1.205, 1.209, 1.221, 1.225, 1.227, 1.227, 1.233, 1.238, 1.241, 1.242, 1.242, 1.243, 1.241, 1.239, 1.236, 1.233,
+                            1.038, 1.057, 1.079, 1.098, 1.116, 1.133, 1.149, 1.161, 1.165, 1.174, 1.179, 1.187, 1.192, 1.203, 1.207, 1.208, 1.213, 1.219, 1.228, 1.228, 1.229, 1.233, 1.235, 1.243, 1.244, 1.244, 1.244, 1.244, 1.243, 1.241, 1.237, 1.233,
+                            1.045, 1.071, 1.089, 1.107, 1.128, 1.139, 1.153, 1.164, 1.174, 1.181, 1.187, 1.193, 1.204, 1.207, 1.209, 1.213, 1.218, 1.221, 1.227, 1.231, 1.234, 1.236, 1.241, 1.243, 1.244, 1.246, 1.245, 1.245, 1.244, 1.241, 1.237, 1.232,
+                            1.059, 1.074, 1.094, 1.121, 1.131, 1.147, 1.161, 1.173, 1.181, 1.185, 1.194, 1.205, 1.208, 1.209, 1.213, 1.217, 1.219, 1.227, 1.229, 1.232, 1.237, 1.242, 1.243, 1.245, 1.246, 1.247, 1.245, 1.246, 1.245, 1.243, 1.235, 1.227,
+                            1.071, 1.079, 1.102, 1.121, 1.136, 1.152, 1.165, 1.179, 1.184, 1.195, 1.199, 1.208, 1.209, 1.212, 1.215, 1.222, 1.226, 1.228, 1.229, 1.234, 1.242, 1.244, 1.246, 1.247, 1.247, 1.247, 1.246, 1.247, 1.246, 1.241, 1.231, 1.224,
+                            1.072, 1.091, 1.106, 1.129, 1.144, 1.159, 1.171, 1.184, 1.192, 1.199, 1.206, 1.213, 1.216, 1.218, 1.222, 1.226, 1.229, 1.231, 1.233, 1.236, 1.242, 1.244, 1.249, 1.248, 1.249, 1.248, 1.247, 1.246, 1.245, 1.239, 1.226, 1.221,
+                            1.074, 1.092, 1.112, 1.129, 1.145, 1.164, 1.177, 1.191, 1.197, 1.203, 1.208, 1.216, 1.218, 1.221, 1.223, 1.227, 1.235, 1.233, 1.237, 1.238, 1.243, 1.247, 1.249, 1.249, 1.248, 1.246, 1.244, 1.244, 1.242, 1.236, 1.226, 1.214,
+                            1.087, 1.102, 1.122, 1.139, 1.154, 1.167, 1.186, 1.196, 1.201, 1.207, 1.211, 1.217, 1.219, 1.222, 1.226, 1.228, 1.234, 1.235, 1.238, 1.239, 1.243, 1.247, 1.249, 1.248, 1.248, 1.244, 1.244, 1.244, 1.243, 1.231, 1.227, 1.212,
+                            1.093, 1.114, 1.128, 1.146, 1.165, 1.171, 1.192, 1.197, 1.203, 1.209, 1.211, 1.219, 1.221, 1.223, 1.227, 1.229, 1.233, 1.235, 1.237, 1.241, 1.246, 1.251, 1.252, 1.251, 1.248, 1.243, 1.243, 1.239, 1.236, 1.231, 1.226, 1.209,
+                            1.106, 1.121, 1.138, 1.154, 1.165, 1.179, 1.195, 1.198, 1.207, 1.211, 1.217, 1.221, 1.224, 1.227, 1.229, 1.229, 1.231, 1.234, 1.238, 1.241, 1.246, 1.251, 1.251, 1.251, 1.249, 1.244, 1.242, 1.241, 1.236, 1.233, 1.219, 1.204,
+                            1.115, 1.122, 1.142, 1.154, 1.168, 1.182, 1.196, 1.203, 1.208, 1.211, 1.219, 1.222, 1.227, 1.228, 1.229, 1.229, 1.232, 1.236, 1.239, 1.241, 1.247, 1.251, 1.249, 1.249, 1.246, 1.244, 1.242, 1.237, 1.233, 1.227, 1.215, 1.197,
+                            1.121, 1.133, 1.143, 1.162, 1.173, 1.185, 1.197, 1.204, 1.211, 1.214, 1.221, 1.224, 1.227, 1.229, 1.229, 1.228, 1.229, 1.235, 1.239, 1.241, 1.246, 1.247, 1.249, 1.249, 1.247, 1.245, 1.241, 1.235, 1.229, 1.218, 1.209, 1.194,
+                            1.128, 1.139, 1.152, 1.163, 1.178, 1.188, 1.199, 1.209, 1.212, 1.217, 1.221, 1.225, 1.227, 1.229, 1.227, 1.228, 1.228, 1.235, 1.239, 1.241, 1.244, 1.245, 1.248, 1.249, 1.245, 1.241, 1.238, 1.231, 1.223, 1.215, 1.206, 1.184,
+                            1.131, 1.146, 1.159, 1.171, 1.181, 1.189, 1.206, 1.211, 1.217, 1.219, 1.222, 1.225, 1.227, 1.229, 1.229, 1.227, 1.228, 1.233, 1.237, 1.239, 1.241, 1.244, 1.245, 1.246, 1.243, 1.235, 1.228, 1.225, 1.219, 1.211, 1.204, 1.178,
+                            1.134, 1.148, 1.165, 1.176, 1.186, 1.194, 1.205, 1.214, 1.217, 1.218, 1.221, 1.223, 1.225, 1.227, 1.228, 1.227, 1.228, 1.233, 1.236, 1.238, 1.239, 1.241, 1.242, 1.241, 1.239, 1.228, 1.225, 1.222, 1.214, 1.207, 1.198, 1.176,
+                            1.147, 1.153, 1.167, 1.179, 1.189, 1.197, 1.205, 1.213, 1.217, 1.217, 1.222, 1.224, 1.225, 1.226, 1.229, 1.228, 1.229, 1.233, 1.235, 1.234, 1.234, 1.237, 1.239, 1.238, 1.228, 1.226, 1.223, 1.221, 1.212, 1.205, 1.189, 1.164,
+                            1.153, 1.159, 1.171, 1.181, 1.192, 1.201, 1.206, 1.212, 1.216, 1.219, 1.222, 1.223, 1.225, 1.223, 1.227, 1.226, 1.229, 1.231, 1.236, 1.234, 1.234, 1.234, 1.237, 1.232, 1.228, 1.225, 1.219, 1.215, 1.207, 1.193, 1.182, 1.155,
+                            1.154, 1.163, 1.172, 1.186, 1.189, 1.198, 1.206, 1.212, 1.217, 1.221, 1.221, 1.221, 1.219, 1.221, 1.225, 1.226, 1.227, 1.227, 1.233, 1.233, 1.233, 1.229, 1.229, 1.228, 1.224, 1.219, 1.216, 1.209, 1.199, 1.186, 1.173, 1.151,
+                            1.158, 1.168, 1.176, 1.186, 1.192, 1.201, 1.205, 1.209, 1.216, 1.219, 1.221, 1.219, 1.218, 1.218, 1.222, 1.224, 1.224, 1.225, 1.227, 1.228, 1.228, 1.228, 1.228, 1.225, 1.221, 1.214, 1.211, 1.199, 1.191, 1.177, 1.163, 1.141,
+                            1.167, 1.173, 1.181, 1.184, 1.194, 1.199, 1.204, 1.209, 1.212, 1.214, 1.219, 1.219, 1.218, 1.218, 1.218, 1.218, 1.218, 1.219, 1.223, 1.225, 1.225, 1.224, 1.223, 1.219, 1.214, 1.211, 1.203, 1.192, 1.185, 1.168, 1.158, 1.133,
+                            1.168, 1.174, 1.181, 1.184, 1.194, 1.201, 1.205, 1.209, 1.209, 1.209, 1.216, 1.219, 1.219, 1.216, 1.216, 1.215, 1.217, 1.217, 1.218, 1.219, 1.219, 1.217, 1.214, 1.209, 1.208, 1.203, 1.192, 1.187, 1.177, 1.164, 1.146, 1.123,
+                            1.167, 1.175, 1.181, 1.184, 1.194, 1.199, 1.206, 1.209, 1.209, 1.209, 1.215, 1.218, 1.219, 1.214, 1.214, 1.213, 1.213, 1.213, 1.212, 1.212, 1.212, 1.212, 1.208, 1.205, 1.201, 1.191, 1.188, 1.178, 1.169, 1.149, 1.134, 1.114,
+                            1.171, 1.175, 1.181, 1.187, 1.192, 1.198, 1.204, 1.207, 1.208, 1.209, 1.211, 1.212, 1.212, 1.211, 1.209, 1.211, 1.211, 1.209, 1.206, 1.206, 1.205, 1.202, 1.201, 1.197, 1.191, 1.184, 1.178, 1.173, 1.148, 1.134, 1.121, 1.101,
+                            1.172, 1.177, 1.181, 1.188, 1.191, 1.195, 1.198, 1.204, 1.207, 1.209, 1.209, 1.209, 1.209, 1.207, 1.201, 1.201, 1.202, 1.203, 1.199, 1.197, 1.192, 1.185, 1.182, 1.181, 1.181, 1.176, 1.166, 1.148, 1.136, 1.125, 1.112, 1.089,
+                            1.172, 1.177, 1.181, 1.184, 1.189, 1.194, 1.197, 1.201, 1.206, 1.208, 1.206, 1.207, 1.203, 1.197, 1.193, 1.194, 1.194, 1.192, 1.187, 1.184, 1.179, 1.175, 1.168, 1.164, 1.163, 1.157, 1.147, 1.135, 1.127, 1.113, 1.094, 1.078,
+                            1.176, 1.178, 1.182, 1.183, 1.184, 1.191, 1.195, 1.199, 1.201, 1.204, 1.201, 1.198, 1.193, 1.189, 1.187, 1.184, 1.179, 1.181, 1.173, 1.168, 1.165, 1.162, 1.155, 1.154, 1.155, 1.143, 1.135, 1.125, 1.113, 1.098, 1.086, 1.061,
+                            1.178, 1.181, 1.186, 1.184, 1.184, 1.188, 1.192, 1.197, 1.201, 1.199, 1.195, 1.191, 1.188, 1.186, 1.183, 1.177, 1.173, 1.171, 1.164, 1.161, 1.157, 1.152, 1.144, 1.133, 1.133, 1.128, 1.122, 1.102, 1.098, 1.086, 1.062, 1.042,
+                            1.178, 1.179, 1.183, 1.186, 1.187, 1.187, 1.187, 1.189, 1.193, 1.194, 1.189, 1.184, 1.183, 1.179, 1.171, 1.169, 1.163, 1.155, 1.148, 1.145, 1.143, 1.131, 1.125, 1.111, 1.108, 1.104, 1.095, 1.087, 1.079, 1.062, 1.036, 1.019,
+                            1.172, 1.179, 1.183, 1.186, 1.187, 1.182, 1.186, 1.189, 1.189, 1.191, 1.187, 1.181, 1.179, 1.173, 1.168, 1.163, 1.155, 1.145, 1.138, 1.132, 1.124, 1.124, 1.109, 1.107, 1.101, 1.093, 1.076, 1.072, 1.062, 1.042, 1.019, 1.011
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.001, 1.014, 1.027, 1.038, 1.048, 1.061, 1.068, 1.076, 1.084, 1.088, 1.089, 1.093, 1.096, 1.102, 1.105, 1.105, 1.109, 1.113, 1.113, 1.115, 1.119, 1.121, 1.125, 1.129, 1.129, 1.133, 1.131, 1.137, 1.137, 1.132, 1.129, 1.129,
+                            1.005, 1.017, 1.031, 1.046, 1.056, 1.061, 1.074, 1.079, 1.087, 1.089, 1.093, 1.097, 1.104, 1.106, 1.108, 1.111, 1.112, 1.114, 1.118, 1.125, 1.125, 1.126, 1.128, 1.131, 1.132, 1.134, 1.135, 1.137, 1.138, 1.135, 1.131, 1.129,
+                            1.011, 1.022, 1.041, 1.051, 1.061, 1.071, 1.077, 1.085, 1.092, 1.096, 1.098, 1.104, 1.107, 1.114, 1.115, 1.115, 1.117, 1.119, 1.126, 1.127, 1.127, 1.129, 1.131, 1.132, 1.135, 1.136, 1.136, 1.138, 1.138, 1.135, 1.132, 1.129,
+                            1.017, 1.026, 1.045, 1.057, 1.066, 1.073, 1.085, 1.093, 1.097, 1.099, 1.103, 1.109, 1.113, 1.118, 1.119, 1.121, 1.121, 1.125, 1.127, 1.129, 1.131, 1.131, 1.135, 1.137, 1.136, 1.136, 1.136, 1.137, 1.136, 1.136, 1.134, 1.129,
+                            1.017, 1.033, 1.051, 1.062, 1.068, 1.081, 1.091, 1.098, 1.099, 1.103, 1.109, 1.117, 1.118, 1.121, 1.122, 1.126, 1.126, 1.128, 1.129, 1.131, 1.134, 1.135, 1.137, 1.138, 1.138, 1.139, 1.138, 1.138, 1.137, 1.138, 1.135, 1.131,
+                            1.033, 1.039, 1.051, 1.066, 1.075, 1.083, 1.094, 1.099, 1.104, 1.106, 1.115, 1.119, 1.119, 1.122, 1.127, 1.128, 1.128, 1.131, 1.131, 1.133, 1.136, 1.138, 1.138, 1.141, 1.141, 1.139, 1.138, 1.139, 1.139, 1.139, 1.136, 1.133,
+                            1.033, 1.044, 1.059, 1.071, 1.078, 1.088, 1.095, 1.101, 1.106, 1.112, 1.118, 1.119, 1.124, 1.127, 1.129, 1.131, 1.131, 1.131, 1.131, 1.133, 1.137, 1.139, 1.142, 1.144, 1.143, 1.143, 1.141, 1.141, 1.139, 1.139, 1.134, 1.132,
+                            1.035, 1.048, 1.062, 1.073, 1.079, 1.092, 1.096, 1.104, 1.111, 1.113, 1.118, 1.124, 1.126, 1.129, 1.129, 1.133, 1.134, 1.133, 1.131, 1.136, 1.139, 1.142, 1.143, 1.144, 1.143, 1.143, 1.141, 1.142, 1.141, 1.141, 1.135, 1.132,
+                            1.035, 1.049, 1.064, 1.073, 1.084, 1.094, 1.099, 1.109, 1.113, 1.115, 1.119, 1.126, 1.127, 1.129, 1.131, 1.132, 1.134, 1.135, 1.134, 1.137, 1.142, 1.146, 1.147, 1.145, 1.145, 1.145, 1.143, 1.144, 1.142, 1.141, 1.135, 1.131,
+                            1.038, 1.052, 1.064, 1.076, 1.086, 1.095, 1.106, 1.111, 1.115, 1.119, 1.123, 1.126, 1.127, 1.129, 1.132, 1.134, 1.136, 1.135, 1.135, 1.139, 1.145, 1.147, 1.147, 1.147, 1.147, 1.144, 1.142, 1.142, 1.141, 1.138, 1.132, 1.128,
+                            1.043, 1.055, 1.066, 1.078, 1.086, 1.097, 1.108, 1.114, 1.119, 1.123, 1.124, 1.125, 1.129, 1.131, 1.132, 1.133, 1.136, 1.136, 1.136, 1.138, 1.142, 1.147, 1.148, 1.148, 1.147, 1.146, 1.143, 1.143, 1.141, 1.137, 1.131, 1.124,
+                            1.049, 1.056, 1.074, 1.082, 1.091, 1.102, 1.109, 1.115, 1.121, 1.123, 1.123, 1.125, 1.131, 1.131, 1.132, 1.133, 1.136, 1.139, 1.136, 1.137, 1.142, 1.148, 1.149, 1.149, 1.149, 1.145, 1.144, 1.143, 1.141, 1.138, 1.132, 1.122,
+                            1.054, 1.059, 1.075, 1.086, 1.094, 1.103, 1.109, 1.115, 1.121, 1.124, 1.124, 1.128, 1.132, 1.132, 1.132, 1.132, 1.137, 1.139, 1.138, 1.137, 1.141, 1.148, 1.149, 1.149, 1.149, 1.147, 1.145, 1.145, 1.142, 1.138, 1.131, 1.122,
+                            1.056, 1.065, 1.076, 1.087, 1.096, 1.105, 1.111, 1.118, 1.122, 1.125, 1.127, 1.129, 1.133, 1.134, 1.133, 1.134, 1.137, 1.139, 1.137, 1.138, 1.144, 1.147, 1.151, 1.149, 1.149, 1.146, 1.146, 1.144, 1.141, 1.137, 1.131, 1.121,
+                            1.058, 1.071, 1.078, 1.088, 1.098, 1.106, 1.112, 1.121, 1.122, 1.125, 1.128, 1.131, 1.132, 1.133, 1.132, 1.133, 1.136, 1.138, 1.137, 1.139, 1.144, 1.147, 1.149, 1.149, 1.149, 1.147, 1.144, 1.144, 1.139, 1.135, 1.128, 1.121,
+                            1.066, 1.072, 1.079, 1.091, 1.098, 1.107, 1.117, 1.121, 1.123, 1.125, 1.128, 1.131, 1.131, 1.134, 1.132, 1.135, 1.136, 1.139, 1.139, 1.139, 1.142, 1.145, 1.149, 1.149, 1.149, 1.147, 1.144, 1.142, 1.138, 1.134, 1.128, 1.116,
+                            1.069, 1.075, 1.087, 1.094, 1.099, 1.109, 1.117, 1.121, 1.124, 1.126, 1.127, 1.131, 1.131, 1.132, 1.132, 1.132, 1.136, 1.139, 1.141, 1.139, 1.139, 1.145, 1.149, 1.149, 1.149, 1.146, 1.143, 1.142, 1.138, 1.132, 1.126, 1.111,
+                            1.069, 1.076, 1.092, 1.098, 1.105, 1.109, 1.117, 1.121, 1.123, 1.126, 1.128, 1.129, 1.131, 1.132, 1.132, 1.133, 1.134, 1.138, 1.139, 1.138, 1.139, 1.141, 1.148, 1.149, 1.146, 1.143, 1.142, 1.141, 1.137, 1.132, 1.127, 1.109,
+                            1.074, 1.084, 1.093, 1.099, 1.106, 1.111, 1.116, 1.122, 1.123, 1.126, 1.128, 1.128, 1.129, 1.131, 1.132, 1.133, 1.136, 1.138, 1.138, 1.138, 1.139, 1.141, 1.144, 1.146, 1.145, 1.142, 1.139, 1.138, 1.137, 1.131, 1.124, 1.104,
+                            1.078, 1.085, 1.096, 1.098, 1.105, 1.112, 1.119, 1.122, 1.124, 1.126, 1.127, 1.129, 1.131, 1.131, 1.132, 1.133, 1.136, 1.139, 1.141, 1.139, 1.138, 1.139, 1.141, 1.142, 1.144, 1.139, 1.138, 1.138, 1.134, 1.129, 1.121, 1.101,
+                            1.082, 1.086, 1.093, 1.102, 1.104, 1.108, 1.115, 1.121, 1.124, 1.126, 1.124, 1.125, 1.124, 1.128, 1.131, 1.132, 1.134, 1.137, 1.139, 1.139, 1.139, 1.139, 1.139, 1.141, 1.141, 1.138, 1.135, 1.133, 1.131, 1.122, 1.114, 1.101,
+                            1.083, 1.088, 1.097, 1.101, 1.104, 1.107, 1.115, 1.119, 1.122, 1.124, 1.124, 1.125, 1.124, 1.126, 1.127, 1.131, 1.131, 1.133, 1.138, 1.138, 1.139, 1.139, 1.139, 1.139, 1.137, 1.137, 1.133, 1.129, 1.127, 1.119, 1.111, 1.091,
+                            1.086, 1.091, 1.099, 1.101, 1.103, 1.107, 1.115, 1.117, 1.119, 1.122, 1.123, 1.125, 1.126, 1.126, 1.126, 1.129, 1.129, 1.131, 1.133, 1.136, 1.138, 1.138, 1.139, 1.139, 1.134, 1.133, 1.129, 1.127, 1.119, 1.116, 1.106, 1.089,
+                            1.087, 1.092, 1.097, 1.101, 1.104, 1.109, 1.115, 1.117, 1.118, 1.121, 1.123, 1.126, 1.127, 1.126, 1.125, 1.125, 1.126, 1.128, 1.131, 1.136, 1.135, 1.137, 1.135, 1.135, 1.133, 1.131, 1.126, 1.123, 1.117, 1.111, 1.102, 1.088,
+                            1.091, 1.092, 1.097, 1.101, 1.105, 1.107, 1.115, 1.116, 1.117, 1.119, 1.121, 1.124, 1.127, 1.127, 1.125, 1.125, 1.125, 1.126, 1.127, 1.133, 1.132, 1.134, 1.134, 1.133, 1.131, 1.126, 1.124, 1.119, 1.111, 1.103, 1.094, 1.079,
+                            1.093, 1.094, 1.096, 1.099, 1.104, 1.107, 1.111, 1.114, 1.115, 1.117, 1.119, 1.121, 1.124, 1.125, 1.123, 1.123, 1.124, 1.124, 1.125, 1.127, 1.126, 1.129, 1.127, 1.129, 1.127, 1.122, 1.118, 1.112, 1.104, 1.098, 1.091, 1.069,
+                            1.093, 1.094, 1.099, 1.101, 1.106, 1.107, 1.109, 1.112, 1.114, 1.114, 1.118, 1.118, 1.119, 1.118, 1.117, 1.119, 1.118, 1.121, 1.121, 1.121, 1.118, 1.118, 1.123, 1.123, 1.119, 1.117, 1.112, 1.102, 1.099, 1.091, 1.077, 1.063,
+                            1.094, 1.097, 1.101, 1.101, 1.104, 1.106, 1.111, 1.112, 1.113, 1.112, 1.114, 1.115, 1.115, 1.115, 1.113, 1.112, 1.112, 1.112, 1.113, 1.112, 1.111, 1.111, 1.112, 1.112, 1.112, 1.104, 1.099, 1.098, 1.088, 1.078, 1.071, 1.054,
+                            1.095, 1.098, 1.101, 1.102, 1.103, 1.106, 1.107, 1.109, 1.111, 1.111, 1.108, 1.109, 1.111, 1.109, 1.108, 1.108, 1.108, 1.105, 1.104, 1.102, 1.102, 1.101, 1.101, 1.099, 1.098, 1.095, 1.093, 1.085, 1.076, 1.071, 1.058, 1.044,
+                            1.095, 1.098, 1.101, 1.102, 1.102, 1.103, 1.106, 1.107, 1.109, 1.108, 1.107, 1.107, 1.105, 1.103, 1.104, 1.103, 1.103, 1.102, 1.098, 1.096, 1.094, 1.093, 1.091, 1.088, 1.084, 1.078, 1.077, 1.074, 1.068, 1.058, 1.037, 1.028,
+                            1.096, 1.098, 1.101, 1.103, 1.104, 1.103, 1.105, 1.105, 1.107, 1.104, 1.104, 1.103, 1.102, 1.101, 1.098, 1.098, 1.096, 1.091, 1.089, 1.088, 1.087, 1.083, 1.079, 1.073, 1.071, 1.069, 1.065, 1.061, 1.051, 1.038, 1.028, 1.014,
+                            1.095, 1.099, 1.103, 1.104, 1.103, 1.102, 1.105, 1.106, 1.106, 1.103, 1.101, 1.098, 1.097, 1.099, 1.095, 1.093, 1.091, 1.086, 1.085, 1.081, 1.078, 1.076, 1.068, 1.066, 1.062, 1.062, 1.056, 1.049, 1.038, 1.031, 1.014, 1.011
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.001, 1.003, 1.012, 1.017, 1.023, 1.024, 1.031, 1.033, 1.035, 1.037, 1.036, 1.035, 1.036, 1.036, 1.037, 1.036, 1.037, 1.036, 1.041, 1.044, 1.044, 1.045, 1.049, 1.048, 1.051, 1.051, 1.052, 1.052, 1.055, 1.052, 1.052, 1.051,
+                            1.001, 1.006, 1.017, 1.022, 1.024, 1.029, 1.033, 1.036, 1.037, 1.039, 1.037, 1.038, 1.037, 1.038, 1.041, 1.041, 1.042, 1.041, 1.045, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.051, 1.053, 1.054, 1.055, 1.054, 1.053, 1.051,
+                            1.003, 1.012, 1.019, 1.025, 1.026, 1.032, 1.035, 1.041, 1.041, 1.041, 1.041, 1.043, 1.041, 1.045, 1.045, 1.045, 1.046, 1.048, 1.048, 1.048, 1.048, 1.049, 1.052, 1.052, 1.053, 1.054, 1.055, 1.057, 1.056, 1.055, 1.053, 1.053,
+                            1.003, 1.014, 1.019, 1.026, 1.032, 1.034, 1.037, 1.041, 1.042, 1.043, 1.043, 1.046, 1.045, 1.046, 1.048, 1.049, 1.051, 1.054, 1.053, 1.052, 1.052, 1.052, 1.053, 1.055, 1.054, 1.055, 1.056, 1.057, 1.055, 1.055, 1.054, 1.053,
+                            1.006, 1.015, 1.019, 1.028, 1.032, 1.035, 1.039, 1.042, 1.044, 1.044, 1.046, 1.048, 1.048, 1.049, 1.049, 1.051, 1.053, 1.056, 1.055, 1.055, 1.053, 1.054, 1.055, 1.057, 1.056, 1.058, 1.057, 1.057, 1.057, 1.058, 1.055, 1.053,
+                            1.014, 1.018, 1.021, 1.028, 1.034, 1.036, 1.041, 1.042, 1.045, 1.046, 1.047, 1.049, 1.051, 1.052, 1.051, 1.054, 1.056, 1.057, 1.058, 1.059, 1.058, 1.057, 1.058, 1.059, 1.058, 1.059, 1.059, 1.059, 1.058, 1.059, 1.055, 1.054,
+                            1.013, 1.018, 1.022, 1.029, 1.032, 1.037, 1.041, 1.046, 1.047, 1.049, 1.049, 1.052, 1.054, 1.052, 1.052, 1.054, 1.058, 1.058, 1.059, 1.062, 1.063, 1.063, 1.061, 1.061, 1.061, 1.061, 1.061, 1.061, 1.061, 1.059, 1.055, 1.053,
+                            1.015, 1.019, 1.022, 1.029, 1.033, 1.037, 1.041, 1.046, 1.048, 1.049, 1.052, 1.054, 1.054, 1.053, 1.052, 1.054, 1.058, 1.059, 1.061, 1.063, 1.064, 1.064, 1.063, 1.064, 1.063, 1.062, 1.063, 1.062, 1.063, 1.061, 1.056, 1.054,
+                            1.014, 1.017, 1.025, 1.029, 1.033, 1.037, 1.041, 1.046, 1.048, 1.049, 1.054, 1.056, 1.055, 1.053, 1.053, 1.055, 1.059, 1.058, 1.058, 1.062, 1.063, 1.064, 1.065, 1.065, 1.065, 1.064, 1.064, 1.064, 1.064, 1.061, 1.058, 1.054,
+                            1.015, 1.019, 1.024, 1.032, 1.035, 1.039, 1.044, 1.046, 1.049, 1.052, 1.054, 1.057, 1.057, 1.056, 1.057, 1.058, 1.061, 1.061, 1.061, 1.063, 1.063, 1.065, 1.065, 1.066, 1.066, 1.063, 1.065, 1.064, 1.065, 1.063, 1.059, 1.055,
+                            1.012, 1.021, 1.023, 1.031, 1.035, 1.041, 1.045, 1.049, 1.049, 1.054, 1.054, 1.057, 1.057, 1.058, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.066, 1.067, 1.069, 1.068, 1.067, 1.064, 1.066, 1.065, 1.065, 1.063, 1.059, 1.055,
+                            1.013, 1.021, 1.023, 1.032, 1.035, 1.042, 1.048, 1.051, 1.052, 1.054, 1.054, 1.057, 1.057, 1.058, 1.059, 1.061, 1.063, 1.063, 1.064, 1.066, 1.067, 1.069, 1.071, 1.071, 1.069, 1.067, 1.067, 1.066, 1.066, 1.064, 1.062, 1.057,
+                            1.019, 1.022, 1.025, 1.032, 1.036, 1.042, 1.049, 1.051, 1.052, 1.053, 1.054, 1.057, 1.058, 1.059, 1.059, 1.062, 1.062, 1.063, 1.066, 1.067, 1.069, 1.071, 1.072, 1.073, 1.073, 1.069, 1.068, 1.068, 1.067, 1.065, 1.064, 1.057,
+                            1.019, 1.021, 1.027, 1.032, 1.037, 1.042, 1.048, 1.052, 1.053, 1.054, 1.056, 1.057, 1.059, 1.059, 1.059, 1.061, 1.061, 1.063, 1.066, 1.069, 1.071, 1.071, 1.073, 1.073, 1.075, 1.069, 1.069, 1.069, 1.067, 1.067, 1.066, 1.056,
+                            1.019, 1.022, 1.028, 1.034, 1.037, 1.042, 1.047, 1.052, 1.053, 1.054, 1.055, 1.057, 1.058, 1.061, 1.061, 1.061, 1.062, 1.065, 1.067, 1.069, 1.071, 1.072, 1.073, 1.073, 1.075, 1.071, 1.069, 1.069, 1.068, 1.067, 1.065, 1.055,
+                            1.017, 1.023, 1.031, 1.033, 1.037, 1.042, 1.048, 1.051, 1.053, 1.054, 1.056, 1.056, 1.057, 1.059, 1.059, 1.059, 1.061, 1.065, 1.069, 1.069, 1.071, 1.072, 1.072, 1.073, 1.073, 1.071, 1.071, 1.071, 1.068, 1.068, 1.064, 1.056,
+                            1.017, 1.025, 1.029, 1.033, 1.037, 1.043, 1.047, 1.051, 1.052, 1.053, 1.056, 1.056, 1.056, 1.057, 1.059, 1.061, 1.061, 1.066, 1.069, 1.072, 1.073, 1.073, 1.073, 1.072, 1.072, 1.072, 1.071, 1.071, 1.069, 1.069, 1.066, 1.056,
+                            1.018, 1.025, 1.032, 1.035, 1.041, 1.043, 1.048, 1.051, 1.053, 1.054, 1.057, 1.056, 1.057, 1.056, 1.058, 1.059, 1.061, 1.066, 1.069, 1.072, 1.074, 1.074, 1.073, 1.073, 1.073, 1.073, 1.072, 1.071, 1.069, 1.069, 1.065, 1.057,
+                            1.019, 1.025, 1.031, 1.038, 1.041, 1.045, 1.047, 1.049, 1.053, 1.053, 1.056, 1.056, 1.056, 1.056, 1.058, 1.059, 1.062, 1.065, 1.069, 1.071, 1.072, 1.074, 1.073, 1.073, 1.072, 1.072, 1.072, 1.072, 1.071, 1.069, 1.067, 1.057,
+                            1.019, 1.025, 1.031, 1.038, 1.041, 1.044, 1.047, 1.049, 1.053, 1.053, 1.054, 1.053, 1.053, 1.055, 1.056, 1.061, 1.062, 1.066, 1.068, 1.071, 1.071, 1.074, 1.074, 1.073, 1.073, 1.073, 1.072, 1.072, 1.072, 1.068, 1.065, 1.057,
+                            1.019, 1.025, 1.029, 1.036, 1.039, 1.039, 1.046, 1.048, 1.052, 1.053, 1.053, 1.052, 1.051, 1.053, 1.056, 1.059, 1.062, 1.064, 1.067, 1.069, 1.071, 1.071, 1.071, 1.072, 1.071, 1.072, 1.071, 1.071, 1.071, 1.067, 1.062, 1.055,
+                            1.022, 1.025, 1.029, 1.035, 1.037, 1.038, 1.042, 1.046, 1.047, 1.052, 1.053, 1.051, 1.051, 1.053, 1.054, 1.057, 1.059, 1.062, 1.064, 1.067, 1.071, 1.071, 1.072, 1.074, 1.073, 1.073, 1.071, 1.071, 1.069, 1.066, 1.061, 1.053,
+                            1.023, 1.026, 1.029, 1.034, 1.036, 1.038, 1.041, 1.045, 1.046, 1.049, 1.052, 1.052, 1.053, 1.056, 1.055, 1.057, 1.058, 1.059, 1.063, 1.066, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.069, 1.067, 1.065, 1.058, 1.053,
+                            1.023, 1.026, 1.029, 1.034, 1.036, 1.039, 1.041, 1.044, 1.045, 1.047, 1.049, 1.053, 1.054, 1.055, 1.055, 1.055, 1.056, 1.058, 1.061, 1.064, 1.067, 1.068, 1.071, 1.072, 1.071, 1.071, 1.068, 1.066, 1.065, 1.064, 1.058, 1.052,
+                            1.024, 1.026, 1.028, 1.033, 1.035, 1.038, 1.041, 1.044, 1.046, 1.048, 1.049, 1.052, 1.054, 1.054, 1.055, 1.055, 1.056, 1.057, 1.059, 1.063, 1.064, 1.068, 1.069, 1.069, 1.069, 1.068, 1.067, 1.065, 1.064, 1.061, 1.055, 1.046,
+                            1.022, 1.026, 1.028, 1.032, 1.035, 1.037, 1.041, 1.044, 1.046, 1.047, 1.049, 1.051, 1.054, 1.054, 1.054, 1.054, 1.055, 1.057, 1.059, 1.062, 1.062, 1.065, 1.066, 1.068, 1.069, 1.068, 1.067, 1.063, 1.059, 1.057, 1.053, 1.043,
+                            1.022, 1.026, 1.029, 1.031, 1.034, 1.036, 1.039, 1.043, 1.045, 1.046, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.054, 1.055, 1.056, 1.057, 1.059, 1.061, 1.061, 1.062, 1.066, 1.067, 1.065, 1.059, 1.055, 1.054, 1.048, 1.039,
+                            1.025, 1.026, 1.028, 1.028, 1.031, 1.033, 1.037, 1.041, 1.044, 1.045, 1.048, 1.048, 1.048, 1.049, 1.048, 1.049, 1.052, 1.052, 1.052, 1.053, 1.054, 1.054, 1.056, 1.056, 1.057, 1.057, 1.054, 1.054, 1.052, 1.048, 1.045, 1.035,
+                            1.023, 1.024, 1.026, 1.028, 1.029, 1.032, 1.035, 1.038, 1.042, 1.042, 1.044, 1.045, 1.046, 1.046, 1.045, 1.046, 1.047, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.049, 1.051, 1.051, 1.051, 1.047, 1.045, 1.044, 1.033, 1.029,
+                            1.023, 1.024, 1.028, 1.028, 1.029, 1.031, 1.035, 1.036, 1.039, 1.041, 1.043, 1.039, 1.041, 1.042, 1.043, 1.043, 1.044, 1.045, 1.046, 1.046, 1.045, 1.046, 1.044, 1.044, 1.042, 1.043, 1.045, 1.043, 1.039, 1.032, 1.028, 1.022,
+                            1.021, 1.027, 1.032, 1.031, 1.031, 1.033, 1.036, 1.037, 1.037, 1.037, 1.037, 1.037, 1.039, 1.039, 1.041, 1.041, 1.039, 1.039, 1.039, 1.041, 1.042, 1.042, 1.036, 1.036, 1.036, 1.036, 1.036, 1.035, 1.028, 1.026, 1.016, 1.011,
+                            1.025, 1.032, 1.032, 1.032, 1.032, 1.033, 1.037, 1.037, 1.036, 1.035, 1.037, 1.037, 1.037, 1.038, 1.039, 1.038, 1.037, 1.035, 1.036, 1.037, 1.036, 1.035, 1.033, 1.032, 1.032, 1.031, 1.029, 1.022, 1.016, 1.013, 1.011, 1.008
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    1.991, 1.983, 1.889, 1.818, 1.751, 1.681, 1.619, 1.562, 1.514, 1.469, 1.434, 1.405, 1.376, 1.359, 1.343, 1.325, 1.314, 1.309, 1.307, 1.303, 1.304, 1.304, 1.308, 1.322, 1.333, 1.347, 1.364, 1.381, 1.401, 1.419, 1.456, 1.477,
+                    1.983, 1.902, 1.819, 1.751, 1.683, 1.619, 1.562, 1.514, 1.468, 1.433, 1.402, 1.372, 1.347, 1.328, 1.315, 1.299, 1.285, 1.276, 1.273, 1.275, 1.273, 1.272, 1.281, 1.291, 1.301, 1.315, 1.336, 1.351, 1.371, 1.394, 1.431, 1.456,
+                    1.889, 1.816, 1.743, 1.678, 1.614, 1.551, 1.501, 1.455, 1.415, 1.386, 1.353, 1.332, 1.309, 1.291, 1.276, 1.265, 1.251, 1.243, 1.242, 1.243, 1.242, 1.239, 1.247, 1.256, 1.269, 1.279, 1.292, 1.309, 1.332, 1.357, 1.389, 1.419,
+                    1.811, 1.743, 1.672, 1.608, 1.547, 1.495, 1.449, 1.406, 1.371, 1.341, 1.316, 1.295, 1.273, 1.255, 1.243, 1.233, 1.222, 1.216, 1.213, 1.213, 1.213, 1.213, 1.221, 1.229, 1.239, 1.249, 1.262, 1.279, 1.301, 1.324, 1.355, 1.388,
+                    1.742, 1.671, 1.606, 1.544, 1.491, 1.443, 1.403, 1.361, 1.329, 1.306, 1.283, 1.264, 1.244, 1.223, 1.209, 1.203, 1.191, 1.187, 1.184, 1.182, 1.183, 1.186, 1.196, 1.203, 1.211, 1.226, 1.241, 1.255, 1.277, 1.301, 1.327, 1.361,
+                    1.671, 1.609, 1.549, 1.493, 1.441, 1.399, 1.358, 1.325, 1.294, 1.269, 1.249, 1.234, 1.216, 1.194, 1.181, 1.172, 1.165, 1.159, 1.156, 1.157, 1.158, 1.164, 1.174, 1.181, 1.191, 1.205, 1.217, 1.236, 1.255, 1.277, 1.304, 1.339,
+                    1.608, 1.561, 1.499, 1.445, 1.401, 1.359, 1.323, 1.292, 1.264, 1.242, 1.219, 1.201, 1.187, 1.169, 1.156, 1.148, 1.143, 1.136, 1.134, 1.135, 1.139, 1.144, 1.154, 1.165, 1.174, 1.185, 1.198, 1.214, 1.233, 1.258, 1.283, 1.323,
+                    1.559, 1.506, 1.454, 1.405, 1.362, 1.322, 1.291, 1.261, 1.234, 1.212, 1.193, 1.178, 1.162, 1.147, 1.136, 1.128, 1.121, 1.118, 1.116, 1.117, 1.122, 1.129, 1.135, 1.145, 1.156, 1.167, 1.181, 1.197, 1.217, 1.242, 1.271, 1.311,
+                    1.506, 1.463, 1.413, 1.369, 1.327, 1.291, 1.261, 1.232, 1.208, 1.191, 1.171, 1.153, 1.139, 1.126, 1.118, 1.109, 1.102, 1.096, 1.098, 1.097, 1.105, 1.112, 1.119, 1.129, 1.141, 1.153, 1.167, 1.183, 1.205, 1.232, 1.259, 1.299,
+                    1.463, 1.425, 1.378, 1.337, 1.297, 1.262, 1.233, 1.208, 1.187, 1.167, 1.152, 1.134, 1.119, 1.106, 1.095, 1.087, 1.083, 1.079, 1.078, 1.079, 1.088, 1.096, 1.105, 1.115, 1.128, 1.142, 1.154, 1.171, 1.197, 1.219, 1.247, 1.287,
+                    1.425, 1.384, 1.347, 1.307, 1.272, 1.239, 1.209, 1.186, 1.168, 1.151, 1.131, 1.115, 1.099, 1.086, 1.076, 1.069, 1.067, 1.064, 1.063, 1.067, 1.075, 1.085, 1.093, 1.104, 1.117, 1.127, 1.142, 1.159, 1.183, 1.204, 1.231, 1.278,
+                    1.387, 1.355, 1.321, 1.292, 1.258, 1.224, 1.189, 1.167, 1.146, 1.129, 1.113, 1.097, 1.083, 1.071, 1.062, 1.057, 1.052, 1.051, 1.053, 1.059, 1.064, 1.074, 1.086, 1.097, 1.107, 1.119, 1.132, 1.149, 1.175, 1.196, 1.224, 1.276,
+                    1.364, 1.332, 1.303, 1.271, 1.241, 1.206, 1.176, 1.149, 1.129, 1.112, 1.095, 1.081, 1.069, 1.058, 1.049, 1.044, 1.042, 1.042, 1.044, 1.049, 1.056, 1.066, 1.079, 1.089, 1.102, 1.113, 1.126, 1.145, 1.169, 1.192, 1.221, 1.273,
+                    1.343, 1.314, 1.283, 1.251, 1.219, 1.191, 1.161, 1.136, 1.114, 1.098, 1.081, 1.069, 1.057, 1.048, 1.041, 1.035, 1.033, 1.034, 1.038, 1.039, 1.049, 1.058, 1.067, 1.081, 1.093, 1.108, 1.121, 1.143, 1.164, 1.188, 1.218, 1.273,
+                    1.323, 1.297, 1.264, 1.232, 1.198, 1.169, 1.145, 1.125, 1.105, 1.085, 1.071, 1.059, 1.049, 1.042, 1.032, 1.026, 1.024, 1.026, 1.028, 1.032, 1.038, 1.049, 1.059, 1.069, 1.087, 1.101, 1.119, 1.139, 1.161, 1.186, 1.215, 1.269,
+                    1.304, 1.278, 1.248, 1.219, 1.185, 1.154, 1.133, 1.113, 1.091, 1.075, 1.064, 1.057, 1.048, 1.036, 1.025, 1.018, 1.016, 1.018, 1.022, 1.026, 1.034, 1.044, 1.055, 1.065, 1.079, 1.096, 1.116, 1.138, 1.161, 1.185, 1.213, 1.271,
+                    1.286, 1.261, 1.236, 1.209, 1.178, 1.147, 1.123, 1.102, 1.082, 1.066, 1.059, 1.054, 1.047, 1.033, 1.019, 1.012, 1.009, 1.015, 1.019, 1.023, 1.029, 1.042, 1.053, 1.064, 1.077, 1.095, 1.115, 1.137, 1.161, 1.188, 1.216, 1.271,
+                    1.275, 1.247, 1.224, 1.201, 1.173, 1.143, 1.118, 1.096, 1.078, 1.062, 1.055, 1.049, 1.042, 1.029, 1.017, 1.009, 1.008, 1.011, 1.015, 1.022, 1.031, 1.042, 1.051, 1.061, 1.079, 1.096, 1.116, 1.138, 1.163, 1.194, 1.224, 1.279,
+                    1.269, 1.241, 1.216, 1.192, 1.165, 1.136, 1.113, 1.093, 1.075, 1.057, 1.051, 1.043, 1.038, 1.031, 1.019, 1.011, 1.008, 1.009, 1.015, 1.021, 1.031, 1.041, 1.052, 1.063, 1.081, 1.098, 1.119, 1.141, 1.167, 1.199, 1.232, 1.291,
+                    1.263, 1.234, 1.208, 1.181, 1.158, 1.131, 1.109, 1.089, 1.073, 1.056, 1.047, 1.041, 1.035, 1.033, 1.028, 1.015, 1.009, 1.009, 1.015, 1.023, 1.032, 1.041, 1.053, 1.067, 1.085, 1.106, 1.127, 1.149, 1.176, 1.211, 1.244, 1.303,
+                    1.259, 1.225, 1.201, 1.173, 1.148, 1.125, 1.106, 1.087, 1.073, 1.059, 1.047, 1.038, 1.035, 1.034, 1.031, 1.022, 1.012, 1.012, 1.018, 1.026, 1.034, 1.046, 1.059, 1.074, 1.091, 1.113, 1.133, 1.158, 1.184, 1.217, 1.255, 1.314,
+                    1.254, 1.219, 1.193, 1.169, 1.143, 1.119, 1.101, 1.081, 1.068, 1.057, 1.047, 1.039, 1.035, 1.034, 1.029, 1.021, 1.015, 1.014, 1.021, 1.029, 1.038, 1.053, 1.068, 1.082, 1.099, 1.118, 1.141, 1.166, 1.194, 1.231, 1.271, 1.335,
+                    1.249, 1.216, 1.191, 1.165, 1.141, 1.119, 1.099, 1.079, 1.067, 1.058, 1.048, 1.042, 1.036, 1.033, 1.028, 1.022, 1.016, 1.017, 1.026, 1.032, 1.045, 1.061, 1.077, 1.093, 1.111, 1.131, 1.151, 1.182, 1.211, 1.248, 1.293, 1.356,
+                    1.252, 1.218, 1.188, 1.162, 1.141, 1.119, 1.099, 1.079, 1.069, 1.059, 1.049, 1.041, 1.037, 1.032, 1.026, 1.024, 1.021, 1.023, 1.032, 1.041, 1.052, 1.068, 1.087, 1.105, 1.124, 1.144, 1.172, 1.204, 1.233, 1.271, 1.317, 1.379,
+                    1.251, 1.216, 1.191, 1.166, 1.144, 1.122, 1.102, 1.084, 1.071, 1.059, 1.049, 1.043, 1.037, 1.031, 1.026, 1.024, 1.025, 1.031, 1.041, 1.051, 1.061, 1.077, 1.098, 1.117, 1.138, 1.163, 1.192, 1.223, 1.257, 1.297, 1.346, 1.402,
+                    1.255, 1.221, 1.195, 1.172, 1.149, 1.127, 1.108, 1.091, 1.077, 1.064, 1.054, 1.046, 1.041, 1.033, 1.031, 1.029, 1.031, 1.039, 1.049, 1.055, 1.071, 1.089, 1.107, 1.131, 1.155, 1.182, 1.209, 1.241, 1.282, 1.326, 1.371, 1.434,
+                    1.258, 1.225, 1.199, 1.177, 1.155, 1.135, 1.118, 1.099, 1.082, 1.071, 1.063, 1.055, 1.047, 1.041, 1.036, 1.035, 1.039, 1.047, 1.053, 1.064, 1.078, 1.101, 1.121, 1.144, 1.171, 1.197, 1.231, 1.266, 1.306, 1.354, 1.404, 1.468,
+                    1.266, 1.229, 1.202, 1.181, 1.157, 1.142, 1.126, 1.111, 1.094, 1.083, 1.074, 1.067, 1.061, 1.052, 1.047, 1.047, 1.049, 1.053, 1.063, 1.073, 1.091, 1.113, 1.134, 1.155, 1.188, 1.217, 1.254, 1.296, 1.342, 1.391, 1.439, 1.504,
+                    1.275, 1.237, 1.209, 1.187, 1.167, 1.151, 1.136, 1.123, 1.106, 1.098, 1.086, 1.081, 1.072, 1.064, 1.059, 1.059, 1.061, 1.065, 1.074, 1.089, 1.111, 1.132, 1.153, 1.182, 1.209, 1.241, 1.287, 1.336, 1.381, 1.423, 1.476, 1.554,
+                    1.284, 1.253, 1.219, 1.197, 1.176, 1.162, 1.149, 1.139, 1.123, 1.113, 1.104, 1.097, 1.091, 1.081, 1.076, 1.076, 1.078, 1.082, 1.095, 1.115, 1.136, 1.163, 1.185, 1.214, 1.241, 1.279, 1.327, 1.373, 1.418, 1.458, 1.521, 1.604,
+                    1.328, 1.289, 1.249, 1.212, 1.192, 1.175, 1.169, 1.162, 1.153, 1.137, 1.125, 1.119, 1.116, 1.106, 1.101, 1.098, 1.104, 1.112, 1.122, 1.144, 1.172, 1.194, 1.227, 1.252, 1.282, 1.325, 1.368, 1.415, 1.455, 1.507, 1.575, 1.657,
+                    1.345, 1.323, 1.273, 1.241, 1.211, 1.194, 1.187, 1.181, 1.169, 1.164, 1.147, 1.139, 1.133, 1.127, 1.125, 1.123, 1.128, 1.137, 1.146, 1.166, 1.194, 1.227, 1.252, 1.281, 1.316, 1.351, 1.411, 1.451, 1.493, 1.561, 1.647, 1.701
+                ],
+                "sigma": 0.0017,
+                "sigma_Cb": 0.00261
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.81211, -0.38431, -0.42779,
+                            -0.41095, 1.93027, -0.51931,
+                            0.14123, -1.15184, 2.01061
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "ccm":
+                        [
+                            1.72172, -0.43893, -0.28279,
+                            -0.33381, 1.75551, -0.42169,
+                            0.03181, -0.68571, 1.65391
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            1.65333, -0.31911, -0.33422,
+                            -0.22538, 1.80858, -0.58321,
+                            0.00361, -0.60329, 1.59969
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.cac": { }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.25,
+                "limit": 1.0,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/vd55g1_mono.json 0.6.0-2/src/ipa/rpi/pisp/data/vd55g1_mono.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/vd55g1_mono.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/vd55g1_mono.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,1079 @@
+{
+    "version": 2.0,
+    "target": "pisp",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 32138,
+                "reference_gain": 1.23,
+                "reference_aperture": 1.0,
+                "reference_lux": 1060,
+                "reference_Y": 21540
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 20,
+                "reference_slope": 6.825
+            }
+        },
+        {
+            "rpi.denoise":
+            {
+                "normal":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 0.8,
+                        "threshold": 0.05
+                    }
+                },
+                "hdr":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                },
+                "night":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                }
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.001, 1.009, 1.016, 1.022, 1.025, 1.029, 1.034, 1.035, 1.037, 1.038, 1.038, 1.039, 1.041, 1.043, 1.043, 1.043, 1.042, 1.043, 1.045, 1.046, 1.046, 1.045, 1.048, 1.049, 1.051, 1.052, 1.051, 1.051, 1.051, 1.052, 1.053, 1.053,
+                            1.008, 1.012, 1.021, 1.024, 1.029, 1.035, 1.041, 1.042, 1.046, 1.042, 1.043, 1.044, 1.047, 1.048, 1.049, 1.047, 1.049, 1.049, 1.049, 1.052, 1.053, 1.052, 1.054, 1.054, 1.055, 1.055, 1.057, 1.056, 1.057, 1.054, 1.054, 1.053,
+                            1.011, 1.016, 1.024, 1.031, 1.036, 1.043, 1.047, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.052, 1.053, 1.053, 1.056, 1.056, 1.056, 1.055, 1.056, 1.057, 1.059, 1.059, 1.061, 1.061, 1.061, 1.059, 1.056, 1.054,
+                            1.011, 1.017, 1.031, 1.036, 1.043, 1.047, 1.049, 1.051, 1.052, 1.055, 1.055, 1.055, 1.056, 1.056, 1.056, 1.056, 1.056, 1.057, 1.058, 1.059, 1.061, 1.058, 1.059, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.061, 1.059, 1.056,
+                            1.015, 1.026, 1.035, 1.039, 1.046, 1.048, 1.052, 1.054, 1.058, 1.058, 1.058, 1.058, 1.059, 1.059, 1.059, 1.059, 1.059, 1.061, 1.062, 1.061, 1.061, 1.061, 1.061, 1.061, 1.063, 1.063, 1.063, 1.063, 1.063, 1.062, 1.059, 1.056,
+                            1.019, 1.027, 1.035, 1.042, 1.047, 1.051, 1.054, 1.058, 1.059, 1.059, 1.061, 1.061, 1.061, 1.062, 1.061, 1.062, 1.063, 1.063, 1.064, 1.064, 1.066, 1.062, 1.062, 1.062, 1.063, 1.064, 1.063, 1.063, 1.063, 1.063, 1.061, 1.056,
+                            1.019, 1.031, 1.038, 1.043, 1.048, 1.053, 1.055, 1.058, 1.061, 1.062, 1.064, 1.065, 1.065, 1.063, 1.063, 1.064, 1.064, 1.064, 1.065, 1.066, 1.067, 1.065, 1.065, 1.063, 1.064, 1.066, 1.065, 1.066, 1.064, 1.064, 1.058, 1.057,
+                            1.023, 1.034, 1.039, 1.045, 1.053, 1.055, 1.058, 1.059, 1.062, 1.063, 1.065, 1.066, 1.066, 1.065, 1.064, 1.065, 1.065, 1.065, 1.066, 1.066, 1.069, 1.068, 1.067, 1.065, 1.066, 1.066, 1.067, 1.067, 1.066, 1.065, 1.061, 1.057,
+                            1.024, 1.036, 1.042, 1.046, 1.053, 1.055, 1.059, 1.061, 1.064, 1.064, 1.066, 1.068, 1.069, 1.067, 1.066, 1.066, 1.067, 1.066, 1.067, 1.068, 1.069, 1.069, 1.068, 1.067, 1.067, 1.066, 1.067, 1.067, 1.066, 1.064, 1.059, 1.057,
+                            1.024, 1.036, 1.044, 1.049, 1.054, 1.058, 1.061, 1.063, 1.065, 1.066, 1.068, 1.068, 1.069, 1.068, 1.068, 1.067, 1.068, 1.068, 1.069, 1.068, 1.069, 1.071, 1.069, 1.069, 1.067, 1.067, 1.067, 1.067, 1.065, 1.064, 1.059, 1.057,
+                            1.026, 1.039, 1.044, 1.049, 1.054, 1.059, 1.062, 1.065, 1.066, 1.068, 1.068, 1.068, 1.069, 1.068, 1.067, 1.068, 1.068, 1.069, 1.069, 1.068, 1.069, 1.069, 1.069, 1.069, 1.068, 1.067, 1.067, 1.067, 1.066, 1.063, 1.061, 1.058,
+                            1.027, 1.041, 1.047, 1.051, 1.055, 1.059, 1.062, 1.066, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.068, 1.069, 1.069, 1.069, 1.069, 1.069, 1.069, 1.069, 1.068, 1.067, 1.067, 1.065, 1.064, 1.063, 1.056,
+                            1.028, 1.039, 1.047, 1.052, 1.056, 1.059, 1.062, 1.066, 1.068, 1.068, 1.068, 1.068, 1.069, 1.069, 1.069, 1.071, 1.069, 1.069, 1.069, 1.068, 1.068, 1.068, 1.069, 1.069, 1.069, 1.068, 1.067, 1.067, 1.066, 1.065, 1.064, 1.056,
+                            1.033, 1.042, 1.049, 1.055, 1.057, 1.061, 1.063, 1.066, 1.067, 1.068, 1.068, 1.068, 1.069, 1.071, 1.071, 1.071, 1.069, 1.069, 1.071, 1.071, 1.071, 1.069, 1.069, 1.069, 1.069, 1.069, 1.068, 1.066, 1.066, 1.066, 1.065, 1.055,
+                            1.033, 1.046, 1.049, 1.055, 1.058, 1.061, 1.063, 1.065, 1.067, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.069, 1.071, 1.069, 1.069, 1.068, 1.068, 1.067, 1.065, 1.058,
+                            1.034, 1.047, 1.052, 1.055, 1.057, 1.061, 1.063, 1.066, 1.068, 1.069, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.071, 1.072, 1.073, 1.073, 1.072, 1.071, 1.071, 1.071, 1.071, 1.069, 1.068, 1.068, 1.065, 1.058,
+                            1.037, 1.048, 1.053, 1.055, 1.058, 1.061, 1.064, 1.067, 1.069, 1.069, 1.068, 1.069, 1.069, 1.071, 1.071, 1.073, 1.072, 1.072, 1.071, 1.073, 1.073, 1.073, 1.073, 1.073, 1.072, 1.071, 1.071, 1.071, 1.069, 1.067, 1.066, 1.058,
+                            1.038, 1.049, 1.053, 1.056, 1.058, 1.061, 1.066, 1.068, 1.069, 1.069, 1.068, 1.068, 1.069, 1.071, 1.072, 1.072, 1.072, 1.071, 1.073, 1.073, 1.074, 1.073, 1.074, 1.073, 1.073, 1.072, 1.072, 1.071, 1.069, 1.067, 1.066, 1.056,
+                            1.038, 1.049, 1.052, 1.057, 1.059, 1.062, 1.066, 1.068, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.072, 1.072, 1.072, 1.073, 1.074, 1.074, 1.075, 1.074, 1.075, 1.075, 1.074, 1.072, 1.072, 1.072, 1.072, 1.068, 1.066, 1.058,
+                            1.039, 1.049, 1.053, 1.058, 1.061, 1.064, 1.066, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.073, 1.075, 1.075, 1.075, 1.074, 1.075, 1.074, 1.074, 1.073, 1.074, 1.074, 1.073, 1.071, 1.066, 1.058,
+                            1.041, 1.049, 1.055, 1.059, 1.061, 1.064, 1.066, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.072, 1.073, 1.074, 1.074, 1.074, 1.074, 1.075, 1.075, 1.075, 1.075, 1.075, 1.075, 1.073, 1.071, 1.067, 1.058,
+                            1.043, 1.052, 1.057, 1.059, 1.062, 1.065, 1.067, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.073, 1.074, 1.074, 1.073, 1.074, 1.075, 1.075, 1.075, 1.076, 1.076, 1.075, 1.074, 1.071, 1.067, 1.057,
+                            1.048, 1.054, 1.058, 1.061, 1.063, 1.065, 1.066, 1.069, 1.069, 1.071, 1.071, 1.072, 1.073, 1.072, 1.072, 1.072, 1.072, 1.073, 1.073, 1.073, 1.073, 1.074, 1.076, 1.076, 1.076, 1.077, 1.077, 1.076, 1.073, 1.072, 1.067, 1.059,
+                            1.048, 1.055, 1.059, 1.063, 1.063, 1.066, 1.067, 1.069, 1.071, 1.071, 1.072, 1.073, 1.073, 1.071, 1.071, 1.071, 1.072, 1.073, 1.073, 1.073, 1.073, 1.074, 1.075, 1.075, 1.076, 1.077, 1.079, 1.076, 1.075, 1.074, 1.068, 1.063,
+                            1.048, 1.058, 1.063, 1.064, 1.065, 1.066, 1.067, 1.069, 1.069, 1.071, 1.071, 1.073, 1.073, 1.072, 1.072, 1.072, 1.072, 1.072, 1.073, 1.073, 1.075, 1.075, 1.076, 1.076, 1.078, 1.078, 1.079, 1.078, 1.075, 1.072, 1.068, 1.063,
+                            1.049, 1.059, 1.064, 1.066, 1.066, 1.068, 1.069, 1.071, 1.069, 1.071, 1.072, 1.072, 1.072, 1.072, 1.071, 1.072, 1.072, 1.072, 1.072, 1.074, 1.076, 1.075, 1.077, 1.077, 1.079, 1.079, 1.081, 1.078, 1.076, 1.073, 1.068, 1.063,
+                            1.053, 1.059, 1.065, 1.068, 1.068, 1.069, 1.071, 1.071, 1.069, 1.073, 1.072, 1.073, 1.072, 1.072, 1.071, 1.072, 1.074, 1.072, 1.072, 1.074, 1.075, 1.074, 1.076, 1.076, 1.079, 1.079, 1.079, 1.079, 1.077, 1.073, 1.068, 1.061,
+                            1.054, 1.062, 1.066, 1.069, 1.069, 1.071, 1.071, 1.072, 1.069, 1.072, 1.072, 1.073, 1.072, 1.072, 1.069, 1.069, 1.071, 1.071, 1.072, 1.074, 1.073, 1.073, 1.074, 1.076, 1.079, 1.079, 1.081, 1.079, 1.078, 1.074, 1.071, 1.063,
+                            1.055, 1.062, 1.066, 1.069, 1.069, 1.069, 1.069, 1.071, 1.071, 1.072, 1.072, 1.073, 1.073, 1.071, 1.069, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.078, 1.081, 1.082, 1.079, 1.076, 1.074, 1.069, 1.063,
+                            1.055, 1.064, 1.066, 1.068, 1.068, 1.069, 1.069, 1.069, 1.069, 1.071, 1.071, 1.072, 1.072, 1.071, 1.068, 1.067, 1.068, 1.067, 1.067, 1.067, 1.067, 1.068, 1.068, 1.071, 1.075, 1.078, 1.082, 1.077, 1.076, 1.071, 1.065, 1.061,
+                            1.055, 1.059, 1.064, 1.067, 1.068, 1.067, 1.068, 1.067, 1.066, 1.066, 1.067, 1.069, 1.068, 1.067, 1.064, 1.064, 1.061, 1.063, 1.062, 1.062, 1.062, 1.061, 1.063, 1.063, 1.066, 1.071, 1.075, 1.073, 1.069, 1.065, 1.061, 1.055,
+                            1.052, 1.057, 1.063, 1.063, 1.063, 1.059, 1.061, 1.061, 1.061, 1.061, 1.061, 1.063, 1.063, 1.059, 1.057, 1.057, 1.054, 1.055, 1.055, 1.055, 1.055, 1.057, 1.057, 1.057, 1.061, 1.066, 1.066, 1.066, 1.059, 1.057, 1.054, 1.054
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.001, 1.008, 1.019, 1.024, 1.035, 1.044, 1.046, 1.053, 1.059, 1.061, 1.063, 1.063, 1.063, 1.069, 1.069, 1.071, 1.069, 1.072, 1.075, 1.076, 1.079, 1.081, 1.081, 1.083, 1.085, 1.086, 1.086, 1.086, 1.085, 1.085, 1.085, 1.084,
+                            1.005, 1.015, 1.024, 1.035, 1.042, 1.048, 1.053, 1.061, 1.064, 1.066, 1.067, 1.069, 1.071, 1.073, 1.074, 1.076, 1.079, 1.077, 1.079, 1.081, 1.082, 1.084, 1.084, 1.089, 1.091, 1.091, 1.093, 1.092, 1.093, 1.091, 1.089, 1.089,
+                            1.012, 1.022, 1.035, 1.042, 1.049, 1.055, 1.062, 1.071, 1.071, 1.074, 1.074, 1.076, 1.078, 1.079, 1.082, 1.083, 1.083, 1.084, 1.085, 1.088, 1.089, 1.091, 1.092, 1.092, 1.095, 1.095, 1.095, 1.097, 1.095, 1.095, 1.091, 1.089,
+                            1.015, 1.028, 1.041, 1.048, 1.054, 1.061, 1.069, 1.071, 1.074, 1.077, 1.079, 1.081, 1.082, 1.084, 1.086, 1.086, 1.087, 1.088, 1.089, 1.091, 1.093, 1.093, 1.094, 1.094, 1.096, 1.097, 1.096, 1.097, 1.095, 1.095, 1.092, 1.089,
+                            1.018, 1.032, 1.042, 1.053, 1.058, 1.068, 1.073, 1.076, 1.079, 1.081, 1.084, 1.084, 1.087, 1.089, 1.089, 1.091, 1.091, 1.091, 1.092, 1.093, 1.096, 1.095, 1.094, 1.094, 1.097, 1.099, 1.099, 1.099, 1.097, 1.096, 1.093, 1.089,
+                            1.027, 1.036, 1.047, 1.055, 1.067, 1.071, 1.075, 1.079, 1.082, 1.085, 1.087, 1.088, 1.089, 1.091, 1.091, 1.094, 1.095, 1.095, 1.096, 1.097, 1.097, 1.096, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.099, 1.098, 1.094, 1.089,
+                            1.028, 1.041, 1.051, 1.058, 1.071, 1.074, 1.077, 1.081, 1.087, 1.088, 1.089, 1.092, 1.092, 1.093, 1.093, 1.095, 1.094, 1.097, 1.099, 1.099, 1.099, 1.098, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.101, 1.095, 1.089,
+                            1.033, 1.046, 1.056, 1.065, 1.071, 1.075, 1.081, 1.084, 1.087, 1.091, 1.092, 1.095, 1.096, 1.096, 1.095, 1.096, 1.097, 1.098, 1.099, 1.101, 1.101, 1.101, 1.101, 1.099, 1.099, 1.101, 1.101, 1.099, 1.099, 1.098, 1.094, 1.089,
+                            1.037, 1.049, 1.059, 1.066, 1.073, 1.077, 1.084, 1.089, 1.089, 1.092, 1.095, 1.096, 1.096, 1.096, 1.096, 1.096, 1.097, 1.098, 1.099, 1.099, 1.101, 1.102, 1.101, 1.101, 1.101, 1.102, 1.101, 1.101, 1.099, 1.098, 1.094, 1.088,
+                            1.037, 1.049, 1.062, 1.066, 1.075, 1.082, 1.086, 1.089, 1.092, 1.095, 1.096, 1.097, 1.097, 1.096, 1.096, 1.097, 1.098, 1.099, 1.101, 1.101, 1.102, 1.102, 1.102, 1.103, 1.103, 1.103, 1.102, 1.101, 1.099, 1.098, 1.093, 1.087,
+                            1.048, 1.056, 1.063, 1.069, 1.077, 1.083, 1.089, 1.091, 1.093, 1.096, 1.097, 1.097, 1.097, 1.098, 1.098, 1.099, 1.101, 1.101, 1.102, 1.103, 1.102, 1.103, 1.102, 1.104, 1.104, 1.101, 1.101, 1.099, 1.099, 1.096, 1.092, 1.087,
+                            1.048, 1.058, 1.068, 1.073, 1.081, 1.085, 1.089, 1.091, 1.094, 1.097, 1.097, 1.099, 1.097, 1.099, 1.099, 1.099, 1.101, 1.101, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.102, 1.101, 1.101, 1.099, 1.097, 1.095, 1.092, 1.085,
+                            1.048, 1.059, 1.068, 1.075, 1.083, 1.085, 1.091, 1.093, 1.095, 1.098, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.102, 1.101, 1.103, 1.103, 1.103, 1.103, 1.102, 1.102, 1.102, 1.101, 1.101, 1.099, 1.098, 1.094, 1.091, 1.085,
+                            1.048, 1.061, 1.071, 1.078, 1.084, 1.085, 1.088, 1.094, 1.097, 1.099, 1.099, 1.099, 1.101, 1.101, 1.101, 1.101, 1.102, 1.101, 1.103, 1.103, 1.103, 1.103, 1.101, 1.102, 1.102, 1.102, 1.101, 1.098, 1.096, 1.094, 1.091, 1.082,
+                            1.059, 1.067, 1.075, 1.078, 1.084, 1.087, 1.092, 1.094, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.101, 1.103, 1.103, 1.102, 1.103, 1.103, 1.102, 1.101, 1.101, 1.102, 1.103, 1.103, 1.101, 1.099, 1.097, 1.095, 1.091, 1.082,
+                            1.061, 1.071, 1.076, 1.082, 1.086, 1.089, 1.092, 1.096, 1.098, 1.099, 1.101, 1.101, 1.102, 1.102, 1.103, 1.102, 1.102, 1.102, 1.103, 1.103, 1.103, 1.103, 1.102, 1.102, 1.103, 1.103, 1.102, 1.099, 1.097, 1.094, 1.091, 1.079,
+                            1.061, 1.071, 1.078, 1.082, 1.087, 1.091, 1.093, 1.097, 1.099, 1.099, 1.099, 1.101, 1.103, 1.103, 1.103, 1.103, 1.102, 1.102, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.103, 1.099, 1.099, 1.093, 1.091, 1.079,
+                            1.064, 1.074, 1.079, 1.085, 1.088, 1.093, 1.095, 1.098, 1.099, 1.099, 1.101, 1.099, 1.101, 1.103, 1.103, 1.103, 1.103, 1.102, 1.103, 1.103, 1.104, 1.104, 1.105, 1.104, 1.104, 1.103, 1.102, 1.101, 1.099, 1.093, 1.091, 1.078,
+                            1.066, 1.074, 1.076, 1.086, 1.091, 1.094, 1.097, 1.099, 1.099, 1.099, 1.101, 1.102, 1.103, 1.103, 1.104, 1.102, 1.103, 1.103, 1.104, 1.104, 1.105, 1.105, 1.105, 1.105, 1.105, 1.103, 1.102, 1.101, 1.098, 1.094, 1.088, 1.077,
+                            1.066, 1.074, 1.081, 1.087, 1.091, 1.095, 1.097, 1.099, 1.101, 1.102, 1.104, 1.104, 1.104, 1.103, 1.102, 1.102, 1.103, 1.105, 1.105, 1.105, 1.105, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.101, 1.099, 1.096, 1.088, 1.074,
+                            1.067, 1.076, 1.082, 1.088, 1.092, 1.095, 1.101, 1.101, 1.102, 1.103, 1.103, 1.104, 1.104, 1.104, 1.103, 1.103, 1.103, 1.105, 1.105, 1.106, 1.106, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.101, 1.099, 1.094, 1.087, 1.073,
+                            1.071, 1.079, 1.083, 1.089, 1.092, 1.096, 1.099, 1.102, 1.103, 1.103, 1.102, 1.104, 1.104, 1.104, 1.103, 1.103, 1.105, 1.105, 1.106, 1.106, 1.107, 1.105, 1.105, 1.104, 1.103, 1.103, 1.102, 1.101, 1.098, 1.094, 1.087, 1.072,
+                            1.076, 1.082, 1.086, 1.091, 1.093, 1.098, 1.101, 1.101, 1.102, 1.102, 1.102, 1.104, 1.104, 1.104, 1.104, 1.105, 1.105, 1.105, 1.106, 1.106, 1.107, 1.105, 1.105, 1.105, 1.103, 1.102, 1.102, 1.099, 1.097, 1.094, 1.085, 1.073,
+                            1.076, 1.083, 1.089, 1.092, 1.095, 1.097, 1.099, 1.101, 1.101, 1.102, 1.103, 1.104, 1.105, 1.104, 1.103, 1.104, 1.104, 1.105, 1.105, 1.105, 1.105, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.099, 1.097, 1.094, 1.084, 1.074,
+                            1.079, 1.084, 1.091, 1.094, 1.096, 1.098, 1.101, 1.101, 1.102, 1.102, 1.103, 1.105, 1.107, 1.105, 1.105, 1.105, 1.104, 1.104, 1.104, 1.104, 1.104, 1.105, 1.105, 1.104, 1.104, 1.103, 1.102, 1.099, 1.096, 1.092, 1.084, 1.074,
+                            1.078, 1.088, 1.092, 1.096, 1.097, 1.101, 1.101, 1.101, 1.103, 1.103, 1.103, 1.106, 1.106, 1.105, 1.103, 1.103, 1.103, 1.104, 1.104, 1.104, 1.104, 1.104, 1.105, 1.105, 1.104, 1.103, 1.102, 1.098, 1.095, 1.092, 1.082, 1.071,
+                            1.082, 1.091, 1.092, 1.097, 1.099, 1.101, 1.102, 1.102, 1.103, 1.103, 1.104, 1.104, 1.104, 1.104, 1.102, 1.101, 1.101, 1.102, 1.103, 1.103, 1.103, 1.103, 1.104, 1.104, 1.102, 1.102, 1.101, 1.098, 1.095, 1.089, 1.082, 1.068,
+                            1.084, 1.091, 1.094, 1.098, 1.101, 1.102, 1.103, 1.103, 1.103, 1.103, 1.101, 1.103, 1.101, 1.102, 1.101, 1.101, 1.101, 1.099, 1.102, 1.101, 1.101, 1.101, 1.102, 1.103, 1.102, 1.099, 1.098, 1.096, 1.092, 1.086, 1.079, 1.067,
+                            1.084, 1.091, 1.095, 1.099, 1.101, 1.102, 1.103, 1.103, 1.103, 1.102, 1.101, 1.102, 1.101, 1.099, 1.099, 1.099, 1.098, 1.097, 1.097, 1.095, 1.095, 1.094, 1.094, 1.096, 1.096, 1.096, 1.095, 1.092, 1.087, 1.083, 1.076, 1.067,
+                            1.084, 1.092, 1.096, 1.099, 1.099, 1.101, 1.101, 1.102, 1.101, 1.099, 1.098, 1.098, 1.098, 1.097, 1.097, 1.097, 1.097, 1.095, 1.091, 1.091, 1.091, 1.089, 1.089, 1.091, 1.092, 1.091, 1.091, 1.087, 1.083, 1.076, 1.069, 1.061,
+                            1.084, 1.091, 1.094, 1.095, 1.098, 1.099, 1.099, 1.099, 1.099, 1.096, 1.095, 1.095, 1.094, 1.093, 1.093, 1.091, 1.087, 1.088, 1.086, 1.086, 1.084, 1.079, 1.079, 1.082, 1.085, 1.085, 1.081, 1.078, 1.076, 1.069, 1.059, 1.054,
+                            1.087, 1.087, 1.094, 1.095, 1.094, 1.094, 1.096, 1.095, 1.095, 1.092, 1.089, 1.089, 1.088, 1.087, 1.085, 1.081, 1.082, 1.082, 1.081, 1.077, 1.074, 1.073, 1.071, 1.074, 1.077, 1.077, 1.074, 1.074, 1.069, 1.062, 1.054, 1.048
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.001, 1.002, 1.016, 1.027, 1.033, 1.045, 1.052, 1.054, 1.061, 1.065, 1.068, 1.067, 1.069, 1.073, 1.073, 1.077, 1.078, 1.081, 1.087, 1.092, 1.092, 1.095, 1.097, 1.099, 1.101, 1.105, 1.111, 1.112, 1.114, 1.115, 1.121, 1.124,
+                            1.001, 1.014, 1.027, 1.033, 1.043, 1.053, 1.057, 1.061, 1.068, 1.071, 1.071, 1.075, 1.075, 1.076, 1.079, 1.082, 1.084, 1.086, 1.089, 1.092, 1.092, 1.094, 1.097, 1.101, 1.104, 1.108, 1.112, 1.112, 1.115, 1.117, 1.119, 1.122,
+                            1.004, 1.021, 1.031, 1.041, 1.053, 1.058, 1.062, 1.071, 1.073, 1.077, 1.079, 1.082, 1.081, 1.084, 1.084, 1.085, 1.086, 1.089, 1.091, 1.092, 1.093, 1.096, 1.099, 1.102, 1.106, 1.109, 1.112, 1.114, 1.116, 1.118, 1.121, 1.121,
+                            1.013, 1.021, 1.036, 1.045, 1.058, 1.064, 1.071, 1.074, 1.078, 1.082, 1.082, 1.084, 1.084, 1.085, 1.087, 1.087, 1.089, 1.091, 1.093, 1.095, 1.095, 1.097, 1.099, 1.104, 1.105, 1.108, 1.111, 1.115, 1.116, 1.117, 1.119, 1.121,
+                            1.015, 1.028, 1.041, 1.052, 1.061, 1.068, 1.074, 1.078, 1.081, 1.084, 1.083, 1.085, 1.085, 1.086, 1.088, 1.089, 1.091, 1.091, 1.094, 1.096, 1.096, 1.098, 1.099, 1.099, 1.104, 1.107, 1.109, 1.112, 1.116, 1.117, 1.117, 1.119,
+                            1.024, 1.029, 1.047, 1.053, 1.064, 1.071, 1.076, 1.081, 1.083, 1.086, 1.086, 1.087, 1.086, 1.089, 1.089, 1.091, 1.092, 1.092, 1.095, 1.096, 1.097, 1.098, 1.099, 1.099, 1.101, 1.105, 1.108, 1.111, 1.115, 1.116, 1.116, 1.114,
+                            1.024, 1.034, 1.051, 1.057, 1.066, 1.075, 1.078, 1.081, 1.085, 1.087, 1.087, 1.088, 1.089, 1.091, 1.091, 1.091, 1.089, 1.091, 1.091, 1.094, 1.096, 1.097, 1.098, 1.099, 1.103, 1.104, 1.107, 1.108, 1.112, 1.113, 1.114, 1.113,
+                            1.029, 1.042, 1.053, 1.059, 1.071, 1.076, 1.078, 1.082, 1.087, 1.087, 1.088, 1.089, 1.089, 1.089, 1.088, 1.088, 1.089, 1.089, 1.093, 1.094, 1.096, 1.097, 1.098, 1.098, 1.103, 1.103, 1.106, 1.108, 1.109, 1.111, 1.111, 1.108,
+                            1.033, 1.046, 1.057, 1.066, 1.074, 1.077, 1.079, 1.083, 1.087, 1.088, 1.089, 1.089, 1.089, 1.088, 1.086, 1.086, 1.088, 1.089, 1.091, 1.094, 1.095, 1.095, 1.098, 1.099, 1.103, 1.103, 1.103, 1.104, 1.108, 1.107, 1.107, 1.106,
+                            1.037, 1.051, 1.061, 1.071, 1.076, 1.081, 1.084, 1.085, 1.087, 1.086, 1.089, 1.088, 1.089, 1.087, 1.086, 1.087, 1.089, 1.091, 1.092, 1.093, 1.095, 1.096, 1.097, 1.098, 1.099, 1.101, 1.103, 1.105, 1.106, 1.107, 1.106, 1.105,
+                            1.043, 1.054, 1.065, 1.071, 1.076, 1.083, 1.085, 1.086, 1.087, 1.088, 1.088, 1.088, 1.088, 1.087, 1.087, 1.085, 1.086, 1.089, 1.092, 1.093, 1.093, 1.094, 1.097, 1.097, 1.098, 1.099, 1.102, 1.103, 1.103, 1.104, 1.104, 1.101,
+                            1.047, 1.059, 1.067, 1.072, 1.079, 1.084, 1.085, 1.087, 1.087, 1.087, 1.086, 1.088, 1.087, 1.087, 1.086, 1.086, 1.086, 1.089, 1.089, 1.091, 1.091, 1.093, 1.094, 1.095, 1.095, 1.097, 1.099, 1.102, 1.102, 1.103, 1.101, 1.098,
+                            1.049, 1.062, 1.069, 1.074, 1.079, 1.083, 1.086, 1.088, 1.088, 1.089, 1.088, 1.088, 1.087, 1.088, 1.087, 1.087, 1.086, 1.087, 1.088, 1.089, 1.089, 1.091, 1.093, 1.095, 1.097, 1.096, 1.098, 1.098, 1.101, 1.101, 1.099, 1.096,
+                            1.051, 1.062, 1.069, 1.077, 1.082, 1.084, 1.086, 1.087, 1.089, 1.088, 1.088, 1.088, 1.087, 1.088, 1.087, 1.086, 1.086, 1.086, 1.087, 1.088, 1.089, 1.091, 1.093, 1.094, 1.095, 1.096, 1.096, 1.098, 1.101, 1.101, 1.097, 1.094,
+                            1.057, 1.064, 1.076, 1.082, 1.084, 1.086, 1.086, 1.087, 1.089, 1.088, 1.088, 1.088, 1.088, 1.088, 1.088, 1.087, 1.086, 1.086, 1.086, 1.087, 1.088, 1.089, 1.092, 1.095, 1.097, 1.097, 1.097, 1.097, 1.099, 1.098, 1.095, 1.089,
+                            1.063, 1.072, 1.079, 1.083, 1.086, 1.087, 1.089, 1.089, 1.089, 1.089, 1.088, 1.089, 1.087, 1.087, 1.087, 1.087, 1.086, 1.086, 1.087, 1.087, 1.089, 1.089, 1.092, 1.094, 1.094, 1.097, 1.097, 1.097, 1.097, 1.097, 1.094, 1.088,
+                            1.066, 1.079, 1.084, 1.085, 1.086, 1.088, 1.089, 1.089, 1.089, 1.091, 1.089, 1.089, 1.088, 1.088, 1.087, 1.087, 1.086, 1.087, 1.088, 1.089, 1.089, 1.089, 1.092, 1.095, 1.096, 1.098, 1.097, 1.097, 1.097, 1.097, 1.093, 1.087,
+                            1.075, 1.079, 1.085, 1.087, 1.088, 1.089, 1.091, 1.091, 1.092, 1.092, 1.092, 1.089, 1.088, 1.089, 1.087, 1.087, 1.086, 1.087, 1.089, 1.089, 1.089, 1.091, 1.093, 1.097, 1.097, 1.097, 1.097, 1.098, 1.097, 1.097, 1.092, 1.085,
+                            1.076, 1.082, 1.086, 1.089, 1.091, 1.093, 1.095, 1.094, 1.092, 1.092, 1.092, 1.091, 1.091, 1.089, 1.089, 1.088, 1.088, 1.089, 1.089, 1.091, 1.092, 1.093, 1.093, 1.097, 1.097, 1.097, 1.097, 1.098, 1.098, 1.096, 1.089, 1.081,
+                            1.077, 1.085, 1.089, 1.092, 1.094, 1.095, 1.096, 1.096, 1.096, 1.095, 1.094, 1.092, 1.092, 1.089, 1.088, 1.089, 1.091, 1.089, 1.091, 1.091, 1.093, 1.093, 1.095, 1.096, 1.098, 1.098, 1.097, 1.098, 1.098, 1.093, 1.089, 1.081,
+                            1.082, 1.086, 1.092, 1.095, 1.097, 1.097, 1.098, 1.096, 1.097, 1.096, 1.094, 1.093, 1.093, 1.092, 1.089, 1.091, 1.091, 1.092, 1.092, 1.093, 1.094, 1.094, 1.095, 1.096, 1.097, 1.098, 1.099, 1.097, 1.096, 1.094, 1.089, 1.079,
+                            1.087, 1.091, 1.096, 1.097, 1.099, 1.098, 1.101, 1.099, 1.099, 1.097, 1.096, 1.095, 1.095, 1.095, 1.091, 1.093, 1.092, 1.093, 1.093, 1.093, 1.094, 1.095, 1.095, 1.097, 1.098, 1.101, 1.101, 1.099, 1.097, 1.094, 1.091, 1.077,
+                            1.092, 1.094, 1.099, 1.099, 1.102, 1.102, 1.103, 1.103, 1.101, 1.098, 1.097, 1.097, 1.097, 1.097, 1.096, 1.096, 1.095, 1.094, 1.094, 1.094, 1.094, 1.094, 1.095, 1.097, 1.098, 1.101, 1.101, 1.099, 1.098, 1.094, 1.088, 1.076,
+                            1.097, 1.101, 1.103, 1.105, 1.106, 1.106, 1.105, 1.104, 1.103, 1.101, 1.099, 1.099, 1.099, 1.098, 1.097, 1.097, 1.097, 1.097, 1.096, 1.094, 1.095, 1.095, 1.096, 1.097, 1.098, 1.101, 1.101, 1.099, 1.096, 1.094, 1.087, 1.078,
+                            1.101, 1.106, 1.107, 1.108, 1.109, 1.106, 1.106, 1.105, 1.105, 1.102, 1.103, 1.103, 1.102, 1.099, 1.099, 1.098, 1.098, 1.096, 1.096, 1.095, 1.096, 1.095, 1.095, 1.097, 1.098, 1.101, 1.101, 1.098, 1.095, 1.092, 1.084, 1.079,
+                            1.108, 1.109, 1.114, 1.114, 1.112, 1.112, 1.111, 1.112, 1.108, 1.106, 1.105, 1.106, 1.104, 1.101, 1.098, 1.098, 1.098, 1.098, 1.097, 1.096, 1.096, 1.096, 1.097, 1.098, 1.099, 1.099, 1.099, 1.096, 1.095, 1.091, 1.084, 1.079,
+                            1.111, 1.115, 1.116, 1.117, 1.116, 1.113, 1.113, 1.113, 1.111, 1.108, 1.107, 1.107, 1.105, 1.103, 1.099, 1.098, 1.098, 1.098, 1.097, 1.096, 1.096, 1.096, 1.097, 1.097, 1.098, 1.098, 1.097, 1.096, 1.093, 1.091, 1.084, 1.074,
+                            1.115, 1.119, 1.123, 1.122, 1.118, 1.117, 1.114, 1.115, 1.113, 1.108, 1.107, 1.106, 1.106, 1.102, 1.098, 1.098, 1.097, 1.097, 1.096, 1.096, 1.096, 1.093, 1.096, 1.096, 1.097, 1.097, 1.095, 1.094, 1.093, 1.091, 1.084, 1.071,
+                            1.123, 1.126, 1.127, 1.127, 1.124, 1.119, 1.117, 1.115, 1.116, 1.112, 1.107, 1.106, 1.106, 1.101, 1.098, 1.097, 1.097, 1.096, 1.095, 1.094, 1.093, 1.093, 1.092, 1.093, 1.093, 1.092, 1.092, 1.091, 1.091, 1.085, 1.076, 1.069,
+                            1.126, 1.128, 1.129, 1.129, 1.128, 1.124, 1.119, 1.117, 1.117, 1.116, 1.107, 1.106, 1.106, 1.103, 1.098, 1.097, 1.096, 1.095, 1.093, 1.089, 1.089, 1.086, 1.086, 1.085, 1.085, 1.085, 1.084, 1.081, 1.081, 1.078, 1.072, 1.065,
+                            1.127, 1.129, 1.131, 1.131, 1.128, 1.126, 1.123, 1.117, 1.117, 1.114, 1.113, 1.107, 1.105, 1.101, 1.097, 1.094, 1.092, 1.088, 1.086, 1.084, 1.081, 1.078, 1.079, 1.081, 1.082, 1.081, 1.079, 1.078, 1.076, 1.071, 1.062, 1.053,
+                            1.128, 1.131, 1.131, 1.131, 1.127, 1.126, 1.118, 1.118, 1.116, 1.114, 1.114, 1.106, 1.103, 1.101, 1.094, 1.092, 1.086, 1.084, 1.083, 1.079, 1.077, 1.076, 1.071, 1.069, 1.072, 1.072, 1.074, 1.073, 1.071, 1.064, 1.053, 1.052
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.001, 1.019, 1.033, 1.061, 1.077, 1.092, 1.113, 1.124, 1.133, 1.144, 1.145, 1.153, 1.162, 1.167, 1.181, 1.181, 1.191, 1.194, 1.201, 1.212, 1.214, 1.215, 1.222, 1.227, 1.233, 1.234, 1.236, 1.237, 1.241, 1.239, 1.233, 1.232,
+                            1.008, 1.027, 1.052, 1.069, 1.084, 1.102, 1.118, 1.133, 1.138, 1.148, 1.151, 1.163, 1.167, 1.179, 1.182, 1.189, 1.193, 1.198, 1.209, 1.214, 1.217, 1.221, 1.226, 1.231, 1.234, 1.236, 1.236, 1.239, 1.238, 1.239, 1.235, 1.232,
+                            1.021, 1.034, 1.064, 1.079, 1.101, 1.114, 1.129, 1.137, 1.149, 1.158, 1.165, 1.172, 1.181, 1.183, 1.191, 1.194, 1.199, 1.204, 1.212, 1.222, 1.222, 1.225, 1.229, 1.232, 1.239, 1.241, 1.241, 1.241, 1.242, 1.239, 1.235, 1.232,
+                            1.027, 1.043, 1.072, 1.084, 1.114, 1.123, 1.136, 1.149, 1.161, 1.167, 1.174, 1.181, 1.188, 1.191, 1.197, 1.202, 1.205, 1.209, 1.221, 1.225, 1.227, 1.227, 1.233, 1.238, 1.241, 1.242, 1.242, 1.243, 1.241, 1.239, 1.236, 1.233,
+                            1.038, 1.057, 1.079, 1.098, 1.116, 1.133, 1.149, 1.161, 1.165, 1.174, 1.179, 1.187, 1.192, 1.203, 1.207, 1.208, 1.213, 1.219, 1.228, 1.228, 1.229, 1.233, 1.235, 1.243, 1.244, 1.244, 1.244, 1.244, 1.243, 1.241, 1.237, 1.233,
+                            1.045, 1.071, 1.089, 1.107, 1.128, 1.139, 1.153, 1.164, 1.174, 1.181, 1.187, 1.193, 1.204, 1.207, 1.209, 1.213, 1.218, 1.221, 1.227, 1.231, 1.234, 1.236, 1.241, 1.243, 1.244, 1.246, 1.245, 1.245, 1.244, 1.241, 1.237, 1.232,
+                            1.059, 1.074, 1.094, 1.121, 1.131, 1.147, 1.161, 1.173, 1.181, 1.185, 1.194, 1.205, 1.208, 1.209, 1.213, 1.217, 1.219, 1.227, 1.229, 1.232, 1.237, 1.242, 1.243, 1.245, 1.246, 1.247, 1.245, 1.246, 1.245, 1.243, 1.235, 1.227,
+                            1.071, 1.079, 1.102, 1.121, 1.136, 1.152, 1.165, 1.179, 1.184, 1.195, 1.199, 1.208, 1.209, 1.212, 1.215, 1.222, 1.226, 1.228, 1.229, 1.234, 1.242, 1.244, 1.246, 1.247, 1.247, 1.247, 1.246, 1.247, 1.246, 1.241, 1.231, 1.224,
+                            1.072, 1.091, 1.106, 1.129, 1.144, 1.159, 1.171, 1.184, 1.192, 1.199, 1.206, 1.213, 1.216, 1.218, 1.222, 1.226, 1.229, 1.231, 1.233, 1.236, 1.242, 1.244, 1.249, 1.248, 1.249, 1.248, 1.247, 1.246, 1.245, 1.239, 1.226, 1.221,
+                            1.074, 1.092, 1.112, 1.129, 1.145, 1.164, 1.177, 1.191, 1.197, 1.203, 1.208, 1.216, 1.218, 1.221, 1.223, 1.227, 1.235, 1.233, 1.237, 1.238, 1.243, 1.247, 1.249, 1.249, 1.248, 1.246, 1.244, 1.244, 1.242, 1.236, 1.226, 1.214,
+                            1.087, 1.102, 1.122, 1.139, 1.154, 1.167, 1.186, 1.196, 1.201, 1.207, 1.211, 1.217, 1.219, 1.222, 1.226, 1.228, 1.234, 1.235, 1.238, 1.239, 1.243, 1.247, 1.249, 1.248, 1.248, 1.244, 1.244, 1.244, 1.243, 1.231, 1.227, 1.212,
+                            1.093, 1.114, 1.128, 1.146, 1.165, 1.171, 1.192, 1.197, 1.203, 1.209, 1.211, 1.219, 1.221, 1.223, 1.227, 1.229, 1.233, 1.235, 1.237, 1.241, 1.246, 1.251, 1.252, 1.251, 1.248, 1.243, 1.243, 1.239, 1.236, 1.231, 1.226, 1.209,
+                            1.106, 1.121, 1.138, 1.154, 1.165, 1.179, 1.195, 1.198, 1.207, 1.211, 1.217, 1.221, 1.224, 1.227, 1.229, 1.229, 1.231, 1.234, 1.238, 1.241, 1.246, 1.251, 1.251, 1.251, 1.249, 1.244, 1.242, 1.241, 1.236, 1.233, 1.219, 1.204,
+                            1.115, 1.122, 1.142, 1.154, 1.168, 1.182, 1.196, 1.203, 1.208, 1.211, 1.219, 1.222, 1.227, 1.228, 1.229, 1.229, 1.232, 1.236, 1.239, 1.241, 1.247, 1.251, 1.249, 1.249, 1.246, 1.244, 1.242, 1.237, 1.233, 1.227, 1.215, 1.197,
+                            1.121, 1.133, 1.143, 1.162, 1.173, 1.185, 1.197, 1.204, 1.211, 1.214, 1.221, 1.224, 1.227, 1.229, 1.229, 1.228, 1.229, 1.235, 1.239, 1.241, 1.246, 1.247, 1.249, 1.249, 1.247, 1.245, 1.241, 1.235, 1.229, 1.218, 1.209, 1.194,
+                            1.128, 1.139, 1.152, 1.163, 1.178, 1.188, 1.199, 1.209, 1.212, 1.217, 1.221, 1.225, 1.227, 1.229, 1.227, 1.228, 1.228, 1.235, 1.239, 1.241, 1.244, 1.245, 1.248, 1.249, 1.245, 1.241, 1.238, 1.231, 1.223, 1.215, 1.206, 1.184,
+                            1.131, 1.146, 1.159, 1.171, 1.181, 1.189, 1.206, 1.211, 1.217, 1.219, 1.222, 1.225, 1.227, 1.229, 1.229, 1.227, 1.228, 1.233, 1.237, 1.239, 1.241, 1.244, 1.245, 1.246, 1.243, 1.235, 1.228, 1.225, 1.219, 1.211, 1.204, 1.178,
+                            1.134, 1.148, 1.165, 1.176, 1.186, 1.194, 1.205, 1.214, 1.217, 1.218, 1.221, 1.223, 1.225, 1.227, 1.228, 1.227, 1.228, 1.233, 1.236, 1.238, 1.239, 1.241, 1.242, 1.241, 1.239, 1.228, 1.225, 1.222, 1.214, 1.207, 1.198, 1.176,
+                            1.147, 1.153, 1.167, 1.179, 1.189, 1.197, 1.205, 1.213, 1.217, 1.217, 1.222, 1.224, 1.225, 1.226, 1.229, 1.228, 1.229, 1.233, 1.235, 1.234, 1.234, 1.237, 1.239, 1.238, 1.228, 1.226, 1.223, 1.221, 1.212, 1.205, 1.189, 1.164,
+                            1.153, 1.159, 1.171, 1.181, 1.192, 1.201, 1.206, 1.212, 1.216, 1.219, 1.222, 1.223, 1.225, 1.223, 1.227, 1.226, 1.229, 1.231, 1.236, 1.234, 1.234, 1.234, 1.237, 1.232, 1.228, 1.225, 1.219, 1.215, 1.207, 1.193, 1.182, 1.155,
+                            1.154, 1.163, 1.172, 1.186, 1.189, 1.198, 1.206, 1.212, 1.217, 1.221, 1.221, 1.221, 1.219, 1.221, 1.225, 1.226, 1.227, 1.227, 1.233, 1.233, 1.233, 1.229, 1.229, 1.228, 1.224, 1.219, 1.216, 1.209, 1.199, 1.186, 1.173, 1.151,
+                            1.158, 1.168, 1.176, 1.186, 1.192, 1.201, 1.205, 1.209, 1.216, 1.219, 1.221, 1.219, 1.218, 1.218, 1.222, 1.224, 1.224, 1.225, 1.227, 1.228, 1.228, 1.228, 1.228, 1.225, 1.221, 1.214, 1.211, 1.199, 1.191, 1.177, 1.163, 1.141,
+                            1.167, 1.173, 1.181, 1.184, 1.194, 1.199, 1.204, 1.209, 1.212, 1.214, 1.219, 1.219, 1.218, 1.218, 1.218, 1.218, 1.218, 1.219, 1.223, 1.225, 1.225, 1.224, 1.223, 1.219, 1.214, 1.211, 1.203, 1.192, 1.185, 1.168, 1.158, 1.133,
+                            1.168, 1.174, 1.181, 1.184, 1.194, 1.201, 1.205, 1.209, 1.209, 1.209, 1.216, 1.219, 1.219, 1.216, 1.216, 1.215, 1.217, 1.217, 1.218, 1.219, 1.219, 1.217, 1.214, 1.209, 1.208, 1.203, 1.192, 1.187, 1.177, 1.164, 1.146, 1.123,
+                            1.167, 1.175, 1.181, 1.184, 1.194, 1.199, 1.206, 1.209, 1.209, 1.209, 1.215, 1.218, 1.219, 1.214, 1.214, 1.213, 1.213, 1.213, 1.212, 1.212, 1.212, 1.212, 1.208, 1.205, 1.201, 1.191, 1.188, 1.178, 1.169, 1.149, 1.134, 1.114,
+                            1.171, 1.175, 1.181, 1.187, 1.192, 1.198, 1.204, 1.207, 1.208, 1.209, 1.211, 1.212, 1.212, 1.211, 1.209, 1.211, 1.211, 1.209, 1.206, 1.206, 1.205, 1.202, 1.201, 1.197, 1.191, 1.184, 1.178, 1.173, 1.148, 1.134, 1.121, 1.101,
+                            1.172, 1.177, 1.181, 1.188, 1.191, 1.195, 1.198, 1.204, 1.207, 1.209, 1.209, 1.209, 1.209, 1.207, 1.201, 1.201, 1.202, 1.203, 1.199, 1.197, 1.192, 1.185, 1.182, 1.181, 1.181, 1.176, 1.166, 1.148, 1.136, 1.125, 1.112, 1.089,
+                            1.172, 1.177, 1.181, 1.184, 1.189, 1.194, 1.197, 1.201, 1.206, 1.208, 1.206, 1.207, 1.203, 1.197, 1.193, 1.194, 1.194, 1.192, 1.187, 1.184, 1.179, 1.175, 1.168, 1.164, 1.163, 1.157, 1.147, 1.135, 1.127, 1.113, 1.094, 1.078,
+                            1.176, 1.178, 1.182, 1.183, 1.184, 1.191, 1.195, 1.199, 1.201, 1.204, 1.201, 1.198, 1.193, 1.189, 1.187, 1.184, 1.179, 1.181, 1.173, 1.168, 1.165, 1.162, 1.155, 1.154, 1.155, 1.143, 1.135, 1.125, 1.113, 1.098, 1.086, 1.061,
+                            1.178, 1.181, 1.186, 1.184, 1.184, 1.188, 1.192, 1.197, 1.201, 1.199, 1.195, 1.191, 1.188, 1.186, 1.183, 1.177, 1.173, 1.171, 1.164, 1.161, 1.157, 1.152, 1.144, 1.133, 1.133, 1.128, 1.122, 1.102, 1.098, 1.086, 1.062, 1.042,
+                            1.178, 1.179, 1.183, 1.186, 1.187, 1.187, 1.187, 1.189, 1.193, 1.194, 1.189, 1.184, 1.183, 1.179, 1.171, 1.169, 1.163, 1.155, 1.148, 1.145, 1.143, 1.131, 1.125, 1.111, 1.108, 1.104, 1.095, 1.087, 1.079, 1.062, 1.036, 1.019,
+                            1.172, 1.179, 1.183, 1.186, 1.187, 1.182, 1.186, 1.189, 1.189, 1.191, 1.187, 1.181, 1.179, 1.173, 1.168, 1.163, 1.155, 1.145, 1.138, 1.132, 1.124, 1.124, 1.109, 1.107, 1.101, 1.093, 1.076, 1.072, 1.062, 1.042, 1.019, 1.011
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.001, 1.014, 1.027, 1.038, 1.048, 1.061, 1.068, 1.076, 1.084, 1.088, 1.089, 1.093, 1.096, 1.102, 1.105, 1.105, 1.109, 1.113, 1.113, 1.115, 1.119, 1.121, 1.125, 1.129, 1.129, 1.133, 1.131, 1.137, 1.137, 1.132, 1.129, 1.129,
+                            1.005, 1.017, 1.031, 1.046, 1.056, 1.061, 1.074, 1.079, 1.087, 1.089, 1.093, 1.097, 1.104, 1.106, 1.108, 1.111, 1.112, 1.114, 1.118, 1.125, 1.125, 1.126, 1.128, 1.131, 1.132, 1.134, 1.135, 1.137, 1.138, 1.135, 1.131, 1.129,
+                            1.011, 1.022, 1.041, 1.051, 1.061, 1.071, 1.077, 1.085, 1.092, 1.096, 1.098, 1.104, 1.107, 1.114, 1.115, 1.115, 1.117, 1.119, 1.126, 1.127, 1.127, 1.129, 1.131, 1.132, 1.135, 1.136, 1.136, 1.138, 1.138, 1.135, 1.132, 1.129,
+                            1.017, 1.026, 1.045, 1.057, 1.066, 1.073, 1.085, 1.093, 1.097, 1.099, 1.103, 1.109, 1.113, 1.118, 1.119, 1.121, 1.121, 1.125, 1.127, 1.129, 1.131, 1.131, 1.135, 1.137, 1.136, 1.136, 1.136, 1.137, 1.136, 1.136, 1.134, 1.129,
+                            1.017, 1.033, 1.051, 1.062, 1.068, 1.081, 1.091, 1.098, 1.099, 1.103, 1.109, 1.117, 1.118, 1.121, 1.122, 1.126, 1.126, 1.128, 1.129, 1.131, 1.134, 1.135, 1.137, 1.138, 1.138, 1.139, 1.138, 1.138, 1.137, 1.138, 1.135, 1.131,
+                            1.033, 1.039, 1.051, 1.066, 1.075, 1.083, 1.094, 1.099, 1.104, 1.106, 1.115, 1.119, 1.119, 1.122, 1.127, 1.128, 1.128, 1.131, 1.131, 1.133, 1.136, 1.138, 1.138, 1.141, 1.141, 1.139, 1.138, 1.139, 1.139, 1.139, 1.136, 1.133,
+                            1.033, 1.044, 1.059, 1.071, 1.078, 1.088, 1.095, 1.101, 1.106, 1.112, 1.118, 1.119, 1.124, 1.127, 1.129, 1.131, 1.131, 1.131, 1.131, 1.133, 1.137, 1.139, 1.142, 1.144, 1.143, 1.143, 1.141, 1.141, 1.139, 1.139, 1.134, 1.132,
+                            1.035, 1.048, 1.062, 1.073, 1.079, 1.092, 1.096, 1.104, 1.111, 1.113, 1.118, 1.124, 1.126, 1.129, 1.129, 1.133, 1.134, 1.133, 1.131, 1.136, 1.139, 1.142, 1.143, 1.144, 1.143, 1.143, 1.141, 1.142, 1.141, 1.141, 1.135, 1.132,
+                            1.035, 1.049, 1.064, 1.073, 1.084, 1.094, 1.099, 1.109, 1.113, 1.115, 1.119, 1.126, 1.127, 1.129, 1.131, 1.132, 1.134, 1.135, 1.134, 1.137, 1.142, 1.146, 1.147, 1.145, 1.145, 1.145, 1.143, 1.144, 1.142, 1.141, 1.135, 1.131,
+                            1.038, 1.052, 1.064, 1.076, 1.086, 1.095, 1.106, 1.111, 1.115, 1.119, 1.123, 1.126, 1.127, 1.129, 1.132, 1.134, 1.136, 1.135, 1.135, 1.139, 1.145, 1.147, 1.147, 1.147, 1.147, 1.144, 1.142, 1.142, 1.141, 1.138, 1.132, 1.128,
+                            1.043, 1.055, 1.066, 1.078, 1.086, 1.097, 1.108, 1.114, 1.119, 1.123, 1.124, 1.125, 1.129, 1.131, 1.132, 1.133, 1.136, 1.136, 1.136, 1.138, 1.142, 1.147, 1.148, 1.148, 1.147, 1.146, 1.143, 1.143, 1.141, 1.137, 1.131, 1.124,
+                            1.049, 1.056, 1.074, 1.082, 1.091, 1.102, 1.109, 1.115, 1.121, 1.123, 1.123, 1.125, 1.131, 1.131, 1.132, 1.133, 1.136, 1.139, 1.136, 1.137, 1.142, 1.148, 1.149, 1.149, 1.149, 1.145, 1.144, 1.143, 1.141, 1.138, 1.132, 1.122,
+                            1.054, 1.059, 1.075, 1.086, 1.094, 1.103, 1.109, 1.115, 1.121, 1.124, 1.124, 1.128, 1.132, 1.132, 1.132, 1.132, 1.137, 1.139, 1.138, 1.137, 1.141, 1.148, 1.149, 1.149, 1.149, 1.147, 1.145, 1.145, 1.142, 1.138, 1.131, 1.122,
+                            1.056, 1.065, 1.076, 1.087, 1.096, 1.105, 1.111, 1.118, 1.122, 1.125, 1.127, 1.129, 1.133, 1.134, 1.133, 1.134, 1.137, 1.139, 1.137, 1.138, 1.144, 1.147, 1.151, 1.149, 1.149, 1.146, 1.146, 1.144, 1.141, 1.137, 1.131, 1.121,
+                            1.058, 1.071, 1.078, 1.088, 1.098, 1.106, 1.112, 1.121, 1.122, 1.125, 1.128, 1.131, 1.132, 1.133, 1.132, 1.133, 1.136, 1.138, 1.137, 1.139, 1.144, 1.147, 1.149, 1.149, 1.149, 1.147, 1.144, 1.144, 1.139, 1.135, 1.128, 1.121,
+                            1.066, 1.072, 1.079, 1.091, 1.098, 1.107, 1.117, 1.121, 1.123, 1.125, 1.128, 1.131, 1.131, 1.134, 1.132, 1.135, 1.136, 1.139, 1.139, 1.139, 1.142, 1.145, 1.149, 1.149, 1.149, 1.147, 1.144, 1.142, 1.138, 1.134, 1.128, 1.116,
+                            1.069, 1.075, 1.087, 1.094, 1.099, 1.109, 1.117, 1.121, 1.124, 1.126, 1.127, 1.131, 1.131, 1.132, 1.132, 1.132, 1.136, 1.139, 1.141, 1.139, 1.139, 1.145, 1.149, 1.149, 1.149, 1.146, 1.143, 1.142, 1.138, 1.132, 1.126, 1.111,
+                            1.069, 1.076, 1.092, 1.098, 1.105, 1.109, 1.117, 1.121, 1.123, 1.126, 1.128, 1.129, 1.131, 1.132, 1.132, 1.133, 1.134, 1.138, 1.139, 1.138, 1.139, 1.141, 1.148, 1.149, 1.146, 1.143, 1.142, 1.141, 1.137, 1.132, 1.127, 1.109,
+                            1.074, 1.084, 1.093, 1.099, 1.106, 1.111, 1.116, 1.122, 1.123, 1.126, 1.128, 1.128, 1.129, 1.131, 1.132, 1.133, 1.136, 1.138, 1.138, 1.138, 1.139, 1.141, 1.144, 1.146, 1.145, 1.142, 1.139, 1.138, 1.137, 1.131, 1.124, 1.104,
+                            1.078, 1.085, 1.096, 1.098, 1.105, 1.112, 1.119, 1.122, 1.124, 1.126, 1.127, 1.129, 1.131, 1.131, 1.132, 1.133, 1.136, 1.139, 1.141, 1.139, 1.138, 1.139, 1.141, 1.142, 1.144, 1.139, 1.138, 1.138, 1.134, 1.129, 1.121, 1.101,
+                            1.082, 1.086, 1.093, 1.102, 1.104, 1.108, 1.115, 1.121, 1.124, 1.126, 1.124, 1.125, 1.124, 1.128, 1.131, 1.132, 1.134, 1.137, 1.139, 1.139, 1.139, 1.139, 1.139, 1.141, 1.141, 1.138, 1.135, 1.133, 1.131, 1.122, 1.114, 1.101,
+                            1.083, 1.088, 1.097, 1.101, 1.104, 1.107, 1.115, 1.119, 1.122, 1.124, 1.124, 1.125, 1.124, 1.126, 1.127, 1.131, 1.131, 1.133, 1.138, 1.138, 1.139, 1.139, 1.139, 1.139, 1.137, 1.137, 1.133, 1.129, 1.127, 1.119, 1.111, 1.091,
+                            1.086, 1.091, 1.099, 1.101, 1.103, 1.107, 1.115, 1.117, 1.119, 1.122, 1.123, 1.125, 1.126, 1.126, 1.126, 1.129, 1.129, 1.131, 1.133, 1.136, 1.138, 1.138, 1.139, 1.139, 1.134, 1.133, 1.129, 1.127, 1.119, 1.116, 1.106, 1.089,
+                            1.087, 1.092, 1.097, 1.101, 1.104, 1.109, 1.115, 1.117, 1.118, 1.121, 1.123, 1.126, 1.127, 1.126, 1.125, 1.125, 1.126, 1.128, 1.131, 1.136, 1.135, 1.137, 1.135, 1.135, 1.133, 1.131, 1.126, 1.123, 1.117, 1.111, 1.102, 1.088,
+                            1.091, 1.092, 1.097, 1.101, 1.105, 1.107, 1.115, 1.116, 1.117, 1.119, 1.121, 1.124, 1.127, 1.127, 1.125, 1.125, 1.125, 1.126, 1.127, 1.133, 1.132, 1.134, 1.134, 1.133, 1.131, 1.126, 1.124, 1.119, 1.111, 1.103, 1.094, 1.079,
+                            1.093, 1.094, 1.096, 1.099, 1.104, 1.107, 1.111, 1.114, 1.115, 1.117, 1.119, 1.121, 1.124, 1.125, 1.123, 1.123, 1.124, 1.124, 1.125, 1.127, 1.126, 1.129, 1.127, 1.129, 1.127, 1.122, 1.118, 1.112, 1.104, 1.098, 1.091, 1.069,
+                            1.093, 1.094, 1.099, 1.101, 1.106, 1.107, 1.109, 1.112, 1.114, 1.114, 1.118, 1.118, 1.119, 1.118, 1.117, 1.119, 1.118, 1.121, 1.121, 1.121, 1.118, 1.118, 1.123, 1.123, 1.119, 1.117, 1.112, 1.102, 1.099, 1.091, 1.077, 1.063,
+                            1.094, 1.097, 1.101, 1.101, 1.104, 1.106, 1.111, 1.112, 1.113, 1.112, 1.114, 1.115, 1.115, 1.115, 1.113, 1.112, 1.112, 1.112, 1.113, 1.112, 1.111, 1.111, 1.112, 1.112, 1.112, 1.104, 1.099, 1.098, 1.088, 1.078, 1.071, 1.054,
+                            1.095, 1.098, 1.101, 1.102, 1.103, 1.106, 1.107, 1.109, 1.111, 1.111, 1.108, 1.109, 1.111, 1.109, 1.108, 1.108, 1.108, 1.105, 1.104, 1.102, 1.102, 1.101, 1.101, 1.099, 1.098, 1.095, 1.093, 1.085, 1.076, 1.071, 1.058, 1.044,
+                            1.095, 1.098, 1.101, 1.102, 1.102, 1.103, 1.106, 1.107, 1.109, 1.108, 1.107, 1.107, 1.105, 1.103, 1.104, 1.103, 1.103, 1.102, 1.098, 1.096, 1.094, 1.093, 1.091, 1.088, 1.084, 1.078, 1.077, 1.074, 1.068, 1.058, 1.037, 1.028,
+                            1.096, 1.098, 1.101, 1.103, 1.104, 1.103, 1.105, 1.105, 1.107, 1.104, 1.104, 1.103, 1.102, 1.101, 1.098, 1.098, 1.096, 1.091, 1.089, 1.088, 1.087, 1.083, 1.079, 1.073, 1.071, 1.069, 1.065, 1.061, 1.051, 1.038, 1.028, 1.014,
+                            1.095, 1.099, 1.103, 1.104, 1.103, 1.102, 1.105, 1.106, 1.106, 1.103, 1.101, 1.098, 1.097, 1.099, 1.095, 1.093, 1.091, 1.086, 1.085, 1.081, 1.078, 1.076, 1.068, 1.066, 1.062, 1.062, 1.056, 1.049, 1.038, 1.031, 1.014, 1.011
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.001, 1.003, 1.012, 1.017, 1.023, 1.024, 1.031, 1.033, 1.035, 1.037, 1.036, 1.035, 1.036, 1.036, 1.037, 1.036, 1.037, 1.036, 1.041, 1.044, 1.044, 1.045, 1.049, 1.048, 1.051, 1.051, 1.052, 1.052, 1.055, 1.052, 1.052, 1.051,
+                            1.001, 1.006, 1.017, 1.022, 1.024, 1.029, 1.033, 1.036, 1.037, 1.039, 1.037, 1.038, 1.037, 1.038, 1.041, 1.041, 1.042, 1.041, 1.045, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.051, 1.053, 1.054, 1.055, 1.054, 1.053, 1.051,
+                            1.003, 1.012, 1.019, 1.025, 1.026, 1.032, 1.035, 1.041, 1.041, 1.041, 1.041, 1.043, 1.041, 1.045, 1.045, 1.045, 1.046, 1.048, 1.048, 1.048, 1.048, 1.049, 1.052, 1.052, 1.053, 1.054, 1.055, 1.057, 1.056, 1.055, 1.053, 1.053,
+                            1.003, 1.014, 1.019, 1.026, 1.032, 1.034, 1.037, 1.041, 1.042, 1.043, 1.043, 1.046, 1.045, 1.046, 1.048, 1.049, 1.051, 1.054, 1.053, 1.052, 1.052, 1.052, 1.053, 1.055, 1.054, 1.055, 1.056, 1.057, 1.055, 1.055, 1.054, 1.053,
+                            1.006, 1.015, 1.019, 1.028, 1.032, 1.035, 1.039, 1.042, 1.044, 1.044, 1.046, 1.048, 1.048, 1.049, 1.049, 1.051, 1.053, 1.056, 1.055, 1.055, 1.053, 1.054, 1.055, 1.057, 1.056, 1.058, 1.057, 1.057, 1.057, 1.058, 1.055, 1.053,
+                            1.014, 1.018, 1.021, 1.028, 1.034, 1.036, 1.041, 1.042, 1.045, 1.046, 1.047, 1.049, 1.051, 1.052, 1.051, 1.054, 1.056, 1.057, 1.058, 1.059, 1.058, 1.057, 1.058, 1.059, 1.058, 1.059, 1.059, 1.059, 1.058, 1.059, 1.055, 1.054,
+                            1.013, 1.018, 1.022, 1.029, 1.032, 1.037, 1.041, 1.046, 1.047, 1.049, 1.049, 1.052, 1.054, 1.052, 1.052, 1.054, 1.058, 1.058, 1.059, 1.062, 1.063, 1.063, 1.061, 1.061, 1.061, 1.061, 1.061, 1.061, 1.061, 1.059, 1.055, 1.053,
+                            1.015, 1.019, 1.022, 1.029, 1.033, 1.037, 1.041, 1.046, 1.048, 1.049, 1.052, 1.054, 1.054, 1.053, 1.052, 1.054, 1.058, 1.059, 1.061, 1.063, 1.064, 1.064, 1.063, 1.064, 1.063, 1.062, 1.063, 1.062, 1.063, 1.061, 1.056, 1.054,
+                            1.014, 1.017, 1.025, 1.029, 1.033, 1.037, 1.041, 1.046, 1.048, 1.049, 1.054, 1.056, 1.055, 1.053, 1.053, 1.055, 1.059, 1.058, 1.058, 1.062, 1.063, 1.064, 1.065, 1.065, 1.065, 1.064, 1.064, 1.064, 1.064, 1.061, 1.058, 1.054,
+                            1.015, 1.019, 1.024, 1.032, 1.035, 1.039, 1.044, 1.046, 1.049, 1.052, 1.054, 1.057, 1.057, 1.056, 1.057, 1.058, 1.061, 1.061, 1.061, 1.063, 1.063, 1.065, 1.065, 1.066, 1.066, 1.063, 1.065, 1.064, 1.065, 1.063, 1.059, 1.055,
+                            1.012, 1.021, 1.023, 1.031, 1.035, 1.041, 1.045, 1.049, 1.049, 1.054, 1.054, 1.057, 1.057, 1.058, 1.059, 1.061, 1.062, 1.063, 1.063, 1.063, 1.066, 1.067, 1.069, 1.068, 1.067, 1.064, 1.066, 1.065, 1.065, 1.063, 1.059, 1.055,
+                            1.013, 1.021, 1.023, 1.032, 1.035, 1.042, 1.048, 1.051, 1.052, 1.054, 1.054, 1.057, 1.057, 1.058, 1.059, 1.061, 1.063, 1.063, 1.064, 1.066, 1.067, 1.069, 1.071, 1.071, 1.069, 1.067, 1.067, 1.066, 1.066, 1.064, 1.062, 1.057,
+                            1.019, 1.022, 1.025, 1.032, 1.036, 1.042, 1.049, 1.051, 1.052, 1.053, 1.054, 1.057, 1.058, 1.059, 1.059, 1.062, 1.062, 1.063, 1.066, 1.067, 1.069, 1.071, 1.072, 1.073, 1.073, 1.069, 1.068, 1.068, 1.067, 1.065, 1.064, 1.057,
+                            1.019, 1.021, 1.027, 1.032, 1.037, 1.042, 1.048, 1.052, 1.053, 1.054, 1.056, 1.057, 1.059, 1.059, 1.059, 1.061, 1.061, 1.063, 1.066, 1.069, 1.071, 1.071, 1.073, 1.073, 1.075, 1.069, 1.069, 1.069, 1.067, 1.067, 1.066, 1.056,
+                            1.019, 1.022, 1.028, 1.034, 1.037, 1.042, 1.047, 1.052, 1.053, 1.054, 1.055, 1.057, 1.058, 1.061, 1.061, 1.061, 1.062, 1.065, 1.067, 1.069, 1.071, 1.072, 1.073, 1.073, 1.075, 1.071, 1.069, 1.069, 1.068, 1.067, 1.065, 1.055,
+                            1.017, 1.023, 1.031, 1.033, 1.037, 1.042, 1.048, 1.051, 1.053, 1.054, 1.056, 1.056, 1.057, 1.059, 1.059, 1.059, 1.061, 1.065, 1.069, 1.069, 1.071, 1.072, 1.072, 1.073, 1.073, 1.071, 1.071, 1.071, 1.068, 1.068, 1.064, 1.056,
+                            1.017, 1.025, 1.029, 1.033, 1.037, 1.043, 1.047, 1.051, 1.052, 1.053, 1.056, 1.056, 1.056, 1.057, 1.059, 1.061, 1.061, 1.066, 1.069, 1.072, 1.073, 1.073, 1.073, 1.072, 1.072, 1.072, 1.071, 1.071, 1.069, 1.069, 1.066, 1.056,
+                            1.018, 1.025, 1.032, 1.035, 1.041, 1.043, 1.048, 1.051, 1.053, 1.054, 1.057, 1.056, 1.057, 1.056, 1.058, 1.059, 1.061, 1.066, 1.069, 1.072, 1.074, 1.074, 1.073, 1.073, 1.073, 1.073, 1.072, 1.071, 1.069, 1.069, 1.065, 1.057,
+                            1.019, 1.025, 1.031, 1.038, 1.041, 1.045, 1.047, 1.049, 1.053, 1.053, 1.056, 1.056, 1.056, 1.056, 1.058, 1.059, 1.062, 1.065, 1.069, 1.071, 1.072, 1.074, 1.073, 1.073, 1.072, 1.072, 1.072, 1.072, 1.071, 1.069, 1.067, 1.057,
+                            1.019, 1.025, 1.031, 1.038, 1.041, 1.044, 1.047, 1.049, 1.053, 1.053, 1.054, 1.053, 1.053, 1.055, 1.056, 1.061, 1.062, 1.066, 1.068, 1.071, 1.071, 1.074, 1.074, 1.073, 1.073, 1.073, 1.072, 1.072, 1.072, 1.068, 1.065, 1.057,
+                            1.019, 1.025, 1.029, 1.036, 1.039, 1.039, 1.046, 1.048, 1.052, 1.053, 1.053, 1.052, 1.051, 1.053, 1.056, 1.059, 1.062, 1.064, 1.067, 1.069, 1.071, 1.071, 1.071, 1.072, 1.071, 1.072, 1.071, 1.071, 1.071, 1.067, 1.062, 1.055,
+                            1.022, 1.025, 1.029, 1.035, 1.037, 1.038, 1.042, 1.046, 1.047, 1.052, 1.053, 1.051, 1.051, 1.053, 1.054, 1.057, 1.059, 1.062, 1.064, 1.067, 1.071, 1.071, 1.072, 1.074, 1.073, 1.073, 1.071, 1.071, 1.069, 1.066, 1.061, 1.053,
+                            1.023, 1.026, 1.029, 1.034, 1.036, 1.038, 1.041, 1.045, 1.046, 1.049, 1.052, 1.052, 1.053, 1.056, 1.055, 1.057, 1.058, 1.059, 1.063, 1.066, 1.069, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.069, 1.067, 1.065, 1.058, 1.053,
+                            1.023, 1.026, 1.029, 1.034, 1.036, 1.039, 1.041, 1.044, 1.045, 1.047, 1.049, 1.053, 1.054, 1.055, 1.055, 1.055, 1.056, 1.058, 1.061, 1.064, 1.067, 1.068, 1.071, 1.072, 1.071, 1.071, 1.068, 1.066, 1.065, 1.064, 1.058, 1.052,
+                            1.024, 1.026, 1.028, 1.033, 1.035, 1.038, 1.041, 1.044, 1.046, 1.048, 1.049, 1.052, 1.054, 1.054, 1.055, 1.055, 1.056, 1.057, 1.059, 1.063, 1.064, 1.068, 1.069, 1.069, 1.069, 1.068, 1.067, 1.065, 1.064, 1.061, 1.055, 1.046,
+                            1.022, 1.026, 1.028, 1.032, 1.035, 1.037, 1.041, 1.044, 1.046, 1.047, 1.049, 1.051, 1.054, 1.054, 1.054, 1.054, 1.055, 1.057, 1.059, 1.062, 1.062, 1.065, 1.066, 1.068, 1.069, 1.068, 1.067, 1.063, 1.059, 1.057, 1.053, 1.043,
+                            1.022, 1.026, 1.029, 1.031, 1.034, 1.036, 1.039, 1.043, 1.045, 1.046, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.054, 1.055, 1.056, 1.057, 1.059, 1.061, 1.061, 1.062, 1.066, 1.067, 1.065, 1.059, 1.055, 1.054, 1.048, 1.039,
+                            1.025, 1.026, 1.028, 1.028, 1.031, 1.033, 1.037, 1.041, 1.044, 1.045, 1.048, 1.048, 1.048, 1.049, 1.048, 1.049, 1.052, 1.052, 1.052, 1.053, 1.054, 1.054, 1.056, 1.056, 1.057, 1.057, 1.054, 1.054, 1.052, 1.048, 1.045, 1.035,
+                            1.023, 1.024, 1.026, 1.028, 1.029, 1.032, 1.035, 1.038, 1.042, 1.042, 1.044, 1.045, 1.046, 1.046, 1.045, 1.046, 1.047, 1.048, 1.049, 1.049, 1.051, 1.051, 1.051, 1.049, 1.051, 1.051, 1.051, 1.047, 1.045, 1.044, 1.033, 1.029,
+                            1.023, 1.024, 1.028, 1.028, 1.029, 1.031, 1.035, 1.036, 1.039, 1.041, 1.043, 1.039, 1.041, 1.042, 1.043, 1.043, 1.044, 1.045, 1.046, 1.046, 1.045, 1.046, 1.044, 1.044, 1.042, 1.043, 1.045, 1.043, 1.039, 1.032, 1.028, 1.022,
+                            1.021, 1.027, 1.032, 1.031, 1.031, 1.033, 1.036, 1.037, 1.037, 1.037, 1.037, 1.037, 1.039, 1.039, 1.041, 1.041, 1.039, 1.039, 1.039, 1.041, 1.042, 1.042, 1.036, 1.036, 1.036, 1.036, 1.036, 1.035, 1.028, 1.026, 1.016, 1.011,
+                            1.025, 1.032, 1.032, 1.032, 1.032, 1.033, 1.037, 1.037, 1.036, 1.035, 1.037, 1.037, 1.037, 1.038, 1.039, 1.038, 1.037, 1.035, 1.036, 1.037, 1.036, 1.035, 1.033, 1.032, 1.032, 1.031, 1.029, 1.022, 1.016, 1.013, 1.011, 1.008
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    1.991, 1.983, 1.889, 1.818, 1.751, 1.681, 1.619, 1.562, 1.514, 1.469, 1.434, 1.405, 1.376, 1.359, 1.343, 1.325, 1.314, 1.309, 1.307, 1.303, 1.304, 1.304, 1.308, 1.322, 1.333, 1.347, 1.364, 1.381, 1.401, 1.419, 1.456, 1.477,
+                    1.983, 1.902, 1.819, 1.751, 1.683, 1.619, 1.562, 1.514, 1.468, 1.433, 1.402, 1.372, 1.347, 1.328, 1.315, 1.299, 1.285, 1.276, 1.273, 1.275, 1.273, 1.272, 1.281, 1.291, 1.301, 1.315, 1.336, 1.351, 1.371, 1.394, 1.431, 1.456,
+                    1.889, 1.816, 1.743, 1.678, 1.614, 1.551, 1.501, 1.455, 1.415, 1.386, 1.353, 1.332, 1.309, 1.291, 1.276, 1.265, 1.251, 1.243, 1.242, 1.243, 1.242, 1.239, 1.247, 1.256, 1.269, 1.279, 1.292, 1.309, 1.332, 1.357, 1.389, 1.419,
+                    1.811, 1.743, 1.672, 1.608, 1.547, 1.495, 1.449, 1.406, 1.371, 1.341, 1.316, 1.295, 1.273, 1.255, 1.243, 1.233, 1.222, 1.216, 1.213, 1.213, 1.213, 1.213, 1.221, 1.229, 1.239, 1.249, 1.262, 1.279, 1.301, 1.324, 1.355, 1.388,
+                    1.742, 1.671, 1.606, 1.544, 1.491, 1.443, 1.403, 1.361, 1.329, 1.306, 1.283, 1.264, 1.244, 1.223, 1.209, 1.203, 1.191, 1.187, 1.184, 1.182, 1.183, 1.186, 1.196, 1.203, 1.211, 1.226, 1.241, 1.255, 1.277, 1.301, 1.327, 1.361,
+                    1.671, 1.609, 1.549, 1.493, 1.441, 1.399, 1.358, 1.325, 1.294, 1.269, 1.249, 1.234, 1.216, 1.194, 1.181, 1.172, 1.165, 1.159, 1.156, 1.157, 1.158, 1.164, 1.174, 1.181, 1.191, 1.205, 1.217, 1.236, 1.255, 1.277, 1.304, 1.339,
+                    1.608, 1.561, 1.499, 1.445, 1.401, 1.359, 1.323, 1.292, 1.264, 1.242, 1.219, 1.201, 1.187, 1.169, 1.156, 1.148, 1.143, 1.136, 1.134, 1.135, 1.139, 1.144, 1.154, 1.165, 1.174, 1.185, 1.198, 1.214, 1.233, 1.258, 1.283, 1.323,
+                    1.559, 1.506, 1.454, 1.405, 1.362, 1.322, 1.291, 1.261, 1.234, 1.212, 1.193, 1.178, 1.162, 1.147, 1.136, 1.128, 1.121, 1.118, 1.116, 1.117, 1.122, 1.129, 1.135, 1.145, 1.156, 1.167, 1.181, 1.197, 1.217, 1.242, 1.271, 1.311,
+                    1.506, 1.463, 1.413, 1.369, 1.327, 1.291, 1.261, 1.232, 1.208, 1.191, 1.171, 1.153, 1.139, 1.126, 1.118, 1.109, 1.102, 1.096, 1.098, 1.097, 1.105, 1.112, 1.119, 1.129, 1.141, 1.153, 1.167, 1.183, 1.205, 1.232, 1.259, 1.299,
+                    1.463, 1.425, 1.378, 1.337, 1.297, 1.262, 1.233, 1.208, 1.187, 1.167, 1.152, 1.134, 1.119, 1.106, 1.095, 1.087, 1.083, 1.079, 1.078, 1.079, 1.088, 1.096, 1.105, 1.115, 1.128, 1.142, 1.154, 1.171, 1.197, 1.219, 1.247, 1.287,
+                    1.425, 1.384, 1.347, 1.307, 1.272, 1.239, 1.209, 1.186, 1.168, 1.151, 1.131, 1.115, 1.099, 1.086, 1.076, 1.069, 1.067, 1.064, 1.063, 1.067, 1.075, 1.085, 1.093, 1.104, 1.117, 1.127, 1.142, 1.159, 1.183, 1.204, 1.231, 1.278,
+                    1.387, 1.355, 1.321, 1.292, 1.258, 1.224, 1.189, 1.167, 1.146, 1.129, 1.113, 1.097, 1.083, 1.071, 1.062, 1.057, 1.052, 1.051, 1.053, 1.059, 1.064, 1.074, 1.086, 1.097, 1.107, 1.119, 1.132, 1.149, 1.175, 1.196, 1.224, 1.276,
+                    1.364, 1.332, 1.303, 1.271, 1.241, 1.206, 1.176, 1.149, 1.129, 1.112, 1.095, 1.081, 1.069, 1.058, 1.049, 1.044, 1.042, 1.042, 1.044, 1.049, 1.056, 1.066, 1.079, 1.089, 1.102, 1.113, 1.126, 1.145, 1.169, 1.192, 1.221, 1.273,
+                    1.343, 1.314, 1.283, 1.251, 1.219, 1.191, 1.161, 1.136, 1.114, 1.098, 1.081, 1.069, 1.057, 1.048, 1.041, 1.035, 1.033, 1.034, 1.038, 1.039, 1.049, 1.058, 1.067, 1.081, 1.093, 1.108, 1.121, 1.143, 1.164, 1.188, 1.218, 1.273,
+                    1.323, 1.297, 1.264, 1.232, 1.198, 1.169, 1.145, 1.125, 1.105, 1.085, 1.071, 1.059, 1.049, 1.042, 1.032, 1.026, 1.024, 1.026, 1.028, 1.032, 1.038, 1.049, 1.059, 1.069, 1.087, 1.101, 1.119, 1.139, 1.161, 1.186, 1.215, 1.269,
+                    1.304, 1.278, 1.248, 1.219, 1.185, 1.154, 1.133, 1.113, 1.091, 1.075, 1.064, 1.057, 1.048, 1.036, 1.025, 1.018, 1.016, 1.018, 1.022, 1.026, 1.034, 1.044, 1.055, 1.065, 1.079, 1.096, 1.116, 1.138, 1.161, 1.185, 1.213, 1.271,
+                    1.286, 1.261, 1.236, 1.209, 1.178, 1.147, 1.123, 1.102, 1.082, 1.066, 1.059, 1.054, 1.047, 1.033, 1.019, 1.012, 1.009, 1.015, 1.019, 1.023, 1.029, 1.042, 1.053, 1.064, 1.077, 1.095, 1.115, 1.137, 1.161, 1.188, 1.216, 1.271,
+                    1.275, 1.247, 1.224, 1.201, 1.173, 1.143, 1.118, 1.096, 1.078, 1.062, 1.055, 1.049, 1.042, 1.029, 1.017, 1.009, 1.008, 1.011, 1.015, 1.022, 1.031, 1.042, 1.051, 1.061, 1.079, 1.096, 1.116, 1.138, 1.163, 1.194, 1.224, 1.279,
+                    1.269, 1.241, 1.216, 1.192, 1.165, 1.136, 1.113, 1.093, 1.075, 1.057, 1.051, 1.043, 1.038, 1.031, 1.019, 1.011, 1.008, 1.009, 1.015, 1.021, 1.031, 1.041, 1.052, 1.063, 1.081, 1.098, 1.119, 1.141, 1.167, 1.199, 1.232, 1.291,
+                    1.263, 1.234, 1.208, 1.181, 1.158, 1.131, 1.109, 1.089, 1.073, 1.056, 1.047, 1.041, 1.035, 1.033, 1.028, 1.015, 1.009, 1.009, 1.015, 1.023, 1.032, 1.041, 1.053, 1.067, 1.085, 1.106, 1.127, 1.149, 1.176, 1.211, 1.244, 1.303,
+                    1.259, 1.225, 1.201, 1.173, 1.148, 1.125, 1.106, 1.087, 1.073, 1.059, 1.047, 1.038, 1.035, 1.034, 1.031, 1.022, 1.012, 1.012, 1.018, 1.026, 1.034, 1.046, 1.059, 1.074, 1.091, 1.113, 1.133, 1.158, 1.184, 1.217, 1.255, 1.314,
+                    1.254, 1.219, 1.193, 1.169, 1.143, 1.119, 1.101, 1.081, 1.068, 1.057, 1.047, 1.039, 1.035, 1.034, 1.029, 1.021, 1.015, 1.014, 1.021, 1.029, 1.038, 1.053, 1.068, 1.082, 1.099, 1.118, 1.141, 1.166, 1.194, 1.231, 1.271, 1.335,
+                    1.249, 1.216, 1.191, 1.165, 1.141, 1.119, 1.099, 1.079, 1.067, 1.058, 1.048, 1.042, 1.036, 1.033, 1.028, 1.022, 1.016, 1.017, 1.026, 1.032, 1.045, 1.061, 1.077, 1.093, 1.111, 1.131, 1.151, 1.182, 1.211, 1.248, 1.293, 1.356,
+                    1.252, 1.218, 1.188, 1.162, 1.141, 1.119, 1.099, 1.079, 1.069, 1.059, 1.049, 1.041, 1.037, 1.032, 1.026, 1.024, 1.021, 1.023, 1.032, 1.041, 1.052, 1.068, 1.087, 1.105, 1.124, 1.144, 1.172, 1.204, 1.233, 1.271, 1.317, 1.379,
+                    1.251, 1.216, 1.191, 1.166, 1.144, 1.122, 1.102, 1.084, 1.071, 1.059, 1.049, 1.043, 1.037, 1.031, 1.026, 1.024, 1.025, 1.031, 1.041, 1.051, 1.061, 1.077, 1.098, 1.117, 1.138, 1.163, 1.192, 1.223, 1.257, 1.297, 1.346, 1.402,
+                    1.255, 1.221, 1.195, 1.172, 1.149, 1.127, 1.108, 1.091, 1.077, 1.064, 1.054, 1.046, 1.041, 1.033, 1.031, 1.029, 1.031, 1.039, 1.049, 1.055, 1.071, 1.089, 1.107, 1.131, 1.155, 1.182, 1.209, 1.241, 1.282, 1.326, 1.371, 1.434,
+                    1.258, 1.225, 1.199, 1.177, 1.155, 1.135, 1.118, 1.099, 1.082, 1.071, 1.063, 1.055, 1.047, 1.041, 1.036, 1.035, 1.039, 1.047, 1.053, 1.064, 1.078, 1.101, 1.121, 1.144, 1.171, 1.197, 1.231, 1.266, 1.306, 1.354, 1.404, 1.468,
+                    1.266, 1.229, 1.202, 1.181, 1.157, 1.142, 1.126, 1.111, 1.094, 1.083, 1.074, 1.067, 1.061, 1.052, 1.047, 1.047, 1.049, 1.053, 1.063, 1.073, 1.091, 1.113, 1.134, 1.155, 1.188, 1.217, 1.254, 1.296, 1.342, 1.391, 1.439, 1.504,
+                    1.275, 1.237, 1.209, 1.187, 1.167, 1.151, 1.136, 1.123, 1.106, 1.098, 1.086, 1.081, 1.072, 1.064, 1.059, 1.059, 1.061, 1.065, 1.074, 1.089, 1.111, 1.132, 1.153, 1.182, 1.209, 1.241, 1.287, 1.336, 1.381, 1.423, 1.476, 1.554,
+                    1.284, 1.253, 1.219, 1.197, 1.176, 1.162, 1.149, 1.139, 1.123, 1.113, 1.104, 1.097, 1.091, 1.081, 1.076, 1.076, 1.078, 1.082, 1.095, 1.115, 1.136, 1.163, 1.185, 1.214, 1.241, 1.279, 1.327, 1.373, 1.418, 1.458, 1.521, 1.604,
+                    1.328, 1.289, 1.249, 1.212, 1.192, 1.175, 1.169, 1.162, 1.153, 1.137, 1.125, 1.119, 1.116, 1.106, 1.101, 1.098, 1.104, 1.112, 1.122, 1.144, 1.172, 1.194, 1.227, 1.252, 1.282, 1.325, 1.368, 1.415, 1.455, 1.507, 1.575, 1.657,
+                    1.345, 1.323, 1.273, 1.241, 1.211, 1.194, 1.187, 1.181, 1.169, 1.164, 1.147, 1.139, 1.133, 1.127, 1.125, 1.123, 1.128, 1.137, 1.146, 1.166, 1.194, 1.227, 1.252, 1.281, 1.316, 1.351, 1.411, 1.451, 1.493, 1.561, 1.647, 1.701
+                ],
+                "sigma": 0.0017,
+                "sigma_Cb": 0.00261
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.25,
+                "limit": 1.0,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/vd56g3.json 0.6.0-2/src/ipa/rpi/pisp/data/vd56g3.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/vd56g3.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/vd56g3.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,1293 @@
+{
+    "version": 2.0,
+    "target": "pisp",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 5971,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 950,
+                "reference_Y": 23748
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 2.732
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 108,
+                "slope": 0.05756
+            }
+        },
+        {
+            "rpi.denoise":
+            {
+                "normal":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 0.8,
+                        "threshold": 0.05
+                    }
+                },
+                "hdr":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                },
+                "night":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                }
+            }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 7700
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8000
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    3000.0, 1.2153, 0.4578,
+                    6500.0, 0.6724, 0.7526
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.01428,
+                "transverse_neg": 0.01963
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2400,
+                        "table":
+                        [
+                            1.075, 1.079, 1.081, 1.087, 1.087, 1.086, 1.086, 1.086, 1.085, 1.085, 1.085, 1.087, 1.087, 1.087, 1.087, 1.088, 1.085, 1.085, 1.083, 1.079, 1.074, 1.071, 1.065, 1.059, 1.054, 1.047, 1.039, 1.032, 1.023, 1.012, 1.011, 1.011,
+                            1.075, 1.077, 1.078, 1.081, 1.081, 1.081, 1.081, 1.079, 1.078, 1.078, 1.079, 1.081, 1.081, 1.083, 1.084, 1.085, 1.084, 1.083, 1.082, 1.078, 1.074, 1.071, 1.063, 1.059, 1.053, 1.047, 1.039, 1.032, 1.023, 1.018, 1.012, 1.012,
+                            1.074, 1.077, 1.078, 1.079, 1.081, 1.081, 1.079, 1.079, 1.078, 1.078, 1.079, 1.079, 1.081, 1.082, 1.084, 1.085, 1.084, 1.083, 1.082, 1.078, 1.074, 1.069, 1.065, 1.059, 1.054, 1.049, 1.043, 1.034, 1.027, 1.021, 1.021, 1.019,
+                            1.075, 1.077, 1.081, 1.081, 1.081, 1.081, 1.079, 1.079, 1.079, 1.079, 1.079, 1.082, 1.082, 1.084, 1.085, 1.086, 1.086, 1.084, 1.082, 1.079, 1.076, 1.072, 1.068, 1.064, 1.058, 1.052, 1.047, 1.041, 1.031, 1.029, 1.028, 1.027,
+                            1.076, 1.079, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.082, 1.084, 1.085, 1.086, 1.087, 1.087, 1.085, 1.083, 1.081, 1.077, 1.075, 1.071, 1.068, 1.063, 1.056, 1.051, 1.045, 1.035, 1.032, 1.032, 1.033,
+                            1.077, 1.079, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.083, 1.084, 1.085, 1.087, 1.088, 1.087, 1.086, 1.084, 1.082, 1.079, 1.077, 1.074, 1.069, 1.065, 1.061, 1.053, 1.047, 1.038, 1.036, 1.037, 1.039,
+                            1.077, 1.078, 1.081, 1.081, 1.082, 1.082, 1.081, 1.082, 1.082, 1.082, 1.082, 1.083, 1.085, 1.086, 1.087, 1.088, 1.088, 1.086, 1.084, 1.083, 1.082, 1.078, 1.076, 1.072, 1.067, 1.063, 1.058, 1.051, 1.043, 1.041, 1.041, 1.042,
+                            1.077, 1.079, 1.081, 1.082, 1.082, 1.082, 1.082, 1.083, 1.082, 1.082, 1.083, 1.084, 1.086, 1.087, 1.089, 1.089, 1.088, 1.087, 1.085, 1.083, 1.082, 1.079, 1.078, 1.074, 1.069, 1.066, 1.061, 1.055, 1.047, 1.045, 1.045, 1.048,
+                            1.076, 1.079, 1.081, 1.083, 1.083, 1.084, 1.083, 1.083, 1.083, 1.084, 1.084, 1.086, 1.087, 1.088, 1.089, 1.089, 1.088, 1.087, 1.085, 1.084, 1.082, 1.079, 1.078, 1.076, 1.072, 1.068, 1.063, 1.058, 1.049, 1.048, 1.049, 1.051,
+                            1.076, 1.081, 1.082, 1.083, 1.084, 1.084, 1.084, 1.083, 1.083, 1.084, 1.085, 1.086, 1.087, 1.089, 1.089, 1.089, 1.087, 1.086, 1.086, 1.084, 1.082, 1.081, 1.079, 1.076, 1.074, 1.071, 1.065, 1.061, 1.054, 1.051, 1.051, 1.055,
+                            1.078, 1.081, 1.083, 1.084, 1.085, 1.085, 1.084, 1.083, 1.084, 1.084, 1.085, 1.085, 1.087, 1.088, 1.088, 1.088, 1.086, 1.086, 1.086, 1.084, 1.083, 1.082, 1.081, 1.078, 1.075, 1.071, 1.066, 1.063, 1.056, 1.055, 1.055, 1.057,
+                            1.081, 1.083, 1.084, 1.085, 1.086, 1.085, 1.084, 1.084, 1.084, 1.084, 1.085, 1.085, 1.086, 1.087, 1.088, 1.087, 1.087, 1.086, 1.085, 1.084, 1.084, 1.082, 1.081, 1.079, 1.076, 1.072, 1.067, 1.064, 1.057, 1.056, 1.057, 1.058,
+                            1.081, 1.084, 1.085, 1.086, 1.086, 1.086, 1.084, 1.084, 1.084, 1.084, 1.084, 1.085, 1.086, 1.087, 1.088, 1.087, 1.087, 1.086, 1.085, 1.085, 1.084, 1.083, 1.081, 1.079, 1.076, 1.072, 1.069, 1.065, 1.058, 1.057, 1.058, 1.061,
+                            1.081, 1.084, 1.085, 1.086, 1.086, 1.086, 1.084, 1.083, 1.083, 1.083, 1.084, 1.084, 1.085, 1.086, 1.087, 1.088, 1.087, 1.087, 1.085, 1.085, 1.084, 1.083, 1.081, 1.079, 1.077, 1.073, 1.069, 1.066, 1.059, 1.059, 1.061, 1.063,
+                            1.081, 1.084, 1.086, 1.086, 1.086, 1.086, 1.083, 1.082, 1.082, 1.083, 1.083, 1.084, 1.085, 1.086, 1.087, 1.087, 1.087, 1.087, 1.087, 1.086, 1.085, 1.083, 1.081, 1.079, 1.077, 1.074, 1.069, 1.066, 1.061, 1.061, 1.062, 1.065,
+                            1.082, 1.085, 1.086, 1.086, 1.086, 1.084, 1.082, 1.081, 1.082, 1.082, 1.082, 1.083, 1.084, 1.086, 1.086, 1.087, 1.087, 1.087, 1.087, 1.086, 1.085, 1.082, 1.081, 1.079, 1.077, 1.074, 1.071, 1.066, 1.061, 1.061, 1.064, 1.066,
+                            1.082, 1.084, 1.085, 1.085, 1.083, 1.083, 1.081, 1.081, 1.081, 1.082, 1.082, 1.083, 1.084, 1.085, 1.086, 1.087, 1.087, 1.087, 1.087, 1.086, 1.085, 1.083, 1.081, 1.079, 1.077, 1.074, 1.071, 1.067, 1.061, 1.061, 1.064, 1.065,
+                            1.081, 1.082, 1.083, 1.082, 1.081, 1.079, 1.079, 1.079, 1.081, 1.081, 1.081, 1.082, 1.083, 1.084, 1.085, 1.086, 1.086, 1.086, 1.086, 1.085, 1.084, 1.083, 1.082, 1.079, 1.076, 1.074, 1.071, 1.067, 1.061, 1.061, 1.064, 1.066,
+                            1.079, 1.078, 1.078, 1.077, 1.077, 1.077, 1.078, 1.078, 1.079, 1.079, 1.081, 1.081, 1.081, 1.082, 1.083, 1.084, 1.084, 1.084, 1.084, 1.084, 1.083, 1.082, 1.081, 1.079, 1.076, 1.073, 1.071, 1.067, 1.061, 1.061, 1.065, 1.067,
+                            1.073, 1.073, 1.073, 1.074, 1.074, 1.074, 1.074, 1.075, 1.076, 1.077, 1.077, 1.077, 1.077, 1.078, 1.079, 1.079, 1.081, 1.083, 1.083, 1.083, 1.081, 1.081, 1.079, 1.077, 1.075, 1.072, 1.069, 1.066, 1.061, 1.061, 1.064, 1.066,
+                            1.064, 1.064, 1.066, 1.067, 1.067, 1.071, 1.071, 1.072, 1.073, 1.074, 1.074, 1.073, 1.074, 1.075, 1.076, 1.077, 1.078, 1.081, 1.081, 1.081, 1.081, 1.079, 1.078, 1.076, 1.074, 1.071, 1.068, 1.064, 1.059, 1.059, 1.062, 1.064,
+                            1.056, 1.058, 1.059, 1.061, 1.062, 1.065, 1.066, 1.067, 1.068, 1.068, 1.069, 1.068, 1.068, 1.069, 1.071, 1.074, 1.076, 1.078, 1.079, 1.079, 1.079, 1.078, 1.076, 1.074, 1.072, 1.069, 1.065, 1.061, 1.057, 1.057, 1.059, 1.061,
+                            1.048, 1.053, 1.054, 1.057, 1.059, 1.061, 1.062, 1.063, 1.064, 1.064, 1.064, 1.064, 1.065, 1.066, 1.068, 1.071, 1.074, 1.077, 1.078, 1.078, 1.078, 1.076, 1.074, 1.071, 1.069, 1.066, 1.063, 1.058, 1.055, 1.054, 1.056, 1.059,
+                            1.044, 1.047, 1.049, 1.052, 1.054, 1.056, 1.057, 1.059, 1.059, 1.059, 1.061, 1.063, 1.064, 1.065, 1.067, 1.071, 1.073, 1.075, 1.077, 1.076, 1.076, 1.073, 1.071, 1.069, 1.066, 1.064, 1.059, 1.056, 1.051, 1.051, 1.053, 1.055,
+                            1.039, 1.042, 1.045, 1.048, 1.049, 1.051, 1.053, 1.055, 1.056, 1.057, 1.059, 1.061, 1.063, 1.065, 1.068, 1.071, 1.073, 1.074, 1.074, 1.074, 1.072, 1.071, 1.069, 1.066, 1.064, 1.062, 1.057, 1.054, 1.048, 1.048, 1.049, 1.053,
+                            1.036, 1.038, 1.042, 1.045, 1.047, 1.049, 1.051, 1.052, 1.054, 1.056, 1.058, 1.061, 1.063, 1.065, 1.068, 1.069, 1.072, 1.073, 1.073, 1.072, 1.071, 1.069, 1.066, 1.065, 1.062, 1.059, 1.055, 1.052, 1.047, 1.047, 1.047, 1.049,
+                            1.032, 1.036, 1.038, 1.042, 1.044, 1.046, 1.049, 1.051, 1.053, 1.055, 1.058, 1.061, 1.062, 1.066, 1.067, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.067, 1.065, 1.063, 1.061, 1.057, 1.054, 1.051, 1.045, 1.045, 1.046, 1.048,
+                            1.028, 1.032, 1.036, 1.038, 1.042, 1.044, 1.045, 1.049, 1.051, 1.054, 1.057, 1.059, 1.061, 1.065, 1.066, 1.067, 1.068, 1.069, 1.069, 1.069, 1.067, 1.066, 1.064, 1.063, 1.061, 1.055, 1.052, 1.049, 1.044, 1.044, 1.046, 1.048,
+                            1.025, 1.027, 1.032, 1.035, 1.036, 1.041, 1.043, 1.045, 1.049, 1.051, 1.054, 1.057, 1.059, 1.062, 1.065, 1.066, 1.066, 1.066, 1.067, 1.066, 1.065, 1.065, 1.063, 1.061, 1.059, 1.056, 1.052, 1.047, 1.043, 1.042, 1.045, 1.046,
+                            1.017, 1.021, 1.025, 1.029, 1.034, 1.036, 1.041, 1.042, 1.044, 1.047, 1.049, 1.053, 1.055, 1.057, 1.059, 1.061, 1.063, 1.063, 1.063, 1.064, 1.063, 1.062, 1.061, 1.059, 1.057, 1.054, 1.051, 1.046, 1.039, 1.039, 1.039, 1.044,
+                            1.009, 1.015, 1.021, 1.023, 1.027, 1.031, 1.036, 1.037, 1.039, 1.042, 1.043, 1.045, 1.048, 1.051, 1.053, 1.055, 1.057, 1.058, 1.058, 1.059, 1.058, 1.058, 1.057, 1.055, 1.054, 1.051, 1.046, 1.041, 1.037, 1.037, 1.036, 1.038,
+                            1.004, 1.008, 1.014, 1.019, 1.022, 1.024, 1.025, 1.028, 1.029, 1.029, 1.031, 1.036, 1.039, 1.043, 1.046, 1.048, 1.049, 1.049, 1.052, 1.052, 1.052, 1.051, 1.049, 1.048, 1.045, 1.044, 1.041, 1.038, 1.033, 1.029, 1.031, 1.031
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.058, 1.066, 1.068, 1.072, 1.073, 1.075, 1.076, 1.074, 1.073, 1.072, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.069, 1.068, 1.066, 1.064, 1.061, 1.058, 1.053, 1.049, 1.044, 1.037, 1.031, 1.024, 1.014, 1.009, 1.007, 1.006,
+                            1.061, 1.065, 1.068, 1.072, 1.073, 1.074, 1.074, 1.074, 1.072, 1.069, 1.069, 1.071, 1.071, 1.072, 1.073, 1.072, 1.072, 1.069, 1.067, 1.066, 1.062, 1.058, 1.054, 1.051, 1.045, 1.041, 1.034, 1.026, 1.016, 1.011, 1.009, 1.011,
+                            1.062, 1.066, 1.071, 1.073, 1.073, 1.074, 1.074, 1.074, 1.073, 1.069, 1.069, 1.072, 1.074, 1.074, 1.075, 1.075, 1.076, 1.074, 1.072, 1.071, 1.068, 1.065, 1.059, 1.055, 1.052, 1.046, 1.039, 1.032, 1.026, 1.019, 1.019, 1.022,
+                            1.066, 1.071, 1.074, 1.076, 1.078, 1.079, 1.078, 1.078, 1.077, 1.077, 1.077, 1.078, 1.079, 1.081, 1.082, 1.084, 1.083, 1.081, 1.079, 1.076, 1.075, 1.071, 1.067, 1.063, 1.058, 1.053, 1.047, 1.041, 1.032, 1.032, 1.029, 1.029,
+                            1.069, 1.073, 1.077, 1.079, 1.081, 1.082, 1.081, 1.081, 1.081, 1.081, 1.082, 1.083, 1.084, 1.086, 1.086, 1.087, 1.086, 1.086, 1.084, 1.082, 1.079, 1.076, 1.072, 1.069, 1.064, 1.059, 1.053, 1.047, 1.039, 1.037, 1.036, 1.039,
+                            1.071, 1.075, 1.078, 1.081, 1.082, 1.084, 1.084, 1.085, 1.084, 1.084, 1.084, 1.086, 1.087, 1.089, 1.091, 1.091, 1.091, 1.089, 1.088, 1.086, 1.083, 1.081, 1.078, 1.073, 1.069, 1.064, 1.058, 1.052, 1.044, 1.042, 1.042, 1.042,
+                            1.072, 1.078, 1.079, 1.082, 1.085, 1.086, 1.086, 1.087, 1.086, 1.087, 1.088, 1.089, 1.091, 1.093, 1.094, 1.095, 1.095, 1.093, 1.092, 1.091, 1.088, 1.086, 1.083, 1.079, 1.074, 1.071, 1.064, 1.057, 1.049, 1.047, 1.047, 1.051,
+                            1.072, 1.079, 1.082, 1.085, 1.087, 1.089, 1.089, 1.091, 1.091, 1.092, 1.092, 1.094, 1.095, 1.097, 1.099, 1.098, 1.098, 1.096, 1.095, 1.094, 1.093, 1.089, 1.088, 1.084, 1.079, 1.075, 1.069, 1.063, 1.054, 1.053, 1.053, 1.058,
+                            1.073, 1.081, 1.085, 1.088, 1.091, 1.092, 1.093, 1.093, 1.093, 1.094, 1.096, 1.096, 1.099, 1.101, 1.102, 1.101, 1.099, 1.099, 1.098, 1.097, 1.095, 1.093, 1.089, 1.088, 1.084, 1.078, 1.075, 1.068, 1.059, 1.058, 1.059, 1.059,
+                            1.076, 1.083, 1.086, 1.089, 1.093, 1.094, 1.095, 1.095, 1.095, 1.096, 1.098, 1.099, 1.101, 1.103, 1.103, 1.103, 1.102, 1.101, 1.099, 1.099, 1.098, 1.095, 1.093, 1.091, 1.088, 1.084, 1.077, 1.073, 1.066, 1.063, 1.062, 1.066,
+                            1.081, 1.085, 1.089, 1.093, 1.095, 1.096, 1.096, 1.096, 1.097, 1.098, 1.099, 1.101, 1.103, 1.103, 1.104, 1.103, 1.103, 1.102, 1.102, 1.101, 1.099, 1.098, 1.096, 1.093, 1.091, 1.087, 1.082, 1.076, 1.067, 1.066, 1.068, 1.071,
+                            1.085, 1.088, 1.093, 1.095, 1.097, 1.098, 1.097, 1.098, 1.098, 1.099, 1.101, 1.102, 1.103, 1.104, 1.104, 1.104, 1.104, 1.104, 1.103, 1.103, 1.102, 1.099, 1.098, 1.096, 1.093, 1.089, 1.084, 1.078, 1.069, 1.069, 1.071, 1.073,
+                            1.085, 1.092, 1.094, 1.096, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.102, 1.103, 1.104, 1.105, 1.105, 1.105, 1.104, 1.104, 1.103, 1.103, 1.102, 1.099, 1.097, 1.095, 1.091, 1.086, 1.081, 1.075, 1.072, 1.072, 1.074,
+                            1.087, 1.093, 1.096, 1.098, 1.101, 1.101, 1.101, 1.099, 1.101, 1.101, 1.101, 1.101, 1.103, 1.104, 1.105, 1.106, 1.106, 1.105, 1.105, 1.104, 1.104, 1.103, 1.101, 1.099, 1.096, 1.092, 1.087, 1.082, 1.075, 1.074, 1.075, 1.077,
+                            1.088, 1.094, 1.097, 1.099, 1.101, 1.101, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.102, 1.104, 1.105, 1.106, 1.106, 1.106, 1.105, 1.105, 1.105, 1.103, 1.102, 1.099, 1.096, 1.093, 1.089, 1.083, 1.076, 1.076, 1.076, 1.077,
+                            1.089, 1.094, 1.098, 1.099, 1.101, 1.099, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.102, 1.103, 1.104, 1.105, 1.105, 1.107, 1.107, 1.107, 1.105, 1.104, 1.102, 1.099, 1.097, 1.094, 1.091, 1.083, 1.076, 1.076, 1.077, 1.078,
+                            1.091, 1.096, 1.098, 1.099, 1.099, 1.098, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.102, 1.103, 1.104, 1.105, 1.105, 1.106, 1.107, 1.107, 1.105, 1.103, 1.102, 1.099, 1.097, 1.094, 1.089, 1.084, 1.077, 1.077, 1.077, 1.078,
+                            1.091, 1.094, 1.096, 1.097, 1.096, 1.096, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.102, 1.103, 1.103, 1.104, 1.105, 1.106, 1.106, 1.104, 1.103, 1.102, 1.099, 1.097, 1.094, 1.091, 1.084, 1.077, 1.077, 1.078, 1.079,
+                            1.091, 1.091, 1.093, 1.094, 1.093, 1.093, 1.094, 1.095, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.103, 1.104, 1.105, 1.104, 1.103, 1.101, 1.099, 1.097, 1.094, 1.089, 1.084, 1.077, 1.077, 1.078, 1.079,
+                            1.083, 1.087, 1.088, 1.089, 1.089, 1.091, 1.092, 1.094, 1.095, 1.095, 1.096, 1.096, 1.096, 1.097, 1.098, 1.098, 1.098, 1.101, 1.102, 1.103, 1.102, 1.102, 1.101, 1.098, 1.096, 1.092, 1.088, 1.083, 1.076, 1.076, 1.077, 1.079,
+                            1.077, 1.081, 1.082, 1.084, 1.086, 1.087, 1.089, 1.091, 1.092, 1.092, 1.092, 1.092, 1.091, 1.092, 1.092, 1.094, 1.096, 1.098, 1.099, 1.101, 1.102, 1.099, 1.099, 1.097, 1.093, 1.089, 1.087, 1.081, 1.074, 1.073, 1.075, 1.077,
+                            1.067, 1.072, 1.075, 1.078, 1.082, 1.084, 1.085, 1.086, 1.087, 1.087, 1.087, 1.087, 1.086, 1.087, 1.089, 1.091, 1.094, 1.097, 1.098, 1.099, 1.099, 1.098, 1.097, 1.094, 1.091, 1.087, 1.083, 1.079, 1.071, 1.071, 1.072, 1.075,
+                            1.061, 1.065, 1.069, 1.072, 1.075, 1.079, 1.081, 1.082, 1.082, 1.083, 1.083, 1.083, 1.083, 1.084, 1.087, 1.089, 1.092, 1.095, 1.097, 1.097, 1.097, 1.096, 1.094, 1.091, 1.087, 1.084, 1.079, 1.074, 1.068, 1.067, 1.068, 1.069,
+                            1.053, 1.058, 1.063, 1.067, 1.071, 1.073, 1.075, 1.076, 1.078, 1.078, 1.079, 1.079, 1.081, 1.083, 1.085, 1.088, 1.091, 1.093, 1.095, 1.095, 1.093, 1.092, 1.089, 1.086, 1.084, 1.081, 1.075, 1.071, 1.064, 1.061, 1.063, 1.065,
+                            1.049, 1.053, 1.059, 1.062, 1.065, 1.068, 1.071, 1.073, 1.074, 1.075, 1.077, 1.078, 1.079, 1.082, 1.085, 1.088, 1.089, 1.091, 1.091, 1.091, 1.089, 1.088, 1.085, 1.082, 1.079, 1.075, 1.071, 1.066, 1.059, 1.059, 1.061, 1.063,
+                            1.044, 1.048, 1.053, 1.057, 1.061, 1.065, 1.066, 1.069, 1.071, 1.073, 1.074, 1.076, 1.078, 1.082, 1.084, 1.086, 1.088, 1.089, 1.089, 1.088, 1.087, 1.084, 1.081, 1.079, 1.076, 1.071, 1.067, 1.062, 1.055, 1.055, 1.056, 1.059,
+                            1.039, 1.046, 1.049, 1.054, 1.057, 1.059, 1.062, 1.064, 1.067, 1.071, 1.073, 1.075, 1.077, 1.081, 1.082, 1.084, 1.084, 1.085, 1.085, 1.084, 1.083, 1.081, 1.077, 1.075, 1.071, 1.068, 1.063, 1.057, 1.052, 1.051, 1.054, 1.055,
+                            1.034, 1.041, 1.046, 1.049, 1.053, 1.055, 1.058, 1.062, 1.064, 1.067, 1.069, 1.072, 1.075, 1.078, 1.079, 1.081, 1.081, 1.081, 1.081, 1.079, 1.078, 1.076, 1.074, 1.071, 1.068, 1.064, 1.061, 1.054, 1.049, 1.049, 1.052, 1.054,
+                            1.029, 1.034, 1.041, 1.043, 1.048, 1.051, 1.054, 1.056, 1.061, 1.063, 1.066, 1.067, 1.071, 1.073, 1.075, 1.075, 1.075, 1.076, 1.075, 1.075, 1.074, 1.072, 1.071, 1.068, 1.064, 1.061, 1.057, 1.051, 1.047, 1.046, 1.048, 1.054,
+                            1.019, 1.027, 1.033, 1.036, 1.042, 1.046, 1.049, 1.051, 1.053, 1.056, 1.058, 1.061, 1.064, 1.065, 1.066, 1.069, 1.071, 1.071, 1.069, 1.068, 1.068, 1.067, 1.064, 1.062, 1.059, 1.057, 1.052, 1.047, 1.044, 1.043, 1.048, 1.067,
+                            1.009, 1.018, 1.025, 1.028, 1.033, 1.039, 1.042, 1.043, 1.044, 1.046, 1.047, 1.049, 1.052, 1.055, 1.057, 1.059, 1.061, 1.061, 1.061, 1.062, 1.061, 1.058, 1.057, 1.056, 1.052, 1.051, 1.046, 1.042, 1.038, 1.038, 1.059, 1.067,
+                            1.005, 1.009, 1.017, 1.023, 1.026, 1.027, 1.028, 1.029, 1.031, 1.031, 1.032, 1.036, 1.041, 1.044, 1.046, 1.047, 1.047, 1.048, 1.049, 1.049, 1.049, 1.048, 1.046, 1.044, 1.042, 1.039, 1.039, 1.034, 1.033, 1.048, 1.062, 1.062
+                        ]
+                    },
+                    {
+                        "ct": 5000,
+                        "table":
+                        [
+                            1.051, 1.052, 1.057, 1.061, 1.061, 1.061, 1.061, 1.061, 1.061, 1.059, 1.059, 1.059, 1.062, 1.063, 1.065, 1.067, 1.066, 1.064, 1.063, 1.062, 1.058, 1.055, 1.049, 1.047, 1.043, 1.039, 1.037, 1.029, 1.028, 1.024, 1.026, 1.027,
+                            1.048, 1.049, 1.052, 1.053, 1.053, 1.051, 1.051, 1.051, 1.049, 1.048, 1.049, 1.051, 1.052, 1.055, 1.055, 1.056, 1.057, 1.058, 1.058, 1.055, 1.053, 1.051, 1.047, 1.044, 1.041, 1.038, 1.034, 1.029, 1.025, 1.024, 1.025, 1.029,
+                            1.047, 1.048, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.048, 1.048, 1.051, 1.051, 1.053, 1.055, 1.056, 1.056, 1.056, 1.055, 1.054, 1.051, 1.049, 1.046, 1.043, 1.041, 1.037, 1.035, 1.029, 1.026, 1.026, 1.029, 1.031,
+                            1.046, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.049, 1.048, 1.049, 1.051, 1.052, 1.055, 1.056, 1.056, 1.057, 1.057, 1.056, 1.054, 1.052, 1.049, 1.047, 1.045, 1.041, 1.039, 1.035, 1.032, 1.029, 1.031, 1.032, 1.038,
+                            1.047, 1.049, 1.051, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.051, 1.053, 1.055, 1.056, 1.058, 1.058, 1.056, 1.056, 1.053, 1.051, 1.049, 1.048, 1.045, 1.044, 1.041, 1.038, 1.034, 1.031, 1.031, 1.036, 1.041,
+                            1.046, 1.048, 1.048, 1.048, 1.048, 1.049, 1.049, 1.048, 1.048, 1.048, 1.049, 1.051, 1.052, 1.054, 1.055, 1.057, 1.057, 1.057, 1.056, 1.054, 1.051, 1.049, 1.049, 1.047, 1.044, 1.042, 1.039, 1.035, 1.032, 1.033, 1.039, 1.043,
+                            1.046, 1.047, 1.048, 1.048, 1.048, 1.048, 1.048, 1.048, 1.048, 1.049, 1.049, 1.051, 1.053, 1.054, 1.055, 1.057, 1.056, 1.055, 1.055, 1.054, 1.053, 1.051, 1.049, 1.048, 1.046, 1.043, 1.042, 1.038, 1.033, 1.034, 1.042, 1.047,
+                            1.045, 1.046, 1.048, 1.049, 1.049, 1.049, 1.048, 1.048, 1.048, 1.049, 1.049, 1.051, 1.053, 1.055, 1.055, 1.056, 1.055, 1.055, 1.054, 1.054, 1.053, 1.052, 1.051, 1.049, 1.047, 1.045, 1.043, 1.041, 1.036, 1.037, 1.044, 1.047,
+                            1.044, 1.047, 1.048, 1.049, 1.051, 1.049, 1.048, 1.048, 1.048, 1.048, 1.049, 1.051, 1.052, 1.055, 1.056, 1.056, 1.055, 1.054, 1.054, 1.053, 1.053, 1.052, 1.049, 1.049, 1.048, 1.046, 1.044, 1.042, 1.037, 1.037, 1.045, 1.049,
+                            1.045, 1.047, 1.048, 1.051, 1.051, 1.049, 1.049, 1.048, 1.048, 1.048, 1.049, 1.051, 1.051, 1.053, 1.055, 1.055, 1.054, 1.053, 1.053, 1.053, 1.053, 1.051, 1.051, 1.051, 1.048, 1.047, 1.045, 1.042, 1.039, 1.039, 1.048, 1.051,
+                            1.046, 1.047, 1.049, 1.051, 1.051, 1.049, 1.048, 1.047, 1.047, 1.047, 1.048, 1.049, 1.051, 1.053, 1.054, 1.054, 1.053, 1.053, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.048, 1.046, 1.043, 1.039, 1.039, 1.051, 1.055,
+                            1.046, 1.048, 1.049, 1.051, 1.051, 1.051, 1.048, 1.047, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.051, 1.051, 1.051, 1.049, 1.048, 1.047, 1.043, 1.041, 1.041, 1.053, 1.056,
+                            1.047, 1.049, 1.051, 1.051, 1.051, 1.049, 1.049, 1.047, 1.047, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.044, 1.042, 1.042, 1.054, 1.058,
+                            1.048, 1.049, 1.051, 1.052, 1.051, 1.049, 1.048, 1.047, 1.046, 1.046, 1.047, 1.047, 1.048, 1.051, 1.051, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.043, 1.055, 1.057,
+                            1.048, 1.051, 1.052, 1.051, 1.051, 1.049, 1.047, 1.046, 1.046, 1.046, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.051, 1.049, 1.048, 1.048, 1.047, 1.045, 1.044, 1.044, 1.056, 1.058,
+                            1.049, 1.051, 1.052, 1.051, 1.049, 1.048, 1.046, 1.046, 1.044, 1.046, 1.046, 1.047, 1.047, 1.049, 1.051, 1.051, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.051, 1.049, 1.048, 1.048, 1.047, 1.045, 1.044, 1.044, 1.056, 1.059,
+                            1.051, 1.052, 1.053, 1.051, 1.048, 1.047, 1.045, 1.043, 1.043, 1.044, 1.045, 1.046, 1.047, 1.048, 1.051, 1.051, 1.051, 1.053, 1.053, 1.053, 1.052, 1.051, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.046, 1.057, 1.061,
+                            1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.043, 1.044, 1.044, 1.045, 1.045, 1.046, 1.047, 1.048, 1.049, 1.051, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.046, 1.055, 1.083, 1.092,
+                            1.048, 1.048, 1.047, 1.045, 1.045, 1.043, 1.042, 1.042, 1.043, 1.043, 1.044, 1.044, 1.044, 1.045, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.055, 1.073, 1.098, 1.099,
+                            1.044, 1.044, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.041, 1.042, 1.041, 1.041, 1.041, 1.042, 1.044, 1.045, 1.047, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.048, 1.048, 1.072, 1.087, 1.097, 1.099,
+                            1.038, 1.037, 1.036, 1.036, 1.036, 1.037, 1.037, 1.038, 1.038, 1.038, 1.039, 1.038, 1.038, 1.038, 1.039, 1.041, 1.043, 1.045, 1.047, 1.048, 1.049, 1.048, 1.048, 1.047, 1.047, 1.045, 1.045, 1.048, 1.071, 1.087, 1.096, 1.098,
+                            1.029, 1.031, 1.032, 1.033, 1.033, 1.034, 1.034, 1.035, 1.035, 1.034, 1.033, 1.033, 1.034, 1.034, 1.036, 1.039, 1.041, 1.044, 1.045, 1.047, 1.048, 1.046, 1.046, 1.046, 1.044, 1.044, 1.043, 1.042, 1.049, 1.081, 1.095, 1.096,
+                            1.026, 1.027, 1.028, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.033, 1.035, 1.038, 1.039, 1.043, 1.044, 1.045, 1.045, 1.044, 1.044, 1.043, 1.043, 1.041, 1.041, 1.039, 1.039, 1.049, 1.087, 1.095,
+                            1.021, 1.023, 1.025, 1.026, 1.027, 1.028, 1.029, 1.028, 1.029, 1.029, 1.029, 1.029, 1.031, 1.032, 1.035, 1.038, 1.041, 1.043, 1.045, 1.044, 1.044, 1.042, 1.041, 1.041, 1.039, 1.039, 1.039, 1.037, 1.035, 1.036, 1.054, 1.071,
+                            1.017, 1.021, 1.023, 1.024, 1.025, 1.026, 1.027, 1.027, 1.028, 1.027, 1.028, 1.029, 1.032, 1.034, 1.036, 1.039, 1.041, 1.042, 1.044, 1.044, 1.043, 1.041, 1.039, 1.039, 1.038, 1.037, 1.036, 1.034, 1.034, 1.034, 1.046, 1.051,
+                            1.014, 1.019, 1.022, 1.024, 1.024, 1.025, 1.025, 1.026, 1.027, 1.028, 1.029, 1.031, 1.033, 1.035, 1.038, 1.041, 1.042, 1.042, 1.043, 1.042, 1.041, 1.039, 1.038, 1.038, 1.037, 1.036, 1.034, 1.033, 1.032, 1.033, 1.045, 1.047,
+                            1.014, 1.019, 1.021, 1.023, 1.024, 1.025, 1.025, 1.026, 1.027, 1.029, 1.031, 1.032, 1.035, 1.037, 1.039, 1.041, 1.042, 1.042, 1.042, 1.041, 1.041, 1.039, 1.038, 1.037, 1.037, 1.035, 1.034, 1.033, 1.033, 1.033, 1.044, 1.047,
+                            1.015, 1.019, 1.019, 1.022, 1.024, 1.025, 1.025, 1.027, 1.029, 1.031, 1.032, 1.033, 1.036, 1.038, 1.039, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.036, 1.034, 1.034, 1.033, 1.034, 1.043, 1.046,
+                            1.014, 1.016, 1.019, 1.019, 1.022, 1.023, 1.025, 1.026, 1.029, 1.031, 1.032, 1.033, 1.036, 1.037, 1.039, 1.039, 1.039, 1.041, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.037, 1.036, 1.034, 1.034, 1.033, 1.034, 1.042, 1.045,
+                            1.011, 1.013, 1.016, 1.018, 1.021, 1.023, 1.024, 1.024, 1.026, 1.028, 1.029, 1.031, 1.033, 1.035, 1.036, 1.036, 1.037, 1.038, 1.038, 1.038, 1.038, 1.038, 1.037, 1.037, 1.036, 1.036, 1.034, 1.033, 1.032, 1.033, 1.039, 1.044,
+                            1.003, 1.007, 1.012, 1.014, 1.016, 1.019, 1.022, 1.022, 1.022, 1.022, 1.024, 1.025, 1.026, 1.028, 1.029, 1.031, 1.033, 1.034, 1.034, 1.036, 1.036, 1.035, 1.033, 1.034, 1.033, 1.033, 1.032, 1.031, 1.029, 1.029, 1.034, 1.038,
+                            1.001, 1.002, 1.008, 1.011, 1.013, 1.015, 1.014, 1.014, 1.013, 1.012, 1.013, 1.015, 1.019, 1.022, 1.023, 1.025, 1.026, 1.026, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.025, 1.025, 1.026, 1.031, 1.035
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.179, 1.187, 1.194, 1.197, 1.199, 1.201, 1.199, 1.199, 1.198, 1.198, 1.196, 1.195, 1.192, 1.192, 1.191, 1.191, 1.187, 1.182, 1.176, 1.171, 1.162, 1.156, 1.143, 1.132, 1.114, 1.097, 1.081, 1.061, 1.041, 1.019, 1.006, 1.001,
+                            1.187, 1.189, 1.194, 1.197, 1.199, 1.201, 1.201, 1.201, 1.199, 1.199, 1.196, 1.195, 1.195, 1.194, 1.193, 1.192, 1.189, 1.187, 1.181, 1.175, 1.168, 1.157, 1.152, 1.135, 1.122, 1.104, 1.086, 1.069, 1.047, 1.027, 1.012, 1.005,
+                            1.188, 1.189, 1.195, 1.199, 1.201, 1.202, 1.203, 1.204, 1.202, 1.201, 1.201, 1.199, 1.199, 1.201, 1.199, 1.196, 1.195, 1.192, 1.189, 1.183, 1.175, 1.166, 1.155, 1.146, 1.129, 1.117, 1.099, 1.082, 1.061, 1.041, 1.025, 1.012,
+                            1.189, 1.197, 1.199, 1.203, 1.205, 1.207, 1.208, 1.208, 1.208, 1.208, 1.207, 1.207, 1.206, 1.207, 1.207, 1.205, 1.203, 1.202, 1.195, 1.189, 1.183, 1.174, 1.165, 1.154, 1.138, 1.125, 1.108, 1.088, 1.071, 1.049, 1.041, 1.029,
+                            1.198, 1.199, 1.204, 1.207, 1.209, 1.209, 1.209, 1.209, 1.211, 1.211, 1.209, 1.209, 1.209, 1.212, 1.212, 1.212, 1.209, 1.206, 1.202, 1.196, 1.189, 1.182, 1.172, 1.162, 1.151, 1.134, 1.118, 1.099, 1.079, 1.063, 1.049, 1.041,
+                            1.199, 1.204, 1.206, 1.209, 1.211, 1.211, 1.212, 1.213, 1.214, 1.214, 1.214, 1.213, 1.215, 1.216, 1.216, 1.216, 1.213, 1.209, 1.208, 1.202, 1.196, 1.188, 1.179, 1.169, 1.157, 1.142, 1.125, 1.111, 1.088, 1.073, 1.062, 1.054,
+                            1.202, 1.205, 1.208, 1.211, 1.213, 1.215, 1.215, 1.216, 1.216, 1.216, 1.218, 1.219, 1.219, 1.221, 1.221, 1.221, 1.218, 1.215, 1.211, 1.207, 1.202, 1.194, 1.186, 1.177, 1.162, 1.149, 1.137, 1.116, 1.098, 1.082, 1.073, 1.063,
+                            1.202, 1.205, 1.209, 1.213, 1.215, 1.217, 1.218, 1.219, 1.219, 1.221, 1.222, 1.223, 1.223, 1.224, 1.223, 1.223, 1.221, 1.218, 1.215, 1.211, 1.207, 1.201, 1.189, 1.181, 1.171, 1.158, 1.143, 1.129, 1.107, 1.089, 1.081, 1.074,
+                            1.203, 1.207, 1.209, 1.215, 1.217, 1.219, 1.221, 1.222, 1.222, 1.224, 1.225, 1.225, 1.226, 1.227, 1.227, 1.225, 1.223, 1.221, 1.218, 1.215, 1.209, 1.202, 1.195, 1.186, 1.178, 1.164, 1.151, 1.133, 1.115, 1.098, 1.088, 1.083,
+                            1.202, 1.209, 1.213, 1.217, 1.219, 1.221, 1.222, 1.223, 1.224, 1.225, 1.226, 1.228, 1.228, 1.228, 1.228, 1.226, 1.225, 1.223, 1.219, 1.216, 1.212, 1.205, 1.198, 1.192, 1.183, 1.169, 1.154, 1.142, 1.122, 1.106, 1.097, 1.089,
+                            1.206, 1.211, 1.215, 1.218, 1.221, 1.223, 1.224, 1.224, 1.225, 1.226, 1.227, 1.229, 1.229, 1.229, 1.229, 1.228, 1.226, 1.224, 1.222, 1.218, 1.215, 1.209, 1.203, 1.196, 1.188, 1.175, 1.161, 1.149, 1.127, 1.112, 1.103, 1.097,
+                            1.209, 1.213, 1.217, 1.218, 1.222, 1.224, 1.225, 1.225, 1.226, 1.227, 1.229, 1.229, 1.229, 1.229, 1.229, 1.229, 1.227, 1.225, 1.223, 1.221, 1.217, 1.213, 1.207, 1.199, 1.191, 1.179, 1.164, 1.149, 1.133, 1.117, 1.109, 1.103,
+                            1.211, 1.216, 1.218, 1.219, 1.224, 1.225, 1.226, 1.226, 1.227, 1.228, 1.229, 1.229, 1.229, 1.231, 1.231, 1.231, 1.229, 1.227, 1.224, 1.222, 1.219, 1.215, 1.209, 1.202, 1.194, 1.182, 1.169, 1.153, 1.137, 1.122, 1.115, 1.108,
+                            1.211, 1.215, 1.219, 1.219, 1.224, 1.225, 1.227, 1.227, 1.228, 1.229, 1.229, 1.229, 1.229, 1.231, 1.231, 1.231, 1.229, 1.227, 1.226, 1.223, 1.221, 1.217, 1.211, 1.203, 1.195, 1.183, 1.171, 1.156, 1.141, 1.123, 1.116, 1.113,
+                            1.209, 1.215, 1.219, 1.222, 1.225, 1.225, 1.226, 1.226, 1.227, 1.228, 1.229, 1.229, 1.231, 1.231, 1.231, 1.231, 1.231, 1.229, 1.227, 1.224, 1.222, 1.217, 1.211, 1.204, 1.196, 1.184, 1.174, 1.159, 1.142, 1.128, 1.121, 1.114,
+                            1.208, 1.215, 1.218, 1.221, 1.223, 1.223, 1.224, 1.224, 1.226, 1.227, 1.227, 1.228, 1.229, 1.231, 1.231, 1.231, 1.231, 1.229, 1.229, 1.226, 1.223, 1.218, 1.213, 1.207, 1.197, 1.188, 1.176, 1.161, 1.143, 1.129, 1.121, 1.114,
+                            1.208, 1.213, 1.216, 1.219, 1.221, 1.221, 1.222, 1.223, 1.224, 1.225, 1.226, 1.227, 1.228, 1.231, 1.231, 1.231, 1.231, 1.231, 1.229, 1.227, 1.224, 1.218, 1.214, 1.207, 1.197, 1.188, 1.177, 1.161, 1.145, 1.131, 1.122, 1.115,
+                            1.207, 1.208, 1.214, 1.214, 1.217, 1.218, 1.219, 1.221, 1.223, 1.224, 1.225, 1.225, 1.226, 1.227, 1.228, 1.228, 1.229, 1.229, 1.228, 1.226, 1.223, 1.219, 1.215, 1.207, 1.198, 1.188, 1.177, 1.161, 1.147, 1.131, 1.123, 1.116,
+                            1.199, 1.204, 1.208, 1.208, 1.211, 1.212, 1.215, 1.218, 1.221, 1.221, 1.222, 1.223, 1.223, 1.225, 1.225, 1.227, 1.226, 1.227, 1.226, 1.225, 1.223, 1.219, 1.212, 1.207, 1.198, 1.187, 1.177, 1.161, 1.146, 1.131, 1.123, 1.116,
+                            1.193, 1.196, 1.199, 1.201, 1.204, 1.206, 1.209, 1.213, 1.215, 1.217, 1.218, 1.219, 1.221, 1.221, 1.221, 1.222, 1.223, 1.224, 1.224, 1.223, 1.222, 1.218, 1.211, 1.207, 1.197, 1.187, 1.175, 1.161, 1.146, 1.129, 1.122, 1.113,
+                            1.177, 1.182, 1.188, 1.192, 1.195, 1.198, 1.203, 1.208, 1.211, 1.212, 1.214, 1.214, 1.214, 1.215, 1.216, 1.217, 1.219, 1.221, 1.223, 1.222, 1.221, 1.216, 1.212, 1.204, 1.197, 1.186, 1.175, 1.159, 1.143, 1.129, 1.119, 1.114,
+                            1.162, 1.171, 1.177, 1.183, 1.187, 1.192, 1.196, 1.201, 1.204, 1.205, 1.206, 1.207, 1.208, 1.209, 1.212, 1.215, 1.216, 1.219, 1.221, 1.219, 1.218, 1.214, 1.211, 1.203, 1.195, 1.184, 1.173, 1.157, 1.139, 1.128, 1.117, 1.113,
+                            1.149, 1.158, 1.167, 1.172, 1.178, 1.184, 1.189, 1.193, 1.195, 1.196, 1.201, 1.201, 1.201, 1.206, 1.209, 1.212, 1.214, 1.216, 1.218, 1.218, 1.216, 1.212, 1.207, 1.201, 1.192, 1.181, 1.167, 1.155, 1.136, 1.121, 1.114, 1.107,
+                            1.137, 1.147, 1.155, 1.161, 1.169, 1.174, 1.179, 1.183, 1.188, 1.189, 1.193, 1.196, 1.199, 1.201, 1.206, 1.209, 1.213, 1.214, 1.215, 1.214, 1.211, 1.208, 1.202, 1.194, 1.186, 1.177, 1.163, 1.149, 1.132, 1.117, 1.109, 1.104,
+                            1.126, 1.136, 1.144, 1.151, 1.157, 1.163, 1.171, 1.177, 1.181, 1.183, 1.186, 1.191, 1.196, 1.201, 1.204, 1.207, 1.211, 1.213, 1.213, 1.211, 1.209, 1.204, 1.199, 1.191, 1.183, 1.172, 1.158, 1.144, 1.127, 1.112, 1.105, 1.098,
+                            1.114, 1.125, 1.134, 1.142, 1.147, 1.155, 1.161, 1.166, 1.171, 1.177, 1.181, 1.186, 1.191, 1.197, 1.202, 1.204, 1.207, 1.209, 1.209, 1.209, 1.205, 1.201, 1.195, 1.188, 1.178, 1.168, 1.154, 1.139, 1.122, 1.106, 1.099, 1.095,
+                            1.107, 1.114, 1.123, 1.132, 1.137, 1.144, 1.152, 1.157, 1.162, 1.169, 1.176, 1.181, 1.187, 1.193, 1.198, 1.202, 1.204, 1.205, 1.206, 1.204, 1.201, 1.197, 1.191, 1.183, 1.175, 1.162, 1.149, 1.133, 1.117, 1.103, 1.095, 1.088,
+                            1.094, 1.101, 1.112, 1.117, 1.129, 1.133, 1.141, 1.149, 1.156, 1.161, 1.169, 1.175, 1.182, 1.187, 1.192, 1.196, 1.199, 1.201, 1.201, 1.199, 1.196, 1.192, 1.187, 1.181, 1.171, 1.157, 1.145, 1.128, 1.114, 1.099, 1.088, 1.085,
+                            1.083, 1.091, 1.099, 1.104, 1.112, 1.121, 1.128, 1.139, 1.146, 1.154, 1.159, 1.168, 1.174, 1.182, 1.187, 1.188, 1.193, 1.195, 1.195, 1.194, 1.191, 1.188, 1.182, 1.172, 1.163, 1.154, 1.138, 1.123, 1.109, 1.096, 1.085, 1.079,
+                            1.065, 1.074, 1.082, 1.092, 1.101, 1.109, 1.118, 1.126, 1.133, 1.143, 1.149, 1.158, 1.164, 1.171, 1.176, 1.179, 1.185, 1.186, 1.186, 1.185, 1.184, 1.181, 1.172, 1.165, 1.157, 1.148, 1.133, 1.118, 1.101, 1.086, 1.079, 1.071,
+                            1.045, 1.059, 1.067, 1.076, 1.084, 1.097, 1.106, 1.113, 1.123, 1.129, 1.134, 1.141, 1.149, 1.155, 1.161, 1.165, 1.172, 1.175, 1.177, 1.176, 1.174, 1.172, 1.164, 1.156, 1.148, 1.135, 1.121, 1.108, 1.091, 1.079, 1.067, 1.057,
+                            1.038, 1.045, 1.057, 1.067, 1.075, 1.083, 1.094, 1.102, 1.109, 1.115, 1.122, 1.131, 1.136, 1.144, 1.151, 1.155, 1.161, 1.161, 1.164, 1.164, 1.164, 1.161, 1.158, 1.147, 1.138, 1.125, 1.111, 1.095, 1.079, 1.067, 1.057, 1.051
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2400,
+                        "table":
+                        [
+                            1.261, 1.265, 1.267, 1.273, 1.276, 1.283, 1.283, 1.291, 1.294, 1.299, 1.301, 1.304, 1.304, 1.305, 1.297, 1.301, 1.304, 1.303, 1.301, 1.298, 1.285, 1.271, 1.252, 1.234, 1.204, 1.177, 1.148, 1.115, 1.083, 1.048, 1.004, 1.001,
+                            1.274, 1.283, 1.289, 1.292, 1.299, 1.302, 1.309, 1.314, 1.317, 1.321, 1.322, 1.326, 1.329, 1.332, 1.335, 1.335, 1.335, 1.329, 1.322, 1.311, 1.299, 1.286, 1.265, 1.249, 1.224, 1.201, 1.173, 1.141, 1.111, 1.077, 1.031, 1.004,
+                            1.287, 1.292, 1.299, 1.303, 1.306, 1.312, 1.317, 1.322, 1.327, 1.331, 1.334, 1.338, 1.341, 1.344, 1.345, 1.346, 1.344, 1.339, 1.335, 1.324, 1.312, 1.299, 1.286, 1.265, 1.245, 1.218, 1.193, 1.159, 1.126, 1.094, 1.051, 1.028,
+                            1.297, 1.299, 1.307, 1.311, 1.314, 1.321, 1.325, 1.329, 1.335, 1.339, 1.344, 1.348, 1.349, 1.353, 1.353, 1.355, 1.354, 1.351, 1.345, 1.337, 1.324, 1.311, 1.299, 1.279, 1.256, 1.232, 1.202, 1.173, 1.141, 1.109, 1.066, 1.042,
+                            1.303, 1.309, 1.315, 1.318, 1.324, 1.327, 1.334, 1.339, 1.343, 1.347, 1.352, 1.354, 1.361, 1.364, 1.366, 1.365, 1.365, 1.361, 1.358, 1.349, 1.338, 1.323, 1.309, 1.292, 1.269, 1.244, 1.217, 1.189, 1.157, 1.121, 1.079, 1.057,
+                            1.312, 1.316, 1.322, 1.326, 1.329, 1.337, 1.341, 1.346, 1.351, 1.353, 1.358, 1.365, 1.368, 1.371, 1.373, 1.373, 1.373, 1.367, 1.363, 1.358, 1.349, 1.336, 1.319, 1.301, 1.285, 1.257, 1.231, 1.201, 1.168, 1.137, 1.094, 1.065,
+                            1.317, 1.323, 1.329, 1.332, 1.338, 1.342, 1.349, 1.353, 1.356, 1.361, 1.367, 1.372, 1.375, 1.379, 1.381, 1.381, 1.379, 1.377, 1.371, 1.364, 1.357, 1.345, 1.333, 1.312, 1.292, 1.267, 1.239, 1.211, 1.181, 1.142, 1.105, 1.078,
+                            1.321, 1.329, 1.334, 1.341, 1.343, 1.351, 1.355, 1.359, 1.361, 1.368, 1.373, 1.377, 1.381, 1.385, 1.387, 1.387, 1.385, 1.381, 1.376, 1.371, 1.362, 1.351, 1.338, 1.319, 1.299, 1.276, 1.252, 1.221, 1.189, 1.156, 1.113, 1.086,
+                            1.328, 1.334, 1.341, 1.344, 1.351, 1.353, 1.359, 1.363, 1.368, 1.374, 1.377, 1.382, 1.385, 1.389, 1.392, 1.391, 1.389, 1.387, 1.381, 1.375, 1.367, 1.359, 1.345, 1.327, 1.311, 1.284, 1.261, 1.231, 1.201, 1.169, 1.121, 1.091,
+                            1.331, 1.338, 1.343, 1.347, 1.352, 1.358, 1.362, 1.367, 1.371, 1.375, 1.379, 1.385, 1.389, 1.393, 1.395, 1.396, 1.393, 1.391, 1.385, 1.378, 1.373, 1.362, 1.349, 1.335, 1.313, 1.291, 1.265, 1.238, 1.209, 1.175, 1.129, 1.098,
+                            1.331, 1.341, 1.345, 1.349, 1.355, 1.359, 1.364, 1.368, 1.372, 1.378, 1.381, 1.388, 1.392, 1.394, 1.397, 1.397, 1.396, 1.392, 1.388, 1.382, 1.374, 1.363, 1.353, 1.337, 1.317, 1.295, 1.274, 1.244, 1.216, 1.183, 1.138, 1.101,
+                            1.329, 1.341, 1.345, 1.351, 1.355, 1.361, 1.365, 1.368, 1.373, 1.377, 1.381, 1.387, 1.391, 1.394, 1.396, 1.397, 1.397, 1.393, 1.389, 1.383, 1.375, 1.366, 1.357, 1.339, 1.321, 1.299, 1.276, 1.247, 1.219, 1.187, 1.141, 1.108,
+                            1.331, 1.342, 1.345, 1.351, 1.357, 1.361, 1.365, 1.369, 1.372, 1.377, 1.381, 1.385, 1.391, 1.393, 1.396, 1.396, 1.396, 1.394, 1.389, 1.384, 1.375, 1.368, 1.358, 1.339, 1.324, 1.302, 1.278, 1.251, 1.221, 1.192, 1.146, 1.113,
+                            1.332, 1.341, 1.346, 1.352, 1.356, 1.361, 1.365, 1.369, 1.372, 1.376, 1.379, 1.384, 1.389, 1.392, 1.395, 1.396, 1.396, 1.394, 1.391, 1.386, 1.381, 1.368, 1.358, 1.341, 1.325, 1.303, 1.279, 1.252, 1.224, 1.194, 1.148, 1.117,
+                            1.332, 1.339, 1.346, 1.351, 1.355, 1.358, 1.363, 1.367, 1.371, 1.375, 1.378, 1.384, 1.387, 1.392, 1.395, 1.396, 1.395, 1.393, 1.389, 1.385, 1.381, 1.368, 1.357, 1.342, 1.325, 1.302, 1.279, 1.252, 1.224, 1.195, 1.151, 1.119,
+                            1.332, 1.338, 1.344, 1.349, 1.354, 1.357, 1.361, 1.366, 1.369, 1.373, 1.377, 1.383, 1.388, 1.391, 1.392, 1.395, 1.393, 1.393, 1.391, 1.386, 1.379, 1.367, 1.356, 1.342, 1.324, 1.302, 1.279, 1.253, 1.224, 1.195, 1.152, 1.118,
+                            1.331, 1.335, 1.339, 1.346, 1.351, 1.355, 1.357, 1.363, 1.367, 1.372, 1.377, 1.381, 1.386, 1.388, 1.392, 1.393, 1.393, 1.392, 1.389, 1.385, 1.377, 1.367, 1.356, 1.341, 1.325, 1.303, 1.279, 1.252, 1.224, 1.195, 1.152, 1.118,
+                            1.324, 1.329, 1.335, 1.339, 1.347, 1.351, 1.356, 1.359, 1.364, 1.369, 1.375, 1.378, 1.383, 1.388, 1.389, 1.392, 1.392, 1.391, 1.387, 1.383, 1.376, 1.366, 1.355, 1.342, 1.324, 1.302, 1.279, 1.253, 1.225, 1.196, 1.153, 1.116,
+                            1.314, 1.318, 1.328, 1.333, 1.339, 1.345, 1.349, 1.356, 1.361, 1.366, 1.371, 1.376, 1.381, 1.383, 1.387, 1.388, 1.388, 1.387, 1.385, 1.381, 1.376, 1.367, 1.356, 1.341, 1.323, 1.303, 1.279, 1.252, 1.226, 1.196, 1.153, 1.117,
+                            1.303, 1.312, 1.318, 1.322, 1.328, 1.338, 1.345, 1.348, 1.357, 1.362, 1.367, 1.371, 1.375, 1.379, 1.382, 1.384, 1.384, 1.384, 1.382, 1.379, 1.375, 1.365, 1.356, 1.339, 1.322, 1.301, 1.278, 1.251, 1.224, 1.195, 1.152, 1.117,
+                            1.288, 1.299, 1.305, 1.313, 1.321, 1.328, 1.339, 1.345, 1.348, 1.355, 1.362, 1.365, 1.369, 1.373, 1.377, 1.379, 1.381, 1.381, 1.381, 1.377, 1.372, 1.363, 1.353, 1.338, 1.319, 1.299, 1.277, 1.249, 1.219, 1.194, 1.149, 1.116,
+                            1.277, 1.286, 1.293, 1.302, 1.309, 1.319, 1.327, 1.336, 1.342, 1.346, 1.351, 1.357, 1.362, 1.367, 1.371, 1.374, 1.375, 1.377, 1.377, 1.374, 1.368, 1.359, 1.349, 1.335, 1.318, 1.296, 1.271, 1.245, 1.217, 1.193, 1.147, 1.112,
+                            1.256, 1.271, 1.277, 1.288, 1.293, 1.305, 1.316, 1.322, 1.331, 1.336, 1.343, 1.348, 1.354, 1.359, 1.366, 1.368, 1.371, 1.373, 1.372, 1.368, 1.362, 1.356, 1.343, 1.329, 1.311, 1.291, 1.266, 1.238, 1.214, 1.184, 1.142, 1.111,
+                            1.234, 1.251, 1.261, 1.269, 1.282, 1.291, 1.302, 1.313, 1.319, 1.327, 1.334, 1.341, 1.348, 1.353, 1.359, 1.365, 1.367, 1.367, 1.366, 1.362, 1.356, 1.349, 1.339, 1.322, 1.304, 1.284, 1.261, 1.235, 1.208, 1.178, 1.136, 1.104,
+                            1.218, 1.231, 1.244, 1.253, 1.265, 1.278, 1.289, 1.297, 1.304, 1.316, 1.325, 1.333, 1.339, 1.346, 1.351, 1.356, 1.361, 1.361, 1.361, 1.355, 1.349, 1.341, 1.328, 1.314, 1.299, 1.278, 1.255, 1.229, 1.203, 1.175, 1.133, 1.099,
+                            1.199, 1.214, 1.227, 1.235, 1.247, 1.262, 1.271, 1.283, 1.292, 1.301, 1.311, 1.322, 1.331, 1.338, 1.342, 1.349, 1.353, 1.353, 1.351, 1.347, 1.341, 1.331, 1.321, 1.308, 1.289, 1.269, 1.246, 1.219, 1.195, 1.167, 1.127, 1.096,
+                            1.179, 1.195, 1.207, 1.218, 1.231, 1.241, 1.257, 1.267, 1.278, 1.288, 1.297, 1.309, 1.321, 1.328, 1.333, 1.338, 1.344, 1.346, 1.342, 1.336, 1.331, 1.323, 1.312, 1.298, 1.284, 1.262, 1.241, 1.214, 1.191, 1.162, 1.118, 1.092,
+                            1.159, 1.174, 1.189, 1.198, 1.209, 1.225, 1.238, 1.252, 1.261, 1.272, 1.286, 1.295, 1.306, 1.314, 1.324, 1.327, 1.332, 1.333, 1.333, 1.329, 1.322, 1.314, 1.303, 1.293, 1.275, 1.253, 1.231, 1.207, 1.181, 1.151, 1.112, 1.081,
+                            1.142, 1.156, 1.168, 1.179, 1.192, 1.206, 1.221, 1.232, 1.243, 1.255, 1.269, 1.278, 1.291, 1.303, 1.311, 1.313, 1.316, 1.319, 1.321, 1.318, 1.314, 1.303, 1.295, 1.281, 1.268, 1.248, 1.225, 1.197, 1.174, 1.147, 1.106, 1.077,
+                            1.119, 1.134, 1.145, 1.159, 1.171, 1.186, 1.199, 1.212, 1.223, 1.236, 1.247, 1.259, 1.272, 1.281, 1.291, 1.297, 1.299, 1.307, 1.308, 1.306, 1.302, 1.294, 1.284, 1.272, 1.257, 1.239, 1.215, 1.188, 1.163, 1.136, 1.099, 1.069,
+                            1.101, 1.114, 1.126, 1.134, 1.151, 1.163, 1.181, 1.189, 1.202, 1.216, 1.229, 1.239, 1.252, 1.262, 1.269, 1.283, 1.288, 1.293, 1.294, 1.292, 1.289, 1.284, 1.272, 1.261, 1.244, 1.228, 1.204, 1.178, 1.154, 1.131, 1.089, 1.062,
+                            1.087, 1.098, 1.112, 1.124, 1.134, 1.148, 1.161, 1.175, 1.185, 1.201, 1.212, 1.224, 1.236, 1.248, 1.259, 1.268, 1.274, 1.275, 1.275, 1.276, 1.276, 1.272, 1.263, 1.247, 1.232, 1.212, 1.192, 1.166, 1.143, 1.115, 1.078, 1.051
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.333, 1.336, 1.336, 1.343, 1.347, 1.356, 1.361, 1.364, 1.366, 1.371, 1.371, 1.377, 1.382, 1.385, 1.385, 1.385, 1.381, 1.381, 1.375, 1.369, 1.363, 1.348, 1.326, 1.298, 1.269, 1.241, 1.207, 1.169, 1.134, 1.096, 1.044, 1.038,
+                            1.345, 1.351, 1.361, 1.365, 1.369, 1.376, 1.384, 1.389, 1.389, 1.395, 1.398, 1.403, 1.406, 1.409, 1.411, 1.409, 1.409, 1.408, 1.401, 1.389, 1.379, 1.359, 1.339, 1.319, 1.294, 1.264, 1.235, 1.199, 1.163, 1.127, 1.074, 1.044,
+                            1.359, 1.362, 1.375, 1.377, 1.381, 1.388, 1.394, 1.397, 1.401, 1.403, 1.407, 1.413, 1.417, 1.419, 1.422, 1.425, 1.425, 1.419, 1.413, 1.403, 1.391, 1.379, 1.359, 1.339, 1.315, 1.287, 1.254, 1.219, 1.184, 1.151, 1.098, 1.071,
+                            1.366, 1.376, 1.382, 1.386, 1.391, 1.397, 1.401, 1.404, 1.408, 1.411, 1.419, 1.421, 1.426, 1.429, 1.433, 1.433, 1.431, 1.429, 1.423, 1.415, 1.403, 1.391, 1.373, 1.351, 1.329, 1.301, 1.269, 1.231, 1.198, 1.164, 1.118, 1.089,
+                            1.378, 1.383, 1.393, 1.396, 1.399, 1.403, 1.411, 1.414, 1.419, 1.423, 1.426, 1.432, 1.439, 1.444, 1.445, 1.444, 1.442, 1.439, 1.432, 1.424, 1.416, 1.399, 1.385, 1.361, 1.343, 1.314, 1.283, 1.249, 1.215, 1.179, 1.131, 1.098,
+                            1.385, 1.394, 1.399, 1.401, 1.406, 1.412, 1.418, 1.423, 1.427, 1.431, 1.435, 1.442, 1.446, 1.451, 1.452, 1.451, 1.448, 1.445, 1.443, 1.434, 1.424, 1.411, 1.393, 1.377, 1.352, 1.329, 1.296, 1.264, 1.228, 1.195, 1.145, 1.114,
+                            1.391, 1.401, 1.404, 1.408, 1.413, 1.419, 1.425, 1.428, 1.432, 1.437, 1.442, 1.451, 1.453, 1.456, 1.459, 1.461, 1.459, 1.453, 1.449, 1.443, 1.434, 1.419, 1.404, 1.387, 1.362, 1.338, 1.306, 1.272, 1.238, 1.207, 1.153, 1.126,
+                            1.399, 1.405, 1.412, 1.415, 1.419, 1.425, 1.429, 1.436, 1.441, 1.444, 1.451, 1.454, 1.457, 1.463, 1.466, 1.466, 1.465, 1.461, 1.454, 1.449, 1.441, 1.427, 1.414, 1.393, 1.376, 1.347, 1.321, 1.286, 1.251, 1.216, 1.169, 1.134,
+                            1.399, 1.412, 1.416, 1.419, 1.424, 1.429, 1.436, 1.441, 1.445, 1.449, 1.455, 1.461, 1.463, 1.468, 1.472, 1.471, 1.471, 1.468, 1.459, 1.454, 1.445, 1.435, 1.419, 1.402, 1.382, 1.354, 1.329, 1.296, 1.259, 1.225, 1.175, 1.143,
+                            1.403, 1.416, 1.419, 1.423, 1.427, 1.434, 1.439, 1.443, 1.449, 1.452, 1.459, 1.463, 1.468, 1.472, 1.473, 1.472, 1.471, 1.469, 1.466, 1.455, 1.449, 1.438, 1.425, 1.408, 1.389, 1.362, 1.337, 1.304, 1.271, 1.233, 1.184, 1.148,
+                            1.404, 1.418, 1.421, 1.425, 1.429, 1.436, 1.441, 1.444, 1.449, 1.453, 1.461, 1.465, 1.471, 1.472, 1.474, 1.474, 1.472, 1.471, 1.467, 1.459, 1.451, 1.441, 1.428, 1.411, 1.393, 1.368, 1.341, 1.309, 1.277, 1.239, 1.189, 1.152,
+                            1.404, 1.417, 1.421, 1.425, 1.431, 1.437, 1.441, 1.445, 1.449, 1.453, 1.461, 1.465, 1.469, 1.471, 1.472, 1.475, 1.474, 1.471, 1.466, 1.461, 1.452, 1.442, 1.431, 1.411, 1.395, 1.371, 1.345, 1.313, 1.279, 1.242, 1.194, 1.156,
+                            1.405, 1.417, 1.421, 1.428, 1.433, 1.437, 1.441, 1.445, 1.449, 1.453, 1.459, 1.462, 1.467, 1.469, 1.472, 1.475, 1.475, 1.471, 1.467, 1.461, 1.452, 1.443, 1.431, 1.414, 1.396, 1.372, 1.346, 1.315, 1.284, 1.249, 1.199, 1.161,
+                            1.409, 1.418, 1.422, 1.426, 1.432, 1.436, 1.439, 1.444, 1.447, 1.452, 1.457, 1.461, 1.464, 1.469, 1.471, 1.474, 1.474, 1.471, 1.467, 1.462, 1.452, 1.445, 1.431, 1.415, 1.395, 1.374, 1.349, 1.314, 1.285, 1.253, 1.201, 1.165,
+                            1.409, 1.418, 1.421, 1.425, 1.429, 1.433, 1.437, 1.441, 1.446, 1.451, 1.454, 1.459, 1.463, 1.467, 1.469, 1.473, 1.473, 1.469, 1.466, 1.461, 1.455, 1.445, 1.431, 1.416, 1.396, 1.373, 1.349, 1.316, 1.286, 1.254, 1.205, 1.165,
+                            1.409, 1.412, 1.421, 1.422, 1.426, 1.429, 1.436, 1.439, 1.443, 1.449, 1.452, 1.457, 1.462, 1.465, 1.469, 1.471, 1.471, 1.469, 1.467, 1.461, 1.455, 1.445, 1.431, 1.416, 1.396, 1.372, 1.349, 1.317, 1.286, 1.254, 1.205, 1.165,
+                            1.403, 1.409, 1.413, 1.419, 1.423, 1.429, 1.432, 1.437, 1.441, 1.445, 1.451, 1.455, 1.462, 1.464, 1.468, 1.471, 1.471, 1.469, 1.465, 1.461, 1.455, 1.443, 1.429, 1.414, 1.397, 1.372, 1.349, 1.316, 1.286, 1.254, 1.205, 1.163,
+                            1.396, 1.402, 1.409, 1.414, 1.419, 1.423, 1.429, 1.434, 1.439, 1.444, 1.448, 1.453, 1.456, 1.462, 1.463, 1.468, 1.469, 1.468, 1.465, 1.459, 1.452, 1.442, 1.429, 1.412, 1.396, 1.373, 1.349, 1.315, 1.287, 1.253, 1.206, 1.163,
+                            1.389, 1.393, 1.402, 1.406, 1.414, 1.418, 1.424, 1.431, 1.435, 1.441, 1.447, 1.449, 1.455, 1.457, 1.461, 1.462, 1.466, 1.465, 1.461, 1.458, 1.451, 1.442, 1.428, 1.412, 1.395, 1.372, 1.347, 1.315, 1.287, 1.252, 1.205, 1.164,
+                            1.373, 1.385, 1.388, 1.394, 1.403, 1.408, 1.418, 1.424, 1.431, 1.437, 1.441, 1.447, 1.449, 1.454, 1.456, 1.459, 1.461, 1.461, 1.459, 1.457, 1.449, 1.439, 1.427, 1.412, 1.394, 1.371, 1.346, 1.315, 1.284, 1.249, 1.202, 1.162,
+                            1.359, 1.371, 1.377, 1.383, 1.392, 1.403, 1.408, 1.416, 1.423, 1.431, 1.437, 1.439, 1.444, 1.447, 1.451, 1.455, 1.458, 1.459, 1.457, 1.453, 1.447, 1.435, 1.425, 1.409, 1.391, 1.367, 1.341, 1.312, 1.281, 1.246, 1.199, 1.161,
+                            1.345, 1.356, 1.363, 1.371, 1.379, 1.389, 1.401, 1.408, 1.415, 1.421, 1.428, 1.431, 1.436, 1.441, 1.446, 1.449, 1.453, 1.453, 1.453, 1.449, 1.443, 1.433, 1.421, 1.406, 1.389, 1.364, 1.337, 1.306, 1.274, 1.244, 1.197, 1.158,
+                            1.321, 1.337, 1.344, 1.355, 1.362, 1.376, 1.387, 1.396, 1.403, 1.409, 1.416, 1.423, 1.428, 1.433, 1.438, 1.444, 1.447, 1.449, 1.449, 1.443, 1.438, 1.428, 1.417, 1.397, 1.381, 1.359, 1.331, 1.301, 1.271, 1.236, 1.188, 1.157,
+                            1.298, 1.315, 1.325, 1.332, 1.344, 1.357, 1.368, 1.383, 1.391, 1.398, 1.404, 1.413, 1.422, 1.427, 1.434, 1.438, 1.442, 1.443, 1.443, 1.439, 1.431, 1.419, 1.409, 1.394, 1.372, 1.353, 1.325, 1.296, 1.261, 1.231, 1.183, 1.148,
+                            1.278, 1.294, 1.304, 1.316, 1.328, 1.341, 1.353, 1.362, 1.375, 1.386, 1.392, 1.402, 1.411, 1.421, 1.426, 1.431, 1.436, 1.436, 1.436, 1.431, 1.421, 1.414, 1.401, 1.387, 1.365, 1.344, 1.319, 1.289, 1.258, 1.226, 1.178, 1.142,
+                            1.259, 1.273, 1.287, 1.296, 1.311, 1.322, 1.335, 1.349, 1.358, 1.371, 1.381, 1.392, 1.399, 1.411, 1.417, 1.423, 1.425, 1.425, 1.424, 1.419, 1.414, 1.404, 1.392, 1.373, 1.359, 1.336, 1.311, 1.282, 1.249, 1.216, 1.175, 1.139,
+                            1.234, 1.253, 1.266, 1.276, 1.291, 1.301, 1.315, 1.328, 1.344, 1.355, 1.364, 1.377, 1.386, 1.397, 1.406, 1.412, 1.416, 1.419, 1.417, 1.409, 1.404, 1.394, 1.383, 1.368, 1.351, 1.329, 1.301, 1.271, 1.242, 1.208, 1.162, 1.131,
+                            1.213, 1.229, 1.245, 1.254, 1.267, 1.282, 1.297, 1.311, 1.325, 1.337, 1.351, 1.362, 1.374, 1.381, 1.393, 1.399, 1.402, 1.404, 1.404, 1.402, 1.394, 1.384, 1.373, 1.361, 1.342, 1.319, 1.293, 1.266, 1.234, 1.204, 1.157, 1.125,
+                            1.188, 1.208, 1.221, 1.231, 1.245, 1.263, 1.276, 1.291, 1.302, 1.317, 1.333, 1.341, 1.358, 1.366, 1.373, 1.382, 1.386, 1.388, 1.391, 1.388, 1.382, 1.375, 1.365, 1.351, 1.333, 1.311, 1.284, 1.254, 1.225, 1.198, 1.152, 1.121,
+                            1.165, 1.182, 1.195, 1.209, 1.221, 1.239, 1.254, 1.268, 1.278, 1.296, 1.309, 1.322, 1.337, 1.348, 1.355, 1.365, 1.371, 1.374, 1.375, 1.373, 1.372, 1.365, 1.352, 1.341, 1.321, 1.301, 1.273, 1.242, 1.212, 1.183, 1.141, 1.111,
+                            1.141, 1.159, 1.173, 1.183, 1.198, 1.215, 1.229, 1.245, 1.258, 1.271, 1.286, 1.299, 1.317, 1.326, 1.334, 1.347, 1.355, 1.359, 1.362, 1.362, 1.358, 1.351, 1.341, 1.325, 1.307, 1.289, 1.259, 1.233, 1.203, 1.175, 1.119, 1.062,
+                            1.126, 1.139, 1.155, 1.171, 1.182, 1.197, 1.211, 1.225, 1.241, 1.255, 1.267, 1.281, 1.295, 1.309, 1.321, 1.331, 1.337, 1.341, 1.342, 1.343, 1.342, 1.341, 1.329, 1.311, 1.292, 1.271, 1.245, 1.217, 1.189, 1.152, 1.075, 1.049
+                        ]
+                    },
+                    {
+                        "ct": 5000,
+                        "table":
+                        [
+                            1.413, 1.419, 1.423, 1.434, 1.444, 1.447, 1.455, 1.456, 1.459, 1.462, 1.466, 1.469, 1.478, 1.481, 1.482, 1.479, 1.477, 1.474, 1.463, 1.457, 1.445, 1.427, 1.396, 1.368, 1.329, 1.287, 1.247, 1.212, 1.165, 1.123, 1.064, 1.049,
+                            1.434, 1.446, 1.456, 1.464, 1.473, 1.478, 1.491, 1.492, 1.495, 1.502, 1.507, 1.509, 1.512, 1.522, 1.523, 1.519, 1.512, 1.505, 1.499, 1.487, 1.468, 1.451, 1.422, 1.389, 1.354, 1.321, 1.281, 1.242, 1.199, 1.157, 1.105, 1.064,
+                            1.454, 1.459, 1.476, 1.484, 1.489, 1.496, 1.505, 1.515, 1.514, 1.522, 1.529, 1.533, 1.535, 1.542, 1.544, 1.543, 1.539, 1.536, 1.527, 1.513, 1.495, 1.469, 1.451, 1.422, 1.387, 1.352, 1.313, 1.272, 1.227, 1.189, 1.131, 1.097,
+                            1.467, 1.479, 1.488, 1.495, 1.502, 1.512, 1.519, 1.529, 1.534, 1.539, 1.546, 1.551, 1.553, 1.558, 1.562, 1.561, 1.558, 1.554, 1.542, 1.532, 1.514, 1.496, 1.469, 1.446, 1.407, 1.379, 1.335, 1.296, 1.249, 1.211, 1.149, 1.123,
+                            1.485, 1.495, 1.504, 1.509, 1.517, 1.525, 1.539, 1.543, 1.553, 1.558, 1.559, 1.565, 1.568, 1.573, 1.582, 1.582, 1.577, 1.573, 1.563, 1.549, 1.537, 1.514, 1.489, 1.461, 1.434, 1.399, 1.356, 1.316, 1.271, 1.231, 1.168, 1.135,
+                            1.499, 1.504, 1.514, 1.522, 1.531, 1.543, 1.549, 1.561, 1.563, 1.568, 1.579, 1.585, 1.591, 1.595, 1.595, 1.596, 1.595, 1.589, 1.583, 1.569, 1.552, 1.537, 1.511, 1.486, 1.457, 1.418, 1.379, 1.334, 1.291, 1.254, 1.189, 1.149,
+                            1.506, 1.514, 1.527, 1.535, 1.543, 1.553, 1.562, 1.569, 1.577, 1.583, 1.594, 1.601, 1.606, 1.611, 1.612, 1.612, 1.609, 1.604, 1.594, 1.585, 1.569, 1.551, 1.531, 1.502, 1.472, 1.429, 1.396, 1.352, 1.311, 1.264, 1.201, 1.167,
+                            1.513, 1.527, 1.537, 1.546, 1.553, 1.563, 1.576, 1.584, 1.588, 1.595, 1.605, 1.611, 1.617, 1.623, 1.625, 1.623, 1.622, 1.616, 1.607, 1.597, 1.583, 1.563, 1.541, 1.518, 1.489, 1.452, 1.409, 1.372, 1.324, 1.281, 1.221, 1.181,
+                            1.525, 1.537, 1.547, 1.554, 1.561, 1.575, 1.584, 1.591, 1.596, 1.605, 1.613, 1.621, 1.627, 1.633, 1.634, 1.635, 1.631, 1.626, 1.618, 1.608, 1.594, 1.577, 1.555, 1.533, 1.501, 1.467, 1.431, 1.387, 1.341, 1.295, 1.232, 1.189,
+                            1.529, 1.546, 1.552, 1.561, 1.569, 1.581, 1.588, 1.595, 1.604, 1.613, 1.621, 1.626, 1.634, 1.639, 1.639, 1.643, 1.638, 1.634, 1.626, 1.616, 1.605, 1.586, 1.567, 1.548, 1.512, 1.478, 1.445, 1.398, 1.357, 1.313, 1.244, 1.209,
+                            1.529, 1.549, 1.558, 1.565, 1.571, 1.583, 1.593, 1.601, 1.608, 1.618, 1.624, 1.631, 1.639, 1.643, 1.644, 1.644, 1.644, 1.641, 1.633, 1.621, 1.613, 1.594, 1.578, 1.551, 1.524, 1.486, 1.449, 1.408, 1.363, 1.321, 1.255, 1.214,
+                            1.529, 1.552, 1.561, 1.567, 1.577, 1.587, 1.595, 1.604, 1.611, 1.619, 1.626, 1.633, 1.642, 1.648, 1.649, 1.648, 1.645, 1.643, 1.637, 1.627, 1.617, 1.601, 1.584, 1.555, 1.529, 1.493, 1.462, 1.418, 1.373, 1.328, 1.266, 1.225,
+                            1.534, 1.551, 1.562, 1.568, 1.581, 1.591, 1.596, 1.605, 1.612, 1.619, 1.628, 1.633, 1.642, 1.648, 1.651, 1.652, 1.649, 1.643, 1.639, 1.632, 1.619, 1.604, 1.586, 1.561, 1.536, 1.499, 1.466, 1.423, 1.379, 1.335, 1.272, 1.233,
+                            1.535, 1.551, 1.562, 1.569, 1.581, 1.591, 1.598, 1.604, 1.612, 1.619, 1.629, 1.634, 1.639, 1.647, 1.649, 1.652, 1.649, 1.646, 1.643, 1.634, 1.622, 1.606, 1.588, 1.564, 1.538, 1.502, 1.469, 1.425, 1.382, 1.341, 1.275, 1.236,
+                            1.535, 1.549, 1.561, 1.569, 1.578, 1.587, 1.598, 1.604, 1.609, 1.619, 1.629, 1.633, 1.638, 1.644, 1.649, 1.651, 1.649, 1.647, 1.642, 1.634, 1.622, 1.607, 1.588, 1.564, 1.538, 1.505, 1.471, 1.431, 1.385, 1.346, 1.281, 1.236,
+                            1.534, 1.548, 1.559, 1.565, 1.574, 1.585, 1.593, 1.599, 1.607, 1.618, 1.626, 1.631, 1.637, 1.644, 1.648, 1.651, 1.649, 1.647, 1.642, 1.634, 1.625, 1.608, 1.589, 1.566, 1.539, 1.506, 1.472, 1.432, 1.388, 1.347, 1.284, 1.241,
+                            1.532, 1.543, 1.554, 1.562, 1.569, 1.581, 1.592, 1.598, 1.603, 1.614, 1.623, 1.628, 1.634, 1.641, 1.645, 1.647, 1.648, 1.645, 1.641, 1.633, 1.625, 1.606, 1.589, 1.565, 1.538, 1.505, 1.472, 1.431, 1.392, 1.347, 1.287, 1.239,
+                            1.519, 1.531, 1.544, 1.557, 1.565, 1.578, 1.586, 1.594, 1.601, 1.609, 1.619, 1.626, 1.632, 1.641, 1.644, 1.646, 1.647, 1.644, 1.639, 1.631, 1.622, 1.605, 1.589, 1.566, 1.538, 1.505, 1.472, 1.431, 1.392, 1.347, 1.283, 1.227,
+                            1.509, 1.517, 1.531, 1.545, 1.559, 1.567, 1.579, 1.586, 1.596, 1.606, 1.612, 1.621, 1.629, 1.634, 1.637, 1.643, 1.643, 1.641, 1.634, 1.629, 1.621, 1.604, 1.586, 1.566, 1.538, 1.506, 1.471, 1.431, 1.391, 1.336, 1.263, 1.171,
+                            1.492, 1.506, 1.517, 1.528, 1.541, 1.557, 1.568, 1.578, 1.589, 1.598, 1.606, 1.612, 1.621, 1.629, 1.632, 1.634, 1.633, 1.633, 1.631, 1.625, 1.617, 1.601, 1.583, 1.564, 1.535, 1.504, 1.468, 1.431, 1.384, 1.306, 1.205, 1.159,
+                            1.471, 1.486, 1.503, 1.511, 1.525, 1.541, 1.554, 1.565, 1.577, 1.589, 1.597, 1.602, 1.611, 1.617, 1.621, 1.625, 1.625, 1.629, 1.626, 1.622, 1.612, 1.595, 1.578, 1.556, 1.532, 1.499, 1.466, 1.423, 1.379, 1.306, 1.201, 1.145,
+                            1.446, 1.464, 1.481, 1.493, 1.508, 1.523, 1.539, 1.551, 1.561, 1.575, 1.586, 1.592, 1.598, 1.606, 1.612, 1.617, 1.618, 1.622, 1.619, 1.613, 1.604, 1.588, 1.575, 1.551, 1.528, 1.493, 1.457, 1.416, 1.375, 1.326, 1.212, 1.159,
+                            1.419, 1.443, 1.453, 1.468, 1.486, 1.501, 1.519, 1.534, 1.544, 1.558, 1.568, 1.577, 1.585, 1.594, 1.602, 1.607, 1.612, 1.611, 1.609, 1.605, 1.592, 1.581, 1.565, 1.543, 1.516, 1.481, 1.444, 1.405, 1.366, 1.324, 1.254, 1.172,
+                            1.389, 1.415, 1.426, 1.441, 1.463, 1.479, 1.494, 1.515, 1.525, 1.538, 1.555, 1.562, 1.571, 1.579, 1.589, 1.595, 1.601, 1.601, 1.598, 1.592, 1.581, 1.571, 1.553, 1.526, 1.501, 1.472, 1.437, 1.397, 1.355, 1.316, 1.252, 1.212,
+                            1.364, 1.386, 1.405, 1.419, 1.436, 1.456, 1.474, 1.491, 1.504, 1.519, 1.533, 1.541, 1.557, 1.565, 1.573, 1.584, 1.587, 1.588, 1.587, 1.578, 1.571, 1.555, 1.534, 1.514, 1.491, 1.457, 1.425, 1.386, 1.347, 1.304, 1.248, 1.209,
+                            1.335, 1.358, 1.376, 1.395, 1.412, 1.431, 1.449, 1.466, 1.482, 1.495, 1.509, 1.527, 1.538, 1.551, 1.561, 1.566, 1.573, 1.573, 1.569, 1.561, 1.554, 1.541, 1.525, 1.501, 1.476, 1.446, 1.413, 1.372, 1.328, 1.295, 1.235, 1.206,
+                            1.309, 1.333, 1.353, 1.367, 1.386, 1.401, 1.424, 1.441, 1.459, 1.474, 1.489, 1.505, 1.517, 1.533, 1.544, 1.548, 1.553, 1.555, 1.555, 1.546, 1.541, 1.525, 1.507, 1.485, 1.464, 1.435, 1.396, 1.351, 1.317, 1.279, 1.224, 1.188,
+                            1.279, 1.304, 1.326, 1.337, 1.353, 1.379, 1.395, 1.415, 1.432, 1.447, 1.469, 1.482, 1.498, 1.514, 1.524, 1.532, 1.537, 1.537, 1.536, 1.532, 1.522, 1.507, 1.488, 1.472, 1.452, 1.413, 1.378, 1.342, 1.308, 1.271, 1.213, 1.171,
+                            1.253, 1.275, 1.294, 1.304, 1.326, 1.349, 1.368, 1.386, 1.403, 1.421, 1.439, 1.457, 1.473, 1.489, 1.497, 1.504, 1.513, 1.515, 1.515, 1.511, 1.504, 1.489, 1.474, 1.455, 1.431, 1.402, 1.368, 1.329, 1.298, 1.255, 1.201, 1.167,
+                            1.221, 1.238, 1.263, 1.277, 1.296, 1.316, 1.334, 1.353, 1.372, 1.392, 1.411, 1.422, 1.448, 1.458, 1.466, 1.481, 1.489, 1.492, 1.493, 1.489, 1.486, 1.474, 1.455, 1.437, 1.415, 1.381, 1.348, 1.314, 1.275, 1.238, 1.184, 1.155,
+                            1.193, 1.213, 1.227, 1.243, 1.264, 1.287, 1.304, 1.322, 1.339, 1.355, 1.377, 1.395, 1.409, 1.425, 1.438, 1.455, 1.461, 1.466, 1.469, 1.468, 1.464, 1.451, 1.434, 1.415, 1.386, 1.362, 1.331, 1.296, 1.261, 1.225, 1.172, 1.136,
+                            1.172, 1.189, 1.209, 1.225, 1.241, 1.261, 1.279, 1.297, 1.317, 1.334, 1.351, 1.368, 1.387, 1.399, 1.418, 1.426, 1.434, 1.437, 1.437, 1.438, 1.437, 1.433, 1.418, 1.397, 1.365, 1.337, 1.306, 1.269, 1.238, 1.204, 1.156, 1.127
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.096, 1.097, 1.099, 1.101, 1.102, 1.103, 1.106, 1.106, 1.107, 1.106, 1.106, 1.108, 1.109, 1.111, 1.114, 1.115, 1.116, 1.117, 1.114, 1.112, 1.109, 1.106, 1.101, 1.092, 1.083, 1.076, 1.066, 1.054, 1.043, 1.027, 1.008, 1.001,
+                            1.098, 1.099, 1.104, 1.104, 1.103, 1.105, 1.107, 1.108, 1.108, 1.107, 1.108, 1.109, 1.111, 1.113, 1.115, 1.116, 1.117, 1.118, 1.116, 1.115, 1.111, 1.108, 1.102, 1.095, 1.091, 1.078, 1.069, 1.062, 1.049, 1.036, 1.021, 1.006,
+                            1.101, 1.105, 1.105, 1.105, 1.105, 1.107, 1.109, 1.109, 1.109, 1.109, 1.111, 1.111, 1.114, 1.115, 1.117, 1.117, 1.118, 1.119, 1.117, 1.115, 1.112, 1.109, 1.103, 1.098, 1.093, 1.084, 1.075, 1.065, 1.053, 1.041, 1.025, 1.011,
+                            1.101, 1.106, 1.107, 1.106, 1.107, 1.108, 1.111, 1.111, 1.111, 1.111, 1.112, 1.114, 1.116, 1.117, 1.119, 1.119, 1.121, 1.119, 1.119, 1.116, 1.113, 1.111, 1.105, 1.101, 1.094, 1.087, 1.077, 1.069, 1.057, 1.046, 1.031, 1.017,
+                            1.105, 1.108, 1.108, 1.108, 1.108, 1.109, 1.112, 1.111, 1.112, 1.112, 1.112, 1.113, 1.116, 1.117, 1.119, 1.121, 1.121, 1.121, 1.119, 1.116, 1.114, 1.111, 1.106, 1.102, 1.097, 1.089, 1.081, 1.072, 1.059, 1.048, 1.034, 1.021,
+                            1.106, 1.109, 1.111, 1.109, 1.109, 1.111, 1.113, 1.112, 1.112, 1.112, 1.113, 1.114, 1.117, 1.118, 1.119, 1.121, 1.121, 1.119, 1.119, 1.116, 1.115, 1.111, 1.107, 1.104, 1.098, 1.091, 1.083, 1.074, 1.064, 1.052, 1.037, 1.022,
+                            1.107, 1.111, 1.111, 1.111, 1.111, 1.112, 1.113, 1.112, 1.112, 1.113, 1.113, 1.115, 1.116, 1.118, 1.119, 1.119, 1.119, 1.119, 1.117, 1.116, 1.114, 1.111, 1.108, 1.105, 1.099, 1.093, 1.085, 1.077, 1.066, 1.054, 1.041, 1.027,
+                            1.106, 1.111, 1.111, 1.112, 1.112, 1.113, 1.113, 1.112, 1.112, 1.112, 1.113, 1.114, 1.116, 1.116, 1.117, 1.118, 1.118, 1.117, 1.116, 1.115, 1.113, 1.111, 1.108, 1.104, 1.099, 1.093, 1.086, 1.077, 1.068, 1.057, 1.042, 1.029,
+                            1.108, 1.112, 1.112, 1.112, 1.112, 1.113, 1.113, 1.112, 1.112, 1.112, 1.111, 1.113, 1.115, 1.116, 1.116, 1.116, 1.116, 1.115, 1.114, 1.113, 1.112, 1.111, 1.106, 1.103, 1.099, 1.092, 1.085, 1.077, 1.069, 1.058, 1.042, 1.029,
+                            1.109, 1.111, 1.112, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.113, 1.114, 1.114, 1.114, 1.114, 1.113, 1.112, 1.111, 1.109, 1.107, 1.105, 1.102, 1.098, 1.091, 1.085, 1.077, 1.068, 1.059, 1.045, 1.031,
+                            1.109, 1.111, 1.111, 1.111, 1.109, 1.111, 1.109, 1.109, 1.108, 1.108, 1.109, 1.109, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.108, 1.108, 1.107, 1.105, 1.103, 1.099, 1.096, 1.089, 1.083, 1.077, 1.068, 1.058, 1.045, 1.029,
+                            1.108, 1.109, 1.109, 1.109, 1.109, 1.109, 1.107, 1.106, 1.105, 1.105, 1.106, 1.107, 1.107, 1.107, 1.108, 1.108, 1.107, 1.107, 1.106, 1.105, 1.104, 1.102, 1.101, 1.097, 1.092, 1.088, 1.082, 1.074, 1.067, 1.057, 1.046, 1.031,
+                            1.106, 1.108, 1.109, 1.107, 1.107, 1.106, 1.105, 1.104, 1.104, 1.103, 1.102, 1.102, 1.104, 1.104, 1.104, 1.105, 1.105, 1.105, 1.104, 1.103, 1.101, 1.099, 1.098, 1.095, 1.091, 1.085, 1.081, 1.072, 1.065, 1.057, 1.044, 1.031,
+                            1.104, 1.106, 1.107, 1.106, 1.105, 1.104, 1.103, 1.102, 1.101, 1.101, 1.101, 1.101, 1.101, 1.102, 1.103, 1.103, 1.104, 1.103, 1.102, 1.101, 1.099, 1.098, 1.095, 1.092, 1.089, 1.084, 1.079, 1.071, 1.063, 1.055, 1.044, 1.031,
+                            1.105, 1.106, 1.106, 1.105, 1.104, 1.102, 1.101, 1.099, 1.099, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.102, 1.102, 1.101, 1.099, 1.097, 1.096, 1.093, 1.091, 1.087, 1.082, 1.076, 1.069, 1.062, 1.054, 1.043, 1.028,
+                            1.105, 1.106, 1.106, 1.104, 1.103, 1.101, 1.099, 1.099, 1.098, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.099, 1.098, 1.096, 1.095, 1.091, 1.089, 1.086, 1.081, 1.075, 1.071, 1.061, 1.054, 1.043, 1.028,
+                            1.105, 1.105, 1.105, 1.104, 1.102, 1.101, 1.099, 1.098, 1.097, 1.096, 1.096, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.099, 1.098, 1.097, 1.095, 1.093, 1.091, 1.088, 1.085, 1.079, 1.076, 1.069, 1.061, 1.053, 1.043, 1.027,
+                            1.105, 1.105, 1.104, 1.102, 1.101, 1.099, 1.099, 1.097, 1.097, 1.096, 1.096, 1.097, 1.097, 1.097, 1.097, 1.097, 1.098, 1.098, 1.097, 1.096, 1.094, 1.092, 1.091, 1.088, 1.085, 1.079, 1.076, 1.068, 1.062, 1.054, 1.043, 1.027,
+                            1.104, 1.103, 1.103, 1.099, 1.098, 1.098, 1.098, 1.097, 1.097, 1.097, 1.097, 1.097, 1.097, 1.097, 1.097, 1.096, 1.097, 1.097, 1.097, 1.096, 1.094, 1.093, 1.091, 1.089, 1.085, 1.081, 1.076, 1.068, 1.063, 1.054, 1.043, 1.027,
+                            1.099, 1.099, 1.098, 1.098, 1.097, 1.097, 1.097, 1.097, 1.097, 1.096, 1.096, 1.096, 1.095, 1.095, 1.095, 1.095, 1.096, 1.096, 1.097, 1.097, 1.096, 1.094, 1.091, 1.089, 1.085, 1.081, 1.076, 1.068, 1.062, 1.055, 1.044, 1.028,
+                            1.097, 1.096, 1.096, 1.095, 1.095, 1.095, 1.095, 1.097, 1.097, 1.096, 1.095, 1.095, 1.094, 1.094, 1.094, 1.095, 1.096, 1.096, 1.097, 1.098, 1.097, 1.095, 1.092, 1.088, 1.086, 1.083, 1.076, 1.069, 1.062, 1.056, 1.045, 1.031,
+                            1.091, 1.092, 1.093, 1.092, 1.092, 1.093, 1.095, 1.095, 1.095, 1.093, 1.092, 1.092, 1.092, 1.093, 1.094, 1.095, 1.096, 1.097, 1.098, 1.098, 1.097, 1.095, 1.093, 1.088, 1.086, 1.082, 1.076, 1.069, 1.062, 1.056, 1.046, 1.031,
+                            1.085, 1.088, 1.088, 1.089, 1.089, 1.091, 1.092, 1.092, 1.092, 1.092, 1.091, 1.091, 1.092, 1.093, 1.094, 1.096, 1.097, 1.099, 1.098, 1.098, 1.097, 1.095, 1.093, 1.089, 1.085, 1.081, 1.076, 1.069, 1.062, 1.056, 1.045, 1.031,
+                            1.081, 1.082, 1.084, 1.084, 1.085, 1.087, 1.089, 1.091, 1.091, 1.091, 1.091, 1.092, 1.092, 1.094, 1.096, 1.096, 1.099, 1.099, 1.099, 1.098, 1.097, 1.096, 1.093, 1.089, 1.086, 1.082, 1.076, 1.069, 1.062, 1.056, 1.045, 1.031,
+                            1.073, 1.078, 1.081, 1.082, 1.083, 1.084, 1.088, 1.089, 1.089, 1.089, 1.091, 1.091, 1.093, 1.095, 1.096, 1.098, 1.099, 1.101, 1.099, 1.099, 1.096, 1.095, 1.093, 1.089, 1.086, 1.081, 1.077, 1.069, 1.062, 1.055, 1.043, 1.032,
+                            1.068, 1.072, 1.076, 1.079, 1.081, 1.083, 1.084, 1.087, 1.088, 1.088, 1.089, 1.092, 1.093, 1.096, 1.097, 1.099, 1.099, 1.099, 1.099, 1.097, 1.096, 1.095, 1.092, 1.089, 1.086, 1.081, 1.077, 1.071, 1.062, 1.055, 1.045, 1.034,
+                            1.064, 1.066, 1.072, 1.073, 1.077, 1.079, 1.082, 1.084, 1.086, 1.088, 1.089, 1.091, 1.093, 1.095, 1.097, 1.099, 1.099, 1.099, 1.098, 1.097, 1.096, 1.095, 1.092, 1.089, 1.086, 1.081, 1.077, 1.069, 1.064, 1.055, 1.043, 1.035,
+                            1.057, 1.062, 1.065, 1.068, 1.071, 1.075, 1.077, 1.081, 1.084, 1.086, 1.088, 1.089, 1.092, 1.094, 1.096, 1.098, 1.098, 1.098, 1.097, 1.096, 1.095, 1.094, 1.092, 1.089, 1.086, 1.083, 1.077, 1.069, 1.064, 1.055, 1.043, 1.033,
+                            1.051, 1.056, 1.059, 1.062, 1.066, 1.068, 1.074, 1.077, 1.079, 1.083, 1.086, 1.088, 1.089, 1.092, 1.094, 1.096, 1.096, 1.096, 1.096, 1.095, 1.094, 1.093, 1.092, 1.089, 1.086, 1.083, 1.077, 1.068, 1.063, 1.055, 1.043, 1.033,
+                            1.043, 1.048, 1.052, 1.056, 1.059, 1.065, 1.068, 1.071, 1.074, 1.078, 1.081, 1.083, 1.088, 1.089, 1.091, 1.092, 1.094, 1.095, 1.094, 1.094, 1.094, 1.094, 1.092, 1.089, 1.086, 1.083, 1.077, 1.069, 1.062, 1.055, 1.044, 1.031,
+                            1.036, 1.041, 1.045, 1.049, 1.052, 1.059, 1.062, 1.067, 1.069, 1.072, 1.074, 1.077, 1.082, 1.083, 1.086, 1.089, 1.091, 1.092, 1.093, 1.092, 1.092, 1.091, 1.091, 1.088, 1.085, 1.081, 1.076, 1.069, 1.061, 1.054, 1.043, 1.031,
+                            1.029, 1.036, 1.041, 1.045, 1.049, 1.052, 1.056, 1.058, 1.064, 1.064, 1.067, 1.071, 1.075, 1.079, 1.083, 1.085, 1.089, 1.089, 1.089, 1.091, 1.091, 1.091, 1.089, 1.087, 1.083, 1.079, 1.074, 1.066, 1.062, 1.052, 1.041, 1.029
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    3.174, 3.091, 2.978, 2.891, 2.829, 2.779, 2.739, 2.708, 2.683, 2.659, 2.641, 2.623, 2.616, 2.622, 2.629, 2.644, 2.669, 2.691, 2.731, 2.784, 2.843, 2.894, 2.947, 3.004, 3.065, 3.133, 3.214, 3.303, 3.416, 3.541, 3.674, 3.765,
+                    3.093, 2.968, 2.861, 2.778, 2.702, 2.651, 2.599, 2.563, 2.533, 2.509, 2.487, 2.472, 2.466, 2.462, 2.466, 2.481, 2.501, 2.531, 2.568, 2.612, 2.663, 2.712, 2.764, 2.821, 2.881, 2.954, 3.041, 3.137, 3.265, 3.396, 3.482, 3.547,
+                    2.897, 2.851, 2.743, 2.608, 2.521, 2.464, 2.417, 2.381, 2.348, 2.323, 2.302, 2.287, 2.275, 2.264, 2.269, 2.279, 2.297, 2.322, 2.351, 2.392, 2.436, 2.479, 2.526, 2.577, 2.631, 2.701, 2.778, 2.871, 2.985, 3.105, 3.191, 3.254,
+                    2.764, 2.689, 2.586, 2.452, 2.361, 2.303, 2.254, 2.218, 2.189, 2.166, 2.141, 2.123, 2.108, 2.099, 2.098, 2.105, 2.121, 2.144, 2.172, 2.203, 2.238, 2.276, 2.317, 2.358, 2.411, 2.471, 2.541, 2.626, 2.733, 2.844, 2.924, 2.979,
+                    2.581, 2.499, 2.405, 2.296, 2.223, 2.171, 2.126, 2.088, 2.056, 2.031, 2.011, 1.993, 1.975, 1.968, 1.964, 1.968, 1.982, 2.003, 2.027, 2.052, 2.079, 2.109, 2.149, 2.184, 2.231, 2.285, 2.346, 2.427, 2.521, 2.622, 2.691, 2.744,
+                    2.437, 2.343, 2.261, 2.184, 2.116, 2.058, 2.017, 1.979, 1.949, 1.924, 1.899, 1.883, 1.868, 1.859, 1.855, 1.857, 1.866, 1.883, 1.901, 1.923, 1.951, 1.978, 2.011, 2.042, 2.081, 2.133, 2.189, 2.261, 2.349, 2.433, 2.491, 2.541,
+                    2.332, 2.251, 2.166, 2.092, 2.024, 1.969, 1.925, 1.889, 1.856, 1.832, 1.809, 1.791, 1.774, 1.768, 1.762, 1.762, 1.771, 1.779, 1.799, 1.815, 1.837, 1.861, 1.892, 1.924, 1.961, 2.006, 2.059, 2.126, 2.201, 2.279, 2.329, 2.367,
+                    2.249, 2.168, 2.083, 2.005, 1.941, 1.891, 1.845, 1.808, 1.775, 1.749, 1.726, 1.711, 1.696, 1.686, 1.681, 1.681, 1.687, 1.697, 1.712, 1.726, 1.743, 1.765, 1.792, 1.824, 1.859, 1.901, 1.951, 2.009, 2.079, 2.149, 2.194, 2.229,
+                    2.173, 2.094, 2.009, 1.936, 1.871, 1.819, 1.771, 1.736, 1.705, 1.679, 1.656, 1.638, 1.623, 1.612, 1.608, 1.609, 1.613, 1.622, 1.634, 1.647, 1.664, 1.685, 1.709, 1.738, 1.772, 1.813, 1.858, 1.912, 1.979, 2.046, 2.091, 2.121,
+                    2.105, 2.033, 1.947, 1.875, 1.811, 1.756, 1.714, 1.677, 1.643, 1.616, 1.596, 1.577, 1.561, 1.551, 1.544, 1.544, 1.548, 1.556, 1.568, 1.582, 1.596, 1.616, 1.639, 1.665, 1.698, 1.739, 1.783, 1.836, 1.896, 1.959, 1.999, 2.032,
+                    2.045, 1.975, 1.892, 1.819, 1.759, 1.706, 1.661, 1.622, 1.592, 1.563, 1.543, 1.523, 1.509, 1.499, 1.491, 1.491, 1.494, 1.501, 1.512, 1.524, 1.539, 1.558, 1.578, 1.605, 1.638, 1.676, 1.721, 1.769, 1.829, 1.887, 1.923, 1.952,
+                    1.988, 1.923, 1.841, 1.773, 1.711, 1.661, 1.617, 1.579, 1.547, 1.521, 1.496, 1.476, 1.462, 1.452, 1.445, 1.445, 1.448, 1.454, 1.464, 1.476, 1.489, 1.507, 1.529, 1.557, 1.589, 1.626, 1.667, 1.719, 1.774, 1.829, 1.863, 1.893,
+                    1.943, 1.881, 1.803, 1.734, 1.673, 1.621, 1.579, 1.543, 1.508, 1.479, 1.457, 1.436, 1.421, 1.412, 1.405, 1.402, 1.405, 1.412, 1.423, 1.434, 1.449, 1.466, 1.489, 1.516, 1.546, 1.582, 1.625, 1.671, 1.726, 1.777, 1.816, 1.838,
+                    1.913, 1.848, 1.769, 1.701, 1.641, 1.591, 1.548, 1.511, 1.478, 1.449, 1.422, 1.401, 1.387, 1.377, 1.369, 1.368, 1.371, 1.379, 1.389, 1.402, 1.415, 1.432, 1.454, 1.481, 1.513, 1.548, 1.587, 1.633, 1.686, 1.736, 1.772, 1.793,
+                    1.891, 1.819, 1.742, 1.674, 1.614, 1.566, 1.523, 1.485, 1.451, 1.422, 1.397, 1.376, 1.359, 1.347, 1.339, 1.339, 1.343, 1.351, 1.361, 1.375, 1.388, 1.406, 1.429, 1.453, 1.484, 1.517, 1.555, 1.599, 1.652, 1.699, 1.733, 1.755,
+                    1.874, 1.801, 1.721, 1.654, 1.602, 1.552, 1.506, 1.465, 1.429, 1.399, 1.374, 1.352, 1.336, 1.323, 1.315, 1.316, 1.321, 1.329, 1.338, 1.352, 1.369, 1.387, 1.409, 1.435, 1.462, 1.494, 1.529, 1.572, 1.622, 1.669, 1.698, 1.718,
+                    1.868, 1.791, 1.712, 1.647, 1.592, 1.542, 1.497, 1.454, 1.416, 1.385, 1.356, 1.335, 1.319, 1.307, 1.301, 1.299, 1.305, 1.314, 1.324, 1.341, 1.357, 1.376, 1.397, 1.422, 1.449, 1.478, 1.511, 1.551, 1.599, 1.644, 1.671, 1.688,
+                    1.867, 1.789, 1.715, 1.648, 1.591, 1.539, 1.494, 1.451, 1.412, 1.378, 1.352, 1.329, 1.311, 1.301, 1.294, 1.294, 1.298, 1.306, 1.321, 1.335, 1.353, 1.369, 1.391, 1.413, 1.439, 1.469, 1.502, 1.539, 1.583, 1.623, 1.648, 1.666,
+                    1.873, 1.799, 1.724, 1.657, 1.599, 1.546, 1.498, 1.454, 1.416, 1.384, 1.356, 1.334, 1.317, 1.306, 1.299, 1.299, 1.303, 1.311, 1.323, 1.339, 1.354, 1.373, 1.393, 1.414, 1.438, 1.466, 1.495, 1.532, 1.578, 1.617, 1.639, 1.656,
+                    1.884, 1.816, 1.743, 1.675, 1.615, 1.559, 1.509, 1.466, 1.429, 1.397, 1.371, 1.351, 1.332, 1.321, 1.315, 1.313, 1.316, 1.325, 1.337, 1.351, 1.365, 1.383, 1.403, 1.424, 1.449, 1.475, 1.501, 1.537, 1.574, 1.617, 1.639, 1.654,
+                    1.906, 1.845, 1.772, 1.699, 1.636, 1.579, 1.531, 1.489, 1.453, 1.419, 1.395, 1.376, 1.364, 1.354, 1.344, 1.339, 1.338, 1.345, 1.356, 1.368, 1.383, 1.402, 1.422, 1.443, 1.469, 1.492, 1.518, 1.548, 1.583, 1.622, 1.648, 1.658,
+                    1.941, 1.882, 1.804, 1.731, 1.667, 1.611, 1.562, 1.519, 1.484, 1.453, 1.427, 1.412, 1.401, 1.389, 1.381, 1.369, 1.367, 1.372, 1.381, 1.392, 1.409, 1.429, 1.449, 1.473, 1.496, 1.521, 1.546, 1.574, 1.609, 1.637, 1.657, 1.673,
+                    1.987, 1.929, 1.845, 1.773, 1.708, 1.651, 1.603, 1.561, 1.524, 1.495, 1.467, 1.449, 1.441, 1.431, 1.417, 1.404, 1.401, 1.406, 1.415, 1.427, 1.445, 1.463, 1.485, 1.509, 1.536, 1.562, 1.587, 1.612, 1.642, 1.672, 1.678, 1.692,
+                    2.041, 1.978, 1.897, 1.824, 1.757, 1.699, 1.649, 1.606, 1.569, 1.539, 1.513, 1.489, 1.473, 1.461, 1.451, 1.445, 1.445, 1.447, 1.459, 1.472, 1.491, 1.509, 1.533, 1.558, 1.584, 1.607, 1.632, 1.661, 1.692, 1.716, 1.721, 1.728,
+                    2.111, 2.041, 1.957, 1.879, 1.813, 1.755, 1.702, 1.657, 1.622, 1.591, 1.566, 1.543, 1.525, 1.511, 1.501, 1.495, 1.492, 1.497, 1.509, 1.524, 1.543, 1.564, 1.589, 1.615, 1.638, 1.663, 1.688, 1.719, 1.746, 1.774, 1.776, 1.785,
+                    2.186, 2.115, 2.023, 1.943, 1.875, 1.816, 1.762, 1.718, 1.681, 1.649, 1.624, 1.601, 1.583, 1.571, 1.559, 1.552, 1.551, 1.557, 1.571, 1.588, 1.607, 1.628, 1.654, 1.678, 1.704, 1.729, 1.756, 1.783, 1.813, 1.841, 1.849, 1.854,
+                    2.271, 2.188, 2.097, 2.017, 1.948, 1.886, 1.829, 1.784, 1.747, 1.718, 1.693, 1.671, 1.651, 1.639, 1.629, 1.624, 1.625, 1.633, 1.647, 1.663, 1.682, 1.703, 1.728, 1.754, 1.777, 1.805, 1.834, 1.861, 1.892, 1.918, 1.926, 1.939,
+                    2.369, 2.278, 2.182, 2.101, 2.028, 1.967, 1.912, 1.863, 1.827, 1.797, 1.773, 1.751, 1.734, 1.722, 1.713, 1.711, 1.712, 1.719, 1.734, 1.749, 1.768, 1.791, 1.815, 1.839, 1.864, 1.892, 1.919, 1.949, 1.981, 2.011, 2.021, 2.035,
+                    2.479, 2.382, 2.284, 2.202, 2.126, 2.062, 2.005, 1.961, 1.921, 1.891, 1.867, 1.847, 1.832, 1.822, 1.815, 1.814, 1.817, 1.822, 1.837, 1.853, 1.871, 1.891, 1.915, 1.939, 1.964, 1.992, 2.019, 2.053, 2.089, 2.122, 2.133, 2.153,
+                    2.619, 2.509, 2.411, 2.319, 2.239, 2.173, 2.114, 2.072, 2.037, 2.006, 1.982, 1.963, 1.949, 1.941, 1.937, 1.934, 1.937, 1.947, 1.961, 1.977, 1.987, 2.009, 2.034, 2.058, 2.087, 2.112, 2.139, 2.172, 2.211, 2.253, 2.269, 2.297,
+                    2.783, 2.662, 2.554, 2.457, 2.374, 2.304, 2.246, 2.203, 2.166, 2.139, 2.118, 2.099, 2.087, 2.081, 2.077, 2.073, 2.081, 2.092, 2.106, 2.118, 2.133, 2.153, 2.174, 2.197, 2.228, 2.253, 2.281, 2.318, 2.362, 2.407, 2.434, 2.478,
+                    2.878, 2.792, 2.675, 2.577, 2.499, 2.438, 2.396, 2.357, 2.331, 2.309, 2.293, 2.278, 2.267, 2.259, 2.256, 2.258, 2.261, 2.267, 2.278, 2.293, 2.304, 2.319, 2.343, 2.369, 2.389, 2.411, 2.437, 2.469, 2.509, 2.552, 2.621, 2.683
+                ],
+                "sigma": 0.00476,
+                "sigma_Cb": 0.01242
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 2400,
+                        "ccm":
+                        [
+                            1.78571, -0.47464, -0.31106,
+                            -0.35019, 1.75738, -0.40719,
+                            0.21137, -1.36874, 2.15737
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.71274, -0.29097, -0.42177,
+                            -0.51279, 1.96739, -0.45461,
+                            0.07392, -1.05557, 1.98165
+                        ]
+                    },
+                    {
+                        "ct": 5000,
+                        "ccm":
+                        [
+                            1.85104, -0.46872, -0.38232,
+                            -0.37898, 1.69668, -0.31771,
+                            0.13397, -1.75721, 2.62323
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            1.76986, -0.57663, -0.19323,
+                            -0.23588, 1.74842, -0.51254,
+                            0.03796, -0.64141, 1.60345
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.cac": { }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.25,
+                "limit": 1.0,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/data/vd56g3_mono.json 0.6.0-2/src/ipa/rpi/pisp/data/vd56g3_mono.json
--- 0.5.0-1/src/ipa/rpi/pisp/data/vd56g3_mono.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/data/vd56g3_mono.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,1155 @@
+{
+    "version": 2.0,
+    "target": "pisp",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 5971,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 950,
+                "reference_Y": 23748
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 2.732
+            }
+        },
+        {
+            "rpi.denoise":
+            {
+                "normal":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 0.8,
+                        "threshold": 0.05
+                    }
+                },
+                "hdr":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                },
+                "night":
+                {
+                    "sdn":
+                    {
+                        "deviation": 1.6,
+                        "strength": 0.5,
+                        "deviation2": 3.2,
+                        "deviation_no_tdn": 3.2,
+                        "strength_no_tdn": 0.75
+                    },
+                    "cdn":
+                    {
+                        "deviation": 200,
+                        "strength": 0.3
+                    },
+                    "tdn":
+                    {
+                        "deviation": 1.3,
+                        "threshold": 0.1
+                    }
+                }
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "channels": [
+                    {
+                        "comment": "Channel 0 is normal AGC",
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 5000, 10000, 20000, 60000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 10000, 30000, 60000, 90000, 120000 ],
+                                "gain": [ 1.0, 1.5, 2.0, 4.0, 8.0, 12.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.5,
+                                    "y_target":
+                                    [
+                                        0, 0.17,
+                                        1000, 0.17
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 1 is the HDR short channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 60000 ],
+                                "gain": [ 1.0, 1.0, 1.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.95,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.7,
+                                        1000, 0.7
+                                    ]
+                                },
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.0,
+                                    "q_hi": 0.2,
+                                    "y_target":
+                                    [
+                                        0, 0.002,
+                                        1000, 0.002
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 2 is the HDR long channel",
+                        "desaturate": 0,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 30000, 60000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 8.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [  ],
+                            "highlight": [  ],
+                            "shadows": [  ]
+                        },
+                        "channel_constraints": [
+                            {
+                                "bound": "UPPER",
+                                "channel": 4,
+                                "factor": 8
+                            },
+                            {
+                                "bound": "LOWER",
+                                "channel": 4,
+                                "factor": 2
+                            }
+                        ],
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.165,
+                            10000, 0.17
+                        ]
+                    },
+                    {
+                        "comment": "Channel 3 is the night mode channel",
+                        "base_ev": 0.33,
+                        "metering_modes":
+                        {
+                            "centre-weighted":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 4, 4, 4, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 3, 3, 3, 4, 3, 3, 3, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 3, 3, 3, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1,
+                                    1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
+                                    0, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 0,
+                                    0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
+                                ]
+                            },
+                            "spot":
+                            {
+                                "weights":
+                                [
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                                ]
+                            },
+                            "matrix":
+                            {
+                                "weights":
+                                [
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                                ]
+                            }
+                        },
+                        "exposure_modes":
+                        {
+                            "normal":
+                            {
+                                "shutter": [ 100, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "short":
+                            {
+                                "shutter": [ 100, 20000, 33333 ],
+                                "gain": [ 1.0, 2.0, 4.0 ]
+                            },
+                            "long":
+                            {
+                                "shutter": [ 100, 20000, 66666, 120000 ],
+                                "gain": [ 1.0, 2.0, 4.0, 4.0 ]
+                            }
+                        },
+                        "constraint_modes":
+                        {
+                            "normal": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ],
+                            "highlight": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                },
+                                {
+                                    "bound": "UPPER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.8,
+                                        1000, 0.8
+                                    ]
+                                }
+                            ],
+                            "shadows": [
+                                {
+                                    "bound": "LOWER",
+                                    "q_lo": 0.98,
+                                    "q_hi": 1.0,
+                                    "y_target":
+                                    [
+                                        0, 0.5,
+                                        1000, 0.5
+                                    ]
+                                }
+                            ]
+                        },
+                        "y_target":
+                        [
+                            0, 0.16,
+                            1000, 0.16,
+                            10000, 0.17
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2400,
+                        "table":
+                        [
+                            1.075, 1.079, 1.081, 1.087, 1.087, 1.086, 1.086, 1.086, 1.085, 1.085, 1.085, 1.087, 1.087, 1.087, 1.087, 1.088, 1.085, 1.085, 1.083, 1.079, 1.074, 1.071, 1.065, 1.059, 1.054, 1.047, 1.039, 1.032, 1.023, 1.012, 1.011, 1.011,
+                            1.075, 1.077, 1.078, 1.081, 1.081, 1.081, 1.081, 1.079, 1.078, 1.078, 1.079, 1.081, 1.081, 1.083, 1.084, 1.085, 1.084, 1.083, 1.082, 1.078, 1.074, 1.071, 1.063, 1.059, 1.053, 1.047, 1.039, 1.032, 1.023, 1.018, 1.012, 1.012,
+                            1.074, 1.077, 1.078, 1.079, 1.081, 1.081, 1.079, 1.079, 1.078, 1.078, 1.079, 1.079, 1.081, 1.082, 1.084, 1.085, 1.084, 1.083, 1.082, 1.078, 1.074, 1.069, 1.065, 1.059, 1.054, 1.049, 1.043, 1.034, 1.027, 1.021, 1.021, 1.019,
+                            1.075, 1.077, 1.081, 1.081, 1.081, 1.081, 1.079, 1.079, 1.079, 1.079, 1.079, 1.082, 1.082, 1.084, 1.085, 1.086, 1.086, 1.084, 1.082, 1.079, 1.076, 1.072, 1.068, 1.064, 1.058, 1.052, 1.047, 1.041, 1.031, 1.029, 1.028, 1.027,
+                            1.076, 1.079, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.082, 1.084, 1.085, 1.086, 1.087, 1.087, 1.085, 1.083, 1.081, 1.077, 1.075, 1.071, 1.068, 1.063, 1.056, 1.051, 1.045, 1.035, 1.032, 1.032, 1.033,
+                            1.077, 1.079, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.081, 1.083, 1.084, 1.085, 1.087, 1.088, 1.087, 1.086, 1.084, 1.082, 1.079, 1.077, 1.074, 1.069, 1.065, 1.061, 1.053, 1.047, 1.038, 1.036, 1.037, 1.039,
+                            1.077, 1.078, 1.081, 1.081, 1.082, 1.082, 1.081, 1.082, 1.082, 1.082, 1.082, 1.083, 1.085, 1.086, 1.087, 1.088, 1.088, 1.086, 1.084, 1.083, 1.082, 1.078, 1.076, 1.072, 1.067, 1.063, 1.058, 1.051, 1.043, 1.041, 1.041, 1.042,
+                            1.077, 1.079, 1.081, 1.082, 1.082, 1.082, 1.082, 1.083, 1.082, 1.082, 1.083, 1.084, 1.086, 1.087, 1.089, 1.089, 1.088, 1.087, 1.085, 1.083, 1.082, 1.079, 1.078, 1.074, 1.069, 1.066, 1.061, 1.055, 1.047, 1.045, 1.045, 1.048,
+                            1.076, 1.079, 1.081, 1.083, 1.083, 1.084, 1.083, 1.083, 1.083, 1.084, 1.084, 1.086, 1.087, 1.088, 1.089, 1.089, 1.088, 1.087, 1.085, 1.084, 1.082, 1.079, 1.078, 1.076, 1.072, 1.068, 1.063, 1.058, 1.049, 1.048, 1.049, 1.051,
+                            1.076, 1.081, 1.082, 1.083, 1.084, 1.084, 1.084, 1.083, 1.083, 1.084, 1.085, 1.086, 1.087, 1.089, 1.089, 1.089, 1.087, 1.086, 1.086, 1.084, 1.082, 1.081, 1.079, 1.076, 1.074, 1.071, 1.065, 1.061, 1.054, 1.051, 1.051, 1.055,
+                            1.078, 1.081, 1.083, 1.084, 1.085, 1.085, 1.084, 1.083, 1.084, 1.084, 1.085, 1.085, 1.087, 1.088, 1.088, 1.088, 1.086, 1.086, 1.086, 1.084, 1.083, 1.082, 1.081, 1.078, 1.075, 1.071, 1.066, 1.063, 1.056, 1.055, 1.055, 1.057,
+                            1.081, 1.083, 1.084, 1.085, 1.086, 1.085, 1.084, 1.084, 1.084, 1.084, 1.085, 1.085, 1.086, 1.087, 1.088, 1.087, 1.087, 1.086, 1.085, 1.084, 1.084, 1.082, 1.081, 1.079, 1.076, 1.072, 1.067, 1.064, 1.057, 1.056, 1.057, 1.058,
+                            1.081, 1.084, 1.085, 1.086, 1.086, 1.086, 1.084, 1.084, 1.084, 1.084, 1.084, 1.085, 1.086, 1.087, 1.088, 1.087, 1.087, 1.086, 1.085, 1.085, 1.084, 1.083, 1.081, 1.079, 1.076, 1.072, 1.069, 1.065, 1.058, 1.057, 1.058, 1.061,
+                            1.081, 1.084, 1.085, 1.086, 1.086, 1.086, 1.084, 1.083, 1.083, 1.083, 1.084, 1.084, 1.085, 1.086, 1.087, 1.088, 1.087, 1.087, 1.085, 1.085, 1.084, 1.083, 1.081, 1.079, 1.077, 1.073, 1.069, 1.066, 1.059, 1.059, 1.061, 1.063,
+                            1.081, 1.084, 1.086, 1.086, 1.086, 1.086, 1.083, 1.082, 1.082, 1.083, 1.083, 1.084, 1.085, 1.086, 1.087, 1.087, 1.087, 1.087, 1.087, 1.086, 1.085, 1.083, 1.081, 1.079, 1.077, 1.074, 1.069, 1.066, 1.061, 1.061, 1.062, 1.065,
+                            1.082, 1.085, 1.086, 1.086, 1.086, 1.084, 1.082, 1.081, 1.082, 1.082, 1.082, 1.083, 1.084, 1.086, 1.086, 1.087, 1.087, 1.087, 1.087, 1.086, 1.085, 1.082, 1.081, 1.079, 1.077, 1.074, 1.071, 1.066, 1.061, 1.061, 1.064, 1.066,
+                            1.082, 1.084, 1.085, 1.085, 1.083, 1.083, 1.081, 1.081, 1.081, 1.082, 1.082, 1.083, 1.084, 1.085, 1.086, 1.087, 1.087, 1.087, 1.087, 1.086, 1.085, 1.083, 1.081, 1.079, 1.077, 1.074, 1.071, 1.067, 1.061, 1.061, 1.064, 1.065,
+                            1.081, 1.082, 1.083, 1.082, 1.081, 1.079, 1.079, 1.079, 1.081, 1.081, 1.081, 1.082, 1.083, 1.084, 1.085, 1.086, 1.086, 1.086, 1.086, 1.085, 1.084, 1.083, 1.082, 1.079, 1.076, 1.074, 1.071, 1.067, 1.061, 1.061, 1.064, 1.066,
+                            1.079, 1.078, 1.078, 1.077, 1.077, 1.077, 1.078, 1.078, 1.079, 1.079, 1.081, 1.081, 1.081, 1.082, 1.083, 1.084, 1.084, 1.084, 1.084, 1.084, 1.083, 1.082, 1.081, 1.079, 1.076, 1.073, 1.071, 1.067, 1.061, 1.061, 1.065, 1.067,
+                            1.073, 1.073, 1.073, 1.074, 1.074, 1.074, 1.074, 1.075, 1.076, 1.077, 1.077, 1.077, 1.077, 1.078, 1.079, 1.079, 1.081, 1.083, 1.083, 1.083, 1.081, 1.081, 1.079, 1.077, 1.075, 1.072, 1.069, 1.066, 1.061, 1.061, 1.064, 1.066,
+                            1.064, 1.064, 1.066, 1.067, 1.067, 1.071, 1.071, 1.072, 1.073, 1.074, 1.074, 1.073, 1.074, 1.075, 1.076, 1.077, 1.078, 1.081, 1.081, 1.081, 1.081, 1.079, 1.078, 1.076, 1.074, 1.071, 1.068, 1.064, 1.059, 1.059, 1.062, 1.064,
+                            1.056, 1.058, 1.059, 1.061, 1.062, 1.065, 1.066, 1.067, 1.068, 1.068, 1.069, 1.068, 1.068, 1.069, 1.071, 1.074, 1.076, 1.078, 1.079, 1.079, 1.079, 1.078, 1.076, 1.074, 1.072, 1.069, 1.065, 1.061, 1.057, 1.057, 1.059, 1.061,
+                            1.048, 1.053, 1.054, 1.057, 1.059, 1.061, 1.062, 1.063, 1.064, 1.064, 1.064, 1.064, 1.065, 1.066, 1.068, 1.071, 1.074, 1.077, 1.078, 1.078, 1.078, 1.076, 1.074, 1.071, 1.069, 1.066, 1.063, 1.058, 1.055, 1.054, 1.056, 1.059,
+                            1.044, 1.047, 1.049, 1.052, 1.054, 1.056, 1.057, 1.059, 1.059, 1.059, 1.061, 1.063, 1.064, 1.065, 1.067, 1.071, 1.073, 1.075, 1.077, 1.076, 1.076, 1.073, 1.071, 1.069, 1.066, 1.064, 1.059, 1.056, 1.051, 1.051, 1.053, 1.055,
+                            1.039, 1.042, 1.045, 1.048, 1.049, 1.051, 1.053, 1.055, 1.056, 1.057, 1.059, 1.061, 1.063, 1.065, 1.068, 1.071, 1.073, 1.074, 1.074, 1.074, 1.072, 1.071, 1.069, 1.066, 1.064, 1.062, 1.057, 1.054, 1.048, 1.048, 1.049, 1.053,
+                            1.036, 1.038, 1.042, 1.045, 1.047, 1.049, 1.051, 1.052, 1.054, 1.056, 1.058, 1.061, 1.063, 1.065, 1.068, 1.069, 1.072, 1.073, 1.073, 1.072, 1.071, 1.069, 1.066, 1.065, 1.062, 1.059, 1.055, 1.052, 1.047, 1.047, 1.047, 1.049,
+                            1.032, 1.036, 1.038, 1.042, 1.044, 1.046, 1.049, 1.051, 1.053, 1.055, 1.058, 1.061, 1.062, 1.066, 1.067, 1.069, 1.071, 1.071, 1.071, 1.071, 1.069, 1.067, 1.065, 1.063, 1.061, 1.057, 1.054, 1.051, 1.045, 1.045, 1.046, 1.048,
+                            1.028, 1.032, 1.036, 1.038, 1.042, 1.044, 1.045, 1.049, 1.051, 1.054, 1.057, 1.059, 1.061, 1.065, 1.066, 1.067, 1.068, 1.069, 1.069, 1.069, 1.067, 1.066, 1.064, 1.063, 1.061, 1.055, 1.052, 1.049, 1.044, 1.044, 1.046, 1.048,
+                            1.025, 1.027, 1.032, 1.035, 1.036, 1.041, 1.043, 1.045, 1.049, 1.051, 1.054, 1.057, 1.059, 1.062, 1.065, 1.066, 1.066, 1.066, 1.067, 1.066, 1.065, 1.065, 1.063, 1.061, 1.059, 1.056, 1.052, 1.047, 1.043, 1.042, 1.045, 1.046,
+                            1.017, 1.021, 1.025, 1.029, 1.034, 1.036, 1.041, 1.042, 1.044, 1.047, 1.049, 1.053, 1.055, 1.057, 1.059, 1.061, 1.063, 1.063, 1.063, 1.064, 1.063, 1.062, 1.061, 1.059, 1.057, 1.054, 1.051, 1.046, 1.039, 1.039, 1.039, 1.044,
+                            1.009, 1.015, 1.021, 1.023, 1.027, 1.031, 1.036, 1.037, 1.039, 1.042, 1.043, 1.045, 1.048, 1.051, 1.053, 1.055, 1.057, 1.058, 1.058, 1.059, 1.058, 1.058, 1.057, 1.055, 1.054, 1.051, 1.046, 1.041, 1.037, 1.037, 1.036, 1.038,
+                            1.004, 1.008, 1.014, 1.019, 1.022, 1.024, 1.025, 1.028, 1.029, 1.029, 1.031, 1.036, 1.039, 1.043, 1.046, 1.048, 1.049, 1.049, 1.052, 1.052, 1.052, 1.051, 1.049, 1.048, 1.045, 1.044, 1.041, 1.038, 1.033, 1.029, 1.031, 1.031
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.058, 1.066, 1.068, 1.072, 1.073, 1.075, 1.076, 1.074, 1.073, 1.072, 1.071, 1.071, 1.071, 1.071, 1.071, 1.072, 1.069, 1.068, 1.066, 1.064, 1.061, 1.058, 1.053, 1.049, 1.044, 1.037, 1.031, 1.024, 1.014, 1.009, 1.007, 1.006,
+                            1.061, 1.065, 1.068, 1.072, 1.073, 1.074, 1.074, 1.074, 1.072, 1.069, 1.069, 1.071, 1.071, 1.072, 1.073, 1.072, 1.072, 1.069, 1.067, 1.066, 1.062, 1.058, 1.054, 1.051, 1.045, 1.041, 1.034, 1.026, 1.016, 1.011, 1.009, 1.011,
+                            1.062, 1.066, 1.071, 1.073, 1.073, 1.074, 1.074, 1.074, 1.073, 1.069, 1.069, 1.072, 1.074, 1.074, 1.075, 1.075, 1.076, 1.074, 1.072, 1.071, 1.068, 1.065, 1.059, 1.055, 1.052, 1.046, 1.039, 1.032, 1.026, 1.019, 1.019, 1.022,
+                            1.066, 1.071, 1.074, 1.076, 1.078, 1.079, 1.078, 1.078, 1.077, 1.077, 1.077, 1.078, 1.079, 1.081, 1.082, 1.084, 1.083, 1.081, 1.079, 1.076, 1.075, 1.071, 1.067, 1.063, 1.058, 1.053, 1.047, 1.041, 1.032, 1.032, 1.029, 1.029,
+                            1.069, 1.073, 1.077, 1.079, 1.081, 1.082, 1.081, 1.081, 1.081, 1.081, 1.082, 1.083, 1.084, 1.086, 1.086, 1.087, 1.086, 1.086, 1.084, 1.082, 1.079, 1.076, 1.072, 1.069, 1.064, 1.059, 1.053, 1.047, 1.039, 1.037, 1.036, 1.039,
+                            1.071, 1.075, 1.078, 1.081, 1.082, 1.084, 1.084, 1.085, 1.084, 1.084, 1.084, 1.086, 1.087, 1.089, 1.091, 1.091, 1.091, 1.089, 1.088, 1.086, 1.083, 1.081, 1.078, 1.073, 1.069, 1.064, 1.058, 1.052, 1.044, 1.042, 1.042, 1.042,
+                            1.072, 1.078, 1.079, 1.082, 1.085, 1.086, 1.086, 1.087, 1.086, 1.087, 1.088, 1.089, 1.091, 1.093, 1.094, 1.095, 1.095, 1.093, 1.092, 1.091, 1.088, 1.086, 1.083, 1.079, 1.074, 1.071, 1.064, 1.057, 1.049, 1.047, 1.047, 1.051,
+                            1.072, 1.079, 1.082, 1.085, 1.087, 1.089, 1.089, 1.091, 1.091, 1.092, 1.092, 1.094, 1.095, 1.097, 1.099, 1.098, 1.098, 1.096, 1.095, 1.094, 1.093, 1.089, 1.088, 1.084, 1.079, 1.075, 1.069, 1.063, 1.054, 1.053, 1.053, 1.058,
+                            1.073, 1.081, 1.085, 1.088, 1.091, 1.092, 1.093, 1.093, 1.093, 1.094, 1.096, 1.096, 1.099, 1.101, 1.102, 1.101, 1.099, 1.099, 1.098, 1.097, 1.095, 1.093, 1.089, 1.088, 1.084, 1.078, 1.075, 1.068, 1.059, 1.058, 1.059, 1.059,
+                            1.076, 1.083, 1.086, 1.089, 1.093, 1.094, 1.095, 1.095, 1.095, 1.096, 1.098, 1.099, 1.101, 1.103, 1.103, 1.103, 1.102, 1.101, 1.099, 1.099, 1.098, 1.095, 1.093, 1.091, 1.088, 1.084, 1.077, 1.073, 1.066, 1.063, 1.062, 1.066,
+                            1.081, 1.085, 1.089, 1.093, 1.095, 1.096, 1.096, 1.096, 1.097, 1.098, 1.099, 1.101, 1.103, 1.103, 1.104, 1.103, 1.103, 1.102, 1.102, 1.101, 1.099, 1.098, 1.096, 1.093, 1.091, 1.087, 1.082, 1.076, 1.067, 1.066, 1.068, 1.071,
+                            1.085, 1.088, 1.093, 1.095, 1.097, 1.098, 1.097, 1.098, 1.098, 1.099, 1.101, 1.102, 1.103, 1.104, 1.104, 1.104, 1.104, 1.104, 1.103, 1.103, 1.102, 1.099, 1.098, 1.096, 1.093, 1.089, 1.084, 1.078, 1.069, 1.069, 1.071, 1.073,
+                            1.085, 1.092, 1.094, 1.096, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.102, 1.103, 1.104, 1.105, 1.105, 1.105, 1.104, 1.104, 1.103, 1.103, 1.102, 1.099, 1.097, 1.095, 1.091, 1.086, 1.081, 1.075, 1.072, 1.072, 1.074,
+                            1.087, 1.093, 1.096, 1.098, 1.101, 1.101, 1.101, 1.099, 1.101, 1.101, 1.101, 1.101, 1.103, 1.104, 1.105, 1.106, 1.106, 1.105, 1.105, 1.104, 1.104, 1.103, 1.101, 1.099, 1.096, 1.092, 1.087, 1.082, 1.075, 1.074, 1.075, 1.077,
+                            1.088, 1.094, 1.097, 1.099, 1.101, 1.101, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.102, 1.104, 1.105, 1.106, 1.106, 1.106, 1.105, 1.105, 1.105, 1.103, 1.102, 1.099, 1.096, 1.093, 1.089, 1.083, 1.076, 1.076, 1.076, 1.077,
+                            1.089, 1.094, 1.098, 1.099, 1.101, 1.099, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.102, 1.103, 1.104, 1.105, 1.105, 1.107, 1.107, 1.107, 1.105, 1.104, 1.102, 1.099, 1.097, 1.094, 1.091, 1.083, 1.076, 1.076, 1.077, 1.078,
+                            1.091, 1.096, 1.098, 1.099, 1.099, 1.098, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.102, 1.103, 1.104, 1.105, 1.105, 1.106, 1.107, 1.107, 1.105, 1.103, 1.102, 1.099, 1.097, 1.094, 1.089, 1.084, 1.077, 1.077, 1.077, 1.078,
+                            1.091, 1.094, 1.096, 1.097, 1.096, 1.096, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.102, 1.103, 1.103, 1.104, 1.105, 1.106, 1.106, 1.104, 1.103, 1.102, 1.099, 1.097, 1.094, 1.091, 1.084, 1.077, 1.077, 1.078, 1.079,
+                            1.091, 1.091, 1.093, 1.094, 1.093, 1.093, 1.094, 1.095, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.103, 1.104, 1.105, 1.104, 1.103, 1.101, 1.099, 1.097, 1.094, 1.089, 1.084, 1.077, 1.077, 1.078, 1.079,
+                            1.083, 1.087, 1.088, 1.089, 1.089, 1.091, 1.092, 1.094, 1.095, 1.095, 1.096, 1.096, 1.096, 1.097, 1.098, 1.098, 1.098, 1.101, 1.102, 1.103, 1.102, 1.102, 1.101, 1.098, 1.096, 1.092, 1.088, 1.083, 1.076, 1.076, 1.077, 1.079,
+                            1.077, 1.081, 1.082, 1.084, 1.086, 1.087, 1.089, 1.091, 1.092, 1.092, 1.092, 1.092, 1.091, 1.092, 1.092, 1.094, 1.096, 1.098, 1.099, 1.101, 1.102, 1.099, 1.099, 1.097, 1.093, 1.089, 1.087, 1.081, 1.074, 1.073, 1.075, 1.077,
+                            1.067, 1.072, 1.075, 1.078, 1.082, 1.084, 1.085, 1.086, 1.087, 1.087, 1.087, 1.087, 1.086, 1.087, 1.089, 1.091, 1.094, 1.097, 1.098, 1.099, 1.099, 1.098, 1.097, 1.094, 1.091, 1.087, 1.083, 1.079, 1.071, 1.071, 1.072, 1.075,
+                            1.061, 1.065, 1.069, 1.072, 1.075, 1.079, 1.081, 1.082, 1.082, 1.083, 1.083, 1.083, 1.083, 1.084, 1.087, 1.089, 1.092, 1.095, 1.097, 1.097, 1.097, 1.096, 1.094, 1.091, 1.087, 1.084, 1.079, 1.074, 1.068, 1.067, 1.068, 1.069,
+                            1.053, 1.058, 1.063, 1.067, 1.071, 1.073, 1.075, 1.076, 1.078, 1.078, 1.079, 1.079, 1.081, 1.083, 1.085, 1.088, 1.091, 1.093, 1.095, 1.095, 1.093, 1.092, 1.089, 1.086, 1.084, 1.081, 1.075, 1.071, 1.064, 1.061, 1.063, 1.065,
+                            1.049, 1.053, 1.059, 1.062, 1.065, 1.068, 1.071, 1.073, 1.074, 1.075, 1.077, 1.078, 1.079, 1.082, 1.085, 1.088, 1.089, 1.091, 1.091, 1.091, 1.089, 1.088, 1.085, 1.082, 1.079, 1.075, 1.071, 1.066, 1.059, 1.059, 1.061, 1.063,
+                            1.044, 1.048, 1.053, 1.057, 1.061, 1.065, 1.066, 1.069, 1.071, 1.073, 1.074, 1.076, 1.078, 1.082, 1.084, 1.086, 1.088, 1.089, 1.089, 1.088, 1.087, 1.084, 1.081, 1.079, 1.076, 1.071, 1.067, 1.062, 1.055, 1.055, 1.056, 1.059,
+                            1.039, 1.046, 1.049, 1.054, 1.057, 1.059, 1.062, 1.064, 1.067, 1.071, 1.073, 1.075, 1.077, 1.081, 1.082, 1.084, 1.084, 1.085, 1.085, 1.084, 1.083, 1.081, 1.077, 1.075, 1.071, 1.068, 1.063, 1.057, 1.052, 1.051, 1.054, 1.055,
+                            1.034, 1.041, 1.046, 1.049, 1.053, 1.055, 1.058, 1.062, 1.064, 1.067, 1.069, 1.072, 1.075, 1.078, 1.079, 1.081, 1.081, 1.081, 1.081, 1.079, 1.078, 1.076, 1.074, 1.071, 1.068, 1.064, 1.061, 1.054, 1.049, 1.049, 1.052, 1.054,
+                            1.029, 1.034, 1.041, 1.043, 1.048, 1.051, 1.054, 1.056, 1.061, 1.063, 1.066, 1.067, 1.071, 1.073, 1.075, 1.075, 1.075, 1.076, 1.075, 1.075, 1.074, 1.072, 1.071, 1.068, 1.064, 1.061, 1.057, 1.051, 1.047, 1.046, 1.048, 1.054,
+                            1.019, 1.027, 1.033, 1.036, 1.042, 1.046, 1.049, 1.051, 1.053, 1.056, 1.058, 1.061, 1.064, 1.065, 1.066, 1.069, 1.071, 1.071, 1.069, 1.068, 1.068, 1.067, 1.064, 1.062, 1.059, 1.057, 1.052, 1.047, 1.044, 1.043, 1.048, 1.067,
+                            1.009, 1.018, 1.025, 1.028, 1.033, 1.039, 1.042, 1.043, 1.044, 1.046, 1.047, 1.049, 1.052, 1.055, 1.057, 1.059, 1.061, 1.061, 1.061, 1.062, 1.061, 1.058, 1.057, 1.056, 1.052, 1.051, 1.046, 1.042, 1.038, 1.038, 1.059, 1.067,
+                            1.005, 1.009, 1.017, 1.023, 1.026, 1.027, 1.028, 1.029, 1.031, 1.031, 1.032, 1.036, 1.041, 1.044, 1.046, 1.047, 1.047, 1.048, 1.049, 1.049, 1.049, 1.048, 1.046, 1.044, 1.042, 1.039, 1.039, 1.034, 1.033, 1.048, 1.062, 1.062
+                        ]
+                    },
+                    {
+                        "ct": 5000,
+                        "table":
+                        [
+                            1.051, 1.052, 1.057, 1.061, 1.061, 1.061, 1.061, 1.061, 1.061, 1.059, 1.059, 1.059, 1.062, 1.063, 1.065, 1.067, 1.066, 1.064, 1.063, 1.062, 1.058, 1.055, 1.049, 1.047, 1.043, 1.039, 1.037, 1.029, 1.028, 1.024, 1.026, 1.027,
+                            1.048, 1.049, 1.052, 1.053, 1.053, 1.051, 1.051, 1.051, 1.049, 1.048, 1.049, 1.051, 1.052, 1.055, 1.055, 1.056, 1.057, 1.058, 1.058, 1.055, 1.053, 1.051, 1.047, 1.044, 1.041, 1.038, 1.034, 1.029, 1.025, 1.024, 1.025, 1.029,
+                            1.047, 1.048, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.048, 1.048, 1.051, 1.051, 1.053, 1.055, 1.056, 1.056, 1.056, 1.055, 1.054, 1.051, 1.049, 1.046, 1.043, 1.041, 1.037, 1.035, 1.029, 1.026, 1.026, 1.029, 1.031,
+                            1.046, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.049, 1.048, 1.049, 1.051, 1.052, 1.055, 1.056, 1.056, 1.057, 1.057, 1.056, 1.054, 1.052, 1.049, 1.047, 1.045, 1.041, 1.039, 1.035, 1.032, 1.029, 1.031, 1.032, 1.038,
+                            1.047, 1.049, 1.051, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.051, 1.053, 1.055, 1.056, 1.058, 1.058, 1.056, 1.056, 1.053, 1.051, 1.049, 1.048, 1.045, 1.044, 1.041, 1.038, 1.034, 1.031, 1.031, 1.036, 1.041,
+                            1.046, 1.048, 1.048, 1.048, 1.048, 1.049, 1.049, 1.048, 1.048, 1.048, 1.049, 1.051, 1.052, 1.054, 1.055, 1.057, 1.057, 1.057, 1.056, 1.054, 1.051, 1.049, 1.049, 1.047, 1.044, 1.042, 1.039, 1.035, 1.032, 1.033, 1.039, 1.043,
+                            1.046, 1.047, 1.048, 1.048, 1.048, 1.048, 1.048, 1.048, 1.048, 1.049, 1.049, 1.051, 1.053, 1.054, 1.055, 1.057, 1.056, 1.055, 1.055, 1.054, 1.053, 1.051, 1.049, 1.048, 1.046, 1.043, 1.042, 1.038, 1.033, 1.034, 1.042, 1.047,
+                            1.045, 1.046, 1.048, 1.049, 1.049, 1.049, 1.048, 1.048, 1.048, 1.049, 1.049, 1.051, 1.053, 1.055, 1.055, 1.056, 1.055, 1.055, 1.054, 1.054, 1.053, 1.052, 1.051, 1.049, 1.047, 1.045, 1.043, 1.041, 1.036, 1.037, 1.044, 1.047,
+                            1.044, 1.047, 1.048, 1.049, 1.051, 1.049, 1.048, 1.048, 1.048, 1.048, 1.049, 1.051, 1.052, 1.055, 1.056, 1.056, 1.055, 1.054, 1.054, 1.053, 1.053, 1.052, 1.049, 1.049, 1.048, 1.046, 1.044, 1.042, 1.037, 1.037, 1.045, 1.049,
+                            1.045, 1.047, 1.048, 1.051, 1.051, 1.049, 1.049, 1.048, 1.048, 1.048, 1.049, 1.051, 1.051, 1.053, 1.055, 1.055, 1.054, 1.053, 1.053, 1.053, 1.053, 1.051, 1.051, 1.051, 1.048, 1.047, 1.045, 1.042, 1.039, 1.039, 1.048, 1.051,
+                            1.046, 1.047, 1.049, 1.051, 1.051, 1.049, 1.048, 1.047, 1.047, 1.047, 1.048, 1.049, 1.051, 1.053, 1.054, 1.054, 1.053, 1.053, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.048, 1.046, 1.043, 1.039, 1.039, 1.051, 1.055,
+                            1.046, 1.048, 1.049, 1.051, 1.051, 1.051, 1.048, 1.047, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.051, 1.051, 1.051, 1.049, 1.048, 1.047, 1.043, 1.041, 1.041, 1.053, 1.056,
+                            1.047, 1.049, 1.051, 1.051, 1.051, 1.049, 1.049, 1.047, 1.047, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.044, 1.042, 1.042, 1.054, 1.058,
+                            1.048, 1.049, 1.051, 1.052, 1.051, 1.049, 1.048, 1.047, 1.046, 1.046, 1.047, 1.047, 1.048, 1.051, 1.051, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.043, 1.055, 1.057,
+                            1.048, 1.051, 1.052, 1.051, 1.051, 1.049, 1.047, 1.046, 1.046, 1.046, 1.047, 1.047, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.052, 1.051, 1.049, 1.048, 1.048, 1.047, 1.045, 1.044, 1.044, 1.056, 1.058,
+                            1.049, 1.051, 1.052, 1.051, 1.049, 1.048, 1.046, 1.046, 1.044, 1.046, 1.046, 1.047, 1.047, 1.049, 1.051, 1.051, 1.052, 1.053, 1.053, 1.053, 1.052, 1.052, 1.051, 1.049, 1.048, 1.048, 1.047, 1.045, 1.044, 1.044, 1.056, 1.059,
+                            1.051, 1.052, 1.053, 1.051, 1.048, 1.047, 1.045, 1.043, 1.043, 1.044, 1.045, 1.046, 1.047, 1.048, 1.051, 1.051, 1.051, 1.053, 1.053, 1.053, 1.052, 1.051, 1.049, 1.049, 1.049, 1.048, 1.047, 1.046, 1.045, 1.046, 1.057, 1.061,
+                            1.051, 1.051, 1.049, 1.048, 1.047, 1.045, 1.043, 1.043, 1.044, 1.044, 1.045, 1.045, 1.046, 1.047, 1.048, 1.049, 1.051, 1.052, 1.052, 1.052, 1.051, 1.051, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.046, 1.055, 1.083, 1.092,
+                            1.048, 1.048, 1.047, 1.045, 1.045, 1.043, 1.042, 1.042, 1.043, 1.043, 1.044, 1.044, 1.044, 1.045, 1.046, 1.047, 1.048, 1.049, 1.051, 1.051, 1.051, 1.051, 1.049, 1.049, 1.049, 1.048, 1.048, 1.047, 1.055, 1.073, 1.098, 1.099,
+                            1.044, 1.044, 1.042, 1.041, 1.041, 1.041, 1.041, 1.041, 1.042, 1.041, 1.042, 1.041, 1.041, 1.041, 1.042, 1.044, 1.045, 1.047, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.048, 1.048, 1.072, 1.087, 1.097, 1.099,
+                            1.038, 1.037, 1.036, 1.036, 1.036, 1.037, 1.037, 1.038, 1.038, 1.038, 1.039, 1.038, 1.038, 1.038, 1.039, 1.041, 1.043, 1.045, 1.047, 1.048, 1.049, 1.048, 1.048, 1.047, 1.047, 1.045, 1.045, 1.048, 1.071, 1.087, 1.096, 1.098,
+                            1.029, 1.031, 1.032, 1.033, 1.033, 1.034, 1.034, 1.035, 1.035, 1.034, 1.033, 1.033, 1.034, 1.034, 1.036, 1.039, 1.041, 1.044, 1.045, 1.047, 1.048, 1.046, 1.046, 1.046, 1.044, 1.044, 1.043, 1.042, 1.049, 1.081, 1.095, 1.096,
+                            1.026, 1.027, 1.028, 1.029, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.031, 1.033, 1.035, 1.038, 1.039, 1.043, 1.044, 1.045, 1.045, 1.044, 1.044, 1.043, 1.043, 1.041, 1.041, 1.039, 1.039, 1.049, 1.087, 1.095,
+                            1.021, 1.023, 1.025, 1.026, 1.027, 1.028, 1.029, 1.028, 1.029, 1.029, 1.029, 1.029, 1.031, 1.032, 1.035, 1.038, 1.041, 1.043, 1.045, 1.044, 1.044, 1.042, 1.041, 1.041, 1.039, 1.039, 1.039, 1.037, 1.035, 1.036, 1.054, 1.071,
+                            1.017, 1.021, 1.023, 1.024, 1.025, 1.026, 1.027, 1.027, 1.028, 1.027, 1.028, 1.029, 1.032, 1.034, 1.036, 1.039, 1.041, 1.042, 1.044, 1.044, 1.043, 1.041, 1.039, 1.039, 1.038, 1.037, 1.036, 1.034, 1.034, 1.034, 1.046, 1.051,
+                            1.014, 1.019, 1.022, 1.024, 1.024, 1.025, 1.025, 1.026, 1.027, 1.028, 1.029, 1.031, 1.033, 1.035, 1.038, 1.041, 1.042, 1.042, 1.043, 1.042, 1.041, 1.039, 1.038, 1.038, 1.037, 1.036, 1.034, 1.033, 1.032, 1.033, 1.045, 1.047,
+                            1.014, 1.019, 1.021, 1.023, 1.024, 1.025, 1.025, 1.026, 1.027, 1.029, 1.031, 1.032, 1.035, 1.037, 1.039, 1.041, 1.042, 1.042, 1.042, 1.041, 1.041, 1.039, 1.038, 1.037, 1.037, 1.035, 1.034, 1.033, 1.033, 1.033, 1.044, 1.047,
+                            1.015, 1.019, 1.019, 1.022, 1.024, 1.025, 1.025, 1.027, 1.029, 1.031, 1.032, 1.033, 1.036, 1.038, 1.039, 1.041, 1.041, 1.041, 1.041, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.036, 1.034, 1.034, 1.033, 1.034, 1.043, 1.046,
+                            1.014, 1.016, 1.019, 1.019, 1.022, 1.023, 1.025, 1.026, 1.029, 1.031, 1.032, 1.033, 1.036, 1.037, 1.039, 1.039, 1.039, 1.041, 1.039, 1.039, 1.039, 1.039, 1.038, 1.038, 1.037, 1.036, 1.034, 1.034, 1.033, 1.034, 1.042, 1.045,
+                            1.011, 1.013, 1.016, 1.018, 1.021, 1.023, 1.024, 1.024, 1.026, 1.028, 1.029, 1.031, 1.033, 1.035, 1.036, 1.036, 1.037, 1.038, 1.038, 1.038, 1.038, 1.038, 1.037, 1.037, 1.036, 1.036, 1.034, 1.033, 1.032, 1.033, 1.039, 1.044,
+                            1.003, 1.007, 1.012, 1.014, 1.016, 1.019, 1.022, 1.022, 1.022, 1.022, 1.024, 1.025, 1.026, 1.028, 1.029, 1.031, 1.033, 1.034, 1.034, 1.036, 1.036, 1.035, 1.033, 1.034, 1.033, 1.033, 1.032, 1.031, 1.029, 1.029, 1.034, 1.038,
+                            1.001, 1.002, 1.008, 1.011, 1.013, 1.015, 1.014, 1.014, 1.013, 1.012, 1.013, 1.015, 1.019, 1.022, 1.023, 1.025, 1.026, 1.026, 1.029, 1.029, 1.029, 1.029, 1.029, 1.029, 1.028, 1.028, 1.027, 1.025, 1.025, 1.026, 1.031, 1.035
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.179, 1.187, 1.194, 1.197, 1.199, 1.201, 1.199, 1.199, 1.198, 1.198, 1.196, 1.195, 1.192, 1.192, 1.191, 1.191, 1.187, 1.182, 1.176, 1.171, 1.162, 1.156, 1.143, 1.132, 1.114, 1.097, 1.081, 1.061, 1.041, 1.019, 1.006, 1.001,
+                            1.187, 1.189, 1.194, 1.197, 1.199, 1.201, 1.201, 1.201, 1.199, 1.199, 1.196, 1.195, 1.195, 1.194, 1.193, 1.192, 1.189, 1.187, 1.181, 1.175, 1.168, 1.157, 1.152, 1.135, 1.122, 1.104, 1.086, 1.069, 1.047, 1.027, 1.012, 1.005,
+                            1.188, 1.189, 1.195, 1.199, 1.201, 1.202, 1.203, 1.204, 1.202, 1.201, 1.201, 1.199, 1.199, 1.201, 1.199, 1.196, 1.195, 1.192, 1.189, 1.183, 1.175, 1.166, 1.155, 1.146, 1.129, 1.117, 1.099, 1.082, 1.061, 1.041, 1.025, 1.012,
+                            1.189, 1.197, 1.199, 1.203, 1.205, 1.207, 1.208, 1.208, 1.208, 1.208, 1.207, 1.207, 1.206, 1.207, 1.207, 1.205, 1.203, 1.202, 1.195, 1.189, 1.183, 1.174, 1.165, 1.154, 1.138, 1.125, 1.108, 1.088, 1.071, 1.049, 1.041, 1.029,
+                            1.198, 1.199, 1.204, 1.207, 1.209, 1.209, 1.209, 1.209, 1.211, 1.211, 1.209, 1.209, 1.209, 1.212, 1.212, 1.212, 1.209, 1.206, 1.202, 1.196, 1.189, 1.182, 1.172, 1.162, 1.151, 1.134, 1.118, 1.099, 1.079, 1.063, 1.049, 1.041,
+                            1.199, 1.204, 1.206, 1.209, 1.211, 1.211, 1.212, 1.213, 1.214, 1.214, 1.214, 1.213, 1.215, 1.216, 1.216, 1.216, 1.213, 1.209, 1.208, 1.202, 1.196, 1.188, 1.179, 1.169, 1.157, 1.142, 1.125, 1.111, 1.088, 1.073, 1.062, 1.054,
+                            1.202, 1.205, 1.208, 1.211, 1.213, 1.215, 1.215, 1.216, 1.216, 1.216, 1.218, 1.219, 1.219, 1.221, 1.221, 1.221, 1.218, 1.215, 1.211, 1.207, 1.202, 1.194, 1.186, 1.177, 1.162, 1.149, 1.137, 1.116, 1.098, 1.082, 1.073, 1.063,
+                            1.202, 1.205, 1.209, 1.213, 1.215, 1.217, 1.218, 1.219, 1.219, 1.221, 1.222, 1.223, 1.223, 1.224, 1.223, 1.223, 1.221, 1.218, 1.215, 1.211, 1.207, 1.201, 1.189, 1.181, 1.171, 1.158, 1.143, 1.129, 1.107, 1.089, 1.081, 1.074,
+                            1.203, 1.207, 1.209, 1.215, 1.217, 1.219, 1.221, 1.222, 1.222, 1.224, 1.225, 1.225, 1.226, 1.227, 1.227, 1.225, 1.223, 1.221, 1.218, 1.215, 1.209, 1.202, 1.195, 1.186, 1.178, 1.164, 1.151, 1.133, 1.115, 1.098, 1.088, 1.083,
+                            1.202, 1.209, 1.213, 1.217, 1.219, 1.221, 1.222, 1.223, 1.224, 1.225, 1.226, 1.228, 1.228, 1.228, 1.228, 1.226, 1.225, 1.223, 1.219, 1.216, 1.212, 1.205, 1.198, 1.192, 1.183, 1.169, 1.154, 1.142, 1.122, 1.106, 1.097, 1.089,
+                            1.206, 1.211, 1.215, 1.218, 1.221, 1.223, 1.224, 1.224, 1.225, 1.226, 1.227, 1.229, 1.229, 1.229, 1.229, 1.228, 1.226, 1.224, 1.222, 1.218, 1.215, 1.209, 1.203, 1.196, 1.188, 1.175, 1.161, 1.149, 1.127, 1.112, 1.103, 1.097,
+                            1.209, 1.213, 1.217, 1.218, 1.222, 1.224, 1.225, 1.225, 1.226, 1.227, 1.229, 1.229, 1.229, 1.229, 1.229, 1.229, 1.227, 1.225, 1.223, 1.221, 1.217, 1.213, 1.207, 1.199, 1.191, 1.179, 1.164, 1.149, 1.133, 1.117, 1.109, 1.103,
+                            1.211, 1.216, 1.218, 1.219, 1.224, 1.225, 1.226, 1.226, 1.227, 1.228, 1.229, 1.229, 1.229, 1.231, 1.231, 1.231, 1.229, 1.227, 1.224, 1.222, 1.219, 1.215, 1.209, 1.202, 1.194, 1.182, 1.169, 1.153, 1.137, 1.122, 1.115, 1.108,
+                            1.211, 1.215, 1.219, 1.219, 1.224, 1.225, 1.227, 1.227, 1.228, 1.229, 1.229, 1.229, 1.229, 1.231, 1.231, 1.231, 1.229, 1.227, 1.226, 1.223, 1.221, 1.217, 1.211, 1.203, 1.195, 1.183, 1.171, 1.156, 1.141, 1.123, 1.116, 1.113,
+                            1.209, 1.215, 1.219, 1.222, 1.225, 1.225, 1.226, 1.226, 1.227, 1.228, 1.229, 1.229, 1.231, 1.231, 1.231, 1.231, 1.231, 1.229, 1.227, 1.224, 1.222, 1.217, 1.211, 1.204, 1.196, 1.184, 1.174, 1.159, 1.142, 1.128, 1.121, 1.114,
+                            1.208, 1.215, 1.218, 1.221, 1.223, 1.223, 1.224, 1.224, 1.226, 1.227, 1.227, 1.228, 1.229, 1.231, 1.231, 1.231, 1.231, 1.229, 1.229, 1.226, 1.223, 1.218, 1.213, 1.207, 1.197, 1.188, 1.176, 1.161, 1.143, 1.129, 1.121, 1.114,
+                            1.208, 1.213, 1.216, 1.219, 1.221, 1.221, 1.222, 1.223, 1.224, 1.225, 1.226, 1.227, 1.228, 1.231, 1.231, 1.231, 1.231, 1.231, 1.229, 1.227, 1.224, 1.218, 1.214, 1.207, 1.197, 1.188, 1.177, 1.161, 1.145, 1.131, 1.122, 1.115,
+                            1.207, 1.208, 1.214, 1.214, 1.217, 1.218, 1.219, 1.221, 1.223, 1.224, 1.225, 1.225, 1.226, 1.227, 1.228, 1.228, 1.229, 1.229, 1.228, 1.226, 1.223, 1.219, 1.215, 1.207, 1.198, 1.188, 1.177, 1.161, 1.147, 1.131, 1.123, 1.116,
+                            1.199, 1.204, 1.208, 1.208, 1.211, 1.212, 1.215, 1.218, 1.221, 1.221, 1.222, 1.223, 1.223, 1.225, 1.225, 1.227, 1.226, 1.227, 1.226, 1.225, 1.223, 1.219, 1.212, 1.207, 1.198, 1.187, 1.177, 1.161, 1.146, 1.131, 1.123, 1.116,
+                            1.193, 1.196, 1.199, 1.201, 1.204, 1.206, 1.209, 1.213, 1.215, 1.217, 1.218, 1.219, 1.221, 1.221, 1.221, 1.222, 1.223, 1.224, 1.224, 1.223, 1.222, 1.218, 1.211, 1.207, 1.197, 1.187, 1.175, 1.161, 1.146, 1.129, 1.122, 1.113,
+                            1.177, 1.182, 1.188, 1.192, 1.195, 1.198, 1.203, 1.208, 1.211, 1.212, 1.214, 1.214, 1.214, 1.215, 1.216, 1.217, 1.219, 1.221, 1.223, 1.222, 1.221, 1.216, 1.212, 1.204, 1.197, 1.186, 1.175, 1.159, 1.143, 1.129, 1.119, 1.114,
+                            1.162, 1.171, 1.177, 1.183, 1.187, 1.192, 1.196, 1.201, 1.204, 1.205, 1.206, 1.207, 1.208, 1.209, 1.212, 1.215, 1.216, 1.219, 1.221, 1.219, 1.218, 1.214, 1.211, 1.203, 1.195, 1.184, 1.173, 1.157, 1.139, 1.128, 1.117, 1.113,
+                            1.149, 1.158, 1.167, 1.172, 1.178, 1.184, 1.189, 1.193, 1.195, 1.196, 1.201, 1.201, 1.201, 1.206, 1.209, 1.212, 1.214, 1.216, 1.218, 1.218, 1.216, 1.212, 1.207, 1.201, 1.192, 1.181, 1.167, 1.155, 1.136, 1.121, 1.114, 1.107,
+                            1.137, 1.147, 1.155, 1.161, 1.169, 1.174, 1.179, 1.183, 1.188, 1.189, 1.193, 1.196, 1.199, 1.201, 1.206, 1.209, 1.213, 1.214, 1.215, 1.214, 1.211, 1.208, 1.202, 1.194, 1.186, 1.177, 1.163, 1.149, 1.132, 1.117, 1.109, 1.104,
+                            1.126, 1.136, 1.144, 1.151, 1.157, 1.163, 1.171, 1.177, 1.181, 1.183, 1.186, 1.191, 1.196, 1.201, 1.204, 1.207, 1.211, 1.213, 1.213, 1.211, 1.209, 1.204, 1.199, 1.191, 1.183, 1.172, 1.158, 1.144, 1.127, 1.112, 1.105, 1.098,
+                            1.114, 1.125, 1.134, 1.142, 1.147, 1.155, 1.161, 1.166, 1.171, 1.177, 1.181, 1.186, 1.191, 1.197, 1.202, 1.204, 1.207, 1.209, 1.209, 1.209, 1.205, 1.201, 1.195, 1.188, 1.178, 1.168, 1.154, 1.139, 1.122, 1.106, 1.099, 1.095,
+                            1.107, 1.114, 1.123, 1.132, 1.137, 1.144, 1.152, 1.157, 1.162, 1.169, 1.176, 1.181, 1.187, 1.193, 1.198, 1.202, 1.204, 1.205, 1.206, 1.204, 1.201, 1.197, 1.191, 1.183, 1.175, 1.162, 1.149, 1.133, 1.117, 1.103, 1.095, 1.088,
+                            1.094, 1.101, 1.112, 1.117, 1.129, 1.133, 1.141, 1.149, 1.156, 1.161, 1.169, 1.175, 1.182, 1.187, 1.192, 1.196, 1.199, 1.201, 1.201, 1.199, 1.196, 1.192, 1.187, 1.181, 1.171, 1.157, 1.145, 1.128, 1.114, 1.099, 1.088, 1.085,
+                            1.083, 1.091, 1.099, 1.104, 1.112, 1.121, 1.128, 1.139, 1.146, 1.154, 1.159, 1.168, 1.174, 1.182, 1.187, 1.188, 1.193, 1.195, 1.195, 1.194, 1.191, 1.188, 1.182, 1.172, 1.163, 1.154, 1.138, 1.123, 1.109, 1.096, 1.085, 1.079,
+                            1.065, 1.074, 1.082, 1.092, 1.101, 1.109, 1.118, 1.126, 1.133, 1.143, 1.149, 1.158, 1.164, 1.171, 1.176, 1.179, 1.185, 1.186, 1.186, 1.185, 1.184, 1.181, 1.172, 1.165, 1.157, 1.148, 1.133, 1.118, 1.101, 1.086, 1.079, 1.071,
+                            1.045, 1.059, 1.067, 1.076, 1.084, 1.097, 1.106, 1.113, 1.123, 1.129, 1.134, 1.141, 1.149, 1.155, 1.161, 1.165, 1.172, 1.175, 1.177, 1.176, 1.174, 1.172, 1.164, 1.156, 1.148, 1.135, 1.121, 1.108, 1.091, 1.079, 1.067, 1.057,
+                            1.038, 1.045, 1.057, 1.067, 1.075, 1.083, 1.094, 1.102, 1.109, 1.115, 1.122, 1.131, 1.136, 1.144, 1.151, 1.155, 1.161, 1.161, 1.164, 1.164, 1.164, 1.161, 1.158, 1.147, 1.138, 1.125, 1.111, 1.095, 1.079, 1.067, 1.057, 1.051
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2400,
+                        "table":
+                        [
+                            1.261, 1.265, 1.267, 1.273, 1.276, 1.283, 1.283, 1.291, 1.294, 1.299, 1.301, 1.304, 1.304, 1.305, 1.297, 1.301, 1.304, 1.303, 1.301, 1.298, 1.285, 1.271, 1.252, 1.234, 1.204, 1.177, 1.148, 1.115, 1.083, 1.048, 1.004, 1.001,
+                            1.274, 1.283, 1.289, 1.292, 1.299, 1.302, 1.309, 1.314, 1.317, 1.321, 1.322, 1.326, 1.329, 1.332, 1.335, 1.335, 1.335, 1.329, 1.322, 1.311, 1.299, 1.286, 1.265, 1.249, 1.224, 1.201, 1.173, 1.141, 1.111, 1.077, 1.031, 1.004,
+                            1.287, 1.292, 1.299, 1.303, 1.306, 1.312, 1.317, 1.322, 1.327, 1.331, 1.334, 1.338, 1.341, 1.344, 1.345, 1.346, 1.344, 1.339, 1.335, 1.324, 1.312, 1.299, 1.286, 1.265, 1.245, 1.218, 1.193, 1.159, 1.126, 1.094, 1.051, 1.028,
+                            1.297, 1.299, 1.307, 1.311, 1.314, 1.321, 1.325, 1.329, 1.335, 1.339, 1.344, 1.348, 1.349, 1.353, 1.353, 1.355, 1.354, 1.351, 1.345, 1.337, 1.324, 1.311, 1.299, 1.279, 1.256, 1.232, 1.202, 1.173, 1.141, 1.109, 1.066, 1.042,
+                            1.303, 1.309, 1.315, 1.318, 1.324, 1.327, 1.334, 1.339, 1.343, 1.347, 1.352, 1.354, 1.361, 1.364, 1.366, 1.365, 1.365, 1.361, 1.358, 1.349, 1.338, 1.323, 1.309, 1.292, 1.269, 1.244, 1.217, 1.189, 1.157, 1.121, 1.079, 1.057,
+                            1.312, 1.316, 1.322, 1.326, 1.329, 1.337, 1.341, 1.346, 1.351, 1.353, 1.358, 1.365, 1.368, 1.371, 1.373, 1.373, 1.373, 1.367, 1.363, 1.358, 1.349, 1.336, 1.319, 1.301, 1.285, 1.257, 1.231, 1.201, 1.168, 1.137, 1.094, 1.065,
+                            1.317, 1.323, 1.329, 1.332, 1.338, 1.342, 1.349, 1.353, 1.356, 1.361, 1.367, 1.372, 1.375, 1.379, 1.381, 1.381, 1.379, 1.377, 1.371, 1.364, 1.357, 1.345, 1.333, 1.312, 1.292, 1.267, 1.239, 1.211, 1.181, 1.142, 1.105, 1.078,
+                            1.321, 1.329, 1.334, 1.341, 1.343, 1.351, 1.355, 1.359, 1.361, 1.368, 1.373, 1.377, 1.381, 1.385, 1.387, 1.387, 1.385, 1.381, 1.376, 1.371, 1.362, 1.351, 1.338, 1.319, 1.299, 1.276, 1.252, 1.221, 1.189, 1.156, 1.113, 1.086,
+                            1.328, 1.334, 1.341, 1.344, 1.351, 1.353, 1.359, 1.363, 1.368, 1.374, 1.377, 1.382, 1.385, 1.389, 1.392, 1.391, 1.389, 1.387, 1.381, 1.375, 1.367, 1.359, 1.345, 1.327, 1.311, 1.284, 1.261, 1.231, 1.201, 1.169, 1.121, 1.091,
+                            1.331, 1.338, 1.343, 1.347, 1.352, 1.358, 1.362, 1.367, 1.371, 1.375, 1.379, 1.385, 1.389, 1.393, 1.395, 1.396, 1.393, 1.391, 1.385, 1.378, 1.373, 1.362, 1.349, 1.335, 1.313, 1.291, 1.265, 1.238, 1.209, 1.175, 1.129, 1.098,
+                            1.331, 1.341, 1.345, 1.349, 1.355, 1.359, 1.364, 1.368, 1.372, 1.378, 1.381, 1.388, 1.392, 1.394, 1.397, 1.397, 1.396, 1.392, 1.388, 1.382, 1.374, 1.363, 1.353, 1.337, 1.317, 1.295, 1.274, 1.244, 1.216, 1.183, 1.138, 1.101,
+                            1.329, 1.341, 1.345, 1.351, 1.355, 1.361, 1.365, 1.368, 1.373, 1.377, 1.381, 1.387, 1.391, 1.394, 1.396, 1.397, 1.397, 1.393, 1.389, 1.383, 1.375, 1.366, 1.357, 1.339, 1.321, 1.299, 1.276, 1.247, 1.219, 1.187, 1.141, 1.108,
+                            1.331, 1.342, 1.345, 1.351, 1.357, 1.361, 1.365, 1.369, 1.372, 1.377, 1.381, 1.385, 1.391, 1.393, 1.396, 1.396, 1.396, 1.394, 1.389, 1.384, 1.375, 1.368, 1.358, 1.339, 1.324, 1.302, 1.278, 1.251, 1.221, 1.192, 1.146, 1.113,
+                            1.332, 1.341, 1.346, 1.352, 1.356, 1.361, 1.365, 1.369, 1.372, 1.376, 1.379, 1.384, 1.389, 1.392, 1.395, 1.396, 1.396, 1.394, 1.391, 1.386, 1.381, 1.368, 1.358, 1.341, 1.325, 1.303, 1.279, 1.252, 1.224, 1.194, 1.148, 1.117,
+                            1.332, 1.339, 1.346, 1.351, 1.355, 1.358, 1.363, 1.367, 1.371, 1.375, 1.378, 1.384, 1.387, 1.392, 1.395, 1.396, 1.395, 1.393, 1.389, 1.385, 1.381, 1.368, 1.357, 1.342, 1.325, 1.302, 1.279, 1.252, 1.224, 1.195, 1.151, 1.119,
+                            1.332, 1.338, 1.344, 1.349, 1.354, 1.357, 1.361, 1.366, 1.369, 1.373, 1.377, 1.383, 1.388, 1.391, 1.392, 1.395, 1.393, 1.393, 1.391, 1.386, 1.379, 1.367, 1.356, 1.342, 1.324, 1.302, 1.279, 1.253, 1.224, 1.195, 1.152, 1.118,
+                            1.331, 1.335, 1.339, 1.346, 1.351, 1.355, 1.357, 1.363, 1.367, 1.372, 1.377, 1.381, 1.386, 1.388, 1.392, 1.393, 1.393, 1.392, 1.389, 1.385, 1.377, 1.367, 1.356, 1.341, 1.325, 1.303, 1.279, 1.252, 1.224, 1.195, 1.152, 1.118,
+                            1.324, 1.329, 1.335, 1.339, 1.347, 1.351, 1.356, 1.359, 1.364, 1.369, 1.375, 1.378, 1.383, 1.388, 1.389, 1.392, 1.392, 1.391, 1.387, 1.383, 1.376, 1.366, 1.355, 1.342, 1.324, 1.302, 1.279, 1.253, 1.225, 1.196, 1.153, 1.116,
+                            1.314, 1.318, 1.328, 1.333, 1.339, 1.345, 1.349, 1.356, 1.361, 1.366, 1.371, 1.376, 1.381, 1.383, 1.387, 1.388, 1.388, 1.387, 1.385, 1.381, 1.376, 1.367, 1.356, 1.341, 1.323, 1.303, 1.279, 1.252, 1.226, 1.196, 1.153, 1.117,
+                            1.303, 1.312, 1.318, 1.322, 1.328, 1.338, 1.345, 1.348, 1.357, 1.362, 1.367, 1.371, 1.375, 1.379, 1.382, 1.384, 1.384, 1.384, 1.382, 1.379, 1.375, 1.365, 1.356, 1.339, 1.322, 1.301, 1.278, 1.251, 1.224, 1.195, 1.152, 1.117,
+                            1.288, 1.299, 1.305, 1.313, 1.321, 1.328, 1.339, 1.345, 1.348, 1.355, 1.362, 1.365, 1.369, 1.373, 1.377, 1.379, 1.381, 1.381, 1.381, 1.377, 1.372, 1.363, 1.353, 1.338, 1.319, 1.299, 1.277, 1.249, 1.219, 1.194, 1.149, 1.116,
+                            1.277, 1.286, 1.293, 1.302, 1.309, 1.319, 1.327, 1.336, 1.342, 1.346, 1.351, 1.357, 1.362, 1.367, 1.371, 1.374, 1.375, 1.377, 1.377, 1.374, 1.368, 1.359, 1.349, 1.335, 1.318, 1.296, 1.271, 1.245, 1.217, 1.193, 1.147, 1.112,
+                            1.256, 1.271, 1.277, 1.288, 1.293, 1.305, 1.316, 1.322, 1.331, 1.336, 1.343, 1.348, 1.354, 1.359, 1.366, 1.368, 1.371, 1.373, 1.372, 1.368, 1.362, 1.356, 1.343, 1.329, 1.311, 1.291, 1.266, 1.238, 1.214, 1.184, 1.142, 1.111,
+                            1.234, 1.251, 1.261, 1.269, 1.282, 1.291, 1.302, 1.313, 1.319, 1.327, 1.334, 1.341, 1.348, 1.353, 1.359, 1.365, 1.367, 1.367, 1.366, 1.362, 1.356, 1.349, 1.339, 1.322, 1.304, 1.284, 1.261, 1.235, 1.208, 1.178, 1.136, 1.104,
+                            1.218, 1.231, 1.244, 1.253, 1.265, 1.278, 1.289, 1.297, 1.304, 1.316, 1.325, 1.333, 1.339, 1.346, 1.351, 1.356, 1.361, 1.361, 1.361, 1.355, 1.349, 1.341, 1.328, 1.314, 1.299, 1.278, 1.255, 1.229, 1.203, 1.175, 1.133, 1.099,
+                            1.199, 1.214, 1.227, 1.235, 1.247, 1.262, 1.271, 1.283, 1.292, 1.301, 1.311, 1.322, 1.331, 1.338, 1.342, 1.349, 1.353, 1.353, 1.351, 1.347, 1.341, 1.331, 1.321, 1.308, 1.289, 1.269, 1.246, 1.219, 1.195, 1.167, 1.127, 1.096,
+                            1.179, 1.195, 1.207, 1.218, 1.231, 1.241, 1.257, 1.267, 1.278, 1.288, 1.297, 1.309, 1.321, 1.328, 1.333, 1.338, 1.344, 1.346, 1.342, 1.336, 1.331, 1.323, 1.312, 1.298, 1.284, 1.262, 1.241, 1.214, 1.191, 1.162, 1.118, 1.092,
+                            1.159, 1.174, 1.189, 1.198, 1.209, 1.225, 1.238, 1.252, 1.261, 1.272, 1.286, 1.295, 1.306, 1.314, 1.324, 1.327, 1.332, 1.333, 1.333, 1.329, 1.322, 1.314, 1.303, 1.293, 1.275, 1.253, 1.231, 1.207, 1.181, 1.151, 1.112, 1.081,
+                            1.142, 1.156, 1.168, 1.179, 1.192, 1.206, 1.221, 1.232, 1.243, 1.255, 1.269, 1.278, 1.291, 1.303, 1.311, 1.313, 1.316, 1.319, 1.321, 1.318, 1.314, 1.303, 1.295, 1.281, 1.268, 1.248, 1.225, 1.197, 1.174, 1.147, 1.106, 1.077,
+                            1.119, 1.134, 1.145, 1.159, 1.171, 1.186, 1.199, 1.212, 1.223, 1.236, 1.247, 1.259, 1.272, 1.281, 1.291, 1.297, 1.299, 1.307, 1.308, 1.306, 1.302, 1.294, 1.284, 1.272, 1.257, 1.239, 1.215, 1.188, 1.163, 1.136, 1.099, 1.069,
+                            1.101, 1.114, 1.126, 1.134, 1.151, 1.163, 1.181, 1.189, 1.202, 1.216, 1.229, 1.239, 1.252, 1.262, 1.269, 1.283, 1.288, 1.293, 1.294, 1.292, 1.289, 1.284, 1.272, 1.261, 1.244, 1.228, 1.204, 1.178, 1.154, 1.131, 1.089, 1.062,
+                            1.087, 1.098, 1.112, 1.124, 1.134, 1.148, 1.161, 1.175, 1.185, 1.201, 1.212, 1.224, 1.236, 1.248, 1.259, 1.268, 1.274, 1.275, 1.275, 1.276, 1.276, 1.272, 1.263, 1.247, 1.232, 1.212, 1.192, 1.166, 1.143, 1.115, 1.078, 1.051
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.333, 1.336, 1.336, 1.343, 1.347, 1.356, 1.361, 1.364, 1.366, 1.371, 1.371, 1.377, 1.382, 1.385, 1.385, 1.385, 1.381, 1.381, 1.375, 1.369, 1.363, 1.348, 1.326, 1.298, 1.269, 1.241, 1.207, 1.169, 1.134, 1.096, 1.044, 1.038,
+                            1.345, 1.351, 1.361, 1.365, 1.369, 1.376, 1.384, 1.389, 1.389, 1.395, 1.398, 1.403, 1.406, 1.409, 1.411, 1.409, 1.409, 1.408, 1.401, 1.389, 1.379, 1.359, 1.339, 1.319, 1.294, 1.264, 1.235, 1.199, 1.163, 1.127, 1.074, 1.044,
+                            1.359, 1.362, 1.375, 1.377, 1.381, 1.388, 1.394, 1.397, 1.401, 1.403, 1.407, 1.413, 1.417, 1.419, 1.422, 1.425, 1.425, 1.419, 1.413, 1.403, 1.391, 1.379, 1.359, 1.339, 1.315, 1.287, 1.254, 1.219, 1.184, 1.151, 1.098, 1.071,
+                            1.366, 1.376, 1.382, 1.386, 1.391, 1.397, 1.401, 1.404, 1.408, 1.411, 1.419, 1.421, 1.426, 1.429, 1.433, 1.433, 1.431, 1.429, 1.423, 1.415, 1.403, 1.391, 1.373, 1.351, 1.329, 1.301, 1.269, 1.231, 1.198, 1.164, 1.118, 1.089,
+                            1.378, 1.383, 1.393, 1.396, 1.399, 1.403, 1.411, 1.414, 1.419, 1.423, 1.426, 1.432, 1.439, 1.444, 1.445, 1.444, 1.442, 1.439, 1.432, 1.424, 1.416, 1.399, 1.385, 1.361, 1.343, 1.314, 1.283, 1.249, 1.215, 1.179, 1.131, 1.098,
+                            1.385, 1.394, 1.399, 1.401, 1.406, 1.412, 1.418, 1.423, 1.427, 1.431, 1.435, 1.442, 1.446, 1.451, 1.452, 1.451, 1.448, 1.445, 1.443, 1.434, 1.424, 1.411, 1.393, 1.377, 1.352, 1.329, 1.296, 1.264, 1.228, 1.195, 1.145, 1.114,
+                            1.391, 1.401, 1.404, 1.408, 1.413, 1.419, 1.425, 1.428, 1.432, 1.437, 1.442, 1.451, 1.453, 1.456, 1.459, 1.461, 1.459, 1.453, 1.449, 1.443, 1.434, 1.419, 1.404, 1.387, 1.362, 1.338, 1.306, 1.272, 1.238, 1.207, 1.153, 1.126,
+                            1.399, 1.405, 1.412, 1.415, 1.419, 1.425, 1.429, 1.436, 1.441, 1.444, 1.451, 1.454, 1.457, 1.463, 1.466, 1.466, 1.465, 1.461, 1.454, 1.449, 1.441, 1.427, 1.414, 1.393, 1.376, 1.347, 1.321, 1.286, 1.251, 1.216, 1.169, 1.134,
+                            1.399, 1.412, 1.416, 1.419, 1.424, 1.429, 1.436, 1.441, 1.445, 1.449, 1.455, 1.461, 1.463, 1.468, 1.472, 1.471, 1.471, 1.468, 1.459, 1.454, 1.445, 1.435, 1.419, 1.402, 1.382, 1.354, 1.329, 1.296, 1.259, 1.225, 1.175, 1.143,
+                            1.403, 1.416, 1.419, 1.423, 1.427, 1.434, 1.439, 1.443, 1.449, 1.452, 1.459, 1.463, 1.468, 1.472, 1.473, 1.472, 1.471, 1.469, 1.466, 1.455, 1.449, 1.438, 1.425, 1.408, 1.389, 1.362, 1.337, 1.304, 1.271, 1.233, 1.184, 1.148,
+                            1.404, 1.418, 1.421, 1.425, 1.429, 1.436, 1.441, 1.444, 1.449, 1.453, 1.461, 1.465, 1.471, 1.472, 1.474, 1.474, 1.472, 1.471, 1.467, 1.459, 1.451, 1.441, 1.428, 1.411, 1.393, 1.368, 1.341, 1.309, 1.277, 1.239, 1.189, 1.152,
+                            1.404, 1.417, 1.421, 1.425, 1.431, 1.437, 1.441, 1.445, 1.449, 1.453, 1.461, 1.465, 1.469, 1.471, 1.472, 1.475, 1.474, 1.471, 1.466, 1.461, 1.452, 1.442, 1.431, 1.411, 1.395, 1.371, 1.345, 1.313, 1.279, 1.242, 1.194, 1.156,
+                            1.405, 1.417, 1.421, 1.428, 1.433, 1.437, 1.441, 1.445, 1.449, 1.453, 1.459, 1.462, 1.467, 1.469, 1.472, 1.475, 1.475, 1.471, 1.467, 1.461, 1.452, 1.443, 1.431, 1.414, 1.396, 1.372, 1.346, 1.315, 1.284, 1.249, 1.199, 1.161,
+                            1.409, 1.418, 1.422, 1.426, 1.432, 1.436, 1.439, 1.444, 1.447, 1.452, 1.457, 1.461, 1.464, 1.469, 1.471, 1.474, 1.474, 1.471, 1.467, 1.462, 1.452, 1.445, 1.431, 1.415, 1.395, 1.374, 1.349, 1.314, 1.285, 1.253, 1.201, 1.165,
+                            1.409, 1.418, 1.421, 1.425, 1.429, 1.433, 1.437, 1.441, 1.446, 1.451, 1.454, 1.459, 1.463, 1.467, 1.469, 1.473, 1.473, 1.469, 1.466, 1.461, 1.455, 1.445, 1.431, 1.416, 1.396, 1.373, 1.349, 1.316, 1.286, 1.254, 1.205, 1.165,
+                            1.409, 1.412, 1.421, 1.422, 1.426, 1.429, 1.436, 1.439, 1.443, 1.449, 1.452, 1.457, 1.462, 1.465, 1.469, 1.471, 1.471, 1.469, 1.467, 1.461, 1.455, 1.445, 1.431, 1.416, 1.396, 1.372, 1.349, 1.317, 1.286, 1.254, 1.205, 1.165,
+                            1.403, 1.409, 1.413, 1.419, 1.423, 1.429, 1.432, 1.437, 1.441, 1.445, 1.451, 1.455, 1.462, 1.464, 1.468, 1.471, 1.471, 1.469, 1.465, 1.461, 1.455, 1.443, 1.429, 1.414, 1.397, 1.372, 1.349, 1.316, 1.286, 1.254, 1.205, 1.163,
+                            1.396, 1.402, 1.409, 1.414, 1.419, 1.423, 1.429, 1.434, 1.439, 1.444, 1.448, 1.453, 1.456, 1.462, 1.463, 1.468, 1.469, 1.468, 1.465, 1.459, 1.452, 1.442, 1.429, 1.412, 1.396, 1.373, 1.349, 1.315, 1.287, 1.253, 1.206, 1.163,
+                            1.389, 1.393, 1.402, 1.406, 1.414, 1.418, 1.424, 1.431, 1.435, 1.441, 1.447, 1.449, 1.455, 1.457, 1.461, 1.462, 1.466, 1.465, 1.461, 1.458, 1.451, 1.442, 1.428, 1.412, 1.395, 1.372, 1.347, 1.315, 1.287, 1.252, 1.205, 1.164,
+                            1.373, 1.385, 1.388, 1.394, 1.403, 1.408, 1.418, 1.424, 1.431, 1.437, 1.441, 1.447, 1.449, 1.454, 1.456, 1.459, 1.461, 1.461, 1.459, 1.457, 1.449, 1.439, 1.427, 1.412, 1.394, 1.371, 1.346, 1.315, 1.284, 1.249, 1.202, 1.162,
+                            1.359, 1.371, 1.377, 1.383, 1.392, 1.403, 1.408, 1.416, 1.423, 1.431, 1.437, 1.439, 1.444, 1.447, 1.451, 1.455, 1.458, 1.459, 1.457, 1.453, 1.447, 1.435, 1.425, 1.409, 1.391, 1.367, 1.341, 1.312, 1.281, 1.246, 1.199, 1.161,
+                            1.345, 1.356, 1.363, 1.371, 1.379, 1.389, 1.401, 1.408, 1.415, 1.421, 1.428, 1.431, 1.436, 1.441, 1.446, 1.449, 1.453, 1.453, 1.453, 1.449, 1.443, 1.433, 1.421, 1.406, 1.389, 1.364, 1.337, 1.306, 1.274, 1.244, 1.197, 1.158,
+                            1.321, 1.337, 1.344, 1.355, 1.362, 1.376, 1.387, 1.396, 1.403, 1.409, 1.416, 1.423, 1.428, 1.433, 1.438, 1.444, 1.447, 1.449, 1.449, 1.443, 1.438, 1.428, 1.417, 1.397, 1.381, 1.359, 1.331, 1.301, 1.271, 1.236, 1.188, 1.157,
+                            1.298, 1.315, 1.325, 1.332, 1.344, 1.357, 1.368, 1.383, 1.391, 1.398, 1.404, 1.413, 1.422, 1.427, 1.434, 1.438, 1.442, 1.443, 1.443, 1.439, 1.431, 1.419, 1.409, 1.394, 1.372, 1.353, 1.325, 1.296, 1.261, 1.231, 1.183, 1.148,
+                            1.278, 1.294, 1.304, 1.316, 1.328, 1.341, 1.353, 1.362, 1.375, 1.386, 1.392, 1.402, 1.411, 1.421, 1.426, 1.431, 1.436, 1.436, 1.436, 1.431, 1.421, 1.414, 1.401, 1.387, 1.365, 1.344, 1.319, 1.289, 1.258, 1.226, 1.178, 1.142,
+                            1.259, 1.273, 1.287, 1.296, 1.311, 1.322, 1.335, 1.349, 1.358, 1.371, 1.381, 1.392, 1.399, 1.411, 1.417, 1.423, 1.425, 1.425, 1.424, 1.419, 1.414, 1.404, 1.392, 1.373, 1.359, 1.336, 1.311, 1.282, 1.249, 1.216, 1.175, 1.139,
+                            1.234, 1.253, 1.266, 1.276, 1.291, 1.301, 1.315, 1.328, 1.344, 1.355, 1.364, 1.377, 1.386, 1.397, 1.406, 1.412, 1.416, 1.419, 1.417, 1.409, 1.404, 1.394, 1.383, 1.368, 1.351, 1.329, 1.301, 1.271, 1.242, 1.208, 1.162, 1.131,
+                            1.213, 1.229, 1.245, 1.254, 1.267, 1.282, 1.297, 1.311, 1.325, 1.337, 1.351, 1.362, 1.374, 1.381, 1.393, 1.399, 1.402, 1.404, 1.404, 1.402, 1.394, 1.384, 1.373, 1.361, 1.342, 1.319, 1.293, 1.266, 1.234, 1.204, 1.157, 1.125,
+                            1.188, 1.208, 1.221, 1.231, 1.245, 1.263, 1.276, 1.291, 1.302, 1.317, 1.333, 1.341, 1.358, 1.366, 1.373, 1.382, 1.386, 1.388, 1.391, 1.388, 1.382, 1.375, 1.365, 1.351, 1.333, 1.311, 1.284, 1.254, 1.225, 1.198, 1.152, 1.121,
+                            1.165, 1.182, 1.195, 1.209, 1.221, 1.239, 1.254, 1.268, 1.278, 1.296, 1.309, 1.322, 1.337, 1.348, 1.355, 1.365, 1.371, 1.374, 1.375, 1.373, 1.372, 1.365, 1.352, 1.341, 1.321, 1.301, 1.273, 1.242, 1.212, 1.183, 1.141, 1.111,
+                            1.141, 1.159, 1.173, 1.183, 1.198, 1.215, 1.229, 1.245, 1.258, 1.271, 1.286, 1.299, 1.317, 1.326, 1.334, 1.347, 1.355, 1.359, 1.362, 1.362, 1.358, 1.351, 1.341, 1.325, 1.307, 1.289, 1.259, 1.233, 1.203, 1.175, 1.119, 1.062,
+                            1.126, 1.139, 1.155, 1.171, 1.182, 1.197, 1.211, 1.225, 1.241, 1.255, 1.267, 1.281, 1.295, 1.309, 1.321, 1.331, 1.337, 1.341, 1.342, 1.343, 1.342, 1.341, 1.329, 1.311, 1.292, 1.271, 1.245, 1.217, 1.189, 1.152, 1.075, 1.049
+                        ]
+                    },
+                    {
+                        "ct": 5000,
+                        "table":
+                        [
+                            1.413, 1.419, 1.423, 1.434, 1.444, 1.447, 1.455, 1.456, 1.459, 1.462, 1.466, 1.469, 1.478, 1.481, 1.482, 1.479, 1.477, 1.474, 1.463, 1.457, 1.445, 1.427, 1.396, 1.368, 1.329, 1.287, 1.247, 1.212, 1.165, 1.123, 1.064, 1.049,
+                            1.434, 1.446, 1.456, 1.464, 1.473, 1.478, 1.491, 1.492, 1.495, 1.502, 1.507, 1.509, 1.512, 1.522, 1.523, 1.519, 1.512, 1.505, 1.499, 1.487, 1.468, 1.451, 1.422, 1.389, 1.354, 1.321, 1.281, 1.242, 1.199, 1.157, 1.105, 1.064,
+                            1.454, 1.459, 1.476, 1.484, 1.489, 1.496, 1.505, 1.515, 1.514, 1.522, 1.529, 1.533, 1.535, 1.542, 1.544, 1.543, 1.539, 1.536, 1.527, 1.513, 1.495, 1.469, 1.451, 1.422, 1.387, 1.352, 1.313, 1.272, 1.227, 1.189, 1.131, 1.097,
+                            1.467, 1.479, 1.488, 1.495, 1.502, 1.512, 1.519, 1.529, 1.534, 1.539, 1.546, 1.551, 1.553, 1.558, 1.562, 1.561, 1.558, 1.554, 1.542, 1.532, 1.514, 1.496, 1.469, 1.446, 1.407, 1.379, 1.335, 1.296, 1.249, 1.211, 1.149, 1.123,
+                            1.485, 1.495, 1.504, 1.509, 1.517, 1.525, 1.539, 1.543, 1.553, 1.558, 1.559, 1.565, 1.568, 1.573, 1.582, 1.582, 1.577, 1.573, 1.563, 1.549, 1.537, 1.514, 1.489, 1.461, 1.434, 1.399, 1.356, 1.316, 1.271, 1.231, 1.168, 1.135,
+                            1.499, 1.504, 1.514, 1.522, 1.531, 1.543, 1.549, 1.561, 1.563, 1.568, 1.579, 1.585, 1.591, 1.595, 1.595, 1.596, 1.595, 1.589, 1.583, 1.569, 1.552, 1.537, 1.511, 1.486, 1.457, 1.418, 1.379, 1.334, 1.291, 1.254, 1.189, 1.149,
+                            1.506, 1.514, 1.527, 1.535, 1.543, 1.553, 1.562, 1.569, 1.577, 1.583, 1.594, 1.601, 1.606, 1.611, 1.612, 1.612, 1.609, 1.604, 1.594, 1.585, 1.569, 1.551, 1.531, 1.502, 1.472, 1.429, 1.396, 1.352, 1.311, 1.264, 1.201, 1.167,
+                            1.513, 1.527, 1.537, 1.546, 1.553, 1.563, 1.576, 1.584, 1.588, 1.595, 1.605, 1.611, 1.617, 1.623, 1.625, 1.623, 1.622, 1.616, 1.607, 1.597, 1.583, 1.563, 1.541, 1.518, 1.489, 1.452, 1.409, 1.372, 1.324, 1.281, 1.221, 1.181,
+                            1.525, 1.537, 1.547, 1.554, 1.561, 1.575, 1.584, 1.591, 1.596, 1.605, 1.613, 1.621, 1.627, 1.633, 1.634, 1.635, 1.631, 1.626, 1.618, 1.608, 1.594, 1.577, 1.555, 1.533, 1.501, 1.467, 1.431, 1.387, 1.341, 1.295, 1.232, 1.189,
+                            1.529, 1.546, 1.552, 1.561, 1.569, 1.581, 1.588, 1.595, 1.604, 1.613, 1.621, 1.626, 1.634, 1.639, 1.639, 1.643, 1.638, 1.634, 1.626, 1.616, 1.605, 1.586, 1.567, 1.548, 1.512, 1.478, 1.445, 1.398, 1.357, 1.313, 1.244, 1.209,
+                            1.529, 1.549, 1.558, 1.565, 1.571, 1.583, 1.593, 1.601, 1.608, 1.618, 1.624, 1.631, 1.639, 1.643, 1.644, 1.644, 1.644, 1.641, 1.633, 1.621, 1.613, 1.594, 1.578, 1.551, 1.524, 1.486, 1.449, 1.408, 1.363, 1.321, 1.255, 1.214,
+                            1.529, 1.552, 1.561, 1.567, 1.577, 1.587, 1.595, 1.604, 1.611, 1.619, 1.626, 1.633, 1.642, 1.648, 1.649, 1.648, 1.645, 1.643, 1.637, 1.627, 1.617, 1.601, 1.584, 1.555, 1.529, 1.493, 1.462, 1.418, 1.373, 1.328, 1.266, 1.225,
+                            1.534, 1.551, 1.562, 1.568, 1.581, 1.591, 1.596, 1.605, 1.612, 1.619, 1.628, 1.633, 1.642, 1.648, 1.651, 1.652, 1.649, 1.643, 1.639, 1.632, 1.619, 1.604, 1.586, 1.561, 1.536, 1.499, 1.466, 1.423, 1.379, 1.335, 1.272, 1.233,
+                            1.535, 1.551, 1.562, 1.569, 1.581, 1.591, 1.598, 1.604, 1.612, 1.619, 1.629, 1.634, 1.639, 1.647, 1.649, 1.652, 1.649, 1.646, 1.643, 1.634, 1.622, 1.606, 1.588, 1.564, 1.538, 1.502, 1.469, 1.425, 1.382, 1.341, 1.275, 1.236,
+                            1.535, 1.549, 1.561, 1.569, 1.578, 1.587, 1.598, 1.604, 1.609, 1.619, 1.629, 1.633, 1.638, 1.644, 1.649, 1.651, 1.649, 1.647, 1.642, 1.634, 1.622, 1.607, 1.588, 1.564, 1.538, 1.505, 1.471, 1.431, 1.385, 1.346, 1.281, 1.236,
+                            1.534, 1.548, 1.559, 1.565, 1.574, 1.585, 1.593, 1.599, 1.607, 1.618, 1.626, 1.631, 1.637, 1.644, 1.648, 1.651, 1.649, 1.647, 1.642, 1.634, 1.625, 1.608, 1.589, 1.566, 1.539, 1.506, 1.472, 1.432, 1.388, 1.347, 1.284, 1.241,
+                            1.532, 1.543, 1.554, 1.562, 1.569, 1.581, 1.592, 1.598, 1.603, 1.614, 1.623, 1.628, 1.634, 1.641, 1.645, 1.647, 1.648, 1.645, 1.641, 1.633, 1.625, 1.606, 1.589, 1.565, 1.538, 1.505, 1.472, 1.431, 1.392, 1.347, 1.287, 1.239,
+                            1.519, 1.531, 1.544, 1.557, 1.565, 1.578, 1.586, 1.594, 1.601, 1.609, 1.619, 1.626, 1.632, 1.641, 1.644, 1.646, 1.647, 1.644, 1.639, 1.631, 1.622, 1.605, 1.589, 1.566, 1.538, 1.505, 1.472, 1.431, 1.392, 1.347, 1.283, 1.227,
+                            1.509, 1.517, 1.531, 1.545, 1.559, 1.567, 1.579, 1.586, 1.596, 1.606, 1.612, 1.621, 1.629, 1.634, 1.637, 1.643, 1.643, 1.641, 1.634, 1.629, 1.621, 1.604, 1.586, 1.566, 1.538, 1.506, 1.471, 1.431, 1.391, 1.336, 1.263, 1.171,
+                            1.492, 1.506, 1.517, 1.528, 1.541, 1.557, 1.568, 1.578, 1.589, 1.598, 1.606, 1.612, 1.621, 1.629, 1.632, 1.634, 1.633, 1.633, 1.631, 1.625, 1.617, 1.601, 1.583, 1.564, 1.535, 1.504, 1.468, 1.431, 1.384, 1.306, 1.205, 1.159,
+                            1.471, 1.486, 1.503, 1.511, 1.525, 1.541, 1.554, 1.565, 1.577, 1.589, 1.597, 1.602, 1.611, 1.617, 1.621, 1.625, 1.625, 1.629, 1.626, 1.622, 1.612, 1.595, 1.578, 1.556, 1.532, 1.499, 1.466, 1.423, 1.379, 1.306, 1.201, 1.145,
+                            1.446, 1.464, 1.481, 1.493, 1.508, 1.523, 1.539, 1.551, 1.561, 1.575, 1.586, 1.592, 1.598, 1.606, 1.612, 1.617, 1.618, 1.622, 1.619, 1.613, 1.604, 1.588, 1.575, 1.551, 1.528, 1.493, 1.457, 1.416, 1.375, 1.326, 1.212, 1.159,
+                            1.419, 1.443, 1.453, 1.468, 1.486, 1.501, 1.519, 1.534, 1.544, 1.558, 1.568, 1.577, 1.585, 1.594, 1.602, 1.607, 1.612, 1.611, 1.609, 1.605, 1.592, 1.581, 1.565, 1.543, 1.516, 1.481, 1.444, 1.405, 1.366, 1.324, 1.254, 1.172,
+                            1.389, 1.415, 1.426, 1.441, 1.463, 1.479, 1.494, 1.515, 1.525, 1.538, 1.555, 1.562, 1.571, 1.579, 1.589, 1.595, 1.601, 1.601, 1.598, 1.592, 1.581, 1.571, 1.553, 1.526, 1.501, 1.472, 1.437, 1.397, 1.355, 1.316, 1.252, 1.212,
+                            1.364, 1.386, 1.405, 1.419, 1.436, 1.456, 1.474, 1.491, 1.504, 1.519, 1.533, 1.541, 1.557, 1.565, 1.573, 1.584, 1.587, 1.588, 1.587, 1.578, 1.571, 1.555, 1.534, 1.514, 1.491, 1.457, 1.425, 1.386, 1.347, 1.304, 1.248, 1.209,
+                            1.335, 1.358, 1.376, 1.395, 1.412, 1.431, 1.449, 1.466, 1.482, 1.495, 1.509, 1.527, 1.538, 1.551, 1.561, 1.566, 1.573, 1.573, 1.569, 1.561, 1.554, 1.541, 1.525, 1.501, 1.476, 1.446, 1.413, 1.372, 1.328, 1.295, 1.235, 1.206,
+                            1.309, 1.333, 1.353, 1.367, 1.386, 1.401, 1.424, 1.441, 1.459, 1.474, 1.489, 1.505, 1.517, 1.533, 1.544, 1.548, 1.553, 1.555, 1.555, 1.546, 1.541, 1.525, 1.507, 1.485, 1.464, 1.435, 1.396, 1.351, 1.317, 1.279, 1.224, 1.188,
+                            1.279, 1.304, 1.326, 1.337, 1.353, 1.379, 1.395, 1.415, 1.432, 1.447, 1.469, 1.482, 1.498, 1.514, 1.524, 1.532, 1.537, 1.537, 1.536, 1.532, 1.522, 1.507, 1.488, 1.472, 1.452, 1.413, 1.378, 1.342, 1.308, 1.271, 1.213, 1.171,
+                            1.253, 1.275, 1.294, 1.304, 1.326, 1.349, 1.368, 1.386, 1.403, 1.421, 1.439, 1.457, 1.473, 1.489, 1.497, 1.504, 1.513, 1.515, 1.515, 1.511, 1.504, 1.489, 1.474, 1.455, 1.431, 1.402, 1.368, 1.329, 1.298, 1.255, 1.201, 1.167,
+                            1.221, 1.238, 1.263, 1.277, 1.296, 1.316, 1.334, 1.353, 1.372, 1.392, 1.411, 1.422, 1.448, 1.458, 1.466, 1.481, 1.489, 1.492, 1.493, 1.489, 1.486, 1.474, 1.455, 1.437, 1.415, 1.381, 1.348, 1.314, 1.275, 1.238, 1.184, 1.155,
+                            1.193, 1.213, 1.227, 1.243, 1.264, 1.287, 1.304, 1.322, 1.339, 1.355, 1.377, 1.395, 1.409, 1.425, 1.438, 1.455, 1.461, 1.466, 1.469, 1.468, 1.464, 1.451, 1.434, 1.415, 1.386, 1.362, 1.331, 1.296, 1.261, 1.225, 1.172, 1.136,
+                            1.172, 1.189, 1.209, 1.225, 1.241, 1.261, 1.279, 1.297, 1.317, 1.334, 1.351, 1.368, 1.387, 1.399, 1.418, 1.426, 1.434, 1.437, 1.437, 1.438, 1.437, 1.433, 1.418, 1.397, 1.365, 1.337, 1.306, 1.269, 1.238, 1.204, 1.156, 1.127
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.096, 1.097, 1.099, 1.101, 1.102, 1.103, 1.106, 1.106, 1.107, 1.106, 1.106, 1.108, 1.109, 1.111, 1.114, 1.115, 1.116, 1.117, 1.114, 1.112, 1.109, 1.106, 1.101, 1.092, 1.083, 1.076, 1.066, 1.054, 1.043, 1.027, 1.008, 1.001,
+                            1.098, 1.099, 1.104, 1.104, 1.103, 1.105, 1.107, 1.108, 1.108, 1.107, 1.108, 1.109, 1.111, 1.113, 1.115, 1.116, 1.117, 1.118, 1.116, 1.115, 1.111, 1.108, 1.102, 1.095, 1.091, 1.078, 1.069, 1.062, 1.049, 1.036, 1.021, 1.006,
+                            1.101, 1.105, 1.105, 1.105, 1.105, 1.107, 1.109, 1.109, 1.109, 1.109, 1.111, 1.111, 1.114, 1.115, 1.117, 1.117, 1.118, 1.119, 1.117, 1.115, 1.112, 1.109, 1.103, 1.098, 1.093, 1.084, 1.075, 1.065, 1.053, 1.041, 1.025, 1.011,
+                            1.101, 1.106, 1.107, 1.106, 1.107, 1.108, 1.111, 1.111, 1.111, 1.111, 1.112, 1.114, 1.116, 1.117, 1.119, 1.119, 1.121, 1.119, 1.119, 1.116, 1.113, 1.111, 1.105, 1.101, 1.094, 1.087, 1.077, 1.069, 1.057, 1.046, 1.031, 1.017,
+                            1.105, 1.108, 1.108, 1.108, 1.108, 1.109, 1.112, 1.111, 1.112, 1.112, 1.112, 1.113, 1.116, 1.117, 1.119, 1.121, 1.121, 1.121, 1.119, 1.116, 1.114, 1.111, 1.106, 1.102, 1.097, 1.089, 1.081, 1.072, 1.059, 1.048, 1.034, 1.021,
+                            1.106, 1.109, 1.111, 1.109, 1.109, 1.111, 1.113, 1.112, 1.112, 1.112, 1.113, 1.114, 1.117, 1.118, 1.119, 1.121, 1.121, 1.119, 1.119, 1.116, 1.115, 1.111, 1.107, 1.104, 1.098, 1.091, 1.083, 1.074, 1.064, 1.052, 1.037, 1.022,
+                            1.107, 1.111, 1.111, 1.111, 1.111, 1.112, 1.113, 1.112, 1.112, 1.113, 1.113, 1.115, 1.116, 1.118, 1.119, 1.119, 1.119, 1.119, 1.117, 1.116, 1.114, 1.111, 1.108, 1.105, 1.099, 1.093, 1.085, 1.077, 1.066, 1.054, 1.041, 1.027,
+                            1.106, 1.111, 1.111, 1.112, 1.112, 1.113, 1.113, 1.112, 1.112, 1.112, 1.113, 1.114, 1.116, 1.116, 1.117, 1.118, 1.118, 1.117, 1.116, 1.115, 1.113, 1.111, 1.108, 1.104, 1.099, 1.093, 1.086, 1.077, 1.068, 1.057, 1.042, 1.029,
+                            1.108, 1.112, 1.112, 1.112, 1.112, 1.113, 1.113, 1.112, 1.112, 1.112, 1.111, 1.113, 1.115, 1.116, 1.116, 1.116, 1.116, 1.115, 1.114, 1.113, 1.112, 1.111, 1.106, 1.103, 1.099, 1.092, 1.085, 1.077, 1.069, 1.058, 1.042, 1.029,
+                            1.109, 1.111, 1.112, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.113, 1.114, 1.114, 1.114, 1.114, 1.113, 1.112, 1.111, 1.109, 1.107, 1.105, 1.102, 1.098, 1.091, 1.085, 1.077, 1.068, 1.059, 1.045, 1.031,
+                            1.109, 1.111, 1.111, 1.111, 1.109, 1.111, 1.109, 1.109, 1.108, 1.108, 1.109, 1.109, 1.111, 1.111, 1.111, 1.111, 1.111, 1.111, 1.108, 1.108, 1.107, 1.105, 1.103, 1.099, 1.096, 1.089, 1.083, 1.077, 1.068, 1.058, 1.045, 1.029,
+                            1.108, 1.109, 1.109, 1.109, 1.109, 1.109, 1.107, 1.106, 1.105, 1.105, 1.106, 1.107, 1.107, 1.107, 1.108, 1.108, 1.107, 1.107, 1.106, 1.105, 1.104, 1.102, 1.101, 1.097, 1.092, 1.088, 1.082, 1.074, 1.067, 1.057, 1.046, 1.031,
+                            1.106, 1.108, 1.109, 1.107, 1.107, 1.106, 1.105, 1.104, 1.104, 1.103, 1.102, 1.102, 1.104, 1.104, 1.104, 1.105, 1.105, 1.105, 1.104, 1.103, 1.101, 1.099, 1.098, 1.095, 1.091, 1.085, 1.081, 1.072, 1.065, 1.057, 1.044, 1.031,
+                            1.104, 1.106, 1.107, 1.106, 1.105, 1.104, 1.103, 1.102, 1.101, 1.101, 1.101, 1.101, 1.101, 1.102, 1.103, 1.103, 1.104, 1.103, 1.102, 1.101, 1.099, 1.098, 1.095, 1.092, 1.089, 1.084, 1.079, 1.071, 1.063, 1.055, 1.044, 1.031,
+                            1.105, 1.106, 1.106, 1.105, 1.104, 1.102, 1.101, 1.099, 1.099, 1.099, 1.099, 1.099, 1.099, 1.099, 1.101, 1.101, 1.102, 1.102, 1.101, 1.099, 1.097, 1.096, 1.093, 1.091, 1.087, 1.082, 1.076, 1.069, 1.062, 1.054, 1.043, 1.028,
+                            1.105, 1.106, 1.106, 1.104, 1.103, 1.101, 1.099, 1.099, 1.098, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.101, 1.101, 1.101, 1.099, 1.098, 1.096, 1.095, 1.091, 1.089, 1.086, 1.081, 1.075, 1.071, 1.061, 1.054, 1.043, 1.028,
+                            1.105, 1.105, 1.105, 1.104, 1.102, 1.101, 1.099, 1.098, 1.097, 1.096, 1.096, 1.097, 1.097, 1.098, 1.098, 1.099, 1.099, 1.099, 1.098, 1.097, 1.095, 1.093, 1.091, 1.088, 1.085, 1.079, 1.076, 1.069, 1.061, 1.053, 1.043, 1.027,
+                            1.105, 1.105, 1.104, 1.102, 1.101, 1.099, 1.099, 1.097, 1.097, 1.096, 1.096, 1.097, 1.097, 1.097, 1.097, 1.097, 1.098, 1.098, 1.097, 1.096, 1.094, 1.092, 1.091, 1.088, 1.085, 1.079, 1.076, 1.068, 1.062, 1.054, 1.043, 1.027,
+                            1.104, 1.103, 1.103, 1.099, 1.098, 1.098, 1.098, 1.097, 1.097, 1.097, 1.097, 1.097, 1.097, 1.097, 1.097, 1.096, 1.097, 1.097, 1.097, 1.096, 1.094, 1.093, 1.091, 1.089, 1.085, 1.081, 1.076, 1.068, 1.063, 1.054, 1.043, 1.027,
+                            1.099, 1.099, 1.098, 1.098, 1.097, 1.097, 1.097, 1.097, 1.097, 1.096, 1.096, 1.096, 1.095, 1.095, 1.095, 1.095, 1.096, 1.096, 1.097, 1.097, 1.096, 1.094, 1.091, 1.089, 1.085, 1.081, 1.076, 1.068, 1.062, 1.055, 1.044, 1.028,
+                            1.097, 1.096, 1.096, 1.095, 1.095, 1.095, 1.095, 1.097, 1.097, 1.096, 1.095, 1.095, 1.094, 1.094, 1.094, 1.095, 1.096, 1.096, 1.097, 1.098, 1.097, 1.095, 1.092, 1.088, 1.086, 1.083, 1.076, 1.069, 1.062, 1.056, 1.045, 1.031,
+                            1.091, 1.092, 1.093, 1.092, 1.092, 1.093, 1.095, 1.095, 1.095, 1.093, 1.092, 1.092, 1.092, 1.093, 1.094, 1.095, 1.096, 1.097, 1.098, 1.098, 1.097, 1.095, 1.093, 1.088, 1.086, 1.082, 1.076, 1.069, 1.062, 1.056, 1.046, 1.031,
+                            1.085, 1.088, 1.088, 1.089, 1.089, 1.091, 1.092, 1.092, 1.092, 1.092, 1.091, 1.091, 1.092, 1.093, 1.094, 1.096, 1.097, 1.099, 1.098, 1.098, 1.097, 1.095, 1.093, 1.089, 1.085, 1.081, 1.076, 1.069, 1.062, 1.056, 1.045, 1.031,
+                            1.081, 1.082, 1.084, 1.084, 1.085, 1.087, 1.089, 1.091, 1.091, 1.091, 1.091, 1.092, 1.092, 1.094, 1.096, 1.096, 1.099, 1.099, 1.099, 1.098, 1.097, 1.096, 1.093, 1.089, 1.086, 1.082, 1.076, 1.069, 1.062, 1.056, 1.045, 1.031,
+                            1.073, 1.078, 1.081, 1.082, 1.083, 1.084, 1.088, 1.089, 1.089, 1.089, 1.091, 1.091, 1.093, 1.095, 1.096, 1.098, 1.099, 1.101, 1.099, 1.099, 1.096, 1.095, 1.093, 1.089, 1.086, 1.081, 1.077, 1.069, 1.062, 1.055, 1.043, 1.032,
+                            1.068, 1.072, 1.076, 1.079, 1.081, 1.083, 1.084, 1.087, 1.088, 1.088, 1.089, 1.092, 1.093, 1.096, 1.097, 1.099, 1.099, 1.099, 1.099, 1.097, 1.096, 1.095, 1.092, 1.089, 1.086, 1.081, 1.077, 1.071, 1.062, 1.055, 1.045, 1.034,
+                            1.064, 1.066, 1.072, 1.073, 1.077, 1.079, 1.082, 1.084, 1.086, 1.088, 1.089, 1.091, 1.093, 1.095, 1.097, 1.099, 1.099, 1.099, 1.098, 1.097, 1.096, 1.095, 1.092, 1.089, 1.086, 1.081, 1.077, 1.069, 1.064, 1.055, 1.043, 1.035,
+                            1.057, 1.062, 1.065, 1.068, 1.071, 1.075, 1.077, 1.081, 1.084, 1.086, 1.088, 1.089, 1.092, 1.094, 1.096, 1.098, 1.098, 1.098, 1.097, 1.096, 1.095, 1.094, 1.092, 1.089, 1.086, 1.083, 1.077, 1.069, 1.064, 1.055, 1.043, 1.033,
+                            1.051, 1.056, 1.059, 1.062, 1.066, 1.068, 1.074, 1.077, 1.079, 1.083, 1.086, 1.088, 1.089, 1.092, 1.094, 1.096, 1.096, 1.096, 1.096, 1.095, 1.094, 1.093, 1.092, 1.089, 1.086, 1.083, 1.077, 1.068, 1.063, 1.055, 1.043, 1.033,
+                            1.043, 1.048, 1.052, 1.056, 1.059, 1.065, 1.068, 1.071, 1.074, 1.078, 1.081, 1.083, 1.088, 1.089, 1.091, 1.092, 1.094, 1.095, 1.094, 1.094, 1.094, 1.094, 1.092, 1.089, 1.086, 1.083, 1.077, 1.069, 1.062, 1.055, 1.044, 1.031,
+                            1.036, 1.041, 1.045, 1.049, 1.052, 1.059, 1.062, 1.067, 1.069, 1.072, 1.074, 1.077, 1.082, 1.083, 1.086, 1.089, 1.091, 1.092, 1.093, 1.092, 1.092, 1.091, 1.091, 1.088, 1.085, 1.081, 1.076, 1.069, 1.061, 1.054, 1.043, 1.031,
+                            1.029, 1.036, 1.041, 1.045, 1.049, 1.052, 1.056, 1.058, 1.064, 1.064, 1.067, 1.071, 1.075, 1.079, 1.083, 1.085, 1.089, 1.089, 1.089, 1.091, 1.091, 1.091, 1.089, 1.087, 1.083, 1.079, 1.074, 1.066, 1.062, 1.052, 1.041, 1.029
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    3.174, 3.091, 2.978, 2.891, 2.829, 2.779, 2.739, 2.708, 2.683, 2.659, 2.641, 2.623, 2.616, 2.622, 2.629, 2.644, 2.669, 2.691, 2.731, 2.784, 2.843, 2.894, 2.947, 3.004, 3.065, 3.133, 3.214, 3.303, 3.416, 3.541, 3.674, 3.765,
+                    3.093, 2.968, 2.861, 2.778, 2.702, 2.651, 2.599, 2.563, 2.533, 2.509, 2.487, 2.472, 2.466, 2.462, 2.466, 2.481, 2.501, 2.531, 2.568, 2.612, 2.663, 2.712, 2.764, 2.821, 2.881, 2.954, 3.041, 3.137, 3.265, 3.396, 3.482, 3.547,
+                    2.897, 2.851, 2.743, 2.608, 2.521, 2.464, 2.417, 2.381, 2.348, 2.323, 2.302, 2.287, 2.275, 2.264, 2.269, 2.279, 2.297, 2.322, 2.351, 2.392, 2.436, 2.479, 2.526, 2.577, 2.631, 2.701, 2.778, 2.871, 2.985, 3.105, 3.191, 3.254,
+                    2.764, 2.689, 2.586, 2.452, 2.361, 2.303, 2.254, 2.218, 2.189, 2.166, 2.141, 2.123, 2.108, 2.099, 2.098, 2.105, 2.121, 2.144, 2.172, 2.203, 2.238, 2.276, 2.317, 2.358, 2.411, 2.471, 2.541, 2.626, 2.733, 2.844, 2.924, 2.979,
+                    2.581, 2.499, 2.405, 2.296, 2.223, 2.171, 2.126, 2.088, 2.056, 2.031, 2.011, 1.993, 1.975, 1.968, 1.964, 1.968, 1.982, 2.003, 2.027, 2.052, 2.079, 2.109, 2.149, 2.184, 2.231, 2.285, 2.346, 2.427, 2.521, 2.622, 2.691, 2.744,
+                    2.437, 2.343, 2.261, 2.184, 2.116, 2.058, 2.017, 1.979, 1.949, 1.924, 1.899, 1.883, 1.868, 1.859, 1.855, 1.857, 1.866, 1.883, 1.901, 1.923, 1.951, 1.978, 2.011, 2.042, 2.081, 2.133, 2.189, 2.261, 2.349, 2.433, 2.491, 2.541,
+                    2.332, 2.251, 2.166, 2.092, 2.024, 1.969, 1.925, 1.889, 1.856, 1.832, 1.809, 1.791, 1.774, 1.768, 1.762, 1.762, 1.771, 1.779, 1.799, 1.815, 1.837, 1.861, 1.892, 1.924, 1.961, 2.006, 2.059, 2.126, 2.201, 2.279, 2.329, 2.367,
+                    2.249, 2.168, 2.083, 2.005, 1.941, 1.891, 1.845, 1.808, 1.775, 1.749, 1.726, 1.711, 1.696, 1.686, 1.681, 1.681, 1.687, 1.697, 1.712, 1.726, 1.743, 1.765, 1.792, 1.824, 1.859, 1.901, 1.951, 2.009, 2.079, 2.149, 2.194, 2.229,
+                    2.173, 2.094, 2.009, 1.936, 1.871, 1.819, 1.771, 1.736, 1.705, 1.679, 1.656, 1.638, 1.623, 1.612, 1.608, 1.609, 1.613, 1.622, 1.634, 1.647, 1.664, 1.685, 1.709, 1.738, 1.772, 1.813, 1.858, 1.912, 1.979, 2.046, 2.091, 2.121,
+                    2.105, 2.033, 1.947, 1.875, 1.811, 1.756, 1.714, 1.677, 1.643, 1.616, 1.596, 1.577, 1.561, 1.551, 1.544, 1.544, 1.548, 1.556, 1.568, 1.582, 1.596, 1.616, 1.639, 1.665, 1.698, 1.739, 1.783, 1.836, 1.896, 1.959, 1.999, 2.032,
+                    2.045, 1.975, 1.892, 1.819, 1.759, 1.706, 1.661, 1.622, 1.592, 1.563, 1.543, 1.523, 1.509, 1.499, 1.491, 1.491, 1.494, 1.501, 1.512, 1.524, 1.539, 1.558, 1.578, 1.605, 1.638, 1.676, 1.721, 1.769, 1.829, 1.887, 1.923, 1.952,
+                    1.988, 1.923, 1.841, 1.773, 1.711, 1.661, 1.617, 1.579, 1.547, 1.521, 1.496, 1.476, 1.462, 1.452, 1.445, 1.445, 1.448, 1.454, 1.464, 1.476, 1.489, 1.507, 1.529, 1.557, 1.589, 1.626, 1.667, 1.719, 1.774, 1.829, 1.863, 1.893,
+                    1.943, 1.881, 1.803, 1.734, 1.673, 1.621, 1.579, 1.543, 1.508, 1.479, 1.457, 1.436, 1.421, 1.412, 1.405, 1.402, 1.405, 1.412, 1.423, 1.434, 1.449, 1.466, 1.489, 1.516, 1.546, 1.582, 1.625, 1.671, 1.726, 1.777, 1.816, 1.838,
+                    1.913, 1.848, 1.769, 1.701, 1.641, 1.591, 1.548, 1.511, 1.478, 1.449, 1.422, 1.401, 1.387, 1.377, 1.369, 1.368, 1.371, 1.379, 1.389, 1.402, 1.415, 1.432, 1.454, 1.481, 1.513, 1.548, 1.587, 1.633, 1.686, 1.736, 1.772, 1.793,
+                    1.891, 1.819, 1.742, 1.674, 1.614, 1.566, 1.523, 1.485, 1.451, 1.422, 1.397, 1.376, 1.359, 1.347, 1.339, 1.339, 1.343, 1.351, 1.361, 1.375, 1.388, 1.406, 1.429, 1.453, 1.484, 1.517, 1.555, 1.599, 1.652, 1.699, 1.733, 1.755,
+                    1.874, 1.801, 1.721, 1.654, 1.602, 1.552, 1.506, 1.465, 1.429, 1.399, 1.374, 1.352, 1.336, 1.323, 1.315, 1.316, 1.321, 1.329, 1.338, 1.352, 1.369, 1.387, 1.409, 1.435, 1.462, 1.494, 1.529, 1.572, 1.622, 1.669, 1.698, 1.718,
+                    1.868, 1.791, 1.712, 1.647, 1.592, 1.542, 1.497, 1.454, 1.416, 1.385, 1.356, 1.335, 1.319, 1.307, 1.301, 1.299, 1.305, 1.314, 1.324, 1.341, 1.357, 1.376, 1.397, 1.422, 1.449, 1.478, 1.511, 1.551, 1.599, 1.644, 1.671, 1.688,
+                    1.867, 1.789, 1.715, 1.648, 1.591, 1.539, 1.494, 1.451, 1.412, 1.378, 1.352, 1.329, 1.311, 1.301, 1.294, 1.294, 1.298, 1.306, 1.321, 1.335, 1.353, 1.369, 1.391, 1.413, 1.439, 1.469, 1.502, 1.539, 1.583, 1.623, 1.648, 1.666,
+                    1.873, 1.799, 1.724, 1.657, 1.599, 1.546, 1.498, 1.454, 1.416, 1.384, 1.356, 1.334, 1.317, 1.306, 1.299, 1.299, 1.303, 1.311, 1.323, 1.339, 1.354, 1.373, 1.393, 1.414, 1.438, 1.466, 1.495, 1.532, 1.578, 1.617, 1.639, 1.656,
+                    1.884, 1.816, 1.743, 1.675, 1.615, 1.559, 1.509, 1.466, 1.429, 1.397, 1.371, 1.351, 1.332, 1.321, 1.315, 1.313, 1.316, 1.325, 1.337, 1.351, 1.365, 1.383, 1.403, 1.424, 1.449, 1.475, 1.501, 1.537, 1.574, 1.617, 1.639, 1.654,
+                    1.906, 1.845, 1.772, 1.699, 1.636, 1.579, 1.531, 1.489, 1.453, 1.419, 1.395, 1.376, 1.364, 1.354, 1.344, 1.339, 1.338, 1.345, 1.356, 1.368, 1.383, 1.402, 1.422, 1.443, 1.469, 1.492, 1.518, 1.548, 1.583, 1.622, 1.648, 1.658,
+                    1.941, 1.882, 1.804, 1.731, 1.667, 1.611, 1.562, 1.519, 1.484, 1.453, 1.427, 1.412, 1.401, 1.389, 1.381, 1.369, 1.367, 1.372, 1.381, 1.392, 1.409, 1.429, 1.449, 1.473, 1.496, 1.521, 1.546, 1.574, 1.609, 1.637, 1.657, 1.673,
+                    1.987, 1.929, 1.845, 1.773, 1.708, 1.651, 1.603, 1.561, 1.524, 1.495, 1.467, 1.449, 1.441, 1.431, 1.417, 1.404, 1.401, 1.406, 1.415, 1.427, 1.445, 1.463, 1.485, 1.509, 1.536, 1.562, 1.587, 1.612, 1.642, 1.672, 1.678, 1.692,
+                    2.041, 1.978, 1.897, 1.824, 1.757, 1.699, 1.649, 1.606, 1.569, 1.539, 1.513, 1.489, 1.473, 1.461, 1.451, 1.445, 1.445, 1.447, 1.459, 1.472, 1.491, 1.509, 1.533, 1.558, 1.584, 1.607, 1.632, 1.661, 1.692, 1.716, 1.721, 1.728,
+                    2.111, 2.041, 1.957, 1.879, 1.813, 1.755, 1.702, 1.657, 1.622, 1.591, 1.566, 1.543, 1.525, 1.511, 1.501, 1.495, 1.492, 1.497, 1.509, 1.524, 1.543, 1.564, 1.589, 1.615, 1.638, 1.663, 1.688, 1.719, 1.746, 1.774, 1.776, 1.785,
+                    2.186, 2.115, 2.023, 1.943, 1.875, 1.816, 1.762, 1.718, 1.681, 1.649, 1.624, 1.601, 1.583, 1.571, 1.559, 1.552, 1.551, 1.557, 1.571, 1.588, 1.607, 1.628, 1.654, 1.678, 1.704, 1.729, 1.756, 1.783, 1.813, 1.841, 1.849, 1.854,
+                    2.271, 2.188, 2.097, 2.017, 1.948, 1.886, 1.829, 1.784, 1.747, 1.718, 1.693, 1.671, 1.651, 1.639, 1.629, 1.624, 1.625, 1.633, 1.647, 1.663, 1.682, 1.703, 1.728, 1.754, 1.777, 1.805, 1.834, 1.861, 1.892, 1.918, 1.926, 1.939,
+                    2.369, 2.278, 2.182, 2.101, 2.028, 1.967, 1.912, 1.863, 1.827, 1.797, 1.773, 1.751, 1.734, 1.722, 1.713, 1.711, 1.712, 1.719, 1.734, 1.749, 1.768, 1.791, 1.815, 1.839, 1.864, 1.892, 1.919, 1.949, 1.981, 2.011, 2.021, 2.035,
+                    2.479, 2.382, 2.284, 2.202, 2.126, 2.062, 2.005, 1.961, 1.921, 1.891, 1.867, 1.847, 1.832, 1.822, 1.815, 1.814, 1.817, 1.822, 1.837, 1.853, 1.871, 1.891, 1.915, 1.939, 1.964, 1.992, 2.019, 2.053, 2.089, 2.122, 2.133, 2.153,
+                    2.619, 2.509, 2.411, 2.319, 2.239, 2.173, 2.114, 2.072, 2.037, 2.006, 1.982, 1.963, 1.949, 1.941, 1.937, 1.934, 1.937, 1.947, 1.961, 1.977, 1.987, 2.009, 2.034, 2.058, 2.087, 2.112, 2.139, 2.172, 2.211, 2.253, 2.269, 2.297,
+                    2.783, 2.662, 2.554, 2.457, 2.374, 2.304, 2.246, 2.203, 2.166, 2.139, 2.118, 2.099, 2.087, 2.081, 2.077, 2.073, 2.081, 2.092, 2.106, 2.118, 2.133, 2.153, 2.174, 2.197, 2.228, 2.253, 2.281, 2.318, 2.362, 2.407, 2.434, 2.478,
+                    2.878, 2.792, 2.675, 2.577, 2.499, 2.438, 2.396, 2.357, 2.331, 2.309, 2.293, 2.278, 2.267, 2.259, 2.256, 2.258, 2.261, 2.267, 2.278, 2.293, 2.304, 2.319, 2.343, 2.369, 2.389, 2.411, 2.437, 2.469, 2.509, 2.552, 2.621, 2.683
+                ],
+                "sigma": 0.00476,
+                "sigma_Cb": 0.01242
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.25,
+                "limit": 1.0,
+                "strength": 1.0
+            }
+        },
+        {
+            "rpi.hdr":
+            {
+                "Off":
+                {
+                    "cadence": [ 0 ]
+                },
+                "MultiExposureUnmerged":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    }
+                },
+                "SingleExposure":
+                {
+                    "cadence": [ 1 ],
+                    "channel_map":
+                    {
+                        "short": 1
+                    },
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "MultiExposure":
+                {
+                    "cadence": [ 1, 2 ],
+                    "channel_map":
+                    {
+                        "short": 1,
+                        "long": 2
+                    },
+                    "stitch_enable": 1,
+                    "spatial_gain": 2.0,
+                    "tonemap_enable": 1
+                },
+                "Night":
+                {
+                    "cadence": [ 3 ],
+                    "channel_map":
+                    {
+                        "night": 3
+                    },
+                    "tonemap_enable": 1,
+                    "tonemap":
+                    [
+                        0, 0,
+                        5000, 20000,
+                        10000, 30000,
+                        20000, 47000,
+                        30000, 55000,
+                        65535, 65535
+                    ]
+                }
+            }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/pisp/pisp.cpp 0.6.0-2/src/ipa/rpi/pisp/pisp.cpp
--- 0.5.0-1/src/ipa/rpi/pisp/pisp.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/pisp/pisp.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,8 +2,9 @@
 /*
  * Copyright (C) 2023, Raspberry Pi Ltd
  *
- * pisp.cpp - Raspberry Pi PiSP IPA
+ * Raspberry Pi PiSP IPA
  */
+
 #include <algorithm>
 #include <cmath>
 #include <mutex>
@@ -31,6 +32,8 @@
 #include "controller/cac_status.h"
 #include "controller/ccm_status.h"
 #include "controller/contrast_status.h"
+#include "controller/decompand_algorithm.h"
+#include "controller/decompand_status.h"
 #include "controller/denoise_algorithm.h"
 #include "controller/denoise_status.h"
 #include "controller/dpc_status.h"
@@ -112,6 +115,25 @@ int generateLut(const ipa::Pwl &pwl, uin
 	return 0;
 }
 
+int generateDecompandLut(const ipa::Pwl &pwl, Span<uint16_t> lut)
+{
+	if (pwl.empty())
+		return -EINVAL;
+
+	constexpr int step = 1024;
+	for (std::size_t i = 0; i < lut.size(); ++i) {
+		int x = i * step;
+
+		int y = pwl.eval(x);
+		if (y < 0)
+			return -1;
+
+		lut[i] = static_cast<uint16_t>(std::min(y, 65535));
+	}
+
+	return 0;
+}
+
 void packLscLut(uint32_t packed[NumLscVertexes][NumLscVertexes],
 		double const rgb[3][NumLscVertexes][NumLscVertexes])
 {
@@ -218,13 +240,14 @@ private:
 
 	void platformPrepareIsp(const PrepareParams &params,
 				RPiController::Metadata &rpiMetadata) override;
+	void platformPrepareAgc(RPiController::Metadata &rpiMetadata) override;
 	RPiController::StatisticsPtr platformProcessStats(Span<uint8_t> mem) override;
 
 	void handleControls(const ControlList &controls) override;
 
-	void applyWBG(const AwbStatus *awbStatus, const AgcPrepareStatus *agcStatus,
+	void applyWBG(const AwbStatus *awbStatus, double digitalGain,
 		      pisp_be_global_config &global);
-	void applyDgOnly(const AgcPrepareStatus *agcPrepareStatus, pisp_be_global_config &global);
+	void applyDgOnly(double digitalGain, pisp_be_global_config &global);
 	void applyCAC(const CacStatus *cacStatus, pisp_be_global_config &global);
 	void applyContrast(const ContrastStatus *contrastStatus,
 			   pisp_be_global_config &global);
@@ -234,6 +257,7 @@ private:
 	void applyLensShading(const AlscStatus *alscStatus,
 			      pisp_be_global_config &global);
 	void applyDPC(const DpcStatus *dpcStatus, pisp_be_global_config &global);
+	void applyDecompand(const DecompandStatus *decompandStatus, pisp_fe_global_config &feGlobal);
 	void applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global);
 	void applyTdn(const TdnStatus *tdnStatus, const DeviceStatus *deviceStatus,
 		      pisp_be_global_config &global);
@@ -312,6 +336,20 @@ int32_t IpaPiSP::platformStart([[maybe_u
 	/* Cause the stitch block to be reset correctly. */
 	lastStitchHdrStatus_ = HdrStatus();
 
+	/* Setup a default decompand curve on startup if needed. */
+	RPiController::DecompandAlgorithm *decompand = dynamic_cast<RPiController::DecompandAlgorithm *>(
+		controller_.getAlgorithm("decompand"));
+	if (decompand) {
+		std::scoped_lock<FrontEnd> l(*fe_);
+		pisp_fe_global_config feGlobal;
+		DecompandStatus decompandStatus;
+
+		fe_->GetGlobal(feGlobal);
+		decompand->initialValues(decompandStatus.decompandCurve);
+		applyDecompand(&decompandStatus, feGlobal);
+		fe_->SetGlobal(feGlobal);
+	}
+
 	return 0;
 }
 
@@ -341,28 +379,28 @@ void IpaPiSP::platformPrepareIsp([[maybe
 				PISP_BE_RGB_ENABLE_SHARPEN + PISP_BE_RGB_ENABLE_SAT_CONTROL);
 
 	NoiseStatus *noiseStatus = rpiMetadata.getLocked<NoiseStatus>("noise.status");
-	AgcPrepareStatus *agcPrepareStatus = rpiMetadata.getLocked<AgcPrepareStatus>("agc.prepare_status");
 
 	{
 		/* All Frontend config goes first, we do not want to hold the FE lock for long! */
 		std::scoped_lock<FrontEnd> lf(*fe_);
+		pisp_fe_global_config feGlobal;
+
+		fe_->GetGlobal(feGlobal);
 
 		if (noiseStatus)
 			applyFocusStats(noiseStatus);
 
+		DecompandStatus *decompandStatus =
+			rpiMetadata.getLocked<DecompandStatus>("decompand.status");
+		if (decompandStatus)
+			applyDecompand(decompandStatus, feGlobal);
+
 		BlackLevelStatus *blackLevelStatus =
 			rpiMetadata.getLocked<BlackLevelStatus>("black_level.status");
 		if (blackLevelStatus)
 			applyBlackLevel(blackLevelStatus, global);
 
-		AwbStatus *awbStatus = rpiMetadata.getLocked<AwbStatus>("awb.status");
-		if (awbStatus && agcPrepareStatus) {
-			/* Applies digital gain as well. */
-			applyWBG(awbStatus, agcPrepareStatus, global);
-		} else if (agcPrepareStatus) {
-			/* Mono sensor fallback for digital gain. */
-			applyDgOnly(agcPrepareStatus, global);
-		}
+		fe_->SetGlobal(feGlobal);
 	}
 
 	CacStatus *cacStatus = rpiMetadata.getLocked<CacStatus>("cac.status");
@@ -443,6 +481,34 @@ void IpaPiSP::platformPrepareIsp([[maybe
 	}
 }
 
+void IpaPiSP::platformPrepareAgc(RPiController::Metadata &rpiMetadata)
+{
+	std::scoped_lock<RPiController::Metadata> l(rpiMetadata);
+
+	AgcStatus *delayedAgcStatus = rpiMetadata.getLocked<AgcStatus>("agc.delayed_status");
+	/* If no delayed status, use the gain from the last mode switch. */
+	double digitalGain = delayedAgcStatus ? delayedAgcStatus->digitalGain : agcStatus_.digitalGain;
+	AwbStatus *awbStatus = rpiMetadata.getLocked<AwbStatus>("awb.status");
+
+	pisp_be_global_config global;
+	be_->GetGlobal(global);
+
+	{
+		/* All Frontend config goes first, we do not want to hold the FE lock for long! */
+		std::scoped_lock<FrontEnd> lf(*fe_);
+
+		if (awbStatus) {
+			/* Applies digital gain as well. */
+			applyWBG(awbStatus, digitalGain, global);
+		} else {
+			/* Mono sensor fallback for digital gain. */
+			applyDgOnly(digitalGain, global);
+		}
+	}
+
+	be_->SetGlobal(global);
+}
+
 RPiController::StatisticsPtr IpaPiSP::platformProcessStats(Span<uint8_t> mem)
 {
 	using namespace RPiController;
@@ -467,7 +533,7 @@ RPiController::StatisticsPtr IpaPiSP::pl
 
 	/* AGC region sums only get collected on floating zones. */
 	statistics->agcRegions.init({ 0, 0 }, PISP_FLOATING_STATS_NUM_ZONES);
-	for (i = 0; i < statistics->agcRegions.numRegions(); i++)
+	for (i = 0; i < PISP_FLOATING_STATS_NUM_ZONES; i++)
 		statistics->agcRegions.setFloating(i,
 						   { { 0, 0, 0, stats->agc.floating[i].Y_sum },
 						     stats->agc.floating[i].counted, 0 });
@@ -515,16 +581,29 @@ void IpaPiSP::handleControls(const Contr
 	}
 }
 
-void IpaPiSP::applyWBG(const AwbStatus *awbStatus, const AgcPrepareStatus *agcPrepareStatus,
+void IpaPiSP::applyWBG(const AwbStatus *awbStatus, double digitalGain,
 		       pisp_be_global_config &global)
 {
 	pisp_wbg_config wbg;
 	pisp_fe_rgby_config rgby = {};
-	double dg = agcPrepareStatus ? agcPrepareStatus->digitalGain : 1.0;
+	double minColourGain = std::min({ awbStatus->gainR, awbStatus->gainG, awbStatus->gainB, 1.0 });
+	/* The 0.1 here doesn't mean much, but just stops arithmetic errors and extreme behaviour. */
+	double extraGain = 1.0 / std::max({ minColourGain, 0.1 });
 
-	wbg.gain_r = clampField(dg * awbStatus->gainR, 14, 10);
-	wbg.gain_g = clampField(dg * awbStatus->gainG, 14, 10);
-	wbg.gain_b = clampField(dg * awbStatus->gainB, 14, 10);
+	/*
+	 * Apply an extra gain of 1 / minColourGain so as not to apply < 1 gains to any
+	 * channels (which would cause saturated pixels to go cyan or magenta).
+	 * Doing this doesn't really apply more gain than necessary, because one of the
+	 * channels is always getting the minimum gain possible. For this reason we also
+	 * don't change the values that we report externally.
+	 */
+	double gainR = awbStatus->gainR * extraGain;
+	double gainG = awbStatus->gainG * extraGain;
+	double gainB = awbStatus->gainB * extraGain;
+
+	wbg.gain_r = clampField(digitalGain * gainR, 14, 10);
+	wbg.gain_g = clampField(digitalGain * gainG, 14, 10);
+	wbg.gain_b = clampField(digitalGain * gainB, 14, 10);
 
 	/*
 	 * The YCbCr conversion block should contain the appropriate YCbCr
@@ -535,9 +614,9 @@ void IpaPiSP::applyWBG(const AwbStatus *
 	be_->GetYcbcr(csc);
 
 	/* The CSC coefficients already have the << 10 scaling applied. */
-	rgby.gain_r = clampField(csc.coeffs[0] * awbStatus->gainR, 14);
-	rgby.gain_g = clampField(csc.coeffs[1] * awbStatus->gainG, 14);
-	rgby.gain_b = clampField(csc.coeffs[2] * awbStatus->gainB, 14);
+	rgby.gain_r = clampField(csc.coeffs[0] * gainR, 14);
+	rgby.gain_g = clampField(csc.coeffs[1] * gainG, 14);
+	rgby.gain_b = clampField(csc.coeffs[2] * gainB, 14);
 
 	LOG(IPARPI, Debug) << "Applying WB R: " << awbStatus->gainR << " B: "
 			   << awbStatus->gainB;
@@ -547,15 +626,15 @@ void IpaPiSP::applyWBG(const AwbStatus *
 	global.bayer_enables |= PISP_BE_BAYER_ENABLE_WBG;
 }
 
-void IpaPiSP::applyDgOnly(const AgcPrepareStatus *agcPrepareStatus, pisp_be_global_config &global)
+void IpaPiSP::applyDgOnly(double digitalGain, pisp_be_global_config &global)
 {
 	pisp_wbg_config wbg;
 
-	wbg.gain_r = clampField(agcPrepareStatus->digitalGain, 14, 10);
-	wbg.gain_g = clampField(agcPrepareStatus->digitalGain, 14, 10);
-	wbg.gain_b = clampField(agcPrepareStatus->digitalGain, 14, 10);
+	wbg.gain_r = clampField(digitalGain, 14, 10);
+	wbg.gain_g = clampField(digitalGain, 14, 10);
+	wbg.gain_b = clampField(digitalGain, 14, 10);
 
-	LOG(IPARPI, Debug) << "Applying DG (only) : " << agcPrepareStatus->digitalGain;
+	LOG(IPARPI, Debug) << "Applying DG (only) : " << digitalGain;
 
 	be_->SetWbg(wbg);
 	global.bayer_enables |= PISP_BE_BAYER_ENABLE_WBG;
@@ -668,6 +747,17 @@ void IpaPiSP::applyDPC(const DpcStatus *
 	be_->SetDpc(dpc);
 }
 
+void IpaPiSP::applyDecompand(const DecompandStatus *decompandStatus, pisp_fe_global_config &feGlobal)
+{
+	pisp_fe_decompand_config decompand = {};
+
+	if (!generateDecompandLut(decompandStatus->decompandCurve, decompand.lut)) {
+		fe_->SetDecompand(decompand);
+		feGlobal.enables |= PISP_FE_ENABLE_DECOMPAND;
+	} else
+		feGlobal.enables &= ~PISP_FE_ENABLE_DECOMPAND;
+}
+
 void IpaPiSP::applySdn(const SdnStatus *sdnStatus, pisp_be_global_config &global)
 {
 	pisp_be_sdn_config sdn = {};
@@ -985,6 +1075,12 @@ void IpaPiSP::setStatsAndDebin()
 	 */
 	setHistogramWeights();
 
+	/* Configure the first AGC floating region to cover the whole image, for the lux algo. */
+	pisp_fe_floating_stats_config floatingStatsConfig = {};
+	floatingStatsConfig.regions[0].size_x = mode_.width;
+	floatingStatsConfig.regions[0].size_y = mode_.height;
+	fe_->SetFloatingStats(floatingStatsConfig);
+
 	pisp_be_global_config beGlobal;
 	be_->GetGlobal(beGlobal);
 
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx219.json 0.6.0-2/src/ipa/rpi/vc4/data/imx219.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx219.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx219.json	2025-11-27 11:55:28.000000000 +0000
@@ -162,17 +162,17 @@
                             "normal":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 10.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 33333 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 10.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 10.0 ]
                             }
                         },
                         "constraint_modes":
@@ -675,7 +675,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.hdr":
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx219_noir.json 0.6.0-2/src/ipa/rpi/vc4/data/imx219_noir.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx219_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx219_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -78,17 +78,17 @@
                             "normal":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 10.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 33333 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 10.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 10.0 ]
                             }
                         },
                         "constraint_modes":
@@ -609,7 +609,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.hdr":
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx283.json 0.6.0-2/src/ipa/rpi/vc4/data/imx283.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx283.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx283.json	2025-11-27 11:55:28.000000000 +0000
@@ -14,25 +14,25 @@
         {
             "rpi.lux":
             {
-                "reference_shutter_speed": 2461,
-                "reference_gain": 1.0,
+                "reference_shutter_speed": 10857,
+                "reference_gain": 1.49,
                 "reference_aperture": 1.0,
-                "reference_lux": 1148,
-                "reference_Y": 13314
+                "reference_lux": 1050,
+                "reference_Y": 13959
             }
         },
         {
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.204
+                "reference_slope": 2.147
             }
         },
         {
             "rpi.geq":
             {
-                "offset": 199,
-                "slope": 0.01947
+                "offset": 249,
+                "slope": 0.02036
             }
         },
         {
@@ -104,19 +104,35 @@
                     {
                         "lo": 5500,
                         "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 6000,
+                        "hi": 6800
                     }
                 },
                 "bayes": 1,
                 "ct_curve":
                 [
-                    2213.0, 0.9607, 0.2593,
-                    5313.0, 0.4822, 0.5909,
-                    6237.0, 0.4739, 0.6308
+                    2500.0, 0.9429, 0.2809,
+                    2820.0, 0.8488, 0.3472,
+                    2830.0, 0.8303, 0.3609,
+                    2885.0, 0.8177, 0.3703,
+                    3601.0, 0.6935, 0.4705,
+                    3615.0, 0.6918, 0.4719,
+                    3622.0, 0.6894, 0.4741,
+                    4345.0, 0.5999, 0.5546,
+                    4410.0, 0.5942, 0.5601,
+                    4486.0, 0.5878, 0.5661,
+                    4576.0, 0.5779, 0.5756,
+                    5672.0, 0.5211, 0.6318,
+                    5710.0, 0.5168, 0.6362,
+                    6850.0, 0.4841, 0.6702
                 ],
                 "sensitivity_r": 1.0,
                 "sensitivity_b": 1.0,
-                "transverse_pos": 0.0144,
-                "transverse_neg": 0.01
+                "transverse_pos": 0.02601,
+                "transverse_neg": 0.0246
             }
         },
         {
@@ -209,7 +225,136 @@
             {
                 "omega": 1.3,
                 "n_iter": 100,
-                "luminance_strength": 0.7
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2940,
+                        "table":
+                        [
+                            1.021, 1.026, 1.028, 1.029, 1.031, 1.029, 1.029, 1.029, 1.029, 1.031, 1.031, 1.028, 1.027, 1.022, 1.013, 1.008,
+                            1.022, 1.026, 1.027, 1.028, 1.027, 1.026, 1.026, 1.025, 1.026, 1.026, 1.027, 1.027, 1.027, 1.022, 1.014, 1.009,
+                            1.023, 1.026, 1.026, 1.027, 1.026, 1.025, 1.024, 1.024, 1.024, 1.025, 1.026, 1.027, 1.026, 1.023, 1.017, 1.012,
+                            1.024, 1.026, 1.026, 1.026, 1.025, 1.024, 1.024, 1.023, 1.023, 1.024, 1.025, 1.026, 1.026, 1.024, 1.018, 1.013,
+                            1.024, 1.026, 1.026, 1.026, 1.025, 1.024, 1.023, 1.023, 1.023, 1.023, 1.024, 1.026, 1.026, 1.025, 1.019, 1.013,
+                            1.025, 1.026, 1.026, 1.026, 1.025, 1.024, 1.023, 1.023, 1.023, 1.023, 1.024, 1.026, 1.026, 1.025, 1.018, 1.013,
+                            1.025, 1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.023, 1.023, 1.024, 1.024, 1.026, 1.026, 1.024, 1.018, 1.013,
+                            1.025, 1.027, 1.028, 1.028, 1.027, 1.026, 1.025, 1.024, 1.024, 1.024, 1.025, 1.026, 1.026, 1.024, 1.017, 1.012,
+                            1.024, 1.027, 1.029, 1.029, 1.028, 1.027, 1.026, 1.026, 1.025, 1.025, 1.026, 1.026, 1.025, 1.022, 1.014, 1.009,
+                            1.024, 1.027, 1.029, 1.031, 1.031, 1.029, 1.028, 1.028, 1.028, 1.028, 1.027, 1.026, 1.025, 1.021, 1.011, 1.007,
+                            1.022, 1.026, 1.031, 1.031, 1.031, 1.032, 1.031, 1.031, 1.029, 1.029, 1.028, 1.026, 1.022, 1.017, 1.007, 1.003,
+                            1.019, 1.024, 1.029, 1.031, 1.032, 1.032, 1.032, 1.031, 1.029, 1.029, 1.027, 1.024, 1.019, 1.013, 1.003, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.027, 1.035, 1.039, 1.041, 1.043, 1.043, 1.043, 1.043, 1.044, 1.044, 1.044, 1.041, 1.041, 1.034, 1.021, 1.014,
+                            1.029, 1.035, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.041, 1.041, 1.041, 1.041, 1.035, 1.024, 1.017,
+                            1.029, 1.034, 1.036, 1.038, 1.038, 1.038, 1.039, 1.039, 1.039, 1.039, 1.039, 1.041, 1.039, 1.036, 1.027, 1.021,
+                            1.031, 1.034, 1.036, 1.036, 1.037, 1.037, 1.038, 1.037, 1.037, 1.038, 1.038, 1.039, 1.039, 1.037, 1.029, 1.021,
+                            1.031, 1.034, 1.035, 1.036, 1.037, 1.037, 1.037, 1.037, 1.037, 1.037, 1.038, 1.038, 1.038, 1.037, 1.029, 1.022,
+                            1.031, 1.034, 1.035, 1.036, 1.037, 1.037, 1.037, 1.036, 1.036, 1.036, 1.037, 1.038, 1.038, 1.037, 1.029, 1.022,
+                            1.031, 1.035, 1.036, 1.037, 1.037, 1.037, 1.037, 1.036, 1.036, 1.036, 1.037, 1.038, 1.038, 1.036, 1.028, 1.021,
+                            1.031, 1.034, 1.036, 1.037, 1.037, 1.037, 1.036, 1.036, 1.036, 1.036, 1.036, 1.037, 1.037, 1.035, 1.026, 1.019,
+                            1.028, 1.034, 1.037, 1.037, 1.037, 1.037, 1.037, 1.036, 1.036, 1.036, 1.037, 1.037, 1.037, 1.033, 1.022, 1.016,
+                            1.028, 1.034, 1.037, 1.038, 1.039, 1.038, 1.037, 1.037, 1.037, 1.037, 1.037, 1.037, 1.035, 1.031, 1.017, 1.011,
+                            1.025, 1.031, 1.036, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.038, 1.038, 1.036, 1.031, 1.024, 1.011, 1.006,
+                            1.021, 1.028, 1.034, 1.037, 1.039, 1.039, 1.039, 1.038, 1.038, 1.038, 1.036, 1.033, 1.027, 1.019, 1.006, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.026, 1.037, 1.048, 1.054, 1.057, 1.058, 1.059, 1.059, 1.061, 1.059, 1.059, 1.056, 1.049, 1.038, 1.019, 1.013,
+                            1.031, 1.039, 1.049, 1.054, 1.057, 1.058, 1.059, 1.059, 1.059, 1.059, 1.059, 1.056, 1.051, 1.042, 1.026, 1.018,
+                            1.033, 1.044, 1.051, 1.054, 1.057, 1.058, 1.059, 1.059, 1.059, 1.059, 1.058, 1.058, 1.055, 1.046, 1.031, 1.023,
+                            1.035, 1.045, 1.051, 1.055, 1.057, 1.059, 1.059, 1.059, 1.059, 1.059, 1.059, 1.058, 1.056, 1.049, 1.035, 1.026,
+                            1.037, 1.046, 1.052, 1.055, 1.058, 1.059, 1.059, 1.059, 1.059, 1.059, 1.059, 1.058, 1.057, 1.051, 1.037, 1.027,
+                            1.037, 1.047, 1.053, 1.056, 1.059, 1.059, 1.061, 1.059, 1.059, 1.059, 1.059, 1.058, 1.057, 1.051, 1.037, 1.027,
+                            1.037, 1.047, 1.053, 1.057, 1.059, 1.059, 1.061, 1.061, 1.059, 1.059, 1.059, 1.058, 1.056, 1.049, 1.036, 1.026,
+                            1.037, 1.047, 1.054, 1.057, 1.059, 1.059, 1.061, 1.061, 1.059, 1.059, 1.059, 1.058, 1.056, 1.048, 1.034, 1.025,
+                            1.034, 1.045, 1.054, 1.057, 1.059, 1.059, 1.059, 1.059, 1.059, 1.059, 1.058, 1.057, 1.053, 1.045, 1.029, 1.021,
+                            1.032, 1.043, 1.052, 1.057, 1.058, 1.059, 1.059, 1.059, 1.059, 1.059, 1.058, 1.055, 1.049, 1.041, 1.022, 1.013,
+                            1.028, 1.037, 1.048, 1.053, 1.057, 1.059, 1.059, 1.059, 1.059, 1.058, 1.056, 1.051, 1.044, 1.032, 1.013, 1.007,
+                            1.021, 1.033, 1.044, 1.051, 1.055, 1.058, 1.059, 1.059, 1.058, 1.057, 1.052, 1.047, 1.039, 1.026, 1.007, 1.001
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2940,
+                        "table":
+                        [
+                            1.002, 1.012, 1.031, 1.042, 1.051, 1.056, 1.058, 1.058, 1.058, 1.058, 1.057, 1.055, 1.045, 1.033, 1.017, 1.016,
+                            1.011, 1.026, 1.041, 1.048, 1.056, 1.063, 1.066, 1.067, 1.067, 1.066, 1.064, 1.061, 1.051, 1.045, 1.028, 1.017,
+                            1.016, 1.033, 1.047, 1.056, 1.063, 1.067, 1.071, 1.072, 1.072, 1.071, 1.068, 1.064, 1.061, 1.051, 1.033, 1.024,
+                            1.021, 1.038, 1.051, 1.061, 1.067, 1.071, 1.073, 1.075, 1.075, 1.074, 1.071, 1.068, 1.063, 1.054, 1.036, 1.025,
+                            1.023, 1.041, 1.054, 1.063, 1.069, 1.073, 1.075, 1.077, 1.077, 1.076, 1.074, 1.069, 1.064, 1.055, 1.038, 1.027,
+                            1.023, 1.043, 1.055, 1.063, 1.069, 1.074, 1.076, 1.078, 1.078, 1.077, 1.075, 1.071, 1.065, 1.056, 1.039, 1.028,
+                            1.023, 1.043, 1.055, 1.063, 1.069, 1.074, 1.076, 1.077, 1.078, 1.076, 1.074, 1.071, 1.065, 1.056, 1.039, 1.028,
+                            1.023, 1.041, 1.052, 1.062, 1.068, 1.072, 1.074, 1.076, 1.076, 1.075, 1.073, 1.069, 1.064, 1.055, 1.038, 1.028,
+                            1.021, 1.038, 1.051, 1.059, 1.066, 1.069, 1.072, 1.074, 1.074, 1.073, 1.069, 1.067, 1.062, 1.052, 1.036, 1.027,
+                            1.018, 1.032, 1.046, 1.055, 1.061, 1.066, 1.069, 1.069, 1.069, 1.069, 1.067, 1.062, 1.057, 1.047, 1.031, 1.021,
+                            1.011, 1.023, 1.039, 1.049, 1.056, 1.061, 1.062, 1.064, 1.065, 1.064, 1.062, 1.058, 1.049, 1.038, 1.021, 1.016,
+                            1.001, 1.019, 1.035, 1.046, 1.053, 1.058, 1.061, 1.062, 1.062, 1.062, 1.059, 1.053, 1.043, 1.033, 1.016, 1.011
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.001, 1.003, 1.011, 1.016, 1.019, 1.019, 1.021, 1.021, 1.019, 1.019, 1.019, 1.017, 1.017, 1.013, 1.007, 1.006,
+                            1.003, 1.011, 1.015, 1.021, 1.024, 1.026, 1.027, 1.027, 1.027, 1.026, 1.025, 1.023, 1.022, 1.016, 1.012, 1.007,
+                            1.007, 1.015, 1.021, 1.024, 1.027, 1.029, 1.031, 1.031, 1.031, 1.029, 1.028, 1.026, 1.024, 1.022, 1.015, 1.011,
+                            1.011, 1.017, 1.023, 1.027, 1.029, 1.032, 1.033, 1.033, 1.033, 1.033, 1.031, 1.028, 1.026, 1.024, 1.016, 1.011,
+                            1.012, 1.019, 1.025, 1.029, 1.032, 1.033, 1.034, 1.035, 1.035, 1.034, 1.033, 1.031, 1.028, 1.025, 1.018, 1.014,
+                            1.013, 1.021, 1.026, 1.031, 1.033, 1.034, 1.036, 1.036, 1.036, 1.035, 1.034, 1.032, 1.029, 1.026, 1.019, 1.015,
+                            1.013, 1.021, 1.026, 1.031, 1.033, 1.035, 1.036, 1.037, 1.037, 1.036, 1.034, 1.032, 1.029, 1.027, 1.019, 1.016,
+                            1.013, 1.021, 1.026, 1.031, 1.033, 1.035, 1.036, 1.036, 1.036, 1.036, 1.035, 1.033, 1.031, 1.027, 1.021, 1.016,
+                            1.013, 1.021, 1.025, 1.029, 1.032, 1.034, 1.035, 1.035, 1.036, 1.035, 1.034, 1.032, 1.031, 1.027, 1.021, 1.015,
+                            1.012, 1.019, 1.024, 1.027, 1.029, 1.032, 1.034, 1.034, 1.034, 1.034, 1.032, 1.031, 1.029, 1.026, 1.019, 1.015,
+                            1.009, 1.015, 1.022, 1.025, 1.028, 1.029, 1.031, 1.032, 1.032, 1.031, 1.031, 1.029, 1.026, 1.023, 1.017, 1.015,
+                            1.005, 1.014, 1.021, 1.025, 1.027, 1.029, 1.029, 1.031, 1.031, 1.031, 1.029, 1.029, 1.024, 1.021, 1.016, 1.015
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.001, 1.001, 1.006, 1.007, 1.008, 1.009, 1.009, 1.009, 1.009, 1.009, 1.009, 1.011, 1.011, 1.011, 1.009, 1.008,
+                            1.001, 1.005, 1.008, 1.011, 1.012, 1.013, 1.014, 1.014, 1.014, 1.013, 1.013, 1.014, 1.014, 1.012, 1.011, 1.009,
+                            1.004, 1.008, 1.011, 1.012, 1.014, 1.016, 1.016, 1.016, 1.016, 1.016, 1.015, 1.015, 1.015, 1.014, 1.012, 1.011,
+                            1.005, 1.009, 1.012, 1.014, 1.016, 1.017, 1.018, 1.018, 1.018, 1.018, 1.017, 1.016, 1.016, 1.015, 1.012, 1.011,
+                            1.006, 1.011, 1.013, 1.015, 1.017, 1.018, 1.018, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.015, 1.012, 1.011,
+                            1.007, 1.011, 1.013, 1.015, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.013, 1.011,
+                            1.007, 1.012, 1.013, 1.015, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.018, 1.017, 1.014, 1.013,
+                            1.007, 1.012, 1.013, 1.015, 1.016, 1.018, 1.019, 1.019, 1.019, 1.019, 1.019, 1.018, 1.018, 1.017, 1.015, 1.014,
+                            1.007, 1.011, 1.012, 1.014, 1.016, 1.017, 1.018, 1.018, 1.019, 1.019, 1.019, 1.018, 1.018, 1.018, 1.016, 1.015,
+                            1.007, 1.011, 1.012, 1.013, 1.015, 1.016, 1.017, 1.017, 1.018, 1.018, 1.018, 1.018, 1.018, 1.017, 1.016, 1.015,
+                            1.006, 1.009, 1.012, 1.013, 1.014, 1.015, 1.015, 1.016, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.016,
+                            1.005, 1.009, 1.012, 1.013, 1.015, 1.015, 1.015, 1.015, 1.016, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017, 1.017
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    1.223, 1.187, 1.129, 1.085, 1.061, 1.049, 1.046, 1.046, 1.046, 1.051, 1.061, 1.089, 1.134, 1.212, 1.359, 1.367,
+                    1.188, 1.141, 1.098, 1.065, 1.048, 1.037, 1.029, 1.029, 1.034, 1.036, 1.046, 1.066, 1.095, 1.158, 1.269, 1.359,
+                    1.158, 1.109, 1.073, 1.049, 1.035, 1.025, 1.019, 1.016, 1.017, 1.022, 1.033, 1.047, 1.072, 1.127, 1.219, 1.269,
+                    1.147, 1.092, 1.058, 1.039, 1.026, 1.017, 1.011, 1.007, 1.009, 1.015, 1.022, 1.035, 1.058, 1.107, 1.191, 1.236,
+                    1.144, 1.082, 1.051, 1.033, 1.021, 1.011, 1.005, 1.002, 1.004, 1.009, 1.017, 1.031, 1.051, 1.097, 1.177, 1.232,
+                    1.144, 1.081, 1.049, 1.031, 1.018, 1.008, 1.002, 1.001, 1.001, 1.006, 1.015, 1.029, 1.048, 1.096, 1.177, 1.232,
+                    1.144, 1.084, 1.051, 1.032, 1.018, 1.009, 1.004, 1.001, 1.002, 1.009, 1.016, 1.029, 1.051, 1.098, 1.183, 1.232,
+                    1.149, 1.096, 1.057, 1.037, 1.022, 1.014, 1.008, 1.005, 1.007, 1.012, 1.019, 1.033, 1.059, 1.113, 1.205, 1.248,
+                    1.166, 1.117, 1.071, 1.046, 1.031, 1.021, 1.014, 1.012, 1.014, 1.019, 1.029, 1.045, 1.078, 1.141, 1.247, 1.314,
+                    1.202, 1.151, 1.096, 1.061, 1.044, 1.031, 1.023, 1.021, 1.022, 1.029, 1.044, 1.067, 1.109, 1.182, 1.314, 1.424,
+                    1.242, 1.202, 1.134, 1.088, 1.061, 1.045, 1.038, 1.036, 1.039, 1.048, 1.066, 1.103, 1.157, 1.248, 1.424, 1.532,
+                    1.318, 1.238, 1.162, 1.111, 1.078, 1.059, 1.048, 1.048, 1.049, 1.063, 1.089, 1.133, 1.189, 1.296, 1.532, 1.606
+                ],
+                "sigma": 0.00175,
+                "sigma_Cb": 0.00268
             }
         },
         {
@@ -259,48 +404,138 @@
             {
                 "ccms": [
                     {
-                        "ct": 2213,
+                        "ct": 2500,
+                        "ccm":
+                        [
+                            1.82257, -0.40941, -0.41316,
+                            -0.52091, 1.83005, -0.30915,
+                            0.22503, -1.41259, 2.18757
+                        ]
+                    },
+                    {
+                        "ct": 2820,
+                        "ccm":
+                        [
+                            1.80564, -0.47587, -0.32977,
+                            -0.47385, 1.83075, -0.35691,
+                            0.21369, -1.22609, 2.01239
+                        ]
+                    },
+                    {
+                        "ct": 2830,
+                        "ccm":
+                        [
+                            1.80057, -0.51479, -0.28578,
+                            -0.64031, 2.16074, -0.52044,
+                            0.11794, -0.95667, 1.83873
+                        ]
+                    },
+                    {
+                        "ct": 2885,
+                        "ccm":
+                        [
+                            1.78452, -0.49769, -0.28683,
+                            -0.63651, 2.13634, -0.49983,
+                            0.08547, -0.86501, 1.77954
+                        ]
+                    },
+                    {
+                        "ct": 3601,
+                        "ccm":
+                        [
+                            1.85165, -0.57008, -0.28156,
+                            -0.56249, 2.08321, -0.52072,
+                            0.03724, -0.70964, 1.67239
+                        ]
+                    },
+                    {
+                        "ct": 3615,
+                        "ccm":
+                        [
+                            1.87611, -0.60772, -0.26839,
+                            -0.55497, 2.07257, -0.51761,
+                            0.04151, -0.70635, 1.66485
+                        ]
+                    },
+                    {
+                        "ct": 3622,
+                        "ccm":
+                        [
+                            1.85505, -0.58542, -0.26963,
+                            -0.55053, 2.05981, -0.50928,
+                            0.04005, -0.69302, 1.65297
+                        ]
+                    },
+                    {
+                        "ct": 4345,
+                        "ccm":
+                        [
+                            1.81872, -0.57511, -0.24361,
+                            -0.49071, 2.16621, -0.67551,
+                            0.02641, -0.67838, 1.65196
+                        ]
+                    },
+                    {
+                        "ct": 4410,
+                        "ccm":
+                        [
+                            1.83689, -0.60178, -0.23512,
+                            -0.48204, 2.14729, -0.66525,
+                            0.02773, -0.67615, 1.64841
+                        ]
+                    },
+                    {
+                        "ct": 4486,
+                        "ccm":
+                        [
+                            1.85101, -0.60733, -0.24368,
+                            -0.47635, 2.13101, -0.65465,
+                            0.02229, -0.66412, 1.64183
+                        ]
+                    },
+                    {
+                        "ct": 4576,
                         "ccm":
                         [
-                            1.91264, -0.27609, -0.63655,
-                            -0.65708, 2.11718, -0.46009,
-                            0.03629, -1.38441, 2.34811
+                            1.84076, -0.59449, -0.24626,
+                            -0.47307, 2.13369, -0.66062,
+                            0.01984, -0.65788, 1.63804
                         ]
                     },
                     {
-                        "ct": 2255,
+                        "ct": 5657,
                         "ccm":
                         [
-                            1.90369, -0.29309, -0.61059,
-                            -0.64693, 2.08169, -0.43476,
-                            0.04086, -1.29999, 2.25914
+                            1.84536, -0.57827, -0.26709,
+                            -0.44532, 2.04086, -0.59554,
+                            -0.01738, -0.52806, 1.54544
                         ]
                     },
                     {
-                        "ct": 2259,
+                        "ct": 5672,
                         "ccm":
                         [
-                            1.92762, -0.35134, -0.57628,
-                            -0.63523, 2.08481, -0.44958,
-                            0.06754, -1.32953, 2.26199
+                            1.84251, -0.57486, -0.26765,
+                            -0.44925, 2.04615, -0.59689,
+                            -0.03179, -0.51748, 1.54928
                         ]
                     },
                     {
-                        "ct": 5313,
+                        "ct": 5710,
                         "ccm":
                         [
-                            1.75924, -0.54053, -0.21871,
-                            -0.38159, 1.88671, -0.50511,
-                            -0.00747, -0.53492, 1.54239
+                            1.84081, -0.58127, -0.25953,
+                            -0.44169, 2.03593, -0.59424,
+                            -0.02503, -0.52696, 1.55199
                         ]
                     },
                     {
-                        "ct": 6237,
+                        "ct": 6850,
                         "ccm":
                         [
-                            2.19299, -0.74764, -0.44536,
-                            -0.51678, 2.27651, -0.75972,
-                            -0.06498, -0.74269, 1.80767
+                            1.80426, -0.22567, -0.57859,
+                            -0.48629, 2.49024, -1.00395,
+                            -0.10865, -0.63841, 1.74705
                         ]
                     }
                 ]
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx296.json 0.6.0-2/src/ipa/rpi/vc4/data/imx296.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx296.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx296.json	2025-11-27 11:55:28.000000000 +0000
@@ -159,18 +159,18 @@
                 {
                     "normal":
                     {
-                        "shutter": [ 100, 30000, 45000, 60000, 120000 ],
-                        "gain": [ 1.0, 1.0, 2.0, 4.0, 12.0 ]
+                        "shutter": [ 100, 30000, 45000, 60000, 66666 ],
+                        "gain": [ 1.0, 1.0, 2.0, 4.0, 16.0 ]
                     },
                     "short":
                     {
-                        "shutter": [ 100, 5000, 10000, 20000, 30000 ],
+                        "shutter": [ 100, 5000, 10000, 20000, 66666 ],
                         "gain": [ 1.0, 2.0, 4.0, 8.0, 16.0 ]
                     },
                     "long":
                     {
                         "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                     }
                 },
                 "constraint_modes":
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx296_mono.json 0.6.0-2/src/ipa/rpi/vc4/data/imx296_mono.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx296_mono.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx296_mono.json	2025-11-27 11:55:28.000000000 +0000
@@ -62,18 +62,18 @@
                 {
                     "normal":
                     {
-                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                        "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                     },
                     "short":
                     {
-                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                        "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                     },
                     "long":
                     {
                         "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                     }
                 },
                 "constraint_modes":
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx335.json 0.6.0-2/src/ipa/rpi/vc4/data/imx335.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx335.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx335.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,569 @@
+{
+    "version": 2.0,
+    "target": "bcm2835",
+    "vendor": "Arducam",
+    "sku": "B0568",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 3200
+            }
+        },
+        {
+            "rpi.dpc": { }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 9994,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 1139,
+                "reference_Y": 12135
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 3.349
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 247,
+                "slope": 0.02352
+            }
+        },
+        {
+            "rpi.sdn": { }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 8000
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8600
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    2300.0, 0.9361, 0.3378,
+                    2856.0, 0.7548, 0.3455,
+                    3000.0, 0.6862, 0.3666,
+                    4000.0, 0.5371, 0.4791,
+                    4100.0, 0.5144, 0.5084,
+                    6500.0, 0.4316, 0.6585
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.03588,
+                "transverse_neg": 0.03895
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "metering_modes":
+                {
+                    "centre-weighted":
+                    {
+                        "weights":
+                        [
+                            3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+                        ]
+                    },
+                    "spot":
+                    {
+                        "weights":
+                        [
+                            2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                        ]
+                    },
+                    "matrix":
+                    {
+                        "weights":
+                        [
+                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                        ]
+                    }
+                },
+                "exposure_modes":
+                {
+                    "normal":
+                    {
+                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    },
+                    "short":
+                    {
+                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    }
+                },
+                "constraint_modes":
+                {
+                    "normal": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        }
+                    ],
+                    "highlight": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        },
+                        {
+                            "bound": "UPPER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.8,
+                                1000, 0.8
+                            ]
+                        }
+                    ]
+                },
+                "y_target":
+                [
+                    0, 0.16,
+                    1000, 0.165,
+                    10000, 0.17
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.053, 1.047, 1.039, 1.031, 1.024, 1.019, 1.016, 1.014, 1.015, 1.016, 1.021, 1.027, 1.033, 1.041, 1.049, 1.055,
+                            1.049, 1.043, 1.034, 1.026, 1.019, 1.014, 1.011, 1.009, 1.009, 1.012, 1.017, 1.022, 1.029, 1.037, 1.046, 1.051,
+                            1.047, 1.039, 1.029, 1.022, 1.015, 1.009, 1.006, 1.004, 1.006, 1.008, 1.012, 1.018, 1.025, 1.033, 1.042, 1.049,
+                            1.046, 1.037, 1.027, 1.019, 1.011, 1.006, 1.003, 1.002, 1.002, 1.005, 1.009, 1.015, 1.023, 1.031, 1.041, 1.048,
+                            1.046, 1.036, 1.027, 1.018, 1.011, 1.005, 1.002, 1.001, 1.001, 1.004, 1.009, 1.014, 1.022, 1.031, 1.039, 1.048,
+                            1.046, 1.037, 1.027, 1.018, 1.011, 1.005, 1.002, 1.001, 1.001, 1.004, 1.009, 1.014, 1.022, 1.031, 1.039, 1.047,
+                            1.046, 1.038, 1.028, 1.019, 1.013, 1.008, 1.004, 1.003, 1.003, 1.006, 1.009, 1.016, 1.023, 1.032, 1.039, 1.048,
+                            1.048, 1.041, 1.031, 1.024, 1.017, 1.012, 1.008, 1.006, 1.007, 1.009, 1.015, 1.019, 1.026, 1.034, 1.042, 1.049,
+                            1.051, 1.045, 1.037, 1.029, 1.024, 1.018, 1.015, 1.013, 1.013, 1.015, 1.019, 1.025, 1.031, 1.038, 1.046, 1.052,
+                            1.058, 1.051, 1.043, 1.036, 1.029, 1.025, 1.022, 1.021, 1.021, 1.022, 1.025, 1.031, 1.037, 1.044, 1.052, 1.057,
+                            1.065, 1.058, 1.051, 1.043, 1.037, 1.032, 1.029, 1.028, 1.028, 1.029, 1.033, 1.037, 1.044, 1.051, 1.057, 1.063,
+                            1.066, 1.065, 1.056, 1.049, 1.043, 1.038, 1.035, 1.035, 1.035, 1.036, 1.038, 1.043, 1.049, 1.056, 1.063, 1.065
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.058, 1.053, 1.043, 1.035, 1.028, 1.022, 1.018, 1.017, 1.017, 1.019, 1.023, 1.029, 1.038, 1.046, 1.055, 1.059,
+                            1.055, 1.048, 1.038, 1.029, 1.022, 1.017, 1.014, 1.012, 1.012, 1.015, 1.019, 1.025, 1.033, 1.041, 1.051, 1.056,
+                            1.052, 1.043, 1.033, 1.025, 1.017, 1.011, 1.007, 1.006, 1.007, 1.009, 1.013, 1.021, 1.028, 1.037, 1.046, 1.054,
+                            1.049, 1.042, 1.032, 1.022, 1.014, 1.009, 1.005, 1.003, 1.004, 1.007, 1.012, 1.018, 1.026, 1.036, 1.045, 1.051,
+                            1.048, 1.039, 1.029, 1.019, 1.012, 1.006, 1.004, 1.001, 1.001, 1.005, 1.009, 1.016, 1.024, 1.033, 1.043, 1.051,
+                            1.049, 1.039, 1.029, 1.021, 1.013, 1.006, 1.003, 1.001, 1.001, 1.005, 1.011, 1.016, 1.024, 1.034, 1.043, 1.051,
+                            1.049, 1.042, 1.031, 1.022, 1.015, 1.009, 1.004, 1.003, 1.004, 1.006, 1.012, 1.018, 1.026, 1.035, 1.044, 1.051,
+                            1.053, 1.045, 1.036, 1.027, 1.021, 1.015, 1.009, 1.008, 1.009, 1.012, 1.017, 1.022, 1.029, 1.038, 1.047, 1.053,
+                            1.059, 1.049, 1.041, 1.032, 1.025, 1.021, 1.017, 1.014, 1.015, 1.017, 1.022, 1.027, 1.034, 1.043, 1.051, 1.059,
+                            1.062, 1.056, 1.047, 1.039, 1.033, 1.028, 1.024, 1.022, 1.022, 1.024, 1.028, 1.034, 1.041, 1.048, 1.056, 1.062,
+                            1.071, 1.063, 1.054, 1.047, 1.039, 1.035, 1.031, 1.029, 1.031, 1.032, 1.035, 1.041, 1.046, 1.054, 1.062, 1.069,
+                            1.073, 1.071, 1.061, 1.052, 1.046, 1.042, 1.039, 1.039, 1.039, 1.041, 1.043, 1.047, 1.052, 1.061, 1.068, 1.071
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.017, 1.015, 1.011, 1.009, 1.006, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.005, 1.008, 1.011, 1.013, 1.015,
+                            1.016, 1.014, 1.011, 1.008, 1.006, 1.004, 1.003, 1.002, 1.002, 1.002, 1.003, 1.005, 1.008, 1.011, 1.013, 1.015,
+                            1.016, 1.013, 1.011, 1.008, 1.005, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.005, 1.007, 1.009, 1.013, 1.015,
+                            1.016, 1.014, 1.011, 1.008, 1.006, 1.004, 1.002, 1.001, 1.001, 1.002, 1.003, 1.005, 1.007, 1.011, 1.013, 1.016,
+                            1.017, 1.014, 1.011, 1.008, 1.006, 1.003, 1.002, 1.001, 1.001, 1.002, 1.003, 1.005, 1.007, 1.011, 1.013, 1.016,
+                            1.017, 1.014, 1.012, 1.009, 1.006, 1.004, 1.002, 1.001, 1.001, 1.002, 1.003, 1.005, 1.008, 1.011, 1.014, 1.016,
+                            1.018, 1.015, 1.013, 1.011, 1.007, 1.005, 1.004, 1.002, 1.002, 1.003, 1.005, 1.007, 1.009, 1.012, 1.014, 1.017,
+                            1.019, 1.017, 1.015, 1.012, 1.011, 1.008, 1.006, 1.005, 1.005, 1.005, 1.006, 1.008, 1.011, 1.014, 1.017, 1.019,
+                            1.021, 1.019, 1.017, 1.015, 1.013, 1.011, 1.009, 1.008, 1.008, 1.009, 1.009, 1.012, 1.014, 1.016, 1.019, 1.021,
+                            1.023, 1.021, 1.018, 1.016, 1.014, 1.013, 1.012, 1.012, 1.012, 1.012, 1.012, 1.014, 1.016, 1.019, 1.021, 1.022,
+                            1.028, 1.025, 1.021, 1.019, 1.017, 1.016, 1.015, 1.014, 1.014, 1.014, 1.016, 1.017, 1.019, 1.022, 1.023, 1.026,
+                            1.031, 1.028, 1.024, 1.021, 1.019, 1.017, 1.017, 1.017, 1.017, 1.018, 1.018, 1.019, 1.022, 1.024, 1.027, 1.027
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.023, 1.021, 1.016, 1.013, 1.009, 1.007, 1.005, 1.005, 1.005, 1.006, 1.006, 1.008, 1.011, 1.015, 1.019, 1.021,
+                            1.022, 1.018, 1.014, 1.011, 1.008, 1.005, 1.004, 1.003, 1.003, 1.003, 1.004, 1.007, 1.011, 1.014, 1.017, 1.019,
+                            1.021, 1.017, 1.013, 1.009, 1.006, 1.004, 1.002, 1.001, 1.001, 1.002, 1.004, 1.006, 1.009, 1.012, 1.016, 1.019,
+                            1.022, 1.017, 1.014, 1.009, 1.006, 1.003, 1.002, 1.001, 1.001, 1.002, 1.003, 1.006, 1.009, 1.013, 1.017, 1.019,
+                            1.022, 1.018, 1.014, 1.011, 1.007, 1.004, 1.001, 1.001, 1.001, 1.001, 1.003, 1.006, 1.009, 1.013, 1.017, 1.021,
+                            1.022, 1.018, 1.014, 1.011, 1.008, 1.004, 1.002, 1.001, 1.001, 1.001, 1.003, 1.007, 1.009, 1.014, 1.017, 1.021,
+                            1.023, 1.019, 1.015, 1.012, 1.008, 1.006, 1.003, 1.002, 1.001, 1.003, 1.005, 1.008, 1.011, 1.014, 1.018, 1.021,
+                            1.025, 1.021, 1.018, 1.015, 1.012, 1.009, 1.006, 1.005, 1.005, 1.006, 1.008, 1.011, 1.014, 1.017, 1.021, 1.023,
+                            1.027, 1.024, 1.021, 1.018, 1.016, 1.013, 1.012, 1.011, 1.009, 1.011, 1.011, 1.014, 1.017, 1.021, 1.023, 1.026,
+                            1.031, 1.027, 1.023, 1.021, 1.018, 1.016, 1.015, 1.014, 1.014, 1.014, 1.015, 1.018, 1.019, 1.023, 1.027, 1.028,
+                            1.036, 1.031, 1.027, 1.024, 1.021, 1.019, 1.018, 1.017, 1.017, 1.017, 1.018, 1.021, 1.023, 1.026, 1.029, 1.032,
+                            1.039, 1.036, 1.031, 1.027, 1.024, 1.022, 1.021, 1.021, 1.021, 1.021, 1.022, 1.023, 1.026, 1.029, 1.032, 1.033
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.017, 1.015, 1.011, 1.009, 1.007, 1.005, 1.004, 1.003, 1.003, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.012,
+                            1.016, 1.013, 1.011, 1.008, 1.006, 1.004, 1.003, 1.003, 1.003, 1.003, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013,
+                            1.016, 1.012, 1.009, 1.007, 1.005, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.007, 1.009, 1.013,
+                            1.017, 1.013, 1.011, 1.008, 1.006, 1.004, 1.002, 1.002, 1.002, 1.003, 1.003, 1.005, 1.006, 1.008, 1.011, 1.014,
+                            1.018, 1.014, 1.011, 1.009, 1.007, 1.004, 1.003, 1.003, 1.002, 1.003, 1.004, 1.005, 1.007, 1.009, 1.012, 1.015,
+                            1.019, 1.015, 1.012, 1.009, 1.008, 1.005, 1.003, 1.003, 1.003, 1.004, 1.004, 1.006, 1.008, 1.011, 1.013, 1.015,
+                            1.019, 1.016, 1.013, 1.011, 1.009, 1.007, 1.005, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.011, 1.013, 1.016,
+                            1.021, 1.018, 1.016, 1.014, 1.011, 1.009, 1.008, 1.006, 1.006, 1.007, 1.008, 1.009, 1.011, 1.013, 1.015, 1.017,
+                            1.023, 1.021, 1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.012, 1.013, 1.014, 1.016, 1.018, 1.021,
+                            1.027, 1.024, 1.021, 1.019, 1.018, 1.017, 1.016, 1.015, 1.015, 1.014, 1.015, 1.016, 1.017, 1.018, 1.021, 1.022,
+                            1.032, 1.028, 1.025, 1.022, 1.021, 1.019, 1.018, 1.017, 1.017, 1.017, 1.017, 1.018, 1.019, 1.022, 1.023, 1.026,
+                            1.034, 1.033, 1.028, 1.025, 1.023, 1.022, 1.021, 1.021, 1.021, 1.021, 1.021, 1.022, 1.022, 1.024, 1.027, 1.027
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.053, 1.048, 1.039, 1.032, 1.026, 1.021, 1.018, 1.016, 1.016, 1.017, 1.019, 1.023, 1.028, 1.035, 1.042, 1.047,
+                            1.049, 1.042, 1.035, 1.028, 1.022, 1.017, 1.014, 1.014, 1.013, 1.013, 1.016, 1.019, 1.024, 1.031, 1.038, 1.044,
+                            1.045, 1.038, 1.031, 1.023, 1.017, 1.012, 1.009, 1.008, 1.007, 1.008, 1.011, 1.014, 1.019, 1.027, 1.034, 1.039,
+                            1.043, 1.035, 1.027, 1.019, 1.014, 1.009, 1.005, 1.003, 1.003, 1.004, 1.006, 1.011, 1.016, 1.022, 1.029, 1.036,
+                            1.043, 1.035, 1.026, 1.019, 1.013, 1.007, 1.003, 1.002, 1.001, 1.002, 1.005, 1.009, 1.014, 1.021, 1.028, 1.037,
+                            1.044, 1.036, 1.027, 1.019, 1.013, 1.007, 1.004, 1.001, 1.001, 1.002, 1.005, 1.009, 1.014, 1.021, 1.029, 1.036,
+                            1.045, 1.037, 1.028, 1.021, 1.014, 1.008, 1.004, 1.002, 1.002, 1.003, 1.006, 1.009, 1.015, 1.021, 1.029, 1.036,
+                            1.046, 1.039, 1.029, 1.023, 1.017, 1.012, 1.007, 1.004, 1.003, 1.004, 1.007, 1.012, 1.017, 1.023, 1.029, 1.037,
+                            1.051, 1.043, 1.036, 1.028, 1.022, 1.017, 1.012, 1.009, 1.009, 1.009, 1.012, 1.015, 1.021, 1.027, 1.034, 1.041,
+                            1.059, 1.051, 1.043, 1.036, 1.029, 1.023, 1.019, 1.018, 1.016, 1.017, 1.018, 1.022, 1.027, 1.033, 1.041, 1.047,
+                            1.065, 1.058, 1.049, 1.041, 1.036, 1.031, 1.026, 1.024, 1.022, 1.023, 1.025, 1.028, 1.033, 1.039, 1.046, 1.053,
+                            1.069, 1.064, 1.055, 1.047, 1.041, 1.035, 1.031, 1.029, 1.029, 1.029, 1.031, 1.033, 1.038, 1.044, 1.053, 1.055
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.033, 1.036, 1.039, 1.044, 1.049, 1.053, 1.056, 1.057, 1.057, 1.055, 1.052, 1.048, 1.043, 1.038, 1.035, 1.031,
+                            1.035, 1.037, 1.041, 1.045, 1.051, 1.053, 1.057, 1.058, 1.059, 1.056, 1.053, 1.049, 1.046, 1.041, 1.036, 1.033,
+                            1.034, 1.037, 1.042, 1.047, 1.052, 1.056, 1.058, 1.059, 1.059, 1.058, 1.056, 1.052, 1.047, 1.041, 1.035, 1.031,
+                            1.034, 1.037, 1.043, 1.048, 1.053, 1.056, 1.059, 1.061, 1.061, 1.059, 1.056, 1.052, 1.047, 1.042, 1.035, 1.029,
+                            1.032, 1.037, 1.042, 1.048, 1.053, 1.055, 1.058, 1.059, 1.059, 1.058, 1.055, 1.051, 1.046, 1.041, 1.034, 1.028,
+                            1.032, 1.035, 1.041, 1.047, 1.052, 1.055, 1.057, 1.058, 1.057, 1.055, 1.053, 1.049, 1.044, 1.039, 1.032, 1.027,
+                            1.032, 1.034, 1.039, 1.045, 1.049, 1.052, 1.054, 1.056, 1.055, 1.053, 1.049, 1.046, 1.042, 1.037, 1.031, 1.026,
+                            1.031, 1.032, 1.038, 1.042, 1.045, 1.049, 1.051, 1.052, 1.052, 1.049, 1.046, 1.042, 1.038, 1.034, 1.028, 1.024,
+                            1.029, 1.028, 1.034, 1.037, 1.041, 1.044, 1.046, 1.046, 1.046, 1.044, 1.041, 1.037, 1.033, 1.028, 1.022, 1.022,
+                            1.023, 1.024, 1.028, 1.033, 1.036, 1.039, 1.041, 1.041, 1.041, 1.039, 1.036, 1.032, 1.028, 1.023, 1.019, 1.017,
+                            1.018, 1.021, 1.023, 1.028, 1.031, 1.033, 1.034, 1.034, 1.033, 1.031, 1.029, 1.027, 1.023, 1.019, 1.016, 1.014,
+                            1.021, 1.018, 1.019, 1.023, 1.027, 1.028, 1.028, 1.028, 1.028, 1.027, 1.025, 1.023, 1.019, 1.016, 1.014, 1.014
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.027, 1.026, 1.032, 1.039, 1.044, 1.048, 1.051, 1.051, 1.051, 1.051, 1.047, 1.042, 1.037, 1.031, 1.025, 1.024,
+                            1.026, 1.031, 1.037, 1.042, 1.047, 1.051, 1.053, 1.054, 1.054, 1.052, 1.049, 1.046, 1.041, 1.034, 1.028, 1.024,
+                            1.028, 1.032, 1.038, 1.044, 1.048, 1.052, 1.056, 1.058, 1.057, 1.055, 1.052, 1.048, 1.043, 1.037, 1.029, 1.025,
+                            1.028, 1.032, 1.038, 1.044, 1.049, 1.053, 1.056, 1.057, 1.057, 1.055, 1.052, 1.047, 1.042, 1.036, 1.029, 1.024,
+                            1.028, 1.034, 1.039, 1.046, 1.051, 1.054, 1.056, 1.058, 1.058, 1.056, 1.052, 1.048, 1.043, 1.037, 1.029, 1.025,
+                            1.029, 1.034, 1.039, 1.046, 1.051, 1.054, 1.057, 1.059, 1.058, 1.056, 1.052, 1.047, 1.042, 1.037, 1.031, 1.025,
+                            1.028, 1.032, 1.037, 1.044, 1.049, 1.053, 1.056, 1.058, 1.057, 1.055, 1.051, 1.046, 1.041, 1.035, 1.029, 1.024,
+                            1.024, 1.029, 1.033, 1.039, 1.044, 1.048, 1.051, 1.052, 1.051, 1.048, 1.045, 1.041, 1.036, 1.031, 1.024, 1.019,
+                            1.019, 1.024, 1.029, 1.035, 1.039, 1.043, 1.045, 1.046, 1.046, 1.044, 1.041, 1.038, 1.033, 1.027, 1.019, 1.015,
+                            1.018, 1.021, 1.026, 1.031, 1.035, 1.039, 1.042, 1.042, 1.042, 1.041, 1.038, 1.034, 1.029, 1.023, 1.018, 1.014,
+                            1.014, 1.017, 1.021, 1.026, 1.031, 1.034, 1.036, 1.037, 1.036, 1.034, 1.032, 1.029, 1.025, 1.019, 1.014, 1.009,
+                            1.012, 1.009, 1.016, 1.021, 1.025, 1.026, 1.027, 1.028, 1.028, 1.028, 1.025, 1.023, 1.019, 1.014, 1.009, 1.008
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.018, 1.019, 1.024, 1.029, 1.033, 1.037, 1.039, 1.039, 1.039, 1.039, 1.037, 1.035, 1.031, 1.025, 1.019, 1.019,
+                            1.019, 1.023, 1.026, 1.031, 1.034, 1.037, 1.039, 1.041, 1.041, 1.041, 1.039, 1.036, 1.032, 1.028, 1.024, 1.019,
+                            1.021, 1.025, 1.029, 1.033, 1.036, 1.039, 1.041, 1.043, 1.043, 1.043, 1.041, 1.038, 1.035, 1.031, 1.026, 1.022,
+                            1.022, 1.026, 1.031, 1.034, 1.037, 1.041, 1.042, 1.043, 1.043, 1.043, 1.041, 1.038, 1.036, 1.033, 1.027, 1.021,
+                            1.021, 1.026, 1.031, 1.035, 1.038, 1.039, 1.042, 1.043, 1.043, 1.043, 1.041, 1.038, 1.036, 1.032, 1.027, 1.022,
+                            1.021, 1.026, 1.029, 1.034, 1.037, 1.039, 1.041, 1.043, 1.043, 1.041, 1.039, 1.037, 1.035, 1.032, 1.027, 1.021,
+                            1.021, 1.025, 1.029, 1.034, 1.036, 1.039, 1.041, 1.043, 1.043, 1.041, 1.039, 1.036, 1.033, 1.031, 1.026, 1.021,
+                            1.019, 1.022, 1.027, 1.031, 1.035, 1.037, 1.039, 1.041, 1.041, 1.039, 1.037, 1.034, 1.032, 1.028, 1.024, 1.019,
+                            1.017, 1.019, 1.023, 1.027, 1.031, 1.034, 1.035, 1.036, 1.036, 1.036, 1.033, 1.031, 1.028, 1.024, 1.019, 1.018,
+                            1.013, 1.015, 1.021, 1.024, 1.027, 1.029, 1.032, 1.033, 1.032, 1.032, 1.029, 1.028, 1.025, 1.021, 1.016, 1.012,
+                            1.008, 1.011, 1.016, 1.019, 1.023, 1.027, 1.028, 1.029, 1.029, 1.028, 1.027, 1.025, 1.021, 1.017, 1.013, 1.009,
+                            1.008, 1.007, 1.012, 1.017, 1.021, 1.023, 1.024, 1.025, 1.025, 1.025, 1.024, 1.022, 1.018, 1.014, 1.009, 1.007
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.011, 1.012, 1.018, 1.024, 1.028, 1.031, 1.033, 1.034, 1.034, 1.033, 1.032, 1.028, 1.025, 1.019, 1.014, 1.011,
+                            1.011, 1.015, 1.021, 1.025, 1.029, 1.032, 1.035, 1.036, 1.036, 1.035, 1.033, 1.031, 1.027, 1.022, 1.016, 1.012,
+                            1.015, 1.019, 1.024, 1.028, 1.032, 1.035, 1.037, 1.039, 1.039, 1.038, 1.036, 1.033, 1.029, 1.025, 1.021, 1.016,
+                            1.017, 1.022, 1.027, 1.031, 1.035, 1.037, 1.039, 1.042, 1.041, 1.041, 1.039, 1.036, 1.032, 1.028, 1.022, 1.018,
+                            1.018, 1.022, 1.027, 1.032, 1.035, 1.038, 1.041, 1.042, 1.042, 1.041, 1.038, 1.035, 1.032, 1.028, 1.023, 1.018,
+                            1.017, 1.021, 1.026, 1.031, 1.035, 1.038, 1.041, 1.041, 1.042, 1.041, 1.037, 1.034, 1.031, 1.027, 1.022, 1.017,
+                            1.016, 1.019, 1.025, 1.029, 1.034, 1.037, 1.041, 1.041, 1.041, 1.039, 1.037, 1.034, 1.031, 1.026, 1.021, 1.016,
+                            1.015, 1.019, 1.025, 1.029, 1.033, 1.036, 1.039, 1.041, 1.041, 1.038, 1.036, 1.033, 1.029, 1.026, 1.021, 1.016,
+                            1.012, 1.017, 1.022, 1.026, 1.029, 1.033, 1.035, 1.036, 1.036, 1.035, 1.032, 1.031, 1.026, 1.023, 1.017, 1.013,
+                            1.008, 1.011, 1.016, 1.021, 1.024, 1.027, 1.029, 1.029, 1.029, 1.029, 1.028, 1.025, 1.022, 1.017, 1.012, 1.009,
+                            1.004, 1.008, 1.013, 1.017, 1.019, 1.023, 1.025, 1.026, 1.026, 1.025, 1.024, 1.021, 1.018, 1.014, 1.009, 1.005,
+                            1.002, 1.004, 1.009, 1.014, 1.019, 1.022, 1.024, 1.024, 1.024, 1.025, 1.023, 1.019, 1.016, 1.012, 1.006, 1.004
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.009, 1.013, 1.019, 1.026, 1.029, 1.033, 1.036, 1.036, 1.036, 1.035, 1.033, 1.031, 1.027, 1.021, 1.016, 1.013,
+                            1.012, 1.017, 1.023, 1.028, 1.032, 1.036, 1.038, 1.039, 1.039, 1.039, 1.036, 1.034, 1.031, 1.025, 1.019, 1.015,
+                            1.017, 1.021, 1.026, 1.032, 1.036, 1.039, 1.041, 1.043, 1.043, 1.042, 1.041, 1.037, 1.034, 1.028, 1.023, 1.018,
+                            1.018, 1.023, 1.028, 1.033, 1.037, 1.041, 1.043, 1.045, 1.045, 1.044, 1.042, 1.039, 1.035, 1.031, 1.025, 1.019,
+                            1.019, 1.023, 1.029, 1.034, 1.038, 1.041, 1.044, 1.046, 1.046, 1.044, 1.042, 1.039, 1.036, 1.031, 1.025, 1.021,
+                            1.018, 1.024, 1.031, 1.036, 1.039, 1.042, 1.045, 1.047, 1.047, 1.045, 1.043, 1.039, 1.036, 1.032, 1.026, 1.021,
+                            1.018, 1.023, 1.029, 1.035, 1.038, 1.041, 1.045, 1.047, 1.047, 1.045, 1.042, 1.038, 1.034, 1.031, 1.026, 1.021,
+                            1.016, 1.021, 1.027, 1.032, 1.036, 1.039, 1.042, 1.044, 1.044, 1.043, 1.039, 1.036, 1.033, 1.029, 1.024, 1.018,
+                            1.012, 1.017, 1.023, 1.028, 1.032, 1.035, 1.037, 1.039, 1.039, 1.037, 1.036, 1.033, 1.029, 1.025, 1.019, 1.014,
+                            1.008, 1.013, 1.018, 1.024, 1.028, 1.031, 1.033, 1.035, 1.035, 1.034, 1.032, 1.029, 1.026, 1.021, 1.015, 1.011,
+                            1.005, 1.008, 1.014, 1.019, 1.024, 1.027, 1.029, 1.031, 1.031, 1.029, 1.028, 1.026, 1.022, 1.017, 1.011, 1.006,
+                            1.002, 1.004, 1.009, 1.016, 1.019, 1.023, 1.024, 1.025, 1.026, 1.026, 1.024, 1.021, 1.018, 1.014, 1.007, 1.005
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.005, 1.011, 1.017, 1.023, 1.028, 1.032, 1.034, 1.035, 1.036, 1.035, 1.033, 1.031, 1.026, 1.019, 1.013, 1.011,
+                            1.009, 1.013, 1.019, 1.026, 1.031, 1.035, 1.037, 1.039, 1.039, 1.039, 1.036, 1.033, 1.029, 1.022, 1.016, 1.013,
+                            1.012, 1.018, 1.025, 1.031, 1.035, 1.038, 1.042, 1.043, 1.044, 1.043, 1.041, 1.038, 1.034, 1.028, 1.021, 1.015,
+                            1.016, 1.022, 1.028, 1.034, 1.039, 1.043, 1.046, 1.049, 1.049, 1.048, 1.045, 1.042, 1.038, 1.033, 1.027, 1.019,
+                            1.017, 1.022, 1.029, 1.036, 1.041, 1.044, 1.048, 1.049, 1.051, 1.049, 1.047, 1.044, 1.039, 1.033, 1.027, 1.021,
+                            1.016, 1.022, 1.028, 1.035, 1.041, 1.044, 1.049, 1.051, 1.051, 1.049, 1.047, 1.043, 1.039, 1.033, 1.027, 1.021,
+                            1.016, 1.022, 1.029, 1.035, 1.041, 1.045, 1.049, 1.051, 1.051, 1.049, 1.047, 1.043, 1.039, 1.033, 1.027, 1.022,
+                            1.016, 1.021, 1.028, 1.035, 1.039, 1.043, 1.047, 1.049, 1.051, 1.049, 1.046, 1.043, 1.039, 1.033, 1.027, 1.021,
+                            1.013, 1.017, 1.024, 1.031, 1.036, 1.041, 1.044, 1.047, 1.047, 1.046, 1.043, 1.041, 1.036, 1.029, 1.023, 1.019,
+                            1.007, 1.012, 1.019, 1.025, 1.029, 1.034, 1.038, 1.039, 1.039, 1.039, 1.038, 1.034, 1.031, 1.025, 1.018, 1.013,
+                            1.004, 1.008, 1.015, 1.021, 1.026, 1.029, 1.032, 1.035, 1.035, 1.035, 1.032, 1.029, 1.026, 1.021, 1.014, 1.009,
+                            1.001, 1.005, 1.012, 1.018, 1.023, 1.028, 1.029, 1.032, 1.032, 1.033, 1.031, 1.028, 1.023, 1.018, 1.011, 1.007
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    2.085, 1.998, 1.784, 1.621, 1.485, 1.386, 1.347, 1.343, 1.343, 1.346, 1.386, 1.484, 1.619, 1.779, 1.986, 2.064,
+                    2.001, 1.829, 1.641, 1.511, 1.392, 1.304, 1.251, 1.227, 1.227, 1.251, 1.304, 1.389, 1.508, 1.639, 1.818, 1.991,
+                    1.858, 1.708, 1.529, 1.394, 1.297, 1.218, 1.161, 1.135, 1.135, 1.159, 1.216, 1.299, 1.392, 1.526, 1.701, 1.842,
+                    1.782, 1.624, 1.452, 1.318, 1.219, 1.151, 1.096, 1.065, 1.063, 1.091, 1.153, 1.219, 1.317, 1.446, 1.614, 1.763,
+                    1.745, 1.564, 1.399, 1.266, 1.166, 1.096, 1.049, 1.019, 1.019, 1.053, 1.091, 1.163, 1.263, 1.391, 1.554, 1.727,
+                    1.741, 1.542, 1.378, 1.247, 1.144, 1.067, 1.022, 1.004, 1.005, 1.021, 1.066, 1.141, 1.243, 1.371, 1.533, 1.722,
+                    1.739, 1.544, 1.379, 1.248, 1.145, 1.069, 1.025, 1.009, 1.006, 1.026, 1.068, 1.143, 1.244, 1.372, 1.535, 1.721,
+                    1.754, 1.582, 1.411, 1.278, 1.173, 1.099, 1.061, 1.026, 1.027, 1.056, 1.101, 1.176, 1.272, 1.401, 1.565, 1.734,
+                    1.802, 1.641, 1.464, 1.331, 1.228, 1.163, 1.099, 1.072, 1.074, 1.101, 1.157, 1.228, 1.324, 1.453, 1.619, 1.779,
+                    1.879, 1.731, 1.549, 1.414, 1.317, 1.229, 1.172, 1.145, 1.145, 1.171, 1.231, 1.313, 1.405, 1.534, 1.706, 1.854,
+                    2.056, 1.867, 1.676, 1.536, 1.413, 1.327, 1.273, 1.249, 1.249, 1.271, 1.322, 1.404, 1.523, 1.661, 1.847, 2.023,
+                    2.126, 2.051, 1.828, 1.656, 1.515, 1.416, 1.379, 1.374, 1.374, 1.375, 1.411, 1.505, 1.638, 1.803, 2.021, 2.089
+                ],
+                "sigma": 0.00344,
+                "sigma_Cb": 0.0013
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 2300,
+                        "ccm":
+                        [
+                            1.67501, -0.27285, -0.40215,
+                            -0.47081, 1.79623, -0.32543,
+                            0.05891, -1.19433, 2.13543
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "ccm":
+                        [
+                            1.66638, -0.34761, -0.31878,
+                            -0.40736, 1.76103, -0.35367,
+                            0.08999, -1.03207, 1.94208
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.68559, -0.43301, -0.25259,
+                            -0.47141, 1.73804, -0.26664,
+                            0.04007, -0.74364, 1.70357
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "ccm":
+                        [
+                            1.68741, -0.47137, -0.21604,
+                            -0.37371, 1.65574, -0.28203,
+                            0.00512, -0.54385, 1.53873
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "ccm":
+                        [
+                            2.04759, -0.88314, -0.16446,
+                            -0.39326, 1.58237, -0.18911,
+                            0.03138, -0.54996, 1.51858
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            1.65914, -0.42539, -0.23375,
+                            -0.28017, 1.69528, -0.41511,
+                            0.00848, -0.53989, 1.53141
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.sharpen": { }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx415_b0569.json 0.6.0-2/src/ipa/rpi/vc4/data/imx415_b0569.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx415_b0569.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx415_b0569.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,569 @@
+{
+    "version": 2.0,
+    "target": "bcm2835",
+    "vendor": "Arducam",
+    "sku": "B0569",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 3200
+            }
+        },
+        {
+            "rpi.dpc": { }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 9990,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 875,
+                "reference_Y": 15940
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 3.44
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 221,
+                "slope": 0.00645
+            }
+        },
+        {
+            "rpi.sdn": { }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 8000
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8600
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    2300.0, 0.9192, 0.3052,
+                    2856.0, 0.7502, 0.3132,
+                    3000.0, 0.7201, 0.3207,
+                    4000.0, 0.5701, 0.4071,
+                    4100.0, 0.5452, 0.4329,
+                    6500.0, 0.4558, 0.5698
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.0236,
+                "transverse_neg": 0.0396
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "metering_modes":
+                {
+                    "centre-weighted":
+                    {
+                        "weights":
+                        [
+                            3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+                        ]
+                    },
+                    "spot":
+                    {
+                        "weights":
+                        [
+                            2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                        ]
+                    },
+                    "matrix":
+                    {
+                        "weights":
+                        [
+                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                        ]
+                    }
+                },
+                "exposure_modes":
+                {
+                    "normal":
+                    {
+                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    },
+                    "short":
+                    {
+                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    }
+                },
+                "constraint_modes":
+                {
+                    "normal": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        }
+                    ],
+                    "highlight": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        },
+                        {
+                            "bound": "UPPER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.8,
+                                1000, 0.8
+                            ]
+                        }
+                    ]
+                },
+                "y_target":
+                [
+                    0, 0.16,
+                    1000, 0.165,
+                    10000, 0.17
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.052, 1.045, 1.037, 1.031, 1.025, 1.021, 1.017, 1.016, 1.015, 1.016, 1.019, 1.022, 1.028, 1.033, 1.038, 1.044,
+                            1.052, 1.046, 1.038, 1.031, 1.025, 1.021, 1.016, 1.014, 1.015, 1.016, 1.019, 1.023, 1.029, 1.035, 1.039, 1.044,
+                            1.051, 1.045, 1.037, 1.029, 1.022, 1.017, 1.012, 1.011, 1.009, 1.012, 1.016, 1.021, 1.027, 1.034, 1.039, 1.045,
+                            1.049, 1.042, 1.034, 1.026, 1.018, 1.012, 1.009, 1.005, 1.005, 1.008, 1.012, 1.017, 1.023, 1.031, 1.037, 1.043,
+                            1.048, 1.041, 1.033, 1.024, 1.016, 1.009, 1.005, 1.003, 1.003, 1.005, 1.009, 1.014, 1.022, 1.029, 1.036, 1.041,
+                            1.047, 1.039, 1.032, 1.023, 1.015, 1.008, 1.004, 1.002, 1.003, 1.004, 1.008, 1.013, 1.021, 1.028, 1.035, 1.041,
+                            1.047, 1.039, 1.032, 1.022, 1.015, 1.008, 1.003, 1.002, 1.002, 1.004, 1.008, 1.013, 1.021, 1.028, 1.035, 1.041,
+                            1.047, 1.039, 1.032, 1.023, 1.015, 1.008, 1.004, 1.003, 1.003, 1.005, 1.009, 1.014, 1.021, 1.028, 1.035, 1.041,
+                            1.048, 1.039, 1.032, 1.024, 1.016, 1.009, 1.006, 1.004, 1.004, 1.007, 1.011, 1.015, 1.022, 1.029, 1.035, 1.041,
+                            1.048, 1.041, 1.033, 1.026, 1.018, 1.012, 1.009, 1.008, 1.007, 1.009, 1.013, 1.017, 1.023, 1.031, 1.036, 1.042,
+                            1.049, 1.043, 1.036, 1.029, 1.022, 1.016, 1.013, 1.011, 1.011, 1.014, 1.016, 1.021, 1.025, 1.032, 1.039, 1.043,
+                            1.052, 1.045, 1.038, 1.031, 1.024, 1.019, 1.016, 1.015, 1.014, 1.016, 1.019, 1.022, 1.027, 1.034, 1.041, 1.046
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.059, 1.051, 1.042, 1.034, 1.027, 1.022, 1.019, 1.018, 1.018, 1.019, 1.022, 1.025, 1.031, 1.036, 1.043, 1.048,
+                            1.058, 1.051, 1.043, 1.034, 1.027, 1.022, 1.018, 1.017, 1.017, 1.018, 1.021, 1.025, 1.031, 1.037, 1.043, 1.049,
+                            1.059, 1.052, 1.043, 1.034, 1.026, 1.021, 1.016, 1.011, 1.011, 1.014, 1.019, 1.025, 1.031, 1.037, 1.044, 1.049,
+                            1.055, 1.049, 1.041, 1.031, 1.022, 1.016, 1.009, 1.008, 1.008, 1.009, 1.014, 1.019, 1.028, 1.035, 1.043, 1.046,
+                            1.055, 1.048, 1.038, 1.029, 1.019, 1.011, 1.008, 1.005, 1.004, 1.007, 1.011, 1.017, 1.024, 1.033, 1.041, 1.046,
+                            1.053, 1.046, 1.036, 1.027, 1.017, 1.009, 1.005, 1.003, 1.003, 1.004, 1.008, 1.015, 1.023, 1.031, 1.039, 1.044,
+                            1.053, 1.047, 1.037, 1.027, 1.018, 1.011, 1.005, 1.003, 1.003, 1.005, 1.009, 1.016, 1.024, 1.032, 1.039, 1.045,
+                            1.052, 1.046, 1.036, 1.027, 1.017, 1.011, 1.005, 1.004, 1.004, 1.005, 1.009, 1.015, 1.023, 1.031, 1.039, 1.044,
+                            1.054, 1.048, 1.039, 1.029, 1.021, 1.013, 1.008, 1.006, 1.005, 1.009, 1.013, 1.018, 1.026, 1.033, 1.041, 1.045,
+                            1.054, 1.048, 1.039, 1.029, 1.022, 1.016, 1.012, 1.011, 1.011, 1.012, 1.014, 1.019, 1.026, 1.034, 1.041, 1.046,
+                            1.058, 1.051, 1.042, 1.033, 1.025, 1.021, 1.016, 1.013, 1.013, 1.016, 1.021, 1.024, 1.028, 1.036, 1.043, 1.049,
+                            1.058, 1.055, 1.045, 1.037, 1.029, 1.024, 1.021, 1.019, 1.019, 1.019, 1.021, 1.026, 1.032, 1.039, 1.048, 1.051
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.039, 1.035, 1.029, 1.023, 1.018, 1.013, 1.011, 1.009, 1.009, 1.009, 1.011, 1.014, 1.017, 1.022, 1.026, 1.029,
+                            1.041, 1.037, 1.031, 1.024, 1.018, 1.014, 1.011, 1.009, 1.009, 1.009, 1.011, 1.014, 1.018, 1.023, 1.027, 1.031,
+                            1.041, 1.037, 1.031, 1.024, 1.018, 1.014, 1.009, 1.007, 1.006, 1.007, 1.009, 1.014, 1.018, 1.023, 1.028, 1.031,
+                            1.039, 1.035, 1.029, 1.021, 1.015, 1.009, 1.006, 1.003, 1.002, 1.003, 1.007, 1.011, 1.015, 1.021, 1.026, 1.029,
+                            1.039, 1.034, 1.028, 1.021, 1.014, 1.007, 1.004, 1.002, 1.001, 1.002, 1.005, 1.009, 1.015, 1.021, 1.025, 1.028,
+                            1.039, 1.034, 1.028, 1.021, 1.013, 1.007, 1.003, 1.002, 1.002, 1.002, 1.004, 1.008, 1.014, 1.021, 1.024, 1.028,
+                            1.039, 1.034, 1.028, 1.021, 1.014, 1.007, 1.004, 1.002, 1.001, 1.003, 1.005, 1.009, 1.014, 1.019, 1.025, 1.029,
+                            1.039, 1.034, 1.029, 1.022, 1.014, 1.008, 1.005, 1.003, 1.003, 1.004, 1.006, 1.009, 1.015, 1.021, 1.025, 1.029,
+                            1.039, 1.035, 1.029, 1.022, 1.016, 1.011, 1.007, 1.005, 1.004, 1.006, 1.009, 1.012, 1.016, 1.022, 1.026, 1.029,
+                            1.041, 1.036, 1.031, 1.023, 1.017, 1.013, 1.011, 1.008, 1.008, 1.009, 1.011, 1.014, 1.018, 1.023, 1.027, 1.031,
+                            1.042, 1.039, 1.032, 1.026, 1.021, 1.017, 1.014, 1.012, 1.012, 1.013, 1.014, 1.017, 1.021, 1.024, 1.029, 1.032,
+                            1.045, 1.039, 1.034, 1.027, 1.022, 1.018, 1.016, 1.016, 1.015, 1.015, 1.016, 1.018, 1.021, 1.026, 1.031, 1.034
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.051, 1.043, 1.037, 1.029, 1.023, 1.018, 1.014, 1.013, 1.012, 1.012, 1.014, 1.016, 1.021, 1.025, 1.029, 1.034,
+                            1.051, 1.045, 1.038, 1.029, 1.023, 1.019, 1.015, 1.012, 1.012, 1.012, 1.013, 1.016, 1.021, 1.026, 1.031, 1.034,
+                            1.049, 1.046, 1.038, 1.029, 1.021, 1.016, 1.011, 1.008, 1.008, 1.008, 1.011, 1.015, 1.021, 1.026, 1.032, 1.034,
+                            1.049, 1.043, 1.035, 1.026, 1.018, 1.012, 1.008, 1.004, 1.003, 1.004, 1.008, 1.012, 1.017, 1.023, 1.028, 1.033,
+                            1.047, 1.042, 1.033, 1.025, 1.017, 1.009, 1.004, 1.002, 1.001, 1.002, 1.004, 1.009, 1.015, 1.022, 1.027, 1.031,
+                            1.048, 1.042, 1.034, 1.025, 1.016, 1.009, 1.004, 1.002, 1.001, 1.001, 1.004, 1.009, 1.015, 1.022, 1.027, 1.032,
+                            1.047, 1.041, 1.033, 1.024, 1.016, 1.008, 1.003, 1.002, 1.001, 1.001, 1.005, 1.009, 1.015, 1.022, 1.027, 1.031,
+                            1.048, 1.041, 1.034, 1.025, 1.017, 1.011, 1.005, 1.003, 1.002, 1.003, 1.007, 1.011, 1.016, 1.023, 1.028, 1.032,
+                            1.048, 1.042, 1.035, 1.026, 1.018, 1.011, 1.008, 1.006, 1.005, 1.006, 1.009, 1.012, 1.018, 1.024, 1.028, 1.033,
+                            1.049, 1.043, 1.035, 1.027, 1.021, 1.015, 1.011, 1.008, 1.008, 1.009, 1.012, 1.016, 1.019, 1.024, 1.029, 1.034,
+                            1.051, 1.046, 1.039, 1.031, 1.024, 1.019, 1.016, 1.015, 1.014, 1.014, 1.015, 1.019, 1.023, 1.027, 1.033, 1.035,
+                            1.054, 1.046, 1.039, 1.032, 1.026, 1.022, 1.018, 1.017, 1.017, 1.017, 1.018, 1.021, 1.024, 1.029, 1.035, 1.037
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.047, 1.041, 1.035, 1.028, 1.023, 1.018, 1.015, 1.013, 1.012, 1.012, 1.014, 1.016, 1.019, 1.023, 1.027, 1.028,
+                            1.048, 1.044, 1.036, 1.029, 1.023, 1.018, 1.015, 1.013, 1.012, 1.012, 1.014, 1.016, 1.019, 1.024, 1.028, 1.031,
+                            1.049, 1.045, 1.037, 1.029, 1.022, 1.017, 1.012, 1.009, 1.009, 1.009, 1.011, 1.016, 1.019, 1.025, 1.029, 1.032,
+                            1.047, 1.043, 1.035, 1.027, 1.019, 1.012, 1.008, 1.005, 1.004, 1.005, 1.008, 1.012, 1.017, 1.022, 1.027, 1.029,
+                            1.047, 1.041, 1.034, 1.025, 1.017, 1.009, 1.005, 1.003, 1.002, 1.003, 1.006, 1.009, 1.015, 1.021, 1.026, 1.029,
+                            1.046, 1.041, 1.033, 1.025, 1.017, 1.009, 1.004, 1.003, 1.002, 1.002, 1.005, 1.009, 1.015, 1.021, 1.026, 1.029,
+                            1.046, 1.041, 1.033, 1.025, 1.017, 1.009, 1.005, 1.003, 1.002, 1.003, 1.005, 1.009, 1.015, 1.021, 1.026, 1.029,
+                            1.045, 1.041, 1.034, 1.026, 1.017, 1.011, 1.006, 1.004, 1.003, 1.004, 1.007, 1.011, 1.016, 1.022, 1.026, 1.028,
+                            1.046, 1.041, 1.034, 1.026, 1.018, 1.012, 1.008, 1.006, 1.005, 1.007, 1.009, 1.013, 1.017, 1.022, 1.027, 1.029,
+                            1.046, 1.042, 1.035, 1.028, 1.021, 1.016, 1.012, 1.009, 1.009, 1.011, 1.012, 1.015, 1.019, 1.024, 1.028, 1.029,
+                            1.049, 1.044, 1.038, 1.029, 1.024, 1.019, 1.016, 1.015, 1.014, 1.015, 1.015, 1.019, 1.022, 1.026, 1.029, 1.032,
+                            1.051, 1.045, 1.039, 1.031, 1.027, 1.022, 1.019, 1.018, 1.017, 1.018, 1.019, 1.021, 1.023, 1.028, 1.032, 1.034
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.069, 1.058, 1.048, 1.037, 1.029, 1.024, 1.018, 1.015, 1.013, 1.014, 1.016, 1.018, 1.023, 1.028, 1.034, 1.039,
+                            1.068, 1.061, 1.048, 1.037, 1.029, 1.024, 1.018, 1.014, 1.013, 1.013, 1.015, 1.018, 1.023, 1.029, 1.036, 1.039,
+                            1.068, 1.061, 1.048, 1.037, 1.028, 1.021, 1.014, 1.011, 1.008, 1.009, 1.012, 1.016, 1.023, 1.031, 1.037, 1.041,
+                            1.065, 1.056, 1.045, 1.034, 1.023, 1.015, 1.009, 1.005, 1.003, 1.005, 1.007, 1.012, 1.019, 1.026, 1.034, 1.039,
+                            1.064, 1.054, 1.043, 1.033, 1.021, 1.012, 1.006, 1.003, 1.001, 1.001, 1.005, 1.009, 1.017, 1.025, 1.032, 1.038,
+                            1.064, 1.054, 1.044, 1.033, 1.021, 1.012, 1.006, 1.003, 1.001, 1.001, 1.004, 1.009, 1.017, 1.025, 1.032, 1.038,
+                            1.064, 1.054, 1.043, 1.033, 1.022, 1.014, 1.007, 1.004, 1.002, 1.002, 1.006, 1.011, 1.018, 1.026, 1.032, 1.038,
+                            1.063, 1.055, 1.045, 1.034, 1.023, 1.015, 1.009, 1.006, 1.005, 1.005, 1.008, 1.013, 1.021, 1.027, 1.034, 1.039,
+                            1.065, 1.056, 1.045, 1.036, 1.026, 1.018, 1.013, 1.009, 1.007, 1.009, 1.011, 1.016, 1.023, 1.029, 1.035, 1.041,
+                            1.065, 1.059, 1.048, 1.038, 1.029, 1.024, 1.019, 1.015, 1.014, 1.014, 1.017, 1.022, 1.027, 1.031, 1.037, 1.042,
+                            1.069, 1.063, 1.054, 1.044, 1.036, 1.029, 1.025, 1.022, 1.021, 1.022, 1.023, 1.027, 1.031, 1.036, 1.043, 1.046,
+                            1.073, 1.065, 1.056, 1.046, 1.039, 1.034, 1.031, 1.028, 1.027, 1.027, 1.028, 1.029, 1.034, 1.039, 1.046, 1.048
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2300,
+                        "table":
+                        [
+                            1.049, 1.049, 1.047, 1.044, 1.042, 1.039, 1.036, 1.033, 1.032, 1.031, 1.029, 1.026, 1.022, 1.021, 1.016, 1.011,
+                            1.049, 1.048, 1.045, 1.043, 1.039, 1.035, 1.032, 1.031, 1.027, 1.026, 1.024, 1.022, 1.021, 1.018, 1.014, 1.011,
+                            1.048, 1.046, 1.044, 1.039, 1.035, 1.032, 1.029, 1.026, 1.023, 1.022, 1.019, 1.019, 1.019, 1.016, 1.013, 1.008,
+                            1.046, 1.044, 1.042, 1.036, 1.033, 1.028, 1.025, 1.022, 1.018, 1.018, 1.016, 1.016, 1.015, 1.015, 1.013, 1.007,
+                            1.044, 1.043, 1.041, 1.035, 1.029, 1.026, 1.022, 1.018, 1.016, 1.014, 1.013, 1.013, 1.014, 1.014, 1.011, 1.007,
+                            1.043, 1.042, 1.039, 1.034, 1.028, 1.023, 1.019, 1.017, 1.014, 1.013, 1.012, 1.013, 1.013, 1.013, 1.011, 1.004,
+                            1.041, 1.041, 1.038, 1.033, 1.027, 1.022, 1.018, 1.016, 1.013, 1.012, 1.012, 1.013, 1.013, 1.012, 1.011, 1.004,
+                            1.041, 1.039, 1.036, 1.032, 1.026, 1.021, 1.019, 1.017, 1.013, 1.012, 1.013, 1.014, 1.012, 1.012, 1.009, 1.003,
+                            1.037, 1.036, 1.034, 1.031, 1.027, 1.023, 1.019, 1.017, 1.015, 1.014, 1.014, 1.014, 1.013, 1.012, 1.007, 1.003,
+                            1.035, 1.034, 1.033, 1.031, 1.027, 1.024, 1.021, 1.019, 1.017, 1.016, 1.015, 1.014, 1.013, 1.012, 1.006, 1.001,
+                            1.033, 1.033, 1.032, 1.031, 1.029, 1.026, 1.024, 1.021, 1.019, 1.018, 1.017, 1.015, 1.014, 1.012, 1.005, 1.001,
+                            1.032, 1.032, 1.032, 1.031, 1.029, 1.027, 1.026, 1.024, 1.021, 1.019, 1.018, 1.017, 1.014, 1.012, 1.006, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "table":
+                        [
+                            1.031, 1.031, 1.031, 1.029, 1.027, 1.027, 1.026, 1.024, 1.022, 1.021, 1.018, 1.015, 1.012, 1.008, 1.004, 1.001,
+                            1.033, 1.033, 1.033, 1.031, 1.029, 1.028, 1.027, 1.025, 1.023, 1.021, 1.019, 1.016, 1.013, 1.011, 1.007, 1.003,
+                            1.033, 1.034, 1.033, 1.032, 1.029, 1.028, 1.027, 1.024, 1.022, 1.019, 1.018, 1.015, 1.013, 1.011, 1.007, 1.004,
+                            1.036, 1.035, 1.034, 1.032, 1.029, 1.027, 1.024, 1.023, 1.021, 1.018, 1.017, 1.015, 1.014, 1.011, 1.008, 1.004,
+                            1.032, 1.032, 1.032, 1.029, 1.027, 1.024, 1.022, 1.019, 1.016, 1.015, 1.012, 1.012, 1.011, 1.009, 1.006, 1.003,
+                            1.034, 1.034, 1.032, 1.031, 1.028, 1.025, 1.022, 1.019, 1.017, 1.016, 1.014, 1.014, 1.012, 1.011, 1.007, 1.003,
+                            1.031, 1.031, 1.029, 1.028, 1.026, 1.022, 1.019, 1.017, 1.015, 1.013, 1.012, 1.012, 1.011, 1.009, 1.005, 1.002,
+                            1.032, 1.031, 1.031, 1.029, 1.027, 1.024, 1.022, 1.019, 1.017, 1.016, 1.015, 1.014, 1.012, 1.011, 1.006, 1.003,
+                            1.029, 1.029, 1.028, 1.027, 1.025, 1.023, 1.021, 1.018, 1.016, 1.015, 1.013, 1.012, 1.011, 1.008, 1.005, 1.001,
+                            1.029, 1.029, 1.029, 1.028, 1.027, 1.025, 1.022, 1.021, 1.019, 1.017, 1.016, 1.014, 1.012, 1.009, 1.006, 1.001,
+                            1.027, 1.027, 1.027, 1.026, 1.025, 1.024, 1.023, 1.022, 1.019, 1.018, 1.015, 1.013, 1.011, 1.008, 1.002, 1.001,
+                            1.025, 1.026, 1.026, 1.025, 1.024, 1.024, 1.024, 1.022, 1.021, 1.019, 1.016, 1.013, 1.011, 1.008, 1.002, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.039, 1.038, 1.035, 1.033, 1.029, 1.028, 1.026, 1.023, 1.023, 1.021, 1.019, 1.017, 1.014, 1.012, 1.009, 1.008,
+                            1.037, 1.035, 1.034, 1.031, 1.028, 1.024, 1.022, 1.019, 1.016, 1.015, 1.014, 1.013, 1.013, 1.011, 1.009, 1.007,
+                            1.036, 1.035, 1.033, 1.029, 1.025, 1.022, 1.019, 1.016, 1.013, 1.012, 1.012, 1.012, 1.011, 1.009, 1.007, 1.005,
+                            1.035, 1.033, 1.031, 1.026, 1.023, 1.019, 1.015, 1.012, 1.009, 1.008, 1.007, 1.008, 1.009, 1.009, 1.006, 1.005,
+                            1.034, 1.032, 1.029, 1.025, 1.021, 1.016, 1.012, 1.008, 1.006, 1.006, 1.006, 1.007, 1.007, 1.007, 1.006, 1.004,
+                            1.033, 1.032, 1.028, 1.024, 1.019, 1.013, 1.009, 1.007, 1.005, 1.003, 1.004, 1.005, 1.006, 1.007, 1.005, 1.003,
+                            1.032, 1.031, 1.027, 1.023, 1.018, 1.012, 1.009, 1.006, 1.004, 1.003, 1.004, 1.006, 1.006, 1.006, 1.005, 1.003,
+                            1.032, 1.029, 1.027, 1.023, 1.019, 1.013, 1.009, 1.007, 1.004, 1.004, 1.005, 1.006, 1.006, 1.007, 1.005, 1.003,
+                            1.031, 1.029, 1.026, 1.022, 1.019, 1.014, 1.011, 1.008, 1.006, 1.005, 1.006, 1.006, 1.006, 1.006, 1.005, 1.002,
+                            1.031, 1.028, 1.025, 1.022, 1.019, 1.015, 1.013, 1.009, 1.008, 1.007, 1.007, 1.007, 1.007, 1.006, 1.004, 1.001,
+                            1.029, 1.028, 1.026, 1.022, 1.021, 1.018, 1.015, 1.013, 1.011, 1.011, 1.009, 1.008, 1.007, 1.006, 1.004, 1.002,
+                            1.029, 1.028, 1.026, 1.023, 1.021, 1.019, 1.017, 1.015, 1.013, 1.012, 1.011, 1.009, 1.008, 1.007, 1.004, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.032, 1.032, 1.031, 1.031, 1.029, 1.029, 1.027, 1.025, 1.025, 1.023, 1.021, 1.019, 1.015, 1.012, 1.011, 1.009,
+                            1.028, 1.028, 1.028, 1.027, 1.026, 1.024, 1.022, 1.021, 1.019, 1.018, 1.017, 1.014, 1.013, 1.011, 1.008, 1.006,
+                            1.026, 1.026, 1.025, 1.025, 1.022, 1.021, 1.019, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.008, 1.006, 1.002,
+                            1.027, 1.027, 1.026, 1.024, 1.022, 1.021, 1.018, 1.016, 1.014, 1.013, 1.011, 1.011, 1.011, 1.009, 1.006, 1.003,
+                            1.024, 1.025, 1.024, 1.022, 1.021, 1.018, 1.015, 1.013, 1.011, 1.011, 1.009, 1.009, 1.008, 1.007, 1.005, 1.002,
+                            1.025, 1.025, 1.024, 1.023, 1.021, 1.017, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009, 1.009, 1.007, 1.005, 1.002,
+                            1.024, 1.024, 1.023, 1.022, 1.019, 1.016, 1.014, 1.011, 1.009, 1.008, 1.008, 1.008, 1.007, 1.007, 1.005, 1.001,
+                            1.023, 1.023, 1.023, 1.022, 1.019, 1.016, 1.013, 1.012, 1.009, 1.009, 1.009, 1.009, 1.008, 1.007, 1.004, 1.001,
+                            1.023, 1.022, 1.022, 1.021, 1.019, 1.016, 1.014, 1.012, 1.011, 1.009, 1.009, 1.008, 1.007, 1.006, 1.003, 1.001,
+                            1.022, 1.022, 1.021, 1.021, 1.019, 1.017, 1.015, 1.014, 1.012, 1.011, 1.011, 1.009, 1.008, 1.006, 1.002, 1.001,
+                            1.021, 1.021, 1.021, 1.019, 1.019, 1.018, 1.016, 1.014, 1.013, 1.011, 1.011, 1.009, 1.007, 1.006, 1.002, 1.001,
+                            1.021, 1.021, 1.019, 1.019, 1.019, 1.018, 1.017, 1.015, 1.014, 1.013, 1.011, 1.009, 1.007, 1.005, 1.002, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.029, 1.029, 1.029, 1.027, 1.027, 1.026, 1.025, 1.022, 1.022, 1.019, 1.018, 1.016, 1.012, 1.011, 1.008, 1.007,
+                            1.027, 1.027, 1.027, 1.026, 1.025, 1.023, 1.021, 1.018, 1.017, 1.016, 1.014, 1.013, 1.012, 1.009, 1.007, 1.005,
+                            1.027, 1.027, 1.026, 1.025, 1.023, 1.021, 1.018, 1.016, 1.015, 1.014, 1.013, 1.012, 1.011, 1.008, 1.006, 1.003,
+                            1.027, 1.027, 1.026, 1.025, 1.022, 1.019, 1.017, 1.015, 1.013, 1.011, 1.011, 1.011, 1.009, 1.009, 1.007, 1.004,
+                            1.026, 1.026, 1.025, 1.023, 1.021, 1.017, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009, 1.008, 1.008, 1.006, 1.003,
+                            1.025, 1.026, 1.025, 1.023, 1.019, 1.017, 1.014, 1.011, 1.009, 1.008, 1.008, 1.009, 1.009, 1.008, 1.006, 1.003,
+                            1.025, 1.025, 1.024, 1.023, 1.019, 1.016, 1.013, 1.011, 1.008, 1.008, 1.008, 1.009, 1.008, 1.007, 1.005, 1.002,
+                            1.024, 1.024, 1.024, 1.022, 1.019, 1.015, 1.013, 1.011, 1.009, 1.008, 1.009, 1.009, 1.008, 1.007, 1.005, 1.002,
+                            1.023, 1.023, 1.023, 1.022, 1.019, 1.016, 1.014, 1.012, 1.009, 1.009, 1.009, 1.009, 1.008, 1.007, 1.004, 1.001,
+                            1.022, 1.023, 1.022, 1.021, 1.019, 1.017, 1.015, 1.013, 1.011, 1.011, 1.011, 1.009, 1.008, 1.006, 1.003, 1.001,
+                            1.022, 1.022, 1.022, 1.021, 1.019, 1.018, 1.016, 1.014, 1.013, 1.012, 1.011, 1.009, 1.008, 1.006, 1.002, 1.001,
+                            1.022, 1.022, 1.021, 1.021, 1.021, 1.019, 1.017, 1.016, 1.014, 1.013, 1.012, 1.009, 1.008, 1.006, 1.002, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.017, 1.019, 1.021, 1.022, 1.023, 1.024, 1.025, 1.025, 1.024, 1.023, 1.022, 1.019, 1.015, 1.012, 1.007, 1.007,
+                            1.019, 1.021, 1.023, 1.025, 1.027, 1.027, 1.028, 1.028, 1.027, 1.025, 1.023, 1.021, 1.018, 1.014, 1.011, 1.007,
+                            1.021, 1.023, 1.025, 1.027, 1.028, 1.028, 1.029, 1.028, 1.027, 1.026, 1.024, 1.022, 1.021, 1.015, 1.012, 1.008,
+                            1.021, 1.024, 1.026, 1.027, 1.028, 1.029, 1.028, 1.028, 1.027, 1.026, 1.024, 1.022, 1.021, 1.016, 1.013, 1.008,
+                            1.021, 1.022, 1.025, 1.026, 1.026, 1.027, 1.027, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.015, 1.012, 1.008,
+                            1.019, 1.022, 1.024, 1.026, 1.026, 1.025, 1.025, 1.024, 1.023, 1.022, 1.021, 1.019, 1.018, 1.015, 1.012, 1.007,
+                            1.019, 1.021, 1.022, 1.024, 1.024, 1.024, 1.023, 1.022, 1.021, 1.021, 1.019, 1.018, 1.017, 1.013, 1.011, 1.006,
+                            1.018, 1.019, 1.021, 1.023, 1.023, 1.023, 1.022, 1.021, 1.021, 1.019, 1.019, 1.017, 1.014, 1.012, 1.009, 1.006,
+                            1.017, 1.017, 1.019, 1.021, 1.022, 1.021, 1.021, 1.021, 1.019, 1.019, 1.018, 1.016, 1.013, 1.011, 1.007, 1.005,
+                            1.014, 1.015, 1.017, 1.018, 1.019, 1.019, 1.019, 1.019, 1.018, 1.017, 1.016, 1.013, 1.011, 1.009, 1.005, 1.002,
+                            1.012, 1.014, 1.016, 1.017, 1.018, 1.019, 1.018, 1.017, 1.017, 1.016, 1.015, 1.013, 1.011, 1.007, 1.003, 1.001,
+                            1.011, 1.013, 1.015, 1.016, 1.017, 1.017, 1.017, 1.017, 1.016, 1.015, 1.013, 1.011, 1.009, 1.007, 1.002, 1.001
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    2.072, 1.922, 1.693, 1.523, 1.394, 1.297, 1.232, 1.229, 1.229, 1.239, 1.311, 1.412, 1.545, 1.719, 1.959, 2.114,
+                    1.988, 1.787, 1.576, 1.423, 1.315, 1.245, 1.171, 1.141, 1.143, 1.179, 1.256, 1.328, 1.442, 1.602, 1.819, 2.028,
+                    1.901, 1.718, 1.513, 1.361, 1.246, 1.167, 1.115, 1.087, 1.087, 1.124, 1.178, 1.263, 1.382, 1.541, 1.749, 1.939,
+                    1.864, 1.649, 1.453, 1.304, 1.192, 1.116, 1.079, 1.037, 1.042, 1.084, 1.128, 1.211, 1.328, 1.482, 1.684, 1.905,
+                    1.837, 1.614, 1.421, 1.275, 1.165, 1.084, 1.034, 1.015, 1.018, 1.042, 1.097, 1.184, 1.299, 1.451, 1.649, 1.879,
+                    1.832, 1.606, 1.413, 1.268, 1.158, 1.075, 1.019, 1.005, 1.006, 1.029, 1.089, 1.177, 1.293, 1.445, 1.645, 1.875,
+                    1.832, 1.601, 1.408, 1.264, 1.155, 1.071, 1.017, 1.004, 1.005, 1.026, 1.085, 1.172, 1.288, 1.439, 1.639, 1.875,
+                    1.846, 1.622, 1.428, 1.282, 1.171, 1.091, 1.045, 1.017, 1.023, 1.051, 1.102, 1.189, 1.307, 1.461, 1.661, 1.889,
+                    1.868, 1.668, 1.469, 1.319, 1.207, 1.127, 1.085, 1.051, 1.051, 1.094, 1.141, 1.226, 1.345, 1.501, 1.707, 1.912,
+                    1.932, 1.727, 1.521, 1.368, 1.259, 1.188, 1.128, 1.096, 1.098, 1.141, 1.201, 1.275, 1.393, 1.554, 1.765, 1.976,
+                    1.999, 1.828, 1.609, 1.447, 1.333, 1.256, 1.191, 1.167, 1.167, 1.199, 1.269, 1.352, 1.475, 1.642, 1.865, 2.042,
+                    2.121, 1.933, 1.702, 1.531, 1.408, 1.315, 1.246, 1.236, 1.237, 1.257, 1.329, 1.426, 1.558, 1.733, 1.969, 2.164
+                ],
+                "sigma": 0.0015,
+                "sigma_Cb": 0.00181
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 2300,
+                        "ccm":
+                        [
+                            2.01006, -0.36954, -0.64052,
+                            -0.77988, 2.37335, -0.59347,
+                            -0.04284, -1.95411, 2.99694
+                        ]
+                    },
+                    {
+                        "ct": 2856,
+                        "ccm":
+                        [
+                            1.98064, -0.55194, -0.42869,
+                            -0.67072, 2.25175, -0.58103,
+                            0.07094, -1.54263, 2.47169
+                        ]
+                    },
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.95595, -0.61286, -0.34309,
+                            -0.72298, 2.15643, -0.43345,
+                            0.01524, -1.22374, 2.20851
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "ccm":
+                        [
+                            1.93512, -0.67428, -0.26084,
+                            -0.58341, 2.01782, -0.43441,
+                            -0.02507, -0.83669, 1.86177
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "ccm":
+                        [
+                            2.47688, -1.30776, -0.16912,
+                            -0.58124, 1.90087, -0.31963,
+                            0.05938, -0.85106, 1.79169
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            2.01272, -0.81917, -0.19355,
+                            -0.43585, 2.05126, -0.61541,
+                            0.03546, -0.81222, 1.77676
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.sharpen": { }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx462.json 0.6.0-2/src/ipa/rpi/vc4/data/imx462.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx462.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx462.json	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,8 @@
 {
     "version": 2.0,
     "target": "bcm2835",
-    "description": "This is an interim tuning only. Please consider doing a more formal tuning for your application.",
+    "vendor": "Innomaker",
+    "sku": "CAM-MIPI462RAW",
     "algorithms": [
         {
             "rpi.black_level":
@@ -15,25 +16,25 @@
         {
             "rpi.lux":
             {
-                "reference_shutter_speed": 6813,
+                "reference_shutter_speed": 5437,
                 "reference_gain": 1.0,
                 "reference_aperture": 1.0,
-                "reference_lux": 890,
-                "reference_Y": 12900
+                "reference_lux": 972,
+                "reference_Y": 12728
             }
         },
         {
             "rpi.noise":
             {
                 "reference_constant": 0,
-                "reference_slope": 2.67
+                "reference_slope": 3.849
             }
         },
         {
             "rpi.geq":
             {
-                "offset": 187,
-                "slope": 0.00842
+                "offset": 194,
+                "slope": 0.01041
             }
         },
         {
@@ -42,34 +43,121 @@
         {
             "rpi.awb":
             {
-                "bayes": 0
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2800,
+                        "hi": 6700
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2800,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    2820.0, 0.8648, 0.3773,
+                    2865.0, 0.8518, 0.3879,
+                    2895.0, 0.8512, 0.3884,
+                    2906.0, 0.8483, 0.3907,
+                    2918.0, 0.8327, 0.4035,
+                    3587.0, 0.7422, 0.4765,
+                    3615.0, 0.7419, 0.4767,
+                    3620.0, 0.7381, 0.4798,
+                    4330.0, 0.6429, 0.5549,
+                    4490.0, 0.6299, 0.5651,
+                    4535.0, 0.6235, 0.5701,
+                    4580.0, 0.6183, 0.5741,
+                    5640.0, 0.5627, 0.6171,
+                    5675.0, 0.5612, 0.6182,
+                    5750.0, 0.5591, 0.6198,
+                    6737.0, 0.4923, 0.6707
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.04605,
+                "transverse_neg": 0.02754
             }
         },
         {
             "rpi.agc":
             {
-                "speed": 0.2,
                 "metering_modes":
                 {
-                    "matrix":
+                    "centre-weighted":
                     {
                         "weights":
                         [
-                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                            3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
                         ]
                     },
-                    "centre-weighted":
+                    "spot":
                     {
                         "weights":
                         [
-                            3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+                            2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                         ]
                     },
-                    "spot":
+                    "matrix":
                     {
                         "weights":
                         [
-                            2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
                         ]
                     }
                 },
@@ -77,23 +165,34 @@
                 {
                     "normal":
                     {
-                        "shutter": [ 10, 30000, 60000 ],
-                        "gain": [ 1.0, 2.0, 8.0 ]
+                        "shutter": [ 100, 10000, 30000, 60000, 66666 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
                     },
                     "short":
                     {
-                        "shutter": [ 10, 5000, 10000, 20000, 120000 ],
+                        "shutter": [ 100, 5000, 10000, 20000, 66666 ],
                         "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
                     },
                     "long":
                     {
-                        "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
                     }
                 },
                 "constraint_modes":
                 {
-                    "normal": [  ],
+                    "normal": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        }
+                    ],
                     "highlight": [
                         {
                             "bound": "LOWER",
@@ -120,8 +219,8 @@
                 "y_target":
                 [
                     0, 0.16,
-                    1000, 0.16,
-                    10000, 0.16
+                    1000, 0.165,
+                    10000, 0.17
                 ]
             }
         },
@@ -130,24 +229,136 @@
             {
                 "omega": 1.3,
                 "n_iter": 100,
-                "luminance_strength": 0.7,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 2900,
+                        "table":
+                        [
+                            1.051, 1.043, 1.033, 1.025, 1.019, 1.015, 1.011, 1.011, 1.011, 1.011, 1.013, 1.017, 1.021, 1.028, 1.035, 1.036,
+                            1.047, 1.038, 1.028, 1.021, 1.016, 1.013, 1.009, 1.008, 1.007, 1.008, 1.011, 1.013, 1.018, 1.025, 1.032, 1.036,
+                            1.044, 1.035, 1.024, 1.017, 1.013, 1.009, 1.006, 1.004, 1.004, 1.005, 1.007, 1.011, 1.015, 1.021, 1.028, 1.032,
+                            1.041, 1.031, 1.022, 1.015, 1.009, 1.006, 1.004, 1.003, 1.002, 1.003, 1.005, 1.007, 1.011, 1.017, 1.026, 1.029,
+                            1.041, 1.029, 1.021, 1.014, 1.008, 1.005, 1.003, 1.001, 1.001, 1.002, 1.003, 1.006, 1.011, 1.016, 1.024, 1.027,
+                            1.039, 1.029, 1.019, 1.013, 1.007, 1.004, 1.001, 1.001, 1.001, 1.001, 1.002, 1.005, 1.009, 1.015, 1.023, 1.026,
+                            1.039, 1.028, 1.019, 1.012, 1.007, 1.004, 1.001, 1.001, 1.001, 1.001, 1.002, 1.005, 1.009, 1.015, 1.023, 1.026,
+                            1.039, 1.029, 1.019, 1.013, 1.007, 1.004, 1.002, 1.001, 1.001, 1.001, 1.003, 1.006, 1.009, 1.015, 1.023, 1.027,
+                            1.041, 1.031, 1.021, 1.014, 1.009, 1.005, 1.003, 1.002, 1.001, 1.002, 1.004, 1.007, 1.011, 1.016, 1.024, 1.028,
+                            1.043, 1.033, 1.023, 1.016, 1.011, 1.007, 1.005, 1.003, 1.003, 1.004, 1.007, 1.009, 1.013, 1.019, 1.027, 1.029,
+                            1.045, 1.035, 1.026, 1.018, 1.013, 1.009, 1.006, 1.004, 1.004, 1.006, 1.008, 1.011, 1.016, 1.022, 1.028, 1.032,
+                            1.047, 1.039, 1.029, 1.021, 1.014, 1.012, 1.006, 1.004, 1.005, 1.006, 1.011, 1.014, 1.017, 1.025, 1.029, 1.037
+                        ]
+                    },
+                    {
+                        "ct": 4250,
+                        "table":
+                        [
+                            1.058, 1.049, 1.037, 1.028, 1.022, 1.017, 1.013, 1.012, 1.012, 1.012, 1.015, 1.019, 1.025, 1.031, 1.042, 1.045,
+                            1.054, 1.043, 1.032, 1.024, 1.018, 1.014, 1.011, 1.009, 1.009, 1.009, 1.012, 1.016, 1.021, 1.027, 1.037, 1.043,
+                            1.049, 1.038, 1.028, 1.021, 1.014, 1.011, 1.007, 1.005, 1.005, 1.006, 1.009, 1.012, 1.017, 1.023, 1.033, 1.038,
+                            1.046, 1.035, 1.024, 1.017, 1.011, 1.007, 1.004, 1.003, 1.003, 1.004, 1.006, 1.009, 1.014, 1.021, 1.029, 1.033,
+                            1.044, 1.032, 1.022, 1.015, 1.009, 1.005, 1.003, 1.002, 1.002, 1.002, 1.004, 1.007, 1.012, 1.018, 1.027, 1.032,
+                            1.043, 1.031, 1.021, 1.014, 1.008, 1.004, 1.002, 1.001, 1.001, 1.002, 1.003, 1.007, 1.011, 1.017, 1.026, 1.032,
+                            1.043, 1.031, 1.021, 1.013, 1.007, 1.004, 1.001, 1.001, 1.001, 1.001, 1.002, 1.006, 1.011, 1.017, 1.026, 1.032,
+                            1.043, 1.031, 1.021, 1.013, 1.007, 1.004, 1.002, 1.001, 1.001, 1.001, 1.003, 1.007, 1.012, 1.017, 1.026, 1.032,
+                            1.044, 1.032, 1.021, 1.014, 1.009, 1.005, 1.003, 1.002, 1.002, 1.003, 1.005, 1.008, 1.013, 1.019, 1.027, 1.032,
+                            1.046, 1.035, 1.024, 1.017, 1.011, 1.007, 1.005, 1.003, 1.004, 1.005, 1.007, 1.011, 1.015, 1.021, 1.031, 1.034,
+                            1.048, 1.037, 1.027, 1.019, 1.012, 1.009, 1.007, 1.005, 1.005, 1.006, 1.007, 1.011, 1.016, 1.023, 1.032, 1.036,
+                            1.048, 1.039, 1.029, 1.019, 1.012, 1.009, 1.007, 1.006, 1.006, 1.006, 1.007, 1.011, 1.018, 1.025, 1.034, 1.041
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.056, 1.047, 1.036, 1.028, 1.022, 1.017, 1.014, 1.013, 1.013, 1.013, 1.015, 1.019, 1.026, 1.034, 1.042, 1.046,
+                            1.051, 1.043, 1.031, 1.023, 1.018, 1.014, 1.011, 1.009, 1.009, 1.009, 1.012, 1.016, 1.021, 1.028, 1.038, 1.042,
+                            1.049, 1.037, 1.027, 1.019, 1.014, 1.011, 1.007, 1.006, 1.006, 1.007, 1.009, 1.012, 1.017, 1.024, 1.033, 1.038,
+                            1.046, 1.034, 1.023, 1.016, 1.011, 1.007, 1.005, 1.004, 1.004, 1.005, 1.007, 1.009, 1.015, 1.021, 1.032, 1.036,
+                            1.044, 1.032, 1.021, 1.014, 1.009, 1.005, 1.003, 1.002, 1.002, 1.003, 1.005, 1.008, 1.013, 1.019, 1.029, 1.034,
+                            1.043, 1.031, 1.021, 1.013, 1.007, 1.004, 1.002, 1.001, 1.001, 1.002, 1.004, 1.007, 1.012, 1.018, 1.028, 1.033,
+                            1.043, 1.029, 1.019, 1.013, 1.007, 1.003, 1.002, 1.001, 1.001, 1.002, 1.003, 1.007, 1.011, 1.017, 1.027, 1.033,
+                            1.043, 1.031, 1.019, 1.013, 1.008, 1.004, 1.002, 1.001, 1.001, 1.002, 1.004, 1.007, 1.012, 1.018, 1.027, 1.033,
+                            1.043, 1.032, 1.021, 1.013, 1.008, 1.005, 1.003, 1.002, 1.002, 1.003, 1.005, 1.008, 1.013, 1.019, 1.028, 1.033,
+                            1.044, 1.035, 1.024, 1.016, 1.011, 1.007, 1.004, 1.003, 1.003, 1.005, 1.007, 1.009, 1.015, 1.022, 1.032, 1.035,
+                            1.045, 1.036, 1.024, 1.016, 1.012, 1.008, 1.005, 1.004, 1.004, 1.005, 1.008, 1.011, 1.018, 1.025, 1.034, 1.036,
+                            1.045, 1.037, 1.026, 1.015, 1.013, 1.009, 1.007, 1.005, 1.005, 1.006, 1.008, 1.011, 1.022, 1.028, 1.034, 1.039
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 2900,
+                        "table":
+                        [
+                            1.008, 1.007, 1.006, 1.005, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.005, 1.007, 1.009, 1.013, 1.014,
+                            1.007, 1.006, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.006, 1.008, 1.011, 1.013,
+                            1.007, 1.005, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.007, 1.011, 1.013,
+                            1.006, 1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.007, 1.009, 1.011,
+                            1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.001, 1.001, 1.001, 1.002, 1.003, 1.003, 1.005, 1.007, 1.009, 1.011,
+                            1.004, 1.003, 1.002, 1.002, 1.002, 1.001, 1.001, 1.001, 1.001, 1.002, 1.002, 1.003, 1.004, 1.007, 1.009, 1.011,
+                            1.004, 1.003, 1.002, 1.002, 1.002, 1.001, 1.001, 1.001, 1.001, 1.001, 1.002, 1.003, 1.005, 1.006, 1.009, 1.011,
+                            1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.001, 1.002, 1.002, 1.003, 1.004, 1.005, 1.007, 1.009, 1.011,
+                            1.005, 1.004, 1.003, 1.003, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.004, 1.005, 1.006, 1.007, 1.009, 1.012,
+                            1.004, 1.003, 1.002, 1.002, 1.002, 1.002, 1.002, 1.003, 1.003, 1.004, 1.005, 1.005, 1.007, 1.008, 1.012, 1.014,
+                            1.004, 1.003, 1.002, 1.001, 1.002, 1.002, 1.002, 1.002, 1.003, 1.004, 1.005, 1.005, 1.007, 1.009, 1.013, 1.016,
+                            1.003, 1.002, 1.001, 1.001, 1.001, 1.001, 1.001, 1.002, 1.003, 1.004, 1.005, 1.004, 1.005, 1.009, 1.015, 1.017
+                        ]
+                    },
+                    {
+                        "ct": 4250,
+                        "table":
+                        [
+                            1.001, 1.004, 1.005, 1.007, 1.008, 1.009, 1.009, 1.009, 1.009, 1.009, 1.009, 1.009, 1.008, 1.007, 1.007, 1.007,
+                            1.003, 1.005, 1.006, 1.007, 1.009, 1.011, 1.012, 1.012, 1.011, 1.011, 1.009, 1.009, 1.008, 1.007, 1.007, 1.007,
+                            1.003, 1.005, 1.006, 1.008, 1.009, 1.012, 1.013, 1.014, 1.013, 1.012, 1.011, 1.009, 1.009, 1.008, 1.008, 1.007,
+                            1.004, 1.005, 1.006, 1.008, 1.011, 1.013, 1.014, 1.014, 1.014, 1.014, 1.013, 1.011, 1.009, 1.009, 1.008, 1.008,
+                            1.004, 1.005, 1.006, 1.009, 1.012, 1.014, 1.014, 1.015, 1.014, 1.014, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.004, 1.004, 1.007, 1.009, 1.013, 1.014, 1.015, 1.014, 1.014, 1.014, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.004, 1.005, 1.008, 1.009, 1.013, 1.014, 1.015, 1.015, 1.015, 1.015, 1.014, 1.012, 1.009, 1.009, 1.009, 1.009,
+                            1.004, 1.005, 1.007, 1.011, 1.013, 1.015, 1.015, 1.015, 1.015, 1.015, 1.014, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.004, 1.005, 1.007, 1.009, 1.013, 1.014, 1.015, 1.015, 1.016, 1.015, 1.015, 1.012, 1.011, 1.009, 1.009, 1.009,
+                            1.004, 1.005, 1.006, 1.009, 1.011, 1.013, 1.015, 1.015, 1.015, 1.015, 1.013, 1.012, 1.011, 1.011, 1.011, 1.009,
+                            1.003, 1.004, 1.006, 1.007, 1.009, 1.012, 1.013, 1.014, 1.015, 1.014, 1.012, 1.011, 1.011, 1.011, 1.011, 1.011,
+                            1.003, 1.002, 1.005, 1.006, 1.008, 1.011, 1.012, 1.013, 1.013, 1.012, 1.011, 1.011, 1.011, 1.012, 1.012, 1.012
+                        ]
+                    },
+                    {
+                        "ct": 6000,
+                        "table":
+                        [
+                            1.001, 1.002, 1.004, 1.006, 1.008, 1.009, 1.009, 1.009, 1.009, 1.009, 1.008, 1.007, 1.006, 1.005, 1.004, 1.003,
+                            1.002, 1.003, 1.005, 1.007, 1.009, 1.011, 1.012, 1.012, 1.011, 1.011, 1.009, 1.007, 1.007, 1.006, 1.005, 1.004,
+                            1.003, 1.004, 1.006, 1.008, 1.011, 1.013, 1.014, 1.014, 1.014, 1.013, 1.011, 1.009, 1.008, 1.006, 1.006, 1.006,
+                            1.003, 1.004, 1.007, 1.009, 1.013, 1.014, 1.015, 1.015, 1.015, 1.014, 1.013, 1.011, 1.009, 1.007, 1.007, 1.006,
+                            1.003, 1.004, 1.007, 1.011, 1.014, 1.015, 1.015, 1.015, 1.015, 1.015, 1.014, 1.012, 1.011, 1.008, 1.007, 1.006,
+                            1.003, 1.005, 1.008, 1.011, 1.014, 1.015, 1.015, 1.016, 1.015, 1.015, 1.014, 1.012, 1.011, 1.008, 1.007, 1.007,
+                            1.004, 1.006, 1.009, 1.012, 1.015, 1.015, 1.016, 1.016, 1.016, 1.016, 1.015, 1.013, 1.011, 1.008, 1.008, 1.007,
+                            1.004, 1.006, 1.009, 1.012, 1.015, 1.016, 1.016, 1.016, 1.016, 1.016, 1.015, 1.013, 1.011, 1.009, 1.008, 1.007,
+                            1.003, 1.006, 1.008, 1.011, 1.014, 1.016, 1.016, 1.017, 1.017, 1.016, 1.015, 1.013, 1.011, 1.009, 1.008, 1.008,
+                            1.002, 1.005, 1.007, 1.009, 1.013, 1.015, 1.016, 1.017, 1.017, 1.016, 1.014, 1.013, 1.011, 1.009, 1.009, 1.009,
+                            1.003, 1.003, 1.005, 1.008, 1.011, 1.013, 1.015, 1.016, 1.016, 1.015, 1.013, 1.012, 1.009, 1.009, 1.011, 1.009,
+                            1.003, 1.002, 1.002, 1.006, 1.009, 1.011, 1.013, 1.014, 1.014, 1.014, 1.012, 1.011, 1.009, 1.011, 1.011, 1.011
+                        ]
+                    }
+                ],
                 "luminance_lut":
                 [
-                    2.844, 2.349, 2.018, 1.775, 1.599, 1.466, 1.371, 1.321, 1.306, 1.316, 1.357, 1.439, 1.552, 1.705, 1.915, 2.221,
-                    2.576, 2.151, 1.851, 1.639, 1.478, 1.358, 1.272, 1.231, 1.218, 1.226, 1.262, 1.335, 1.438, 1.571, 1.766, 2.067,
-                    2.381, 2.005, 1.739, 1.545, 1.389, 1.278, 1.204, 1.166, 1.153, 1.161, 1.194, 1.263, 1.356, 1.489, 1.671, 1.943,
-                    2.242, 1.899, 1.658, 1.481, 1.329, 1.225, 1.156, 1.113, 1.096, 1.107, 1.143, 1.201, 1.289, 1.423, 1.607, 1.861,
-                    2.152, 1.831, 1.602, 1.436, 1.291, 1.193, 1.121, 1.069, 1.047, 1.062, 1.107, 1.166, 1.249, 1.384, 1.562, 1.801,
-                    2.104, 1.795, 1.572, 1.407, 1.269, 1.174, 1.099, 1.041, 1.008, 1.029, 1.083, 1.146, 1.232, 1.364, 1.547, 1.766,
-                    2.104, 1.796, 1.572, 1.403, 1.264, 1.171, 1.097, 1.036, 1.001, 1.025, 1.077, 1.142, 1.231, 1.363, 1.549, 1.766,
-                    2.148, 1.827, 1.594, 1.413, 1.276, 1.184, 1.114, 1.062, 1.033, 1.049, 1.092, 1.153, 1.242, 1.383, 1.577, 1.795,
-                    2.211, 1.881, 1.636, 1.455, 1.309, 1.214, 1.149, 1.104, 1.081, 1.089, 1.125, 1.184, 1.273, 1.423, 1.622, 1.846,
-                    2.319, 1.958, 1.698, 1.516, 1.362, 1.262, 1.203, 1.156, 1.137, 1.142, 1.171, 1.229, 1.331, 1.484, 1.682, 1.933,
-                    2.459, 2.072, 1.789, 1.594, 1.441, 1.331, 1.261, 1.219, 1.199, 1.205, 1.232, 1.301, 1.414, 1.571, 1.773, 2.052,
-                    2.645, 2.206, 1.928, 1.728, 1.559, 1.451, 1.352, 1.301, 1.282, 1.289, 1.319, 1.395, 1.519, 1.685, 1.904, 2.227
+                    2.014, 1.787, 1.516, 1.342, 1.226, 1.143, 1.095, 1.095, 1.095, 1.119, 1.197, 1.295, 1.441, 1.661, 2.015, 2.098,
+                    1.853, 1.631, 1.399, 1.246, 1.153, 1.086, 1.047, 1.038, 1.038, 1.065, 1.133, 1.206, 1.333, 1.527, 1.821, 2.015,
+                    1.748, 1.525, 1.317, 1.177, 1.086, 1.046, 1.019, 1.013, 1.013, 1.031, 1.065, 1.141, 1.259, 1.431, 1.695, 1.827,
+                    1.683, 1.452, 1.261, 1.131, 1.049, 1.019, 1.012, 1.007, 1.007, 1.011, 1.031, 1.097, 1.207, 1.369, 1.611, 1.761,
+                    1.651, 1.407, 1.225, 1.101, 1.031, 1.014, 1.007, 1.003, 1.003, 1.006, 1.017, 1.071, 1.174, 1.329, 1.558, 1.731,
+                    1.649, 1.386, 1.209, 1.088, 1.025, 1.011, 1.003, 1.001, 1.001, 1.005, 1.013, 1.057, 1.158, 1.312, 1.536, 1.728,
+                    1.649, 1.386, 1.209, 1.088, 1.025, 1.011, 1.004, 1.002, 1.002, 1.005, 1.013, 1.057, 1.158, 1.312, 1.536, 1.728,
+                    1.649, 1.403, 1.224, 1.101, 1.031, 1.014, 1.008, 1.004, 1.005, 1.009, 1.017, 1.069, 1.173, 1.332, 1.562, 1.729,
+                    1.679, 1.448, 1.259, 1.131, 1.049, 1.019, 1.013, 1.009, 1.009, 1.015, 1.032, 1.096, 1.207, 1.373, 1.615, 1.758,
+                    1.744, 1.522, 1.315, 1.177, 1.088, 1.047, 1.019, 1.015, 1.016, 1.031, 1.066, 1.141, 1.261, 1.437, 1.696, 1.823,
+                    1.847, 1.627, 1.397, 1.245, 1.145, 1.082, 1.048, 1.039, 1.039, 1.065, 1.118, 1.205, 1.336, 1.529, 1.817, 1.926,
+                    2.001, 1.696, 1.454, 1.291, 1.183, 1.113, 1.076, 1.061, 1.065, 1.097, 1.154, 1.249, 1.381, 1.588, 1.894, 2.089
                 ],
-                "sigma": 0.005,
-                "sigma_Cb": 0.005
+                "sigma": 0.0007,
+                "sigma_Cb": 0.00148
             }
         },
         {
@@ -193,23 +404,181 @@
             }
         },
         {
-            "rpi.sharpen": { }
-        },
-        {
             "rpi.ccm":
             {
                 "ccms": [
                     {
-                        "ct": 3900,
+                        "ct": 2820,
+                        "ccm":
+                        [
+                            1.94275, -0.47725, -0.46549,
+                            -0.80691, 2.51614, -0.70923,
+                            -0.09116, -1.45539, 2.54656
+                        ]
+                    },
+                    {
+                        "ct": 2865,
+                        "ccm":
+                        [
+                            1.94537, -0.55088, -0.39448,
+                            -0.78364, 2.40893, -0.62529,
+                            -0.11215, -1.27981, 2.39196
+                        ]
+                    },
+                    {
+                        "ct": 2895,
+                        "ccm":
+                        [
+                            1.94654, -0.54458, -0.40197,
+                            -0.79315, 2.40489, -0.61174,
+                            -0.10536, -1.29819, 2.40354
+                        ]
+                    },
+                    {
+                        "ct": 2906,
                         "ccm":
                         [
-                            1.54659, -0.17707, -0.36953,
-                            -0.51471, 1.72733, -0.21262,
-                            0.06667, -0.92279, 1.85612
+                            1.97308, -0.59029, -0.38278,
+                            -0.76004, 2.32223, -0.56219,
+                            -0.09668, -1.35448, 2.45116
+                        ]
+                    },
+                    {
+                        "ct": 2918,
+                        "ccm":
+                        [
+                            2.06262, -0.62917, -0.43344,
+                            -0.60088, 2.06833, -0.46745,
+                            -0.02829, -1.76479, 2.79309
+                        ]
+                    },
+                    {
+                        "ct": 3587,
+                        "ccm":
+                        [
+                            1.94164, -0.63474, -0.30689,
+                            -0.66171, 2.20498, -0.54328,
+                            -0.07964, -1.06716, 2.14679
+                        ]
+                    },
+                    {
+                        "ct": 3615,
+                        "ccm":
+                        [
+                            1.96985, -0.66795, -0.30191,
+                            -0.66083, 2.15661, -0.49577,
+                            -0.07616, -1.03297, 2.10913
+                        ]
+                    },
+                    {
+                        "ct": 3620,
+                        "ccm":
+                        [
+                            1.96232, -0.65151, -0.31081,
+                            -0.66289, 2.19357, -0.53068,
+                            -0.07759, -0.99765, 2.07524
+                        ]
+                    },
+                    {
+                        "ct": 3631,
+                        "ccm":
+                        [
+                            1.95443, -0.64347, -0.31095,
+                            -0.66931, 2.21098, -0.54167,
+                            -0.07611, -1.00921, 2.08532
+                        ]
+                    },
+                    {
+                        "ct": 4330,
+                        "ccm":
+                        [
+                            1.94204, -0.70564, -0.23641,
+                            -0.57674, 2.21537, -0.63864,
+                            -0.02472, -0.99615, 2.02087
+                        ]
+                    },
+                    {
+                        "ct": 4490,
+                        "ccm":
+                        [
+                            1.92513, -0.67236, -0.25277,
+                            -0.59381, 2.25314, -0.65933,
+                            -0.03119, -0.89239, 1.92358
+                        ]
+                    },
+                    {
+                        "ct": 4535,
+                        "ccm":
+                        [
+                            1.94867, -0.71843, -0.23024,
+                            -0.58089, 2.22172, -0.64083,
+                            -0.02545, -0.91741, 1.94286
+                        ]
+                    },
+                    {
+                        "ct": 4580,
+                        "ccm":
+                        [
+                            1.95936, -0.72007, -0.23928,
+                            -0.57199, 2.21291, -0.64091,
+                            -0.03954, -0.89568, 1.93523
+                        ]
+                    },
+                    {
+                        "ct": 5640,
+                        "ccm":
+                        [
+                            1.94535, -0.67569, -0.26965,
+                            -0.54101, 2.11492, -0.57391,
+                            -0.07573, -0.72894, 1.80467
+                        ]
+                    },
+                    {
+                        "ct": 5675,
+                        "ccm":
+                        [
+                            1.94758, -0.68616, -0.26142,
+                            -0.53389, 2.10686, -0.57297,
+                            -0.07208, -0.72845, 1.80053
+                        ]
+                    },
+                    {
+                        "ct": 5700,
+                        "ccm":
+                        [
+                            1.93648, -0.66552, -0.27096,
+                            -0.52365, 2.10259, -0.57894,
+                            -0.06974, -0.74559, 1.81533
+                        ]
+                    },
+                    {
+                        "ct": 5750,
+                        "ccm":
+                        [
+                            1.93206, -0.67219, -0.25987,
+                            -0.53541, 2.12308, -0.58766,
+                            -0.07266, -0.71877, 1.79143
+                        ]
+                    },
+                    {
+                        "ct": 6737,
+                        "ccm":
+                        [
+                            1.97325, -0.45639, -0.51685,
+                            -0.55999, 2.58263, -1.02264,
+                            -0.15076, -0.89349, 2.04425
                         ]
                     }
                 ]
             }
+        },
+        {
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         }
     ]
 }
\ No newline at end of file
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx477.json 0.6.0-2/src/ipa/rpi/vc4/data/imx477.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx477.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx477.json	2025-11-27 11:55:28.000000000 +0000
@@ -167,17 +167,17 @@
                             "normal":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 33333 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -680,7 +680,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.hdr":
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx477_noir.json 0.6.0-2/src/ipa/rpi/vc4/data/imx477_noir.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx477_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx477_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -78,17 +78,17 @@
                             "normal":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 33333 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -636,7 +636,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.hdr":
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx477_scientific.json 0.6.0-2/src/ipa/rpi/vc4/data/imx477_scientific.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx477_scientific.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx477_scientific.json	2025-11-27 11:55:28.000000000 +0000
@@ -173,17 +173,17 @@
                     "normal":
                     {
                         "shutter": [ 100, 10000, 30000, 60000, 66666 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                     },
                     "short":
                     {
-                        "shutter": [ 100, 5000, 10000, 20000, 33333 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
+                        "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                     },
                     "long":
                     {
                         "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                     }
                 },
                 "constraint_modes":
@@ -482,7 +482,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         }
     ]
 }
\ No newline at end of file
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx708.json 0.6.0-2/src/ipa/rpi/vc4/data/imx708.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx708.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx708.json	2025-11-27 11:55:28.000000000 +0000
@@ -24,8 +24,8 @@
         {
             "rpi.noise":
             {
-                "reference_constant": 16.0,
-                "reference_slope": 4.0
+                "reference_constant": 0.0,
+                "reference_slope": 2.5
             }
         },
         {
@@ -169,18 +169,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 15000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+                                "shutter": [ 100, 15000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.0, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -611,7 +611,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.af":
@@ -638,11 +643,27 @@
                         "step_coarse": 1.0,
                         "step_fine": 0.25,
                         "contrast_ratio": 0.75,
-                        "pdaf_gain": -0.02,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 10,
+                        "pdaf_gain": -0.016,
                         "pdaf_squelch": 0.125,
-                        "max_slew": 2.0,
+                        "max_slew": 1.5,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
+                        "step_frames": 5
+                    },
+                    "fast":
+                    {
+                        "step_coarse": 1.25,
+                        "step_fine": 0.0,
+                        "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 8,
+                        "pdaf_gain": -0.02,
+                        "pdaf_squelch": 0.125,
+                        "max_slew": 2.0,
+                        "pdaf_frames": 16,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -650,6 +671,7 @@
                 "conf_thresh": 16,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": false,
                 "map": [ 0.0, 445, 15.0, 925 ]
             }
         },
@@ -668,4 +690,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx708_noir.json 0.6.0-2/src/ipa/rpi/vc4/data/imx708_noir.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx708_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx708_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -24,8 +24,8 @@
         {
             "rpi.noise":
             {
-                "reference_constant": 16.0,
-                "reference_slope": 4.0
+                "reference_constant": 0.0,
+                "reference_slope": 2.5
             }
         },
         {
@@ -169,18 +169,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 15000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+                                "shutter": [ 100, 15000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.0, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -710,7 +710,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.af":
@@ -737,11 +742,27 @@
                         "step_coarse": 1.0,
                         "step_fine": 0.25,
                         "contrast_ratio": 0.75,
-                        "pdaf_gain": -0.02,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 10,
+                        "pdaf_gain": -0.016,
                         "pdaf_squelch": 0.125,
-                        "max_slew": 2.0,
+                        "max_slew": 1.5,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
+                        "step_frames": 5
+                    },
+                    "fast":
+                    {
+                        "step_coarse": 1.25,
+                        "step_fine": 0.0,
+                        "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 8,
+                        "pdaf_gain": -0.02,
+                        "pdaf_squelch": 0.125,
+                        "max_slew": 2.0,
+                        "pdaf_frames": 16,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -749,6 +770,7 @@
                 "conf_thresh": 16,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": true,
                 "map": [ 0.0, 445, 15.0, 925 ]
             }
         },
@@ -767,4 +789,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx708_wide.json 0.6.0-2/src/ipa/rpi/vc4/data/imx708_wide.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx708_wide.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx708_wide.json	2025-11-27 11:55:28.000000000 +0000
@@ -24,8 +24,8 @@
         {
             "rpi.noise":
             {
-                "reference_constant": 16.0,
-                "reference_slope": 4.0
+                "reference_constant": 0.0,
+                "reference_slope": 2.5
             }
         },
         {
@@ -159,18 +159,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 15000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+                                "shutter": [ 100, 15000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.0, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -610,7 +610,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.af":
@@ -637,23 +642,27 @@
                         "step_coarse": 2.0,
                         "step_fine": 0.5,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 10,
                         "pdaf_gain": -0.03,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 4.0,
+                        "max_slew": 3.0,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
-                        "step_frames": 4
+                        "step_frames": 5
                     },
                     "fast":
                     {
-                        "step_coarse": 2.0,
-                        "step_fine": 0.5,
+                        "step_coarse": 2.5,
+                        "step_fine": 0.0,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 8,
                         "pdaf_gain": -0.05,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 5.0,
+                        "max_slew": 4.0,
                         "pdaf_frames": 16,
-                        "dropout_frames": 6,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -661,6 +670,7 @@
                 "conf_thresh": 12,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": false,
                 "map": [ 0.0, 420, 35.0, 920 ]
             }
         },
@@ -679,4 +689,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/imx708_wide_noir.json 0.6.0-2/src/ipa/rpi/vc4/data/imx708_wide_noir.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/imx708_wide_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/imx708_wide_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -24,8 +24,8 @@
         {
             "rpi.noise":
             {
-                "reference_constant": 16.0,
-                "reference_slope": 4.0
+                "reference_constant": 0.0,
+                "reference_slope": 2.5
             }
         },
         {
@@ -159,18 +159,18 @@
                         {
                             "normal":
                             {
-                                "shutter": [ 100, 15000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 1.0, 2.0, 4.0, 6.0 ]
+                                "shutter": [ 100, 15000, 30000, 60000, 66666 ],
+                                "gain": [ 1.0, 1.0, 2.0, 4.0, 16.0 ]
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 1000, 30000, 60000, 90000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 16.0 ]
                             }
                         },
                         "constraint_modes":
@@ -601,7 +601,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.af":
@@ -628,23 +633,27 @@
                         "step_coarse": 2.0,
                         "step_fine": 0.5,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 10,
                         "pdaf_gain": -0.03,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 4.0,
+                        "max_slew": 3.0,
                         "pdaf_frames": 20,
                         "dropout_frames": 6,
-                        "step_frames": 4
+                        "step_frames": 5
                     },
                     "fast":
                     {
-                        "step_coarse": 2.0,
-                        "step_fine": 0.5,
+                        "step_coarse": 2.5,
+                        "step_fine": 0.0,
                         "contrast_ratio": 0.75,
+                        "retrigger_ratio": 0.8,
+                        "retrigger_delay": 8,
                         "pdaf_gain": -0.05,
                         "pdaf_squelch": 0.2,
-                        "max_slew": 5.0,
+                        "max_slew": 4.0,
                         "pdaf_frames": 16,
-                        "dropout_frames": 6,
+                        "dropout_frames": 4,
                         "step_frames": 4
                     }
                 },
@@ -652,6 +661,7 @@
                 "conf_thresh": 12,
                 "conf_clip": 512,
                 "skip_frames": 5,
+                "check_for_ir": true,
                 "map": [ 0.0, 420, 35.0, 920 ]
             }
         },
@@ -670,4 +680,4 @@
             }
         }
     ]
-}
\ No newline at end of file
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/meson.build 0.6.0-2/src/ipa/rpi/vc4/data/meson.build
--- 0.5.0-1/src/ipa/rpi/vc4/data/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -8,8 +8,10 @@ conf_files = files([
     'imx296.json',
     'imx296_mono.json',
     'imx327.json',
+    'imx335.json',
     'imx378.json',
     'imx415.json',
+    'imx415_b0569.json',
     'imx462.json',
     'imx477.json',
     'imx477_noir.json',
@@ -26,6 +28,10 @@ conf_files = files([
     'ov9281_mono.json',
     'se327m12.json',
     'uncalibrated.json',
+    'vd55g1.json',
+    'vd55g1_mono.json',
+    'vd56g3.json',
+    'vd56g3_mono.json',
 ])
 
 install_data(conf_files,
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/ov5647.json 0.6.0-2/src/ipa/rpi/vc4/data/ov5647.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/ov5647.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/ov5647.json	2025-11-27 11:55:28.000000000 +0000
@@ -166,13 +166,13 @@
                             },
                             "short":
                             {
-                                "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+                                "shutter": [ 100, 5000, 10000, 20000, 66666 ],
                                 "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
                             },
                             "long":
                             {
                                 "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                                "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
                             }
                         },
                         "constraint_modes":
@@ -676,7 +676,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         },
         {
             "rpi.hdr":
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/ov5647_noir.json 0.6.0-2/src/ipa/rpi/vc4/data/ov5647_noir.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/ov5647_noir.json	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/ov5647_noir.json	2025-11-27 11:55:28.000000000 +0000
@@ -80,13 +80,13 @@
                     },
                     "short":
                     {
-                        "shutter": [ 100, 5000, 10000, 20000, 33333 ],
+                        "shutter": [ 100, 5000, 10000, 20000, 66666 ],
                         "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
                     },
                     "long":
                     {
                         "shutter": [ 100, 10000, 30000, 60000, 120000 ],
-                        "gain": [ 1.0, 2.0, 4.0, 6.0, 12.0 ]
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
                     }
                 },
                 "constraint_modes":
@@ -406,7 +406,12 @@
             }
         },
         {
-            "rpi.sharpen": { }
+            "rpi.sharpen":
+            {
+                "threshold": 0.75,
+                "limit": 0.5,
+                "strength": 1.0
+            }
         }
     ]
 }
\ No newline at end of file
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/vd55g1.json 0.6.0-2/src/ipa/rpi/vc4/data/vd55g1.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/vd55g1.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/vd55g1.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,426 @@
+{
+    "version": 2.0,
+    "target": "bcm2835",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 32138,
+                "reference_gain": 1.23,
+                "reference_aperture": 1.0,
+                "reference_lux": 1060,
+                "reference_Y": 21540
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 20,
+                "reference_slope": 6.825
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 81,
+                "slope": 0.05471
+            }
+        },
+        {
+            "rpi.sdn": { }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 8000
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8600
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    3000.0, 1.1165, 0.3945,
+                    4100.0, 0.9019, 0.5013,
+                    6500.0, 0.6595, 0.7035
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.01,
+                "transverse_neg": 0.01
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "metering_modes":
+                {
+                    "centre-weighted":
+                    {
+                        "weights":
+                        [
+                            3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+                        ]
+                    },
+                    "spot":
+                    {
+                        "weights":
+                        [
+                            2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                        ]
+                    },
+                    "matrix":
+                    {
+                        "weights":
+                        [
+                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                        ]
+                    }
+                },
+                "exposure_modes":
+                {
+                    "normal":
+                    {
+                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    },
+                    "short":
+                    {
+                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    }
+                },
+                "constraint_modes":
+                {
+                    "normal": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        }
+                    ],
+                    "highlight": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        },
+                        {
+                            "bound": "UPPER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.8,
+                                1000, 0.8
+                            ]
+                        }
+                    ]
+                },
+                "y_target":
+                [
+                    0, 0.16,
+                    1000, 0.165,
+                    10000, 0.17
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.001, 1.007, 1.019, 1.024, 1.024, 1.028, 1.028, 1.031, 1.031, 1.032, 1.035, 1.037, 1.037, 1.037, 1.035, 1.032,
+                            1.007, 1.015, 1.025, 1.035, 1.038, 1.039, 1.039, 1.039, 1.042, 1.042, 1.042, 1.044, 1.044, 1.041, 1.036, 1.033,
+                            1.012, 1.024, 1.035, 1.039, 1.044, 1.045, 1.046, 1.046, 1.046, 1.047, 1.047, 1.047, 1.046, 1.044, 1.041, 1.033,
+                            1.017, 1.029, 1.039, 1.044, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.045, 1.041, 1.033,
+                            1.021, 1.032, 1.041, 1.047, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.046, 1.042, 1.032,
+                            1.025, 1.035, 1.043, 1.048, 1.049, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.051, 1.047, 1.042, 1.032,
+                            1.027, 1.036, 1.043, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.054, 1.055, 1.054, 1.053, 1.051, 1.042, 1.032,
+                            1.034, 1.039, 1.045, 1.049, 1.051, 1.052, 1.052, 1.053, 1.054, 1.055, 1.055, 1.056, 1.055, 1.052, 1.044, 1.034,
+                            1.037, 1.044, 1.049, 1.051, 1.051, 1.052, 1.053, 1.053, 1.054, 1.055, 1.056, 1.058, 1.057, 1.054, 1.045, 1.035,
+                            1.041, 1.045, 1.049, 1.051, 1.052, 1.052, 1.053, 1.053, 1.053, 1.053, 1.056, 1.059, 1.059, 1.055, 1.045, 1.035,
+                            1.042, 1.043, 1.049, 1.049, 1.051, 1.051, 1.049, 1.048, 1.048, 1.048, 1.049, 1.057, 1.056, 1.047, 1.038, 1.035,
+                            1.042, 1.042, 1.043, 1.041, 1.042, 1.042, 1.041, 1.039, 1.035, 1.037, 1.041, 1.043, 1.044, 1.043, 1.034, 1.033
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.001, 1.008, 1.026, 1.041, 1.045, 1.049, 1.052, 1.054, 1.058, 1.062, 1.066, 1.067, 1.067, 1.066, 1.065, 1.059,
+                            1.008, 1.024, 1.037, 1.051, 1.057, 1.061, 1.064, 1.066, 1.068, 1.069, 1.071, 1.073, 1.073, 1.069, 1.066, 1.059,
+                            1.023, 1.037, 1.051, 1.057, 1.064, 1.069, 1.069, 1.071, 1.073, 1.075, 1.075, 1.075, 1.074, 1.073, 1.067, 1.059,
+                            1.031, 1.043, 1.057, 1.064, 1.069, 1.072, 1.073, 1.074, 1.076, 1.077, 1.077, 1.076, 1.075, 1.073, 1.066, 1.059,
+                            1.039, 1.049, 1.063, 1.069, 1.073, 1.074, 1.075, 1.077, 1.077, 1.078, 1.078, 1.077, 1.076, 1.071, 1.064, 1.054,
+                            1.044, 1.055, 1.064, 1.072, 1.074, 1.076, 1.077, 1.078, 1.078, 1.078, 1.078, 1.077, 1.076, 1.071, 1.061, 1.049,
+                            1.049, 1.061, 1.069, 1.074, 1.077, 1.078, 1.078, 1.079, 1.079, 1.079, 1.079, 1.078, 1.077, 1.071, 1.059, 1.048,
+                            1.057, 1.063, 1.072, 1.076, 1.078, 1.079, 1.079, 1.079, 1.079, 1.081, 1.079, 1.079, 1.076, 1.071, 1.056, 1.041,
+                            1.061, 1.067, 1.074, 1.077, 1.078, 1.079, 1.079, 1.079, 1.079, 1.081, 1.079, 1.079, 1.075, 1.069, 1.053, 1.039,
+                            1.064, 1.071, 1.075, 1.077, 1.077, 1.078, 1.077, 1.077, 1.077, 1.078, 1.078, 1.075, 1.069, 1.061, 1.052, 1.039,
+                            1.064, 1.071, 1.074, 1.076, 1.075, 1.074, 1.072, 1.071, 1.067, 1.066, 1.068, 1.068, 1.064, 1.052, 1.038, 1.027,
+                            1.064, 1.069, 1.072, 1.071, 1.071, 1.064, 1.061, 1.059, 1.055, 1.053, 1.057, 1.054, 1.051, 1.041, 1.027, 1.025
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.001, 1.012, 1.029, 1.046, 1.053, 1.057, 1.062, 1.065, 1.067, 1.073, 1.077, 1.085, 1.092, 1.094, 1.099, 1.101,
+                            1.012, 1.028, 1.042, 1.054, 1.061, 1.064, 1.065, 1.067, 1.071, 1.075, 1.077, 1.084, 1.089, 1.093, 1.094, 1.093,
+                            1.023, 1.038, 1.054, 1.061, 1.065, 1.066, 1.067, 1.068, 1.071, 1.074, 1.077, 1.081, 1.085, 1.089, 1.091, 1.084,
+                            1.035, 1.048, 1.059, 1.065, 1.067, 1.067, 1.067, 1.068, 1.069, 1.072, 1.075, 1.078, 1.081, 1.082, 1.082, 1.076,
+                            1.045, 1.053, 1.062, 1.066, 1.067, 1.067, 1.067, 1.066, 1.067, 1.071, 1.073, 1.075, 1.078, 1.078, 1.076, 1.071,
+                            1.053, 1.062, 1.067, 1.068, 1.068, 1.068, 1.067, 1.067, 1.067, 1.069, 1.073, 1.075, 1.077, 1.077, 1.071, 1.066,
+                            1.062, 1.067, 1.071, 1.071, 1.071, 1.069, 1.068, 1.068, 1.069, 1.071, 1.074, 1.075, 1.077, 1.076, 1.066, 1.059,
+                            1.068, 1.074, 1.078, 1.078, 1.076, 1.074, 1.072, 1.071, 1.071, 1.074, 1.075, 1.076, 1.077, 1.074, 1.064, 1.052,
+                            1.081, 1.084, 1.084, 1.083, 1.081, 1.079, 1.076, 1.076, 1.074, 1.074, 1.076, 1.076, 1.076, 1.073, 1.062, 1.049,
+                            1.094, 1.095, 1.093, 1.091, 1.086, 1.081, 1.079, 1.076, 1.074, 1.074, 1.074, 1.076, 1.073, 1.063, 1.057, 1.047,
+                            1.105, 1.103, 1.098, 1.094, 1.091, 1.086, 1.078, 1.076, 1.071, 1.066, 1.065, 1.064, 1.062, 1.057, 1.041, 1.031,
+                            1.108, 1.106, 1.102, 1.097, 1.091, 1.085, 1.077, 1.071, 1.065, 1.059, 1.054, 1.053, 1.053, 1.047, 1.031, 1.025
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.045, 1.066, 1.103, 1.134, 1.161, 1.176, 1.192, 1.204, 1.212, 1.226, 1.232, 1.239, 1.242, 1.241, 1.239, 1.228,
+                            1.066, 1.094, 1.132, 1.151, 1.176, 1.192, 1.204, 1.212, 1.224, 1.231, 1.239, 1.246, 1.245, 1.242, 1.236, 1.228,
+                            1.091, 1.116, 1.151, 1.176, 1.194, 1.208, 1.215, 1.224, 1.233, 1.239, 1.247, 1.249, 1.247, 1.243, 1.229, 1.223,
+                            1.113, 1.131, 1.167, 1.194, 1.208, 1.216, 1.226, 1.232, 1.239, 1.246, 1.249, 1.249, 1.247, 1.239, 1.223, 1.209,
+                            1.131, 1.151, 1.181, 1.204, 1.215, 1.225, 1.229, 1.233, 1.241, 1.247, 1.248, 1.248, 1.243, 1.235, 1.209, 1.196,
+                            1.148, 1.165, 1.189, 1.211, 1.219, 1.227, 1.229, 1.232, 1.239, 1.245, 1.247, 1.244, 1.235, 1.219, 1.196, 1.177,
+                            1.162, 1.178, 1.199, 1.214, 1.221, 1.224, 1.229, 1.231, 1.234, 1.239, 1.237, 1.233, 1.224, 1.208, 1.177, 1.155,
+                            1.173, 1.183, 1.201, 1.213, 1.219, 1.222, 1.223, 1.228, 1.229, 1.232, 1.231, 1.224, 1.208, 1.188, 1.155, 1.127,
+                            1.177, 1.187, 1.201, 1.211, 1.214, 1.219, 1.219, 1.218, 1.218, 1.218, 1.215, 1.205, 1.188, 1.155, 1.127, 1.094,
+                            1.182, 1.186, 1.198, 1.202, 1.209, 1.211, 1.202, 1.201, 1.197, 1.191, 1.182, 1.175, 1.155, 1.127, 1.091, 1.061,
+                            1.182, 1.186, 1.191, 1.198, 1.199, 1.189, 1.184, 1.175, 1.165, 1.156, 1.142, 1.136, 1.111, 1.088, 1.047, 1.014,
+                            1.182, 1.185, 1.187, 1.189, 1.189, 1.184, 1.175, 1.165, 1.154, 1.133, 1.125, 1.109, 1.089, 1.047, 1.014, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.018, 1.036, 1.056, 1.076, 1.091, 1.096, 1.103, 1.113, 1.117, 1.122, 1.126, 1.128, 1.129, 1.129, 1.125, 1.121,
+                            1.033, 1.053, 1.071, 1.086, 1.096, 1.107, 1.115, 1.119, 1.123, 1.126, 1.129, 1.132, 1.132, 1.129, 1.126, 1.121,
+                            1.041, 1.062, 1.083, 1.096, 1.107, 1.116, 1.121, 1.125, 1.128, 1.131, 1.136, 1.136, 1.135, 1.132, 1.125, 1.121,
+                            1.051, 1.067, 1.091, 1.106, 1.115, 1.121, 1.126, 1.127, 1.131, 1.135, 1.138, 1.139, 1.136, 1.134, 1.124, 1.119,
+                            1.062, 1.077, 1.097, 1.112, 1.118, 1.123, 1.127, 1.129, 1.133, 1.136, 1.141, 1.141, 1.138, 1.133, 1.121, 1.111,
+                            1.069, 1.083, 1.101, 1.115, 1.119, 1.124, 1.127, 1.128, 1.133, 1.135, 1.141, 1.141, 1.138, 1.129, 1.113, 1.107,
+                            1.081, 1.092, 1.102, 1.115, 1.119, 1.121, 1.126, 1.128, 1.132, 1.134, 1.136, 1.138, 1.133, 1.127, 1.109, 1.097,
+                            1.085, 1.093, 1.103, 1.113, 1.118, 1.121, 1.121, 1.126, 1.129, 1.132, 1.132, 1.132, 1.127, 1.115, 1.097, 1.081,
+                            1.089, 1.094, 1.102, 1.109, 1.113, 1.118, 1.119, 1.119, 1.126, 1.128, 1.128, 1.125, 1.115, 1.099, 1.081, 1.059,
+                            1.091, 1.095, 1.099, 1.105, 1.109, 1.112, 1.112, 1.111, 1.111, 1.113, 1.112, 1.108, 1.099, 1.081, 1.057, 1.035,
+                            1.092, 1.095, 1.098, 1.101, 1.102, 1.099, 1.097, 1.096, 1.091, 1.089, 1.085, 1.077, 1.071, 1.052, 1.029, 1.005,
+                            1.092, 1.095, 1.098, 1.098, 1.098, 1.096, 1.092, 1.089, 1.082, 1.075, 1.071, 1.062, 1.049, 1.029, 1.005, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.004, 1.015, 1.021, 1.031, 1.033, 1.033, 1.034, 1.038, 1.041, 1.043, 1.045, 1.048, 1.048, 1.048, 1.046, 1.044,
+                            1.009, 1.019, 1.029, 1.033, 1.039, 1.041, 1.043, 1.046, 1.047, 1.049, 1.049, 1.049, 1.051, 1.049, 1.048, 1.045,
+                            1.009, 1.021, 1.031, 1.039, 1.041, 1.046, 1.048, 1.051, 1.053, 1.056, 1.057, 1.057, 1.055, 1.052, 1.049, 1.046,
+                            1.014, 1.022, 1.034, 1.041, 1.047, 1.049, 1.051, 1.055, 1.057, 1.059, 1.059, 1.059, 1.058, 1.057, 1.051, 1.048,
+                            1.014, 1.024, 1.035, 1.045, 1.047, 1.051, 1.053, 1.055, 1.059, 1.062, 1.064, 1.064, 1.061, 1.059, 1.053, 1.048,
+                            1.016, 1.027, 1.036, 1.046, 1.048, 1.051, 1.053, 1.055, 1.062, 1.066, 1.066, 1.066, 1.064, 1.061, 1.055, 1.048,
+                            1.018, 1.028, 1.036, 1.044, 1.046, 1.049, 1.051, 1.055, 1.062, 1.065, 1.066, 1.066, 1.065, 1.062, 1.055, 1.046,
+                            1.019, 1.028, 1.034, 1.039, 1.045, 1.048, 1.049, 1.053, 1.059, 1.064, 1.066, 1.065, 1.064, 1.059, 1.051, 1.043,
+                            1.019, 1.026, 1.032, 1.038, 1.043, 1.045, 1.048, 1.049, 1.054, 1.059, 1.064, 1.064, 1.059, 1.053, 1.044, 1.036,
+                            1.019, 1.023, 1.029, 1.036, 1.038, 1.042, 1.045, 1.047, 1.049, 1.052, 1.054, 1.054, 1.053, 1.044, 1.033, 1.022,
+                            1.021, 1.024, 1.028, 1.032, 1.035, 1.036, 1.036, 1.037, 1.039, 1.039, 1.037, 1.037, 1.036, 1.028, 1.018, 1.005,
+                            1.022, 1.025, 1.026, 1.031, 1.032, 1.031, 1.031, 1.032, 1.031, 1.031, 1.031, 1.024, 1.024, 1.013, 1.005, 1.001
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    1.749, 1.701, 1.554, 1.445, 1.359, 1.311, 1.277, 1.261, 1.255, 1.252, 1.256, 1.271, 1.302, 1.351, 1.407, 1.429,
+                    1.701, 1.554, 1.442, 1.352, 1.291, 1.247, 1.208, 1.187, 1.177, 1.175, 1.188, 1.209, 1.241, 1.292, 1.348, 1.403,
+                    1.536, 1.421, 1.325, 1.255, 1.203, 1.166, 1.136, 1.119, 1.113, 1.115, 1.131, 1.155, 1.188, 1.229, 1.288, 1.335,
+                    1.411, 1.319, 1.247, 1.191, 1.142, 1.105, 1.079, 1.064, 1.059, 1.074, 1.093, 1.116, 1.149, 1.195, 1.249, 1.298,
+                    1.318, 1.258, 1.191, 1.136, 1.096, 1.062, 1.042, 1.028, 1.032, 1.046, 1.066, 1.092, 1.125, 1.171, 1.233, 1.284,
+                    1.259, 1.209, 1.144, 1.096, 1.062, 1.041, 1.021, 1.011, 1.015, 1.025, 1.052, 1.079, 1.114, 1.165, 1.232, 1.284,
+                    1.231, 1.182, 1.125, 1.079, 1.046, 1.031, 1.013, 1.006, 1.007, 1.019, 1.043, 1.076, 1.119, 1.175, 1.248, 1.298,
+                    1.214, 1.167, 1.112, 1.069, 1.042, 1.026, 1.017, 1.007, 1.008, 1.029, 1.054, 1.091, 1.137, 1.202, 1.289, 1.356,
+                    1.205, 1.155, 1.108, 1.073, 1.048, 1.031, 1.018, 1.016, 1.023, 1.045, 1.082, 1.125, 1.183, 1.256, 1.355, 1.432,
+                    1.218, 1.167, 1.131, 1.091, 1.064, 1.043, 1.033, 1.029, 1.045, 1.076, 1.119, 1.175, 1.243, 1.339, 1.437, 1.537,
+                    1.251, 1.193, 1.161, 1.128, 1.099, 1.083, 1.068, 1.069, 1.085, 1.126, 1.181, 1.242, 1.334, 1.437, 1.558, 1.675,
+                    1.262, 1.244, 1.185, 1.158, 1.134, 1.115, 1.111, 1.112, 1.127, 1.179, 1.236, 1.326, 1.419, 1.527, 1.675, 1.709
+                ],
+                "sigma": 0.00295,
+                "sigma_Cb": 0.00457
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.80909, -0.38313, -0.42596,
+                            -0.41239, 1.92703, -0.51463,
+                            0.13887, -1.15693, 2.01806
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "ccm":
+                        [
+                            1.72337, -0.44225, -0.28112,
+                            -0.33186, 1.74819, -0.41633,
+                            0.03269, -0.69284, 1.66014
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            1.65983, -0.32804, -0.33179,
+                            -0.22463, 1.80614, -0.58151,
+                            0.00516, -0.60942, 1.60425
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.sharpen": { }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/vd55g1_mono.json 0.6.0-2/src/ipa/rpi/vc4/data/vd55g1_mono.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/vd55g1_mono.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/vd55g1_mono.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,299 @@
+{
+    "version": 2.0,
+    "target": "bcm2835",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 32138,
+                "reference_gain": 1.23,
+                "reference_aperture": 1.0,
+                "reference_lux": 1060,
+                "reference_Y": 21540
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 20,
+                "reference_slope": 6.825
+            }
+        },
+        {
+            "rpi.sdn": { }
+        },
+        {
+            "rpi.agc":
+            {
+                "metering_modes":
+                {
+                    "centre-weighted":
+                    {
+                        "weights":
+                        [
+                            3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0
+                        ]
+                    },
+                    "spot":
+                    {
+                        "weights":
+                        [
+                            2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+                        ]
+                    },
+                    "matrix":
+                    {
+                        "weights":
+                        [
+                            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+                        ]
+                    }
+                },
+                "exposure_modes":
+                {
+                    "normal":
+                    {
+                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    },
+                    "short":
+                    {
+                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    }
+                },
+                "constraint_modes":
+                {
+                    "normal": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        }
+                    ],
+                    "highlight": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        },
+                        {
+                            "bound": "UPPER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.8,
+                                1000, 0.8
+                            ]
+                        }
+                    ]
+                },
+                "y_target":
+                [
+                    0, 0.16,
+                    1000, 0.165,
+                    10000, 0.17
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.8,
+                "calibrations_Cr": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.001, 1.007, 1.019, 1.024, 1.024, 1.028, 1.028, 1.031, 1.031, 1.032, 1.035, 1.037, 1.037, 1.037, 1.035, 1.032,
+                            1.007, 1.015, 1.025, 1.035, 1.038, 1.039, 1.039, 1.039, 1.042, 1.042, 1.042, 1.044, 1.044, 1.041, 1.036, 1.033,
+                            1.012, 1.024, 1.035, 1.039, 1.044, 1.045, 1.046, 1.046, 1.046, 1.047, 1.047, 1.047, 1.046, 1.044, 1.041, 1.033,
+                            1.017, 1.029, 1.039, 1.044, 1.048, 1.049, 1.049, 1.049, 1.049, 1.049, 1.049, 1.048, 1.047, 1.045, 1.041, 1.033,
+                            1.021, 1.032, 1.041, 1.047, 1.049, 1.049, 1.051, 1.051, 1.051, 1.051, 1.051, 1.049, 1.048, 1.046, 1.042, 1.032,
+                            1.025, 1.035, 1.043, 1.048, 1.049, 1.051, 1.051, 1.052, 1.052, 1.052, 1.052, 1.052, 1.051, 1.047, 1.042, 1.032,
+                            1.027, 1.036, 1.043, 1.048, 1.049, 1.051, 1.052, 1.053, 1.053, 1.054, 1.055, 1.054, 1.053, 1.051, 1.042, 1.032,
+                            1.034, 1.039, 1.045, 1.049, 1.051, 1.052, 1.052, 1.053, 1.054, 1.055, 1.055, 1.056, 1.055, 1.052, 1.044, 1.034,
+                            1.037, 1.044, 1.049, 1.051, 1.051, 1.052, 1.053, 1.053, 1.054, 1.055, 1.056, 1.058, 1.057, 1.054, 1.045, 1.035,
+                            1.041, 1.045, 1.049, 1.051, 1.052, 1.052, 1.053, 1.053, 1.053, 1.053, 1.056, 1.059, 1.059, 1.055, 1.045, 1.035,
+                            1.042, 1.043, 1.049, 1.049, 1.051, 1.051, 1.049, 1.048, 1.048, 1.048, 1.049, 1.057, 1.056, 1.047, 1.038, 1.035,
+                            1.042, 1.042, 1.043, 1.041, 1.042, 1.042, 1.041, 1.039, 1.035, 1.037, 1.041, 1.043, 1.044, 1.043, 1.034, 1.033
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.001, 1.008, 1.026, 1.041, 1.045, 1.049, 1.052, 1.054, 1.058, 1.062, 1.066, 1.067, 1.067, 1.066, 1.065, 1.059,
+                            1.008, 1.024, 1.037, 1.051, 1.057, 1.061, 1.064, 1.066, 1.068, 1.069, 1.071, 1.073, 1.073, 1.069, 1.066, 1.059,
+                            1.023, 1.037, 1.051, 1.057, 1.064, 1.069, 1.069, 1.071, 1.073, 1.075, 1.075, 1.075, 1.074, 1.073, 1.067, 1.059,
+                            1.031, 1.043, 1.057, 1.064, 1.069, 1.072, 1.073, 1.074, 1.076, 1.077, 1.077, 1.076, 1.075, 1.073, 1.066, 1.059,
+                            1.039, 1.049, 1.063, 1.069, 1.073, 1.074, 1.075, 1.077, 1.077, 1.078, 1.078, 1.077, 1.076, 1.071, 1.064, 1.054,
+                            1.044, 1.055, 1.064, 1.072, 1.074, 1.076, 1.077, 1.078, 1.078, 1.078, 1.078, 1.077, 1.076, 1.071, 1.061, 1.049,
+                            1.049, 1.061, 1.069, 1.074, 1.077, 1.078, 1.078, 1.079, 1.079, 1.079, 1.079, 1.078, 1.077, 1.071, 1.059, 1.048,
+                            1.057, 1.063, 1.072, 1.076, 1.078, 1.079, 1.079, 1.079, 1.079, 1.081, 1.079, 1.079, 1.076, 1.071, 1.056, 1.041,
+                            1.061, 1.067, 1.074, 1.077, 1.078, 1.079, 1.079, 1.079, 1.079, 1.081, 1.079, 1.079, 1.075, 1.069, 1.053, 1.039,
+                            1.064, 1.071, 1.075, 1.077, 1.077, 1.078, 1.077, 1.077, 1.077, 1.078, 1.078, 1.075, 1.069, 1.061, 1.052, 1.039,
+                            1.064, 1.071, 1.074, 1.076, 1.075, 1.074, 1.072, 1.071, 1.067, 1.066, 1.068, 1.068, 1.064, 1.052, 1.038, 1.027,
+                            1.064, 1.069, 1.072, 1.071, 1.071, 1.064, 1.061, 1.059, 1.055, 1.053, 1.057, 1.054, 1.051, 1.041, 1.027, 1.025
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.001, 1.012, 1.029, 1.046, 1.053, 1.057, 1.062, 1.065, 1.067, 1.073, 1.077, 1.085, 1.092, 1.094, 1.099, 1.101,
+                            1.012, 1.028, 1.042, 1.054, 1.061, 1.064, 1.065, 1.067, 1.071, 1.075, 1.077, 1.084, 1.089, 1.093, 1.094, 1.093,
+                            1.023, 1.038, 1.054, 1.061, 1.065, 1.066, 1.067, 1.068, 1.071, 1.074, 1.077, 1.081, 1.085, 1.089, 1.091, 1.084,
+                            1.035, 1.048, 1.059, 1.065, 1.067, 1.067, 1.067, 1.068, 1.069, 1.072, 1.075, 1.078, 1.081, 1.082, 1.082, 1.076,
+                            1.045, 1.053, 1.062, 1.066, 1.067, 1.067, 1.067, 1.066, 1.067, 1.071, 1.073, 1.075, 1.078, 1.078, 1.076, 1.071,
+                            1.053, 1.062, 1.067, 1.068, 1.068, 1.068, 1.067, 1.067, 1.067, 1.069, 1.073, 1.075, 1.077, 1.077, 1.071, 1.066,
+                            1.062, 1.067, 1.071, 1.071, 1.071, 1.069, 1.068, 1.068, 1.069, 1.071, 1.074, 1.075, 1.077, 1.076, 1.066, 1.059,
+                            1.068, 1.074, 1.078, 1.078, 1.076, 1.074, 1.072, 1.071, 1.071, 1.074, 1.075, 1.076, 1.077, 1.074, 1.064, 1.052,
+                            1.081, 1.084, 1.084, 1.083, 1.081, 1.079, 1.076, 1.076, 1.074, 1.074, 1.076, 1.076, 1.076, 1.073, 1.062, 1.049,
+                            1.094, 1.095, 1.093, 1.091, 1.086, 1.081, 1.079, 1.076, 1.074, 1.074, 1.074, 1.076, 1.073, 1.063, 1.057, 1.047,
+                            1.105, 1.103, 1.098, 1.094, 1.091, 1.086, 1.078, 1.076, 1.071, 1.066, 1.065, 1.064, 1.062, 1.057, 1.041, 1.031,
+                            1.108, 1.106, 1.102, 1.097, 1.091, 1.085, 1.077, 1.071, 1.065, 1.059, 1.054, 1.053, 1.053, 1.047, 1.031, 1.025
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            1.045, 1.066, 1.103, 1.134, 1.161, 1.176, 1.192, 1.204, 1.212, 1.226, 1.232, 1.239, 1.242, 1.241, 1.239, 1.228,
+                            1.066, 1.094, 1.132, 1.151, 1.176, 1.192, 1.204, 1.212, 1.224, 1.231, 1.239, 1.246, 1.245, 1.242, 1.236, 1.228,
+                            1.091, 1.116, 1.151, 1.176, 1.194, 1.208, 1.215, 1.224, 1.233, 1.239, 1.247, 1.249, 1.247, 1.243, 1.229, 1.223,
+                            1.113, 1.131, 1.167, 1.194, 1.208, 1.216, 1.226, 1.232, 1.239, 1.246, 1.249, 1.249, 1.247, 1.239, 1.223, 1.209,
+                            1.131, 1.151, 1.181, 1.204, 1.215, 1.225, 1.229, 1.233, 1.241, 1.247, 1.248, 1.248, 1.243, 1.235, 1.209, 1.196,
+                            1.148, 1.165, 1.189, 1.211, 1.219, 1.227, 1.229, 1.232, 1.239, 1.245, 1.247, 1.244, 1.235, 1.219, 1.196, 1.177,
+                            1.162, 1.178, 1.199, 1.214, 1.221, 1.224, 1.229, 1.231, 1.234, 1.239, 1.237, 1.233, 1.224, 1.208, 1.177, 1.155,
+                            1.173, 1.183, 1.201, 1.213, 1.219, 1.222, 1.223, 1.228, 1.229, 1.232, 1.231, 1.224, 1.208, 1.188, 1.155, 1.127,
+                            1.177, 1.187, 1.201, 1.211, 1.214, 1.219, 1.219, 1.218, 1.218, 1.218, 1.215, 1.205, 1.188, 1.155, 1.127, 1.094,
+                            1.182, 1.186, 1.198, 1.202, 1.209, 1.211, 1.202, 1.201, 1.197, 1.191, 1.182, 1.175, 1.155, 1.127, 1.091, 1.061,
+                            1.182, 1.186, 1.191, 1.198, 1.199, 1.189, 1.184, 1.175, 1.165, 1.156, 1.142, 1.136, 1.111, 1.088, 1.047, 1.014,
+                            1.182, 1.185, 1.187, 1.189, 1.189, 1.184, 1.175, 1.165, 1.154, 1.133, 1.125, 1.109, 1.089, 1.047, 1.014, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 4100,
+                        "table":
+                        [
+                            1.018, 1.036, 1.056, 1.076, 1.091, 1.096, 1.103, 1.113, 1.117, 1.122, 1.126, 1.128, 1.129, 1.129, 1.125, 1.121,
+                            1.033, 1.053, 1.071, 1.086, 1.096, 1.107, 1.115, 1.119, 1.123, 1.126, 1.129, 1.132, 1.132, 1.129, 1.126, 1.121,
+                            1.041, 1.062, 1.083, 1.096, 1.107, 1.116, 1.121, 1.125, 1.128, 1.131, 1.136, 1.136, 1.135, 1.132, 1.125, 1.121,
+                            1.051, 1.067, 1.091, 1.106, 1.115, 1.121, 1.126, 1.127, 1.131, 1.135, 1.138, 1.139, 1.136, 1.134, 1.124, 1.119,
+                            1.062, 1.077, 1.097, 1.112, 1.118, 1.123, 1.127, 1.129, 1.133, 1.136, 1.141, 1.141, 1.138, 1.133, 1.121, 1.111,
+                            1.069, 1.083, 1.101, 1.115, 1.119, 1.124, 1.127, 1.128, 1.133, 1.135, 1.141, 1.141, 1.138, 1.129, 1.113, 1.107,
+                            1.081, 1.092, 1.102, 1.115, 1.119, 1.121, 1.126, 1.128, 1.132, 1.134, 1.136, 1.138, 1.133, 1.127, 1.109, 1.097,
+                            1.085, 1.093, 1.103, 1.113, 1.118, 1.121, 1.121, 1.126, 1.129, 1.132, 1.132, 1.132, 1.127, 1.115, 1.097, 1.081,
+                            1.089, 1.094, 1.102, 1.109, 1.113, 1.118, 1.119, 1.119, 1.126, 1.128, 1.128, 1.125, 1.115, 1.099, 1.081, 1.059,
+                            1.091, 1.095, 1.099, 1.105, 1.109, 1.112, 1.112, 1.111, 1.111, 1.113, 1.112, 1.108, 1.099, 1.081, 1.057, 1.035,
+                            1.092, 1.095, 1.098, 1.101, 1.102, 1.099, 1.097, 1.096, 1.091, 1.089, 1.085, 1.077, 1.071, 1.052, 1.029, 1.005,
+                            1.092, 1.095, 1.098, 1.098, 1.098, 1.096, 1.092, 1.089, 1.082, 1.075, 1.071, 1.062, 1.049, 1.029, 1.005, 1.001
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.004, 1.015, 1.021, 1.031, 1.033, 1.033, 1.034, 1.038, 1.041, 1.043, 1.045, 1.048, 1.048, 1.048, 1.046, 1.044,
+                            1.009, 1.019, 1.029, 1.033, 1.039, 1.041, 1.043, 1.046, 1.047, 1.049, 1.049, 1.049, 1.051, 1.049, 1.048, 1.045,
+                            1.009, 1.021, 1.031, 1.039, 1.041, 1.046, 1.048, 1.051, 1.053, 1.056, 1.057, 1.057, 1.055, 1.052, 1.049, 1.046,
+                            1.014, 1.022, 1.034, 1.041, 1.047, 1.049, 1.051, 1.055, 1.057, 1.059, 1.059, 1.059, 1.058, 1.057, 1.051, 1.048,
+                            1.014, 1.024, 1.035, 1.045, 1.047, 1.051, 1.053, 1.055, 1.059, 1.062, 1.064, 1.064, 1.061, 1.059, 1.053, 1.048,
+                            1.016, 1.027, 1.036, 1.046, 1.048, 1.051, 1.053, 1.055, 1.062, 1.066, 1.066, 1.066, 1.064, 1.061, 1.055, 1.048,
+                            1.018, 1.028, 1.036, 1.044, 1.046, 1.049, 1.051, 1.055, 1.062, 1.065, 1.066, 1.066, 1.065, 1.062, 1.055, 1.046,
+                            1.019, 1.028, 1.034, 1.039, 1.045, 1.048, 1.049, 1.053, 1.059, 1.064, 1.066, 1.065, 1.064, 1.059, 1.051, 1.043,
+                            1.019, 1.026, 1.032, 1.038, 1.043, 1.045, 1.048, 1.049, 1.054, 1.059, 1.064, 1.064, 1.059, 1.053, 1.044, 1.036,
+                            1.019, 1.023, 1.029, 1.036, 1.038, 1.042, 1.045, 1.047, 1.049, 1.052, 1.054, 1.054, 1.053, 1.044, 1.033, 1.022,
+                            1.021, 1.024, 1.028, 1.032, 1.035, 1.036, 1.036, 1.037, 1.039, 1.039, 1.037, 1.037, 1.036, 1.028, 1.018, 1.005,
+                            1.022, 1.025, 1.026, 1.031, 1.032, 1.031, 1.031, 1.032, 1.031, 1.031, 1.031, 1.024, 1.024, 1.013, 1.005, 1.001
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    1.749, 1.701, 1.554, 1.445, 1.359, 1.311, 1.277, 1.261, 1.255, 1.252, 1.256, 1.271, 1.302, 1.351, 1.407, 1.429,
+                    1.701, 1.554, 1.442, 1.352, 1.291, 1.247, 1.208, 1.187, 1.177, 1.175, 1.188, 1.209, 1.241, 1.292, 1.348, 1.403,
+                    1.536, 1.421, 1.325, 1.255, 1.203, 1.166, 1.136, 1.119, 1.113, 1.115, 1.131, 1.155, 1.188, 1.229, 1.288, 1.335,
+                    1.411, 1.319, 1.247, 1.191, 1.142, 1.105, 1.079, 1.064, 1.059, 1.074, 1.093, 1.116, 1.149, 1.195, 1.249, 1.298,
+                    1.318, 1.258, 1.191, 1.136, 1.096, 1.062, 1.042, 1.028, 1.032, 1.046, 1.066, 1.092, 1.125, 1.171, 1.233, 1.284,
+                    1.259, 1.209, 1.144, 1.096, 1.062, 1.041, 1.021, 1.011, 1.015, 1.025, 1.052, 1.079, 1.114, 1.165, 1.232, 1.284,
+                    1.231, 1.182, 1.125, 1.079, 1.046, 1.031, 1.013, 1.006, 1.007, 1.019, 1.043, 1.076, 1.119, 1.175, 1.248, 1.298,
+                    1.214, 1.167, 1.112, 1.069, 1.042, 1.026, 1.017, 1.007, 1.008, 1.029, 1.054, 1.091, 1.137, 1.202, 1.289, 1.356,
+                    1.205, 1.155, 1.108, 1.073, 1.048, 1.031, 1.018, 1.016, 1.023, 1.045, 1.082, 1.125, 1.183, 1.256, 1.355, 1.432,
+                    1.218, 1.167, 1.131, 1.091, 1.064, 1.043, 1.033, 1.029, 1.045, 1.076, 1.119, 1.175, 1.243, 1.339, 1.437, 1.537,
+                    1.251, 1.193, 1.161, 1.128, 1.099, 1.083, 1.068, 1.069, 1.085, 1.126, 1.181, 1.242, 1.334, 1.437, 1.558, 1.675,
+                    1.262, 1.244, 1.185, 1.158, 1.134, 1.115, 1.111, 1.112, 1.127, 1.179, 1.236, 1.326, 1.419, 1.527, 1.675, 1.709
+                ],
+                "sigma": 0.00295,
+                "sigma_Cb": 0.00457
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.sharpen": { }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/vd56g3.json 0.6.0-2/src/ipa/rpi/vc4/data/vd56g3.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/vd56g3.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/vd56g3.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,417 @@
+{
+    "version": 2.0,
+    "target": "bcm2835",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 17247,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 1090,
+                "reference_Y": 24531
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 3.289
+            }
+        },
+        {
+            "rpi.geq":
+            {
+                "offset": 762,
+                "slope": 0.02394
+            }
+        },
+        {
+            "rpi.sdn": { }
+        },
+        {
+            "rpi.awb":
+            {
+                "priors": [
+                    {
+                        "lux": 0,
+                        "prior":
+                        [
+                            2000, 1.0,
+                            3000, 0.0,
+                            13000, 0.0
+                        ]
+                    },
+                    {
+                        "lux": 800,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            6000, 2.0,
+                            13000, 2.0
+                        ]
+                    },
+                    {
+                        "lux": 1500,
+                        "prior":
+                        [
+                            2000, 0.0,
+                            4000, 1.0,
+                            6000, 6.0,
+                            6500, 7.0,
+                            7000, 1.0,
+                            13000, 1.0
+                        ]
+                    }
+                ],
+                "modes":
+                {
+                    "auto":
+                    {
+                        "lo": 2500,
+                        "hi": 8000
+                    },
+                    "incandescent":
+                    {
+                        "lo": 2500,
+                        "hi": 3000
+                    },
+                    "tungsten":
+                    {
+                        "lo": 3000,
+                        "hi": 3500
+                    },
+                    "fluorescent":
+                    {
+                        "lo": 4000,
+                        "hi": 4700
+                    },
+                    "indoor":
+                    {
+                        "lo": 3000,
+                        "hi": 5000
+                    },
+                    "daylight":
+                    {
+                        "lo": 5500,
+                        "hi": 6500
+                    },
+                    "cloudy":
+                    {
+                        "lo": 7000,
+                        "hi": 8600
+                    }
+                },
+                "bayes": 1,
+                "ct_curve":
+                [
+                    3000.0, 1.1702, 0.4424,
+                    4000.0, 0.9551, 0.5528,
+                    6500.0, 0.7007, 0.7375
+                ],
+                "sensitivity_r": 1.0,
+                "sensitivity_b": 1.0,
+                "transverse_pos": 0.01,
+                "transverse_neg": 0.01
+            }
+        },
+        {
+            "rpi.agc":
+            {
+                "metering_modes":
+                {
+                    "centre-weighted":
+                    {
+                        "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+                    },
+                    "spot":
+                    {
+                        "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+                    },
+                    "matrix":
+                    {
+                        "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+                    }
+                },
+                "exposure_modes":
+                {
+                    "normal":
+                    {
+                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    },
+                    "short":
+                    {
+                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    }
+                },
+                "constraint_modes":
+                {
+                    "normal": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        }
+                    ],
+                    "highlight": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        },
+                        {
+                            "bound": "UPPER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.8,
+                                1000, 0.8
+                            ]
+                        }
+                    ]
+                },
+                "y_target":
+                [
+                    0, 0.16,
+                    1000, 0.165,
+                    10000, 0.17
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.5,
+                "calibrations_Cr": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            0.792, 0.798, 0.799, 0.803, 0.806, 0.808, 0.809, 0.809, 0.807, 0.803, 0.801, 0.798, 0.796, 0.795, 0.794, 0.792,
+                            0.801, 0.801, 0.802, 0.809, 0.812, 0.816, 0.818, 0.818, 0.818, 0.816, 0.814, 0.813, 0.811, 0.809, 0.806, 0.803,
+                            0.806, 0.806, 0.809, 0.813, 0.817, 0.823, 0.824, 0.826, 0.826, 0.825, 0.822, 0.819, 0.818, 0.817, 0.816, 0.814,
+                            0.808, 0.809, 0.813, 0.817, 0.823, 0.825, 0.828, 0.831, 0.831, 0.829, 0.827, 0.825, 0.824, 0.825, 0.825, 0.825,
+                            0.809, 0.811, 0.815, 0.821, 0.825, 0.828, 0.831, 0.832, 0.832, 0.832, 0.831, 0.831, 0.831, 0.832, 0.834, 0.835,
+                            0.809, 0.811, 0.816, 0.821, 0.826, 0.829, 0.832, 0.832, 0.835, 0.834, 0.833, 0.832, 0.833, 0.834, 0.836, 0.837,
+                            0.809, 0.809, 0.816, 0.821, 0.826, 0.829, 0.832, 0.834, 0.835, 0.834, 0.833, 0.832, 0.833, 0.835, 0.836, 0.836,
+                            0.804, 0.805, 0.811, 0.817, 0.821, 0.826, 0.829, 0.832, 0.833, 0.832, 0.831, 0.831, 0.831, 0.832, 0.834, 0.833,
+                            0.796, 0.797, 0.804, 0.811, 0.817, 0.821, 0.824, 0.829, 0.829, 0.827, 0.827, 0.826, 0.827, 0.829, 0.829, 0.829,
+                            0.788, 0.788, 0.796, 0.803, 0.809, 0.814, 0.817, 0.821, 0.821, 0.821, 0.819, 0.819, 0.821, 0.825, 0.827, 0.827,
+                            0.775, 0.777, 0.784, 0.791, 0.797, 0.802, 0.806, 0.811, 0.813, 0.813, 0.812, 0.813, 0.816, 0.818, 0.819, 0.819,
+                            0.767, 0.774, 0.777, 0.784, 0.791, 0.797, 0.802, 0.806, 0.809, 0.811, 0.811, 0.812, 0.812, 0.816, 0.816, 0.816
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.009, 1.013, 1.018, 1.027, 1.034, 1.038, 1.038, 1.038, 1.037, 1.032, 1.026, 1.018, 1.011, 1.005, 0.999, 0.991,
+                            1.012, 1.015, 1.023, 1.032, 1.041, 1.045, 1.051, 1.052, 1.052, 1.047, 1.042, 1.035, 1.029, 1.023, 1.016, 1.006,
+                            1.015, 1.018, 1.027, 1.037, 1.044, 1.051, 1.056, 1.058, 1.058, 1.055, 1.051, 1.044, 1.041, 1.036, 1.032, 1.028,
+                            1.014, 1.021, 1.029, 1.037, 1.045, 1.052, 1.057, 1.061, 1.061, 1.058, 1.054, 1.051, 1.049, 1.047, 1.045, 1.042,
+                            1.012, 1.018, 1.029, 1.039, 1.046, 1.053, 1.056, 1.059, 1.061, 1.059, 1.058, 1.055, 1.055, 1.054, 1.055, 1.055,
+                            1.011, 1.014, 1.027, 1.036, 1.046, 1.052, 1.057, 1.059, 1.061, 1.061, 1.059, 1.057, 1.057, 1.058, 1.058, 1.058,
+                            1.006, 1.011, 1.024, 1.035, 1.044, 1.051, 1.056, 1.058, 1.061, 1.061, 1.058, 1.057, 1.057, 1.057, 1.058, 1.058,
+                            0.998, 1.006, 1.017, 1.028, 1.038, 1.046, 1.051, 1.056, 1.058, 1.057, 1.055, 1.055, 1.055, 1.056, 1.056, 1.054,
+                            0.988, 0.994, 1.006, 1.018, 1.028, 1.038, 1.046, 1.051, 1.051, 1.051, 1.049, 1.048, 1.049, 1.049, 1.051, 1.051,
+                            0.972, 0.979, 0.993, 1.006, 1.018, 1.027, 1.033, 1.039, 1.041, 1.041, 1.039, 1.039, 1.041, 1.044, 1.046, 1.046,
+                            0.954, 0.962, 0.977, 0.989, 1.001, 1.011, 1.018, 1.024, 1.029, 1.032, 1.032, 1.032, 1.033, 1.035, 1.038, 1.039,
+                            0.944, 0.954, 0.962, 0.977, 0.989, 1.001, 1.011, 1.018, 1.024, 1.024, 1.026, 1.027, 1.029, 1.029, 1.029, 1.029
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.288, 1.292, 1.304, 1.324, 1.339, 1.348, 1.349, 1.348, 1.347, 1.339, 1.326, 1.314, 1.302, 1.287, 1.274, 1.261,
+                            1.292, 1.304, 1.322, 1.334, 1.349, 1.359, 1.368, 1.368, 1.364, 1.361, 1.352, 1.337, 1.327, 1.315, 1.303, 1.289,
+                            1.305, 1.312, 1.332, 1.348, 1.359, 1.371, 1.379, 1.385, 1.385, 1.379, 1.373, 1.363, 1.354, 1.347, 1.335, 1.327,
+                            1.312, 1.321, 1.337, 1.357, 1.369, 1.379, 1.387, 1.396, 1.397, 1.395, 1.389, 1.381, 1.376, 1.373, 1.371, 1.365,
+                            1.319, 1.328, 1.343, 1.361, 1.377, 1.387, 1.396, 1.399, 1.403, 1.403, 1.399, 1.395, 1.394, 1.394, 1.395, 1.397,
+                            1.319, 1.328, 1.345, 1.365, 1.379, 1.391, 1.399, 1.403, 1.411, 1.411, 1.409, 1.406, 1.406, 1.408, 1.411, 1.409,
+                            1.317, 1.326, 1.345, 1.365, 1.379, 1.391, 1.401, 1.408, 1.411, 1.412, 1.411, 1.409, 1.409, 1.413, 1.416, 1.419,
+                            1.308, 1.319, 1.339, 1.359, 1.375, 1.389, 1.399, 1.405, 1.409, 1.411, 1.409, 1.409, 1.409, 1.415, 1.418, 1.419,
+                            1.291, 1.308, 1.328, 1.351, 1.366, 1.381, 1.391, 1.401, 1.405, 1.405, 1.405, 1.406, 1.408, 1.412, 1.417, 1.419,
+                            1.272, 1.291, 1.311, 1.331, 1.353, 1.369, 1.381, 1.391, 1.396, 1.397, 1.398, 1.402, 1.404, 1.411, 1.415, 1.417,
+                            1.247, 1.272, 1.291, 1.316, 1.338, 1.354, 1.369, 1.381, 1.388, 1.391, 1.394, 1.395, 1.399, 1.404, 1.411, 1.415,
+                            1.247, 1.247, 1.274, 1.296, 1.319, 1.341, 1.355, 1.369, 1.381, 1.389, 1.389, 1.394, 1.395, 1.401, 1.405, 1.406
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            2.614, 2.679, 2.791, 2.891, 2.984, 3.058, 3.058, 3.058, 3.056, 3.005, 2.933, 2.848, 2.764, 2.672, 2.575, 2.484,
+                            2.659, 2.754, 2.869, 2.975, 3.053, 3.142, 3.178, 3.178, 3.159, 3.106, 3.037, 2.963, 2.874, 2.784, 2.686, 2.605,
+                            2.687, 2.805, 2.933, 3.053, 3.142, 3.192, 3.267, 3.267, 3.264, 3.231, 3.179, 3.116, 3.042, 2.963, 2.878, 2.808,
+                            2.718, 2.847, 2.969, 3.091, 3.192, 3.267, 3.295, 3.341, 3.341, 3.331, 3.278, 3.238, 3.187, 3.127, 3.064, 3.012,
+                            2.722, 2.877, 2.993, 3.117, 3.216, 3.295, 3.341, 3.369, 3.386, 3.381, 3.352, 3.324, 3.281, 3.249, 3.207, 3.157,
+                            2.722, 2.877, 3.007, 3.128, 3.237, 3.314, 3.369, 3.396, 3.417, 3.401, 3.381, 3.358, 3.331, 3.303, 3.278, 3.255,
+                            2.722, 2.872, 3.007, 3.128, 3.237, 3.316, 3.378, 3.416, 3.419, 3.418, 3.396, 3.374, 3.357, 3.329, 3.309, 3.295,
+                            2.708, 2.855, 2.989, 3.117, 3.225, 3.312, 3.378, 3.401, 3.418, 3.403, 3.395, 3.374, 3.358, 3.335, 3.309, 3.301,
+                            2.686, 2.807, 2.941, 3.083, 3.193, 3.281, 3.333, 3.378, 3.395, 3.395, 3.381, 3.362, 3.345, 3.323, 3.305, 3.288,
+                            2.636, 2.731, 2.877, 3.011, 3.129, 3.221, 3.281, 3.333, 3.352, 3.352, 3.333, 3.323, 3.301, 3.295, 3.272, 3.253,
+                            2.547, 2.651, 2.781, 2.931, 3.039, 3.129, 3.221, 3.271, 3.284, 3.284, 3.275, 3.261, 3.255, 3.229, 3.199, 3.185,
+                            2.483, 2.547, 2.671, 2.809, 2.942, 3.041, 3.138, 3.191, 3.207, 3.207, 3.207, 3.192, 3.172, 3.156, 3.149, 3.118
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            2.129, 2.159, 2.221, 2.281, 2.333, 2.368, 2.368, 2.368, 2.358, 2.331, 2.293, 2.243, 2.193, 2.144, 2.087, 2.036,
+                            2.151, 2.211, 2.274, 2.326, 2.372, 2.416, 2.435, 2.435, 2.419, 2.391, 2.356, 2.313, 2.267, 2.217, 2.166, 2.113,
+                            2.183, 2.242, 2.306, 2.368, 2.423, 2.456, 2.481, 2.487, 2.487, 2.471, 2.441, 2.406, 2.373, 2.329, 2.286, 2.248,
+                            2.201, 2.273, 2.338, 2.404, 2.456, 2.492, 2.519, 2.537, 2.537, 2.529, 2.508, 2.484, 2.456, 2.429, 2.396, 2.371,
+                            2.206, 2.291, 2.359, 2.425, 2.481, 2.518, 2.547, 2.561, 2.566, 2.564, 2.551, 2.534, 2.517, 2.497, 2.478, 2.459,
+                            2.206, 2.294, 2.367, 2.435, 2.489, 2.533, 2.561, 2.576, 2.588, 2.581, 2.571, 2.559, 2.548, 2.533, 2.528, 2.509,
+                            2.206, 2.295, 2.367, 2.439, 2.498, 2.539, 2.573, 2.591, 2.594, 2.591, 2.581, 2.571, 2.561, 2.552, 2.543, 2.534,
+                            2.203, 2.289, 2.366, 2.439, 2.498, 2.539, 2.573, 2.591, 2.594, 2.592, 2.581, 2.575, 2.566, 2.559, 2.549, 2.544,
+                            2.193, 2.271, 2.344, 2.419, 2.485, 2.531, 2.565, 2.577, 2.591, 2.586, 2.577, 2.573, 2.563, 2.554, 2.545, 2.543,
+                            2.171, 2.229, 2.312, 2.393, 2.459, 2.505, 2.533, 2.565, 2.569, 2.569, 2.564, 2.553, 2.548, 2.535, 2.531, 2.527,
+                            2.117, 2.179, 2.262, 2.343, 2.414, 2.461, 2.505, 2.532, 2.539, 2.539, 2.532, 2.524, 2.515, 2.511, 2.501, 2.493,
+                            2.077, 2.117, 2.201, 2.287, 2.365, 2.417, 2.468, 2.499, 2.503, 2.503, 2.503, 2.497, 2.491, 2.479, 2.468, 2.456
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.576, 1.602, 1.624, 1.648, 1.664, 1.674, 1.674, 1.673, 1.663, 1.651, 1.633, 1.611, 1.593, 1.568, 1.544, 1.521,
+                            1.583, 1.609, 1.635, 1.659, 1.671, 1.676, 1.684, 1.687, 1.676, 1.664, 1.651, 1.634, 1.614, 1.594, 1.568, 1.551,
+                            1.583, 1.611, 1.637, 1.661, 1.676, 1.684, 1.689, 1.692, 1.691, 1.679, 1.669, 1.661, 1.648, 1.633, 1.617, 1.597,
+                            1.583, 1.611, 1.636, 1.659, 1.674, 1.684, 1.692, 1.695, 1.694, 1.691, 1.682, 1.677, 1.668, 1.661, 1.652, 1.639,
+                            1.578, 1.607, 1.631, 1.653, 1.669, 1.683, 1.693, 1.695, 1.696, 1.692, 1.687, 1.683, 1.678, 1.676, 1.672, 1.668,
+                            1.574, 1.604, 1.628, 1.651, 1.669, 1.683, 1.693, 1.697, 1.697, 1.694, 1.689, 1.686, 1.685, 1.683, 1.682, 1.681,
+                            1.568, 1.602, 1.629, 1.653, 1.671, 1.683, 1.694, 1.698, 1.698, 1.696, 1.689, 1.687, 1.687, 1.687, 1.687, 1.684,
+                            1.567, 1.599, 1.628, 1.654, 1.671, 1.687, 1.697, 1.699, 1.699, 1.697, 1.691, 1.688, 1.688, 1.689, 1.689, 1.687,
+                            1.564, 1.598, 1.628, 1.654, 1.671, 1.687, 1.697, 1.699, 1.699, 1.695, 1.691, 1.689, 1.689, 1.688, 1.687, 1.686,
+                            1.556, 1.582, 1.619, 1.646, 1.667, 1.682, 1.689, 1.694, 1.695, 1.691, 1.689, 1.687, 1.684, 1.684, 1.683, 1.684,
+                            1.539, 1.567, 1.597, 1.629, 1.653, 1.667, 1.682, 1.687, 1.687, 1.684, 1.681, 1.679, 1.679, 1.674, 1.674, 1.673,
+                            1.523, 1.539, 1.581, 1.612, 1.639, 1.656, 1.671, 1.681, 1.683, 1.681, 1.679, 1.675, 1.671, 1.666, 1.665, 1.661
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    2.049, 1.919, 1.821, 1.752, 1.701, 1.665, 1.647, 1.645, 1.645, 1.646, 1.651, 1.668, 1.697, 1.741, 1.802, 1.887,
+                    1.873, 1.746, 1.626, 1.534, 1.468, 1.423, 1.393, 1.377, 1.375, 1.378, 1.396, 1.424, 1.465, 1.523, 1.605, 1.711,
+                    1.653, 1.538, 1.427, 1.349, 1.291, 1.251, 1.225, 1.207, 1.206, 1.211, 1.231, 1.261, 1.299, 1.351, 1.423, 1.517,
+                    1.518, 1.433, 1.328, 1.235, 1.179, 1.141, 1.113, 1.098, 1.098, 1.102, 1.125, 1.155, 1.195, 1.245, 1.321, 1.399,
+                    1.426, 1.347, 1.249, 1.191, 1.139, 1.085, 1.047, 1.029, 1.029, 1.034, 1.058, 1.097, 1.147, 1.205, 1.259, 1.323,
+                    1.429, 1.339, 1.237, 1.161, 1.102, 1.058, 1.033, 1.015, 1.001, 1.023, 1.039, 1.069, 1.111, 1.164, 1.232, 1.309,
+                    1.442, 1.347, 1.244, 1.168, 1.119, 1.083, 1.049, 1.017, 1.004, 1.025, 1.062, 1.092, 1.125, 1.169, 1.238, 1.317,
+                    1.533, 1.422, 1.335, 1.244, 1.168, 1.119, 1.086, 1.067, 1.067, 1.071, 1.094, 1.125, 1.169, 1.238, 1.301, 1.371,
+                    1.669, 1.539, 1.422, 1.337, 1.274, 1.228, 1.196, 1.174, 1.172, 1.172, 1.191, 1.218, 1.252, 1.301, 1.377, 1.468,
+                    1.891, 1.748, 1.616, 1.524, 1.453, 1.401, 1.365, 1.341, 1.329, 1.329, 1.341, 1.364, 1.399, 1.446, 1.514, 1.608,
+                    2.245, 2.074, 1.925, 1.815, 1.733, 1.673, 1.626, 1.595, 1.573, 1.571, 1.571, 1.589, 1.624, 1.677, 1.736, 1.841,
+                    2.532, 2.348, 2.221, 2.124, 2.051, 1.994, 1.946, 1.912, 1.892, 1.889, 1.889, 1.889, 1.902, 1.929, 1.981, 2.058
+                ],
+                "sigma": 0.0041,
+                "sigma_Cb": 0.01178
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.ccm":
+            {
+                "ccms": [
+                    {
+                        "ct": 3000,
+                        "ccm":
+                        [
+                            1.65876, -0.24897, -0.40979,
+                            -0.49453, 1.89553, -0.40099,
+                            0.03049, -1.01729, 1.98679
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "ccm":
+                        [
+                            1.64934, -0.37359, -0.27574,
+                            -0.39441, 1.73642, -0.34201,
+                            -0.00897, -0.68344, 1.69241
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "ccm":
+                        [
+                            1.64354, -0.39984, -0.24369,
+                            -0.23773, 1.66846, -0.43072,
+                            0.01321, -0.65019, 1.63698
+                        ]
+                    }
+                ]
+            }
+        },
+        {
+            "rpi.sharpen": { }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/data/vd56g3_mono.json 0.6.0-2/src/ipa/rpi/vc4/data/vd56g3_mono.json
--- 0.5.0-1/src/ipa/rpi/vc4/data/vd56g3_mono.json	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/data/vd56g3_mono.json	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,290 @@
+{
+    "version": 2.0,
+    "target": "bcm2835",
+    "algorithms": [
+        {
+            "rpi.black_level":
+            {
+                "black_level": 4096
+            }
+        },
+        {
+            "rpi.lux":
+            {
+                "reference_shutter_speed": 17247,
+                "reference_gain": 1.0,
+                "reference_aperture": 1.0,
+                "reference_lux": 1090,
+                "reference_Y": 24531
+            }
+        },
+        {
+            "rpi.noise":
+            {
+                "reference_constant": 0,
+                "reference_slope": 3.289
+            }
+        },
+        {
+            "rpi.sdn": { }
+        },
+        {
+            "rpi.agc":
+            {
+                "metering_modes":
+                {
+                    "centre-weighted":
+                    {
+                        "weights": [ 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0 ]
+                    },
+                    "spot":
+                    {
+                        "weights": [ 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
+                    },
+                    "matrix":
+                    {
+                        "weights": [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
+                    }
+                },
+                "exposure_modes":
+                {
+                    "normal":
+                    {
+                        "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    },
+                    "short":
+                    {
+                        "shutter": [ 100, 5000, 10000, 20000, 120000 ],
+                        "gain": [ 1.0, 2.0, 4.0, 6.0, 6.0 ]
+                    }
+                },
+                "constraint_modes":
+                {
+                    "normal": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        }
+                    ],
+                    "highlight": [
+                        {
+                            "bound": "LOWER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.5,
+                                1000, 0.5
+                            ]
+                        },
+                        {
+                            "bound": "UPPER",
+                            "q_lo": 0.98,
+                            "q_hi": 1.0,
+                            "y_target":
+                            [
+                                0, 0.8,
+                                1000, 0.8
+                            ]
+                        }
+                    ]
+                },
+                "y_target":
+                [
+                    0, 0.16,
+                    1000, 0.165,
+                    10000, 0.17
+                ]
+            }
+        },
+        {
+            "rpi.alsc":
+            {
+                "omega": 1.3,
+                "n_iter": 100,
+                "luminance_strength": 0.5,
+                "calibrations_Cr": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            0.792, 0.798, 0.799, 0.803, 0.806, 0.808, 0.809, 0.809, 0.807, 0.803, 0.801, 0.798, 0.796, 0.795, 0.794, 0.792,
+                            0.801, 0.801, 0.802, 0.809, 0.812, 0.816, 0.818, 0.818, 0.818, 0.816, 0.814, 0.813, 0.811, 0.809, 0.806, 0.803,
+                            0.806, 0.806, 0.809, 0.813, 0.817, 0.823, 0.824, 0.826, 0.826, 0.825, 0.822, 0.819, 0.818, 0.817, 0.816, 0.814,
+                            0.808, 0.809, 0.813, 0.817, 0.823, 0.825, 0.828, 0.831, 0.831, 0.829, 0.827, 0.825, 0.824, 0.825, 0.825, 0.825,
+                            0.809, 0.811, 0.815, 0.821, 0.825, 0.828, 0.831, 0.832, 0.832, 0.832, 0.831, 0.831, 0.831, 0.832, 0.834, 0.835,
+                            0.809, 0.811, 0.816, 0.821, 0.826, 0.829, 0.832, 0.832, 0.835, 0.834, 0.833, 0.832, 0.833, 0.834, 0.836, 0.837,
+                            0.809, 0.809, 0.816, 0.821, 0.826, 0.829, 0.832, 0.834, 0.835, 0.834, 0.833, 0.832, 0.833, 0.835, 0.836, 0.836,
+                            0.804, 0.805, 0.811, 0.817, 0.821, 0.826, 0.829, 0.832, 0.833, 0.832, 0.831, 0.831, 0.831, 0.832, 0.834, 0.833,
+                            0.796, 0.797, 0.804, 0.811, 0.817, 0.821, 0.824, 0.829, 0.829, 0.827, 0.827, 0.826, 0.827, 0.829, 0.829, 0.829,
+                            0.788, 0.788, 0.796, 0.803, 0.809, 0.814, 0.817, 0.821, 0.821, 0.821, 0.819, 0.819, 0.821, 0.825, 0.827, 0.827,
+                            0.775, 0.777, 0.784, 0.791, 0.797, 0.802, 0.806, 0.811, 0.813, 0.813, 0.812, 0.813, 0.816, 0.818, 0.819, 0.819,
+                            0.767, 0.774, 0.777, 0.784, 0.791, 0.797, 0.802, 0.806, 0.809, 0.811, 0.811, 0.812, 0.812, 0.816, 0.816, 0.816
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            1.009, 1.013, 1.018, 1.027, 1.034, 1.038, 1.038, 1.038, 1.037, 1.032, 1.026, 1.018, 1.011, 1.005, 0.999, 0.991,
+                            1.012, 1.015, 1.023, 1.032, 1.041, 1.045, 1.051, 1.052, 1.052, 1.047, 1.042, 1.035, 1.029, 1.023, 1.016, 1.006,
+                            1.015, 1.018, 1.027, 1.037, 1.044, 1.051, 1.056, 1.058, 1.058, 1.055, 1.051, 1.044, 1.041, 1.036, 1.032, 1.028,
+                            1.014, 1.021, 1.029, 1.037, 1.045, 1.052, 1.057, 1.061, 1.061, 1.058, 1.054, 1.051, 1.049, 1.047, 1.045, 1.042,
+                            1.012, 1.018, 1.029, 1.039, 1.046, 1.053, 1.056, 1.059, 1.061, 1.059, 1.058, 1.055, 1.055, 1.054, 1.055, 1.055,
+                            1.011, 1.014, 1.027, 1.036, 1.046, 1.052, 1.057, 1.059, 1.061, 1.061, 1.059, 1.057, 1.057, 1.058, 1.058, 1.058,
+                            1.006, 1.011, 1.024, 1.035, 1.044, 1.051, 1.056, 1.058, 1.061, 1.061, 1.058, 1.057, 1.057, 1.057, 1.058, 1.058,
+                            0.998, 1.006, 1.017, 1.028, 1.038, 1.046, 1.051, 1.056, 1.058, 1.057, 1.055, 1.055, 1.055, 1.056, 1.056, 1.054,
+                            0.988, 0.994, 1.006, 1.018, 1.028, 1.038, 1.046, 1.051, 1.051, 1.051, 1.049, 1.048, 1.049, 1.049, 1.051, 1.051,
+                            0.972, 0.979, 0.993, 1.006, 1.018, 1.027, 1.033, 1.039, 1.041, 1.041, 1.039, 1.039, 1.041, 1.044, 1.046, 1.046,
+                            0.954, 0.962, 0.977, 0.989, 1.001, 1.011, 1.018, 1.024, 1.029, 1.032, 1.032, 1.032, 1.033, 1.035, 1.038, 1.039,
+                            0.944, 0.954, 0.962, 0.977, 0.989, 1.001, 1.011, 1.018, 1.024, 1.024, 1.026, 1.027, 1.029, 1.029, 1.029, 1.029
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.288, 1.292, 1.304, 1.324, 1.339, 1.348, 1.349, 1.348, 1.347, 1.339, 1.326, 1.314, 1.302, 1.287, 1.274, 1.261,
+                            1.292, 1.304, 1.322, 1.334, 1.349, 1.359, 1.368, 1.368, 1.364, 1.361, 1.352, 1.337, 1.327, 1.315, 1.303, 1.289,
+                            1.305, 1.312, 1.332, 1.348, 1.359, 1.371, 1.379, 1.385, 1.385, 1.379, 1.373, 1.363, 1.354, 1.347, 1.335, 1.327,
+                            1.312, 1.321, 1.337, 1.357, 1.369, 1.379, 1.387, 1.396, 1.397, 1.395, 1.389, 1.381, 1.376, 1.373, 1.371, 1.365,
+                            1.319, 1.328, 1.343, 1.361, 1.377, 1.387, 1.396, 1.399, 1.403, 1.403, 1.399, 1.395, 1.394, 1.394, 1.395, 1.397,
+                            1.319, 1.328, 1.345, 1.365, 1.379, 1.391, 1.399, 1.403, 1.411, 1.411, 1.409, 1.406, 1.406, 1.408, 1.411, 1.409,
+                            1.317, 1.326, 1.345, 1.365, 1.379, 1.391, 1.401, 1.408, 1.411, 1.412, 1.411, 1.409, 1.409, 1.413, 1.416, 1.419,
+                            1.308, 1.319, 1.339, 1.359, 1.375, 1.389, 1.399, 1.405, 1.409, 1.411, 1.409, 1.409, 1.409, 1.415, 1.418, 1.419,
+                            1.291, 1.308, 1.328, 1.351, 1.366, 1.381, 1.391, 1.401, 1.405, 1.405, 1.405, 1.406, 1.408, 1.412, 1.417, 1.419,
+                            1.272, 1.291, 1.311, 1.331, 1.353, 1.369, 1.381, 1.391, 1.396, 1.397, 1.398, 1.402, 1.404, 1.411, 1.415, 1.417,
+                            1.247, 1.272, 1.291, 1.316, 1.338, 1.354, 1.369, 1.381, 1.388, 1.391, 1.394, 1.395, 1.399, 1.404, 1.411, 1.415,
+                            1.247, 1.247, 1.274, 1.296, 1.319, 1.341, 1.355, 1.369, 1.381, 1.389, 1.389, 1.394, 1.395, 1.401, 1.405, 1.406
+                        ]
+                    }
+                ],
+                "calibrations_Cb": [
+                    {
+                        "ct": 3000,
+                        "table":
+                        [
+                            2.614, 2.679, 2.791, 2.891, 2.984, 3.058, 3.058, 3.058, 3.056, 3.005, 2.933, 2.848, 2.764, 2.672, 2.575, 2.484,
+                            2.659, 2.754, 2.869, 2.975, 3.053, 3.142, 3.178, 3.178, 3.159, 3.106, 3.037, 2.963, 2.874, 2.784, 2.686, 2.605,
+                            2.687, 2.805, 2.933, 3.053, 3.142, 3.192, 3.267, 3.267, 3.264, 3.231, 3.179, 3.116, 3.042, 2.963, 2.878, 2.808,
+                            2.718, 2.847, 2.969, 3.091, 3.192, 3.267, 3.295, 3.341, 3.341, 3.331, 3.278, 3.238, 3.187, 3.127, 3.064, 3.012,
+                            2.722, 2.877, 2.993, 3.117, 3.216, 3.295, 3.341, 3.369, 3.386, 3.381, 3.352, 3.324, 3.281, 3.249, 3.207, 3.157,
+                            2.722, 2.877, 3.007, 3.128, 3.237, 3.314, 3.369, 3.396, 3.417, 3.401, 3.381, 3.358, 3.331, 3.303, 3.278, 3.255,
+                            2.722, 2.872, 3.007, 3.128, 3.237, 3.316, 3.378, 3.416, 3.419, 3.418, 3.396, 3.374, 3.357, 3.329, 3.309, 3.295,
+                            2.708, 2.855, 2.989, 3.117, 3.225, 3.312, 3.378, 3.401, 3.418, 3.403, 3.395, 3.374, 3.358, 3.335, 3.309, 3.301,
+                            2.686, 2.807, 2.941, 3.083, 3.193, 3.281, 3.333, 3.378, 3.395, 3.395, 3.381, 3.362, 3.345, 3.323, 3.305, 3.288,
+                            2.636, 2.731, 2.877, 3.011, 3.129, 3.221, 3.281, 3.333, 3.352, 3.352, 3.333, 3.323, 3.301, 3.295, 3.272, 3.253,
+                            2.547, 2.651, 2.781, 2.931, 3.039, 3.129, 3.221, 3.271, 3.284, 3.284, 3.275, 3.261, 3.255, 3.229, 3.199, 3.185,
+                            2.483, 2.547, 2.671, 2.809, 2.942, 3.041, 3.138, 3.191, 3.207, 3.207, 3.207, 3.192, 3.172, 3.156, 3.149, 3.118
+                        ]
+                    },
+                    {
+                        "ct": 4000,
+                        "table":
+                        [
+                            2.129, 2.159, 2.221, 2.281, 2.333, 2.368, 2.368, 2.368, 2.358, 2.331, 2.293, 2.243, 2.193, 2.144, 2.087, 2.036,
+                            2.151, 2.211, 2.274, 2.326, 2.372, 2.416, 2.435, 2.435, 2.419, 2.391, 2.356, 2.313, 2.267, 2.217, 2.166, 2.113,
+                            2.183, 2.242, 2.306, 2.368, 2.423, 2.456, 2.481, 2.487, 2.487, 2.471, 2.441, 2.406, 2.373, 2.329, 2.286, 2.248,
+                            2.201, 2.273, 2.338, 2.404, 2.456, 2.492, 2.519, 2.537, 2.537, 2.529, 2.508, 2.484, 2.456, 2.429, 2.396, 2.371,
+                            2.206, 2.291, 2.359, 2.425, 2.481, 2.518, 2.547, 2.561, 2.566, 2.564, 2.551, 2.534, 2.517, 2.497, 2.478, 2.459,
+                            2.206, 2.294, 2.367, 2.435, 2.489, 2.533, 2.561, 2.576, 2.588, 2.581, 2.571, 2.559, 2.548, 2.533, 2.528, 2.509,
+                            2.206, 2.295, 2.367, 2.439, 2.498, 2.539, 2.573, 2.591, 2.594, 2.591, 2.581, 2.571, 2.561, 2.552, 2.543, 2.534,
+                            2.203, 2.289, 2.366, 2.439, 2.498, 2.539, 2.573, 2.591, 2.594, 2.592, 2.581, 2.575, 2.566, 2.559, 2.549, 2.544,
+                            2.193, 2.271, 2.344, 2.419, 2.485, 2.531, 2.565, 2.577, 2.591, 2.586, 2.577, 2.573, 2.563, 2.554, 2.545, 2.543,
+                            2.171, 2.229, 2.312, 2.393, 2.459, 2.505, 2.533, 2.565, 2.569, 2.569, 2.564, 2.553, 2.548, 2.535, 2.531, 2.527,
+                            2.117, 2.179, 2.262, 2.343, 2.414, 2.461, 2.505, 2.532, 2.539, 2.539, 2.532, 2.524, 2.515, 2.511, 2.501, 2.493,
+                            2.077, 2.117, 2.201, 2.287, 2.365, 2.417, 2.468, 2.499, 2.503, 2.503, 2.503, 2.497, 2.491, 2.479, 2.468, 2.456
+                        ]
+                    },
+                    {
+                        "ct": 6500,
+                        "table":
+                        [
+                            1.576, 1.602, 1.624, 1.648, 1.664, 1.674, 1.674, 1.673, 1.663, 1.651, 1.633, 1.611, 1.593, 1.568, 1.544, 1.521,
+                            1.583, 1.609, 1.635, 1.659, 1.671, 1.676, 1.684, 1.687, 1.676, 1.664, 1.651, 1.634, 1.614, 1.594, 1.568, 1.551,
+                            1.583, 1.611, 1.637, 1.661, 1.676, 1.684, 1.689, 1.692, 1.691, 1.679, 1.669, 1.661, 1.648, 1.633, 1.617, 1.597,
+                            1.583, 1.611, 1.636, 1.659, 1.674, 1.684, 1.692, 1.695, 1.694, 1.691, 1.682, 1.677, 1.668, 1.661, 1.652, 1.639,
+                            1.578, 1.607, 1.631, 1.653, 1.669, 1.683, 1.693, 1.695, 1.696, 1.692, 1.687, 1.683, 1.678, 1.676, 1.672, 1.668,
+                            1.574, 1.604, 1.628, 1.651, 1.669, 1.683, 1.693, 1.697, 1.697, 1.694, 1.689, 1.686, 1.685, 1.683, 1.682, 1.681,
+                            1.568, 1.602, 1.629, 1.653, 1.671, 1.683, 1.694, 1.698, 1.698, 1.696, 1.689, 1.687, 1.687, 1.687, 1.687, 1.684,
+                            1.567, 1.599, 1.628, 1.654, 1.671, 1.687, 1.697, 1.699, 1.699, 1.697, 1.691, 1.688, 1.688, 1.689, 1.689, 1.687,
+                            1.564, 1.598, 1.628, 1.654, 1.671, 1.687, 1.697, 1.699, 1.699, 1.695, 1.691, 1.689, 1.689, 1.688, 1.687, 1.686,
+                            1.556, 1.582, 1.619, 1.646, 1.667, 1.682, 1.689, 1.694, 1.695, 1.691, 1.689, 1.687, 1.684, 1.684, 1.683, 1.684,
+                            1.539, 1.567, 1.597, 1.629, 1.653, 1.667, 1.682, 1.687, 1.687, 1.684, 1.681, 1.679, 1.679, 1.674, 1.674, 1.673,
+                            1.523, 1.539, 1.581, 1.612, 1.639, 1.656, 1.671, 1.681, 1.683, 1.681, 1.679, 1.675, 1.671, 1.666, 1.665, 1.661
+                        ]
+                    }
+                ],
+                "luminance_lut":
+                [
+                    2.049, 1.919, 1.821, 1.752, 1.701, 1.665, 1.647, 1.645, 1.645, 1.646, 1.651, 1.668, 1.697, 1.741, 1.802, 1.887,
+                    1.873, 1.746, 1.626, 1.534, 1.468, 1.423, 1.393, 1.377, 1.375, 1.378, 1.396, 1.424, 1.465, 1.523, 1.605, 1.711,
+                    1.653, 1.538, 1.427, 1.349, 1.291, 1.251, 1.225, 1.207, 1.206, 1.211, 1.231, 1.261, 1.299, 1.351, 1.423, 1.517,
+                    1.518, 1.433, 1.328, 1.235, 1.179, 1.141, 1.113, 1.098, 1.098, 1.102, 1.125, 1.155, 1.195, 1.245, 1.321, 1.399,
+                    1.426, 1.347, 1.249, 1.191, 1.139, 1.085, 1.047, 1.029, 1.029, 1.034, 1.058, 1.097, 1.147, 1.205, 1.259, 1.323,
+                    1.429, 1.339, 1.237, 1.161, 1.102, 1.058, 1.033, 1.015, 1.001, 1.023, 1.039, 1.069, 1.111, 1.164, 1.232, 1.309,
+                    1.442, 1.347, 1.244, 1.168, 1.119, 1.083, 1.049, 1.017, 1.004, 1.025, 1.062, 1.092, 1.125, 1.169, 1.238, 1.317,
+                    1.533, 1.422, 1.335, 1.244, 1.168, 1.119, 1.086, 1.067, 1.067, 1.071, 1.094, 1.125, 1.169, 1.238, 1.301, 1.371,
+                    1.669, 1.539, 1.422, 1.337, 1.274, 1.228, 1.196, 1.174, 1.172, 1.172, 1.191, 1.218, 1.252, 1.301, 1.377, 1.468,
+                    1.891, 1.748, 1.616, 1.524, 1.453, 1.401, 1.365, 1.341, 1.329, 1.329, 1.341, 1.364, 1.399, 1.446, 1.514, 1.608,
+                    2.245, 2.074, 1.925, 1.815, 1.733, 1.673, 1.626, 1.595, 1.573, 1.571, 1.571, 1.589, 1.624, 1.677, 1.736, 1.841,
+                    2.532, 2.348, 2.221, 2.124, 2.051, 1.994, 1.946, 1.912, 1.892, 1.889, 1.889, 1.889, 1.902, 1.929, 1.981, 2.058
+                ],
+                "sigma": 0.0041,
+                "sigma_Cb": 0.01178
+            }
+        },
+        {
+            "rpi.contrast":
+            {
+                "ce_enable": 1,
+                "gamma_curve":
+                [
+                    0, 0,
+                    1024, 5040,
+                    2048, 9338,
+                    3072, 12356,
+                    4096, 15312,
+                    5120, 18051,
+                    6144, 20790,
+                    7168, 23193,
+                    8192, 25744,
+                    9216, 27942,
+                    10240, 30035,
+                    11264, 32005,
+                    12288, 33975,
+                    13312, 35815,
+                    14336, 37600,
+                    15360, 39168,
+                    16384, 40642,
+                    18432, 43379,
+                    20480, 45749,
+                    22528, 47753,
+                    24576, 49621,
+                    26624, 51253,
+                    28672, 52698,
+                    30720, 53796,
+                    32768, 54876,
+                    36864, 57012,
+                    40960, 58656,
+                    45056, 59954,
+                    49152, 61183,
+                    53248, 62355,
+                    57344, 63419,
+                    61440, 64476,
+                    65535, 65535
+                ]
+            }
+        },
+        {
+            "rpi.sharpen": { }
+        }
+    ]
+}
diff -pruN 0.5.0-1/src/ipa/rpi/vc4/vc4.cpp 0.6.0-2/src/ipa/rpi/vc4/vc4.cpp
--- 0.5.0-1/src/ipa/rpi/vc4/vc4.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/rpi/vc4/vc4.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -43,6 +43,9 @@ public:
 	IpaVc4()
 		: IpaBase(), lsTable_(nullptr)
 	{
+		lastAwbStatus_.gainR = 1.0;
+		lastAwbStatus_.gainG = 1.0;
+		lastAwbStatus_.gainB = 1.0;
 	}
 
 	~IpaVc4()
@@ -57,13 +60,14 @@ private:
 	int32_t platformConfigure(const ConfigParams &params, ConfigResult *result) override;
 
 	void platformPrepareIsp(const PrepareParams &params, RPiController::Metadata &rpiMetadata) override;
+	void platformPrepareAgc([[maybe_unused]] RPiController::Metadata &rpiMetadata) override;
 	RPiController::StatisticsPtr platformProcessStats(Span<uint8_t> mem) override;
 
 	void handleControls(const ControlList &controls) override;
 	bool validateIspControls();
 
 	void applyAWB(const struct AwbStatus *awbStatus, ControlList &ctrls);
-	void applyDG(const struct AgcPrepareStatus *dgStatus, ControlList &ctrls);
+	void applyDG(double digitalGain, const struct AwbStatus *awbStatus, ControlList &ctrls);
 	void applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls);
 	void applyBlackLevel(const struct BlackLevelStatus *blackLevelStatus, ControlList &ctrls);
 	void applyGamma(const struct ContrastStatus *contrastStatus, ControlList &ctrls);
@@ -77,10 +81,14 @@ private:
 
 	/* VC4 ISP controls. */
 	ControlInfoMap ispCtrls_;
+	ControlList ctrls_;
 
 	/* LS table allocation passed in from the pipeline handler. */
 	SharedFD lsTableHandle_;
 	void *lsTable_;
+
+	/* Remember the most recent AWB values. */
+	AwbStatus lastAwbStatus_;
 };
 
 int32_t IpaVc4::platformInit([[maybe_unused]] const InitParams &params, [[maybe_unused]] InitResult *result)
@@ -106,6 +114,7 @@ int32_t IpaVc4::platformStart([[maybe_un
 int32_t IpaVc4::platformConfigure(const ConfigParams &params, [[maybe_unused]] ConfigResult *result)
 {
 	ispCtrls_ = params.ispControls;
+	ctrls_ = ControlList(ispCtrls_);
 	if (!validateIspControls()) {
 		LOG(IPARPI, Error) << "ISP control validation failed.";
 		return -1;
@@ -138,23 +147,21 @@ int32_t IpaVc4::platformConfigure(const
 void IpaVc4::platformPrepareIsp([[maybe_unused]] const PrepareParams &params,
 				RPiController::Metadata &rpiMetadata)
 {
-	ControlList ctrls(ispCtrls_);
+	ControlList &ctrls = ctrls_;
 
 	/* Lock the metadata buffer to avoid constant locks/unlocks. */
 	std::unique_lock<RPiController::Metadata> lock(rpiMetadata);
 
 	AwbStatus *awbStatus = rpiMetadata.getLocked<AwbStatus>("awb.status");
-	if (awbStatus)
+	if (awbStatus) {
 		applyAWB(awbStatus, ctrls);
+		lastAwbStatus_ = *awbStatus;
+	}
 
 	CcmStatus *ccmStatus = rpiMetadata.getLocked<CcmStatus>("ccm.status");
 	if (ccmStatus)
 		applyCCM(ccmStatus, ctrls);
 
-	AgcPrepareStatus *dgStatus = rpiMetadata.getLocked<AgcPrepareStatus>("agc.prepare_status");
-	if (dgStatus)
-		applyDG(dgStatus, ctrls);
-
 	AlscStatus *lsStatus = rpiMetadata.getLocked<AlscStatus>("alsc.status");
 	if (lsStatus)
 		applyLS(lsStatus, ctrls);
@@ -190,9 +197,18 @@ void IpaVc4::platformPrepareIsp([[maybe_
 		if (!lensctrls.empty())
 			setLensControls.emit(lensctrls);
 	}
+}
+
+void IpaVc4::platformPrepareAgc(RPiController::Metadata &rpiMetadata)
+{
+	AgcStatus *delayedAgcStatus = rpiMetadata.getLocked<AgcStatus>("agc.delayed_status");
+	double digitalGain = delayedAgcStatus ? delayedAgcStatus->digitalGain : agcStatus_.digitalGain;
+	AwbStatus *awbStatus = rpiMetadata.getLocked<AwbStatus>("awb.status");
 
-	if (!ctrls.empty())
-		setIspControls.emit(ctrls);
+	applyDG(digitalGain, awbStatus, ctrls_);
+
+	setIspControls.emit(ctrls_);
+	ctrls_ = ControlList(ispCtrls_);
 }
 
 RPiController::StatisticsPtr IpaVc4::platformProcessStats(Span<uint8_t> mem)
@@ -226,7 +242,13 @@ RPiController::StatisticsPtr IpaVc4::pla
 		LOG(IPARPI, Debug) << "No AGC algorithm - not copying statistics";
 		statistics->agcRegions.init(0);
 	} else {
-		statistics->agcRegions.init(hw.agcRegions);
+		RgbySums fullImage;
+		uint32_t countedSum = 0;
+		uint32_t notCountedSum = 0;
+		/* We're going to pretend there's a floating region where we will put a full image Y sum. */
+		const unsigned int numFloating = 1;
+
+		statistics->agcRegions.init(hw.agcRegions, numFloating);
 		const std::vector<double> &weights = agc->getWeights();
 		for (i = 0; i < statistics->agcRegions.numRegions(); i++) {
 			uint64_t rSum = (stats->agc_stats[i].r_sum << scale) * weights[i];
@@ -237,7 +259,20 @@ RPiController::StatisticsPtr IpaVc4::pla
 			statistics->agcRegions.set(i, { { rSum, gSum, bSum },
 							counted,
 							notcounted });
+
+			/* Accumulate values for the full image Y sum. */
+			fullImage.rSum += stats->agc_stats[i].r_sum << scale;
+			fullImage.gSum += stats->agc_stats[i].g_sum << scale;
+			fullImage.bSum += stats->agc_stats[i].b_sum << scale;
+			countedSum += stats->agc_stats[i].counted;
+			notCountedSum += stats->agc_stats[i].notcounted;
 		}
+
+		/* The "floating" region has the Y sum for the entire image. */
+		fullImage.ySum = fullImage.rSum * lastAwbStatus_.gainR * 0.299 +
+				 fullImage.gSum * lastAwbStatus_.gainG * 0.587 +
+				 fullImage.bSum * lastAwbStatus_.gainB * 0.114;
+		statistics->agcRegions.setFloating(0, { fullImage, countedSum, notCountedSum });
 	}
 
 	statistics->focusRegions.init(hw.focusRegions);
@@ -329,10 +364,24 @@ void IpaVc4::applyAWB(const struct AwbSt
 		  static_cast<int32_t>(awbStatus->gainB * 1000));
 }
 
-void IpaVc4::applyDG(const struct AgcPrepareStatus *dgStatus, ControlList &ctrls)
+void IpaVc4::applyDG(double digitalGain,
+		     const struct AwbStatus *awbStatus, ControlList &ctrls)
 {
+	if (awbStatus) {
+		/*
+		 * We must apply sufficient extra digital gain to stop any of the channel gains being
+		 * less than 1, which would cause saturation artifacts. Note that one of the colour
+		 * channels is still getting the minimum possible gain, so it's not a "real" gain
+		 * increase.
+		 */
+		double minColourGain = std::min({ awbStatus->gainR, awbStatus->gainG, awbStatus->gainB, 1.0 });
+		/* The 0.1 here doesn't mean much, but just stops arithmetic errors and extreme behaviour. */
+		double extraGain = 1.0 / std::max({ minColourGain, 0.1 });
+		digitalGain *= extraGain;
+	}
+
 	ctrls.set(V4L2_CID_DIGITAL_GAIN,
-		  static_cast<int32_t>(dgStatus->digitalGain * 1000));
+		  static_cast<int32_t>(digitalGain * 1000));
 }
 
 void IpaVc4::applyCCM(const struct CcmStatus *ccmStatus, ControlList &ctrls)
diff -pruN 0.5.0-1/src/ipa/simple/algorithms/agc.cpp 0.6.0-2/src/ipa/simple/algorithms/agc.cpp
--- 0.5.0-1/src/ipa/simple/algorithms/agc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/algorithms/agc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -51,18 +51,18 @@ void Agc::updateExposure(IPAContext &con
 	static constexpr uint8_t kExpNumeratorUp = kExpDenominator + 1;
 	static constexpr uint8_t kExpNumeratorDown = kExpDenominator - 1;
 
-	double next;
 	int32_t &exposure = frameContext.sensor.exposure;
 	double &again = frameContext.sensor.gain;
 
 	if (exposureMSV < kExposureOptimal - kExposureSatisfactory) {
-		next = exposure * kExpNumeratorUp / kExpDenominator;
-		if (next - exposure < 1)
-			exposure += 1;
-		else
-			exposure = next;
-		if (exposure >= context.configuration.agc.exposureMax) {
-			next = again * kExpNumeratorUp / kExpDenominator;
+		if (exposure < context.configuration.agc.exposureMax) {
+			int32_t next = exposure * kExpNumeratorUp / kExpDenominator;
+			if (next - exposure < 1)
+				exposure += 1;
+			else
+				exposure = next;
+		} else {
+			double next = again * kExpNumeratorUp / kExpDenominator;
 			if (next - again < context.configuration.agc.againMinStep)
 				again += context.configuration.agc.againMinStep;
 			else
@@ -71,15 +71,14 @@ void Agc::updateExposure(IPAContext &con
 	}
 
 	if (exposureMSV > kExposureOptimal + kExposureSatisfactory) {
-		if (exposure == context.configuration.agc.exposureMax &&
-		    again > context.configuration.agc.againMin) {
-			next = again * kExpNumeratorDown / kExpDenominator;
+		if (again > context.configuration.agc.again10) {
+			double next = again * kExpNumeratorDown / kExpDenominator;
 			if (again - next < context.configuration.agc.againMinStep)
 				again -= context.configuration.agc.againMinStep;
 			else
 				again = next;
 		} else {
-			next = exposure * kExpNumeratorDown / kExpDenominator;
+			int32_t next = exposure * kExpNumeratorDown / kExpDenominator;
 			if (exposure - next < 1)
 				exposure -= 1;
 			else
@@ -92,13 +91,16 @@ void Agc::updateExposure(IPAContext &con
 	again = std::clamp(again, context.configuration.agc.againMin,
 			   context.configuration.agc.againMax);
 
+	context.activeState.agc.exposure = exposure;
+	context.activeState.agc.again = again;
+
 	LOG(IPASoftExposure, Debug)
 		<< "exposureMSV " << exposureMSV
 		<< " exp " << exposure << " again " << again;
 }
 
 void Agc::process(IPAContext &context,
-		  [[maybe_unused]] const uint32_t frame,
+		  const uint32_t frame,
 		  IPAFrameContext &frameContext,
 		  const SwIspStats *stats,
 		  ControlList &metadata)
@@ -108,6 +110,25 @@ void Agc::process(IPAContext &context,
 	metadata.set(controls::ExposureTime, exposureTime.get<std::micro>());
 	metadata.set(controls::AnalogueGain, frameContext.sensor.gain);
 
+	if (frame == 0) {
+		/*
+		 * Init active-state from sensor values in case updateExposure()
+		 * does not run for the first frame.
+		 */
+		context.activeState.agc.exposure = frameContext.sensor.exposure;
+		context.activeState.agc.again = frameContext.sensor.gain;
+	}
+
+	if (!stats->valid) {
+		/*
+		 * Use the new exposure and gain values calculated the last time
+		 * there were valid stats.
+		 */
+		frameContext.sensor.exposure = context.activeState.agc.exposure;
+		frameContext.sensor.gain = context.activeState.agc.again;
+		return;
+	}
+
 	/*
 	 * Calculate Mean Sample Value (MSV) according to formula from:
 	 * https://www.araa.asn.au/acra/acra2007/papers/paper84final.pdf
@@ -124,6 +145,12 @@ void Agc::process(IPAContext &context,
 	unsigned int denom = 0;
 	unsigned int num = 0;
 
+	if (yHistValsPerBin == 0) {
+		LOG(IPASoftExposure, Debug)
+			<< "Not adjusting exposure due to insufficient histogram data";
+		return;
+	}
+
 	for (unsigned int i = 0; i < histogramSize; i++) {
 		unsigned int idx = (i - (i / yHistValsPerBinMod)) / yHistValsPerBin;
 		exposureBins[idx] += histogram[blackLevelHistIdx + i];
diff -pruN 0.5.0-1/src/ipa/simple/algorithms/awb.cpp 0.6.0-2/src/ipa/simple/algorithms/awb.cpp
--- 0.5.0-1/src/ipa/simple/algorithms/awb.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/algorithms/awb.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,7 @@
 
 #include "awb.h"
 
+#include <algorithm>
 #include <numeric>
 #include <stdint.h>
 
@@ -40,6 +41,7 @@ void Awb::prepare(IPAContext &context,
 		  [[maybe_unused]] DebayerParams *params)
 {
 	auto &gains = context.activeState.awb.gains;
+	/* Just report, the gains are applied in LUT algorithm. */
 	frameContext.gains.red = gains.r();
 	frameContext.gains.blue = gains.b();
 }
@@ -60,17 +62,21 @@ void Awb::process(IPAContext &context,
 	};
 	metadata.set(controls::ColourGains, mdGains);
 
+	if (!stats->valid)
+		return;
+
 	/*
 	 * Black level must be subtracted to get the correct AWB ratios, they
 	 * would be off if they were computed from the whole brightness range
 	 * rather than from the sensor range.
 	 */
 	const uint64_t nPixels = std::accumulate(
-		histogram.begin(), histogram.end(), 0);
+		histogram.begin(), histogram.end(), uint64_t(0));
 	const uint64_t offset = blackLevel * nPixels;
-	const uint64_t sumR = stats->sumR_ - offset / 4;
-	const uint64_t sumG = stats->sumG_ - offset / 2;
-	const uint64_t sumB = stats->sumB_ - offset / 4;
+	const uint64_t minValid = 1;
+	const uint64_t sumR = stats->sumR_ > offset / 4 ? stats->sumR_ - offset / 4 : minValid;
+	const uint64_t sumG = stats->sumG_ > offset / 2 ? stats->sumG_ - offset / 2 : minValid;
+	const uint64_t sumB = stats->sumB_ > offset / 4 ? stats->sumB_ - offset / 4 : minValid;
 
 	/*
 	 * Calculate red and blue gains for AWB.
diff -pruN 0.5.0-1/src/ipa/simple/algorithms/blc.cpp 0.6.0-2/src/ipa/simple/algorithms/blc.cpp
--- 0.5.0-1/src/ipa/simple/algorithms/blc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/algorithms/blc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -43,7 +43,7 @@ int BlackLevel::configure(IPAContext &co
 	if (definedLevel_.has_value())
 		context.configuration.black.level = definedLevel_;
 	context.activeState.blc.level =
-		context.configuration.black.level.value_or(255);
+		context.configuration.black.level.value_or(16);
 	return 0;
 }
 
@@ -60,6 +60,9 @@ void BlackLevel::process(IPAContext &con
 	};
 	metadata.set(controls::SensorBlackLevels, blackLevels);
 
+	if (!stats->valid)
+		return;
+
 	if (context.configuration.black.level.has_value())
 		return;
 
@@ -77,6 +80,11 @@ void BlackLevel::process(IPAContext &con
 	constexpr float ignoredPercentage = 0.02;
 	const unsigned int total =
 		std::accumulate(begin(histogram), end(histogram), 0);
+	if (total == 0) {
+		LOG(IPASoftBL, Debug) << "Not guessing black level, histogram is empty";
+		return;
+	}
+
 	const unsigned int pixelThreshold = ignoredPercentage * total;
 	const unsigned int histogramRatio = 256 / SwIspStats::kYHistogramSize;
 	const unsigned int currentBlackIdx =
diff -pruN 0.5.0-1/src/ipa/simple/algorithms/ccm.cpp 0.6.0-2/src/ipa/simple/algorithms/ccm.cpp
--- 0.5.0-1/src/ipa/simple/algorithms/ccm.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/algorithms/ccm.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -3,7 +3,7 @@
  * Copyright (C) 2024, Ideas On Board
  * Copyright (C) 2024-2025, Red Hat Inc.
  *
- * Color correction matrix
+ * Color correction matrix + saturation
  */
 
 #include "ccm.h"
@@ -13,6 +13,8 @@
 
 #include <libcamera/control_ids.h>
 
+#include "libcamera/internal/matrix.h"
+
 namespace {
 
 constexpr unsigned int kTemperatureThreshold = 100;
@@ -35,28 +37,77 @@ int Ccm::init([[maybe_unused]] IPAContex
 	}
 
 	context.ccmEnabled = true;
+	context.ctrlMap[&controls::Saturation] = ControlInfo(0.0f, 2.0f, 1.0f);
+
+	return 0;
+}
+
+int Ccm::configure(IPAContext &context,
+		   [[maybe_unused]] const IPAConfigInfo &configInfo)
+{
+	context.activeState.knobs.saturation = std::optional<double>();
 
 	return 0;
 }
 
+void Ccm::queueRequest(typename Module::Context &context,
+		       [[maybe_unused]] const uint32_t frame,
+		       [[maybe_unused]] typename Module::FrameContext &frameContext,
+		       const ControlList &controls)
+{
+	const auto &saturation = controls.get(controls::Saturation);
+	if (saturation.has_value()) {
+		context.activeState.knobs.saturation = saturation;
+		LOG(IPASoftCcm, Debug) << "Setting saturation to " << saturation.value();
+	}
+}
+
+void Ccm::applySaturation(Matrix<float, 3, 3> &ccm, float saturation)
+{
+	/* https://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion */
+	const Matrix<float, 3, 3> rgb2ycbcr{
+		{ 0.256788235294, 0.504129411765, 0.0979058823529,
+		  -0.148223529412, -0.290992156863, 0.439215686275,
+		  0.439215686275, -0.367788235294, -0.0714274509804 }
+	};
+	const Matrix<float, 3, 3> ycbcr2rgb{
+		{ 1.16438356164, 0, 1.59602678571,
+		  1.16438356164, -0.391762290094, -0.812967647235,
+		  1.16438356164, 2.01723214285, 0 }
+	};
+	const Matrix<float, 3, 3> saturationMatrix{
+		{ 1, 0, 0,
+		  0, saturation, 0,
+		  0, 0, saturation }
+	};
+	ccm = ycbcr2rgb * saturationMatrix * rgb2ycbcr * ccm;
+}
+
 void Ccm::prepare(IPAContext &context, const uint32_t frame,
 		  IPAFrameContext &frameContext, [[maybe_unused]] DebayerParams *params)
 {
+	auto &saturation = context.activeState.knobs.saturation;
+
 	const unsigned int ct = context.activeState.awb.temperatureK;
 
-	/* Change CCM only on bigger temperature changes. */
+	/* Change CCM only on saturation or bigger temperature changes. */
 	if (frame > 0 &&
-	    utils::abs_diff(ct, lastCt_) < kTemperatureThreshold) {
+	    utils::abs_diff(ct, lastCt_) < kTemperatureThreshold &&
+	    saturation == lastSaturation_) {
 		frameContext.ccm.ccm = context.activeState.ccm.ccm;
 		context.activeState.ccm.changed = false;
 		return;
 	}
 
 	lastCt_ = ct;
+	lastSaturation_ = saturation;
 	Matrix<float, 3, 3> ccm = ccm_.getInterpolated(ct);
+	if (saturation)
+		applySaturation(ccm, saturation.value());
 
 	context.activeState.ccm.ccm = ccm;
 	frameContext.ccm.ccm = ccm;
+	frameContext.saturation = saturation;
 	context.activeState.ccm.changed = true;
 }
 
@@ -67,6 +118,9 @@ void Ccm::process([[maybe_unused]] IPACo
 		  ControlList &metadata)
 {
 	metadata.set(controls::ColourCorrectionMatrix, frameContext.ccm.ccm.data());
+
+	const auto &saturation = frameContext.saturation;
+	metadata.set(controls::Saturation, saturation.value_or(1.0));
 }
 
 REGISTER_IPA_ALGORITHM(Ccm, "Ccm")
diff -pruN 0.5.0-1/src/ipa/simple/algorithms/ccm.h 0.6.0-2/src/ipa/simple/algorithms/ccm.h
--- 0.5.0-1/src/ipa/simple/algorithms/ccm.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/algorithms/ccm.h	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,8 @@
 
 #pragma once
 
+#include <optional>
+
 #include "libcamera/internal/matrix.h"
 
 #include <libipa/interpolator.h>
@@ -24,6 +26,12 @@ public:
 	~Ccm() = default;
 
 	int init(IPAContext &context, const YamlObject &tuningData) override;
+	int configure(IPAContext &context,
+		      const IPAConfigInfo &configInfo) override;
+	void queueRequest(typename Module::Context &context,
+			  const uint32_t frame,
+			  typename Module::FrameContext &frameContext,
+			  const ControlList &controls) override;
 	void prepare(IPAContext &context,
 		     const uint32_t frame,
 		     IPAFrameContext &frameContext,
@@ -34,7 +42,10 @@ public:
 		     ControlList &metadata) override;
 
 private:
+	void applySaturation(Matrix<float, 3, 3> &ccm, float saturation);
+
 	unsigned int lastCt_;
+	std::optional<float> lastSaturation_;
 	Interpolator<Matrix<float, 3, 3>> ccm_;
 };
 
diff -pruN 0.5.0-1/src/ipa/simple/algorithms/lut.cpp 0.6.0-2/src/ipa/simple/algorithms/lut.cpp
--- 0.5.0-1/src/ipa/simple/algorithms/lut.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/algorithms/lut.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -61,7 +61,6 @@ void Lut::updateGammaTable(IPAContext &c
 	const unsigned int blackIndex = blackLevel * gammaTable.size() / 256;
 	const auto contrast = context.activeState.knobs.contrast.value_or(1.0);
 
-	std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex, 0);
 	const float divisor = gammaTable.size() - blackIndex - 1.0;
 	for (unsigned int i = blackIndex; i < gammaTable.size(); i++) {
 		double normalized = (i - blackIndex) / divisor;
@@ -75,6 +74,14 @@ void Lut::updateGammaTable(IPAContext &c
 		gammaTable[i] = UINT8_MAX *
 				std::pow(normalized, context.configuration.gamma);
 	}
+	/*
+	 * Due to CCM operations, the table lookup may reach indices below the black
+	 * level. Let's set the table values below black level to the minimum
+	 * non-black value to prevent problems when the minimum value is
+	 * significantly non-zero (for example, when the image should be all grey).
+	 */
+	std::fill(gammaTable.begin(), gammaTable.begin() + blackIndex,
+		  gammaTable[blackIndex]);
 
 	context.activeState.gamma.blackLevel = blackLevel;
 	context.activeState.gamma.contrast = contrast;
@@ -122,7 +129,7 @@ void Lut::prepare(IPAContext &context,
 		Matrix<float, 3, 3> gainCcm = { { gains.r(), 0, 0,
 						  0, gains.g(), 0,
 						  0, 0, gains.b() } };
-		auto ccm = gainCcm * context.activeState.ccm.ccm;
+		auto ccm = context.activeState.ccm.ccm * gainCcm;
 		auto &red = params->redCcm;
 		auto &green = params->greenCcm;
 		auto &blue = params->blueCcm;
diff -pruN 0.5.0-1/src/ipa/simple/ipa_context.h 0.6.0-2/src/ipa/simple/ipa_context.h
--- 0.5.0-1/src/ipa/simple/ipa_context.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/ipa_context.h	2025-11-27 11:55:28.000000000 +0000
@@ -28,7 +28,7 @@ struct IPASessionConfiguration {
 	float gamma;
 	struct {
 		int32_t exposureMin, exposureMax;
-		double againMin, againMax, againMinStep;
+		double againMin, againMax, again10, againMinStep;
 		utils::Duration lineDuration;
 	} agc;
 	struct {
@@ -38,6 +38,11 @@ struct IPASessionConfiguration {
 
 struct IPAActiveState {
 	struct {
+		int32_t exposure;
+		double again;
+	} agc;
+
+	struct {
 		uint8_t level;
 		int32_t lastExposure;
 		double lastGain;
@@ -63,6 +68,7 @@ struct IPAActiveState {
 	struct {
 		/* 0..2 range, 1.0 = normal */
 		std::optional<double> contrast;
+		std::optional<float> saturation;
 	} knobs;
 };
 
@@ -75,11 +81,14 @@ struct IPAFrameContext : public FrameCon
 		int32_t exposure;
 		double gain;
 	} sensor;
+
 	struct {
 		double red;
 		double blue;
 	} gains;
+
 	std::optional<double> contrast;
+	std::optional<float> saturation;
 };
 
 struct IPAContext {
diff -pruN 0.5.0-1/src/ipa/simple/soft_simple.cpp 0.6.0-2/src/ipa/simple/soft_simple.cpp
--- 0.5.0-1/src/ipa/simple/soft_simple.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/ipa/simple/soft_simple.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -216,10 +216,12 @@ int IPASoftSimple::configure(const IPACo
 
 	int32_t againMin = gainInfo.min().get<int32_t>();
 	int32_t againMax = gainInfo.max().get<int32_t>();
+	int32_t againDef = gainInfo.def().get<int32_t>();
 
 	if (camHelper_) {
 		context_.configuration.agc.againMin = camHelper_->gain(againMin);
 		context_.configuration.agc.againMax = camHelper_->gain(againMax);
+		context_.configuration.agc.again10 = camHelper_->gain(1.0);
 		context_.configuration.agc.againMinStep =
 			(context_.configuration.agc.againMax -
 			 context_.configuration.agc.againMin) /
@@ -246,7 +248,10 @@ int IPASoftSimple::configure(const IPACo
 		 * other) we limit the range of the gain values used.
 		 */
 		context_.configuration.agc.againMax = againMax;
-		if (!againMin) {
+		context_.configuration.agc.again10 = againDef;
+		if (againMin) {
+			context_.configuration.agc.againMin = againMin;
+		} else {
 			LOG(IPASoft, Warning)
 				<< "Minimum gain is zero, that can't be linear";
 			context_.configuration.agc.againMin =
diff -pruN 0.5.0-1/src/libcamera/base/log.cpp 0.6.0-2/src/libcamera/base/log.cpp
--- 0.5.0-1/src/libcamera/base/log.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/base/log.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -690,8 +690,9 @@ LogSeverity Logger::parseLogLevel(std::s
 	unsigned int severity = LogInvalid;
 
 	if (std::isdigit(level[0])) {
-		auto [end, ec] = std::from_chars(level.data(), level.data() + level.size(), severity);
-		if (ec != std::errc() || *end != '\0' || severity > LogFatal)
+		const char *levelEnd = level.data() + level.size();
+		auto [end, ec] = std::from_chars(level.data(), levelEnd, severity);
+		if (ec != std::errc() || end != levelEnd || severity > LogFatal)
 			severity = LogInvalid;
 	} else {
 		for (unsigned int i = 0; i < std::size(names); ++i) {
@@ -951,12 +952,10 @@ Loggable::~Loggable()
  *
  * \return A log message
  */
-LogMessage Loggable::_log(const LogCategory *category, LogSeverity severity,
+LogMessage Loggable::_log(const LogCategory &category, LogSeverity severity,
 			  const char *fileName, unsigned int line) const
 {
-	return LogMessage(fileName, line,
-			  category ? *category : LogCategory::defaultCategory(),
-			  severity, logPrefix());
+	return LogMessage(fileName, line, category, severity, logPrefix());
 }
 
 /**
@@ -971,12 +970,10 @@ LogMessage Loggable::_log(const LogCateg
  *
  * \return A log message
  */
-LogMessage _log(const LogCategory *category, LogSeverity severity,
+LogMessage _log(const LogCategory &category, LogSeverity severity,
 		const char *fileName, unsigned int line)
 {
-	return LogMessage(fileName, line,
-			  category ? *category : LogCategory::defaultCategory(),
-			  severity);
+	return LogMessage(fileName, line, category, severity);
 }
 
 /**
diff -pruN 0.5.0-1/src/libcamera/base/meson.build 0.6.0-2/src/libcamera/base/meson.build
--- 0.5.0-1/src/libcamera/base/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/base/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -27,7 +27,7 @@ libcamera_base_internal_sources = files(
 ])
 
 libdw = dependency('libdw', required : false)
-libunwind = dependency('libunwind', required : false)
+libunwind = dependency('libunwind', required : get_option('libunwind'))
 
 if cc.has_header_symbol('execinfo.h', 'backtrace')
     config_h.set('HAVE_BACKTRACE', 1)
diff -pruN 0.5.0-1/src/libcamera/base/semaphore.cpp 0.6.0-2/src/libcamera/base/semaphore.cpp
--- 0.5.0-1/src/libcamera/base/semaphore.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/base/semaphore.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -93,11 +93,9 @@ bool Semaphore::tryAcquire(unsigned int
  */
 void Semaphore::release(unsigned int n)
 {
-	{
-		MutexLocker locker(mutex_);
-		available_ += n;
-	}
+	MutexLocker locker(mutex_);
 
+	available_ += n;
 	cv_.notify_all();
 }
 
diff -pruN 0.5.0-1/src/libcamera/base/shared_fd.cpp 0.6.0-2/src/libcamera/base/shared_fd.cpp
--- 0.5.0-1/src/libcamera/base/shared_fd.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/base/shared_fd.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -284,8 +284,11 @@ SharedFD::Descriptor::Descriptor(int fd,
 
 SharedFD::Descriptor::~Descriptor()
 {
-	if (fd_ != -1)
-		close(fd_);
+	if (fd_ >= 0 && close(fd_) < 0) {
+		int ret = -errno;
+		LOG(SharedFD, Error) << "Failed to close file descriptor "
+				     << fd_ << ": " << strerror(-ret);
+	}
 }
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/base/thread.cpp 0.6.0-2/src/libcamera/base/thread.cpp
--- 0.5.0-1/src/libcamera/base/thread.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/base/thread.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -10,6 +10,7 @@
 #include <atomic>
 #include <list>
 #include <optional>
+#include <pthread.h>
 #include <sys/syscall.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -105,8 +106,12 @@ public:
 class ThreadData
 {
 public:
-	ThreadData()
-		: thread_(nullptr), running_(false), dispatcher_(nullptr)
+	/**
+	 * \brief Constructor for internal thread data
+	 * \param[in] thread The associated thread
+	 */
+	ThreadData(Thread *thread)
+		: thread_(thread), running_(false), dispatcher_(nullptr)
 	{
 	}
 
@@ -140,6 +145,7 @@ class ThreadMain : public Thread
 {
 public:
 	ThreadMain()
+		: Thread("libcamera-main")
 	{
 		data_->running_ = true;
 	}
@@ -167,7 +173,7 @@ ThreadData *ThreadData::current()
 	 * The main thread doesn't receive thread-local data when it is
 	 * started, set it here.
 	 */
-	ThreadData *data = mainThread.data_;
+	ThreadData *data = mainThread.data_.get();
 	data->tid_ = syscall(SYS_gettid);
 	currentThreadData = data;
 	return data;
@@ -230,16 +236,15 @@ ThreadData *ThreadData::current()
 /**
  * \brief Create a thread
  */
-Thread::Thread()
+Thread::Thread(std::string name)
+	: name_(std::move(name)),
+	  data_(std::make_unique<ThreadData>(this))
 {
-	data_ = new ThreadData;
-	data_->thread_ = this;
 }
 
 Thread::~Thread()
 {
-	delete data_->dispatcher_.load(std::memory_order_relaxed);
-	delete data_;
+	delete data_->dispatcher_.load(std::memory_order_acquire);
 }
 
 /**
@@ -284,7 +289,10 @@ void Thread::startThread()
 	thread_local ThreadCleaner cleaner(this, &Thread::finishThread);
 
 	data_->tid_ = syscall(SYS_gettid);
-	currentThreadData = data_;
+	currentThreadData = data_.get();
+
+	if (!name_.empty())
+		pthread_setname_np(pthread_self(), name_.substr(0, 15).c_str());
 
 	run();
 }
@@ -371,7 +379,7 @@ void Thread::exit(int code)
 	data_->exitCode_ = code;
 	data_->exit_.store(true, std::memory_order_release);
 
-	EventDispatcher *dispatcher = data_->dispatcher_.load(std::memory_order_relaxed);
+	EventDispatcher *dispatcher = data_->dispatcher_.load(std::memory_order_acquire);
 	if (!dispatcher)
 		return;
 
@@ -512,12 +520,12 @@ pid_t Thread::currentId()
  * This function retrieves the internal event dispatcher for the thread. The
  * returned event dispatcher is valid until the thread is destroyed.
  *
- * \context This function is \threadsafe.
- *
  * \return Pointer to the event dispatcher
  */
 EventDispatcher *Thread::eventDispatcher()
 {
+	ASSERT(data_.get() == ThreadData::current());
+
 	if (!data_->dispatcher_.load(std::memory_order_relaxed))
 		data_->dispatcher_.store(new EventDispatcherPoll(),
 					 std::memory_order_release);
@@ -621,7 +629,7 @@ void Thread::removeMessages(Object *rece
  */
 void Thread::dispatchMessages(Message::Type type, Object *receiver)
 {
-	ASSERT(data_ == ThreadData::current());
+	ASSERT(data_.get() == ThreadData::current());
 
 	++data_->messages_.recursion_;
 
@@ -677,8 +685,8 @@ void Thread::dispatchMessages(Message::T
  */
 void Thread::moveObject(Object *object)
 {
-	ThreadData *currentData = object->thread_->data_;
-	ThreadData *targetData = data_;
+	ThreadData *currentData = object->thread_->data_.get();
+	ThreadData *targetData = data_.get();
 
 	MutexLocker lockerFrom(currentData->messages_.mutex_, std::defer_lock);
 	MutexLocker lockerTo(targetData->messages_.mutex_, std::defer_lock);
diff -pruN 0.5.0-1/src/libcamera/base/unique_fd.cpp 0.6.0-2/src/libcamera/base/unique_fd.cpp
--- 0.5.0-1/src/libcamera/base/unique_fd.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/base/unique_fd.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,7 @@
 
 #include <libcamera/base/unique_fd.h>
 
+#include <string.h>
 #include <unistd.h>
 #include <utility>
 
@@ -98,8 +99,11 @@ void UniqueFD::reset(int fd)
 
 	std::swap(fd, fd_);
 
-	if (fd >= 0)
-		close(fd);
+	if (fd >= 0 && close(fd) < 0) {
+		int ret = -errno;
+		LOG(UniqueFD, Error) << "Failed to close file descriptor "
+				     << fd << ": " << strerror(-ret);
+	}
 }
 
 /**
diff -pruN 0.5.0-1/src/libcamera/base/utils.cpp 0.6.0-2/src/libcamera/base/utils.cpp
--- 0.5.0-1/src/libcamera/base/utils.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/base/utils.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -187,7 +187,8 @@ std::string time_point_to_string(const t
 }
 
 std::basic_ostream<char, std::char_traits<char>> &
-operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h)
+details::operator<<(std::basic_ostream<char, std::char_traits<char>> &stream,
+		    const details::hex &h)
 {
 	stream << "0x";
 
@@ -426,6 +427,12 @@ std::string toAscii(const std::string &s
  */
 
 /**
+ * \fn Duration::operator-()
+ * \brief Negation operator to negate a \a Duration
+ * \return The duration, with the number of ticks negated
+ */
+
+/**
  * \fn Duration::operator bool()
  * \brief Boolean operator to test if a \a Duration holds a non-zero time value
  *
diff -pruN 0.5.0-1/src/libcamera/camera.cpp 0.6.0-2/src/libcamera/camera.cpp
--- 0.5.0-1/src/libcamera/camera.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/camera.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -488,7 +488,7 @@ std::size_t CameraConfiguration::size()
  *
  * \return A CameraConfiguration::Status value that describes the validation
  * status.
- * \retval CameraConfigutation::Adjusted The configuration has been adjusted
+ * \retval CameraConfiguration::Adjusted The configuration has been adjusted
  * and is now valid. The color space of some or all of the streams may have
  * been changed. The caller shall check the color spaces carefully.
  * \retval CameraConfiguration::Valid The configuration was already valid and
@@ -629,6 +629,15 @@ Camera::Private::~Private()
  */
 
 /**
+ * \var Camera::Private::waitingRequests_
+ * \brief The queue of waiting requests
+ *
+ * This queue tracks all requests that can not yet be queued to the device.
+ * Either because they are not yet prepared or because the maximum number of
+ * queued requests was reached.
+ */
+
+/**
  * \var Camera::Private::controlInfo_
  * \brief The set of controls supported by the camera
  *
@@ -1122,7 +1131,8 @@ std::unique_ptr<CameraConfiguration> Cam
 		return nullptr;
 
 	std::unique_ptr<CameraConfiguration> config =
-		d->pipe_->generateConfiguration(this, roles);
+		d->pipe_->invokeMethod(&PipelineHandler::generateConfiguration,
+				       ConnectionTypeBlocking, this, roles);
 	if (!config) {
 		LOG(Camera, Debug)
 			<< "Pipeline handler failed to generate configuration";
@@ -1267,6 +1277,33 @@ std::unique_ptr<Request> Camera::createR
 }
 
 /**
+ * \brief Patch a control list that contains the AeEnable control
+ * \param[inout] controls The control list to be patched
+ *
+ * The control list is patched in place, turning the AeEnable control into
+ * the equivalent ExposureTimeMode/AnalogueGainMode controls.
+ */
+void Camera::patchControlList(ControlList &controls)
+{
+	const auto &aeEnable = controls.get(controls::AeEnable);
+	if (aeEnable) {
+		if (_d()->controlInfo_.count(controls::AnalogueGainMode.id()) &&
+		    !controls.contains(controls::AnalogueGainMode.id())) {
+			controls.set(controls::AnalogueGainMode,
+				     *aeEnable ? controls::AnalogueGainModeAuto
+					       : controls::AnalogueGainModeManual);
+		}
+
+		if (_d()->controlInfo_.count(controls::ExposureTimeMode.id()) &&
+		    !controls.contains(controls::ExposureTimeMode.id())) {
+			controls.set(controls::ExposureTimeMode,
+				     *aeEnable ? controls::ExposureTimeModeAuto
+					       : controls::ExposureTimeModeManual);
+		}
+	}
+}
+
+/**
  * \brief Queue a request to the camera
  * \param[in] request The request to queue to the camera
  *
@@ -1329,23 +1366,7 @@ int Camera::queueRequest(Request *reques
 	}
 
 	/* Pre-process AeEnable. */
-	ControlList &controls = request->controls();
-	const auto &aeEnable = controls.get(controls::AeEnable);
-	if (aeEnable) {
-		if (_d()->controlInfo_.count(controls::AnalogueGainMode.id()) &&
-		    !controls.contains(controls::AnalogueGainMode.id())) {
-			controls.set(controls::AnalogueGainMode,
-				     *aeEnable ? controls::AnalogueGainModeAuto
-					       : controls::AnalogueGainModeManual);
-		}
-
-		if (_d()->controlInfo_.count(controls::ExposureTimeMode.id()) &&
-		    !controls.contains(controls::ExposureTimeMode.id())) {
-			controls.set(controls::ExposureTimeMode,
-				     *aeEnable ? controls::ExposureTimeModeAuto
-					       : controls::ExposureTimeModeManual);
-		}
-	}
+	patchControlList(request->controls());
 
 	d->pipe_->invokeMethod(&PipelineHandler::queueRequest,
 			       ConnectionTypeQueued, request);
@@ -1383,8 +1404,16 @@ int Camera::start(const ControlList *con
 
 	ASSERT(d->requestSequence_ == 0);
 
-	ret = d->pipe_->invokeMethod(&PipelineHandler::start,
-				     ConnectionTypeBlocking, this, controls);
+	if (controls) {
+		ControlList copy(*controls);
+		patchControlList(copy);
+		ret = d->pipe_->invokeMethod(&PipelineHandler::start,
+					     ConnectionTypeBlocking, this, &copy);
+	} else {
+		ret = d->pipe_->invokeMethod(&PipelineHandler::start,
+					     ConnectionTypeBlocking, this, nullptr);
+	}
+
 	if (ret)
 		return ret;
 
diff -pruN 0.5.0-1/src/libcamera/camera_manager.cpp 0.6.0-2/src/libcamera/camera_manager.cpp
--- 0.5.0-1/src/libcamera/camera_manager.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/camera_manager.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -15,6 +15,7 @@
 
 #include "libcamera/internal/camera.h"
 #include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/global_configuration.h"
 #include "libcamera/internal/ipa_manager.h"
 #include "libcamera/internal/pipeline_handler.h"
 
@@ -38,9 +39,9 @@ LOG_DEFINE_CATEGORY(Camera)
 
 #ifndef __DOXYGEN_PUBLIC__
 CameraManager::Private::Private()
-	: initialized_(false)
+	: Thread("CameraManager"), initialized_(false)
 {
-	ipaManager_ = std::make_unique<IPAManager>();
+	ipaManager_ = std::make_unique<IPAManager>(this->configuration());
 }
 
 int CameraManager::Private::start()
@@ -110,14 +111,16 @@ void CameraManager::Private::createPipel
 	 * file and only fallback on environment variable or all handlers, if
 	 * there is no configuration file.
 	 */
-	const char *pipesList =
-		utils::secure_getenv("LIBCAMERA_PIPELINES_MATCH_LIST");
-	if (pipesList) {
+	const auto pipesList =
+		configuration().envListOption("LIBCAMERA_PIPELINES_MATCH_LIST",
+					      { "pipelines_match_list" },
+					      ",");
+	if (pipesList.has_value()) {
 		/*
 		 * When a list of preferred pipelines is defined, iterate
 		 * through the ordered list to match the enumerated devices.
 		 */
-		for (const auto &pipeName : utils::split(pipesList, ",")) {
+		for (const auto &pipeName : pipesList.value()) {
 			const PipelineHandlerFactoryBase *factory;
 			factory = PipelineHandlerFactoryBase::getFactoryByName(pipeName);
 			if (!factory)
@@ -217,6 +220,10 @@ void CameraManager::Private::addCamera(s
 		cameras_.push_back(camera);
 	}
 
+	LOG(Camera, Info)
+		<< "Adding camera '" << camera->id() << "' for pipeline handler "
+		<< camera->_d()->pipe()->name();
+
 	/* Report the addition to the public signal */
 	CameraManager *const o = LIBCAMERA_O_PTR();
 	o->cameraAdded.emit(camera);
@@ -255,6 +262,13 @@ void CameraManager::Private::removeCamer
 }
 
 /**
+ * \fn const GlobalConfiguration &CameraManager::Private::configuration() const
+ * \brief Get global configuration bound to the camera manager
+ *
+ * \return Reference to the configuration
+ */
+
+/**
  * \fn CameraManager::Private::ipaManager() const
  * \brief Retrieve the IPAManager
  * \context This function is \threadsafe.
diff -pruN 0.5.0-1/src/libcamera/clock_recovery.cpp 0.6.0-2/src/libcamera/clock_recovery.cpp
--- 0.5.0-1/src/libcamera/clock_recovery.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/libcamera/clock_recovery.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Raspberry Pi Ltd
+ *
+ * Clock recovery algorithm
+ */
+
+#include "libcamera/internal/clock_recovery.h"
+
+#include <time.h>
+
+#include <libcamera/base/log.h>
+
+/**
+ * \file clock_recovery.h
+ * \brief Clock recovery - deriving one clock from another independent clock
+ */
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(ClockRec)
+
+/**
+ * \class ClockRecovery
+ * \brief Recover an output clock from an input clock
+ *
+ * The ClockRecovery class derives an output clock from an input clock,
+ * modelling the output clock as being linearly related to the input clock.
+ * For example, we may use it to derive wall clock timestamps from timestamps
+ * measured by the internal system clock which counts local time since boot.
+ *
+ * When pairs of corresponding input and output timestamps are available,
+ * they should be submitted to the model with addSample(). The model will
+ * update, and output clock values for known input clock values can be
+ * obtained using getOutput().
+ *
+ * As a convenience, if the input clock is indeed the time since boot, and the
+ * output clock represents a real wallclock time, then addSample() can be
+ * called with no arguments, and a pair of timestamps will be captured at
+ * that moment.
+ *
+ * The configure() function accepts some configuration parameters to control
+ * the linear fitting process.
+ */
+
+/**
+ * \brief Construct a ClockRecovery
+ */
+ClockRecovery::ClockRecovery()
+{
+	configure();
+	reset();
+}
+
+/**
+ * \brief Set configuration parameters
+ * \param[in] numSamples The approximate duration for which the state of the model
+ * is persistent
+ * \param[in] maxJitter New output samples are clamped to no more than this
+ * amount of jitter, to prevent sudden swings from having a large effect
+ * \param[in] minSamples The fitted clock model is not used to generate outputs
+ * until this many samples have been received
+ * \param[in] errorThreshold If the accumulated differences between input and
+ * output clocks reaches this amount over a few frames, the model is reset
+ */
+void ClockRecovery::configure(unsigned int numSamples, unsigned int maxJitter,
+			      unsigned int minSamples, unsigned int errorThreshold)
+{
+	LOG(ClockRec, Debug)
+		<< "configure " << numSamples << " " << maxJitter << " " << minSamples << " " << errorThreshold;
+
+	numSamples_ = numSamples;
+	maxJitter_ = maxJitter;
+	minSamples_ = minSamples;
+	errorThreshold_ = errorThreshold;
+}
+
+/**
+ * \brief Reset the clock recovery model and start again from scratch
+ */
+void ClockRecovery::reset()
+{
+	LOG(ClockRec, Debug) << "reset";
+
+	lastInput_ = 0;
+	lastOutput_ = 0;
+	xAve_ = 0;
+	yAve_ = 0;
+	x2Ave_ = 0;
+	xyAve_ = 0;
+	count_ = 0;
+	error_ = 0.0;
+	/*
+	 * Setting slope_ and offset_ to zero initially means that the clocks
+	 * advance at exactly the same rate.
+	 */
+	slope_ = 0.0;
+	offset_ = 0.0;
+}
+
+/**
+ * \brief Add a sample point to the clock recovery model, for recovering a wall
+ * clock value from the internal system time since boot
+ *
+ * This is a convenience function to make it easy to derive a wall clock value
+ * (using the Linux CLOCK_REALTIME) from the time since the system started
+ * (measured by CLOCK_BOOTTIME).
+ */
+void ClockRecovery::addSample()
+{
+	LOG(ClockRec, Debug) << "addSample";
+
+	struct timespec bootTime1;
+	struct timespec bootTime2;
+	struct timespec wallTime;
+
+	/* Get boot and wall clocks in microseconds. */
+	clock_gettime(CLOCK_BOOTTIME, &bootTime1);
+	clock_gettime(CLOCK_REALTIME, &wallTime);
+	clock_gettime(CLOCK_BOOTTIME, &bootTime2);
+	uint64_t boot1 = bootTime1.tv_sec * 1000000000ULL + bootTime1.tv_nsec;
+	uint64_t boot2 = bootTime2.tv_sec * 1000000000ULL + bootTime2.tv_nsec;
+	uint64_t boot = (boot1 + boot2) / 2;
+	uint64_t wall = wallTime.tv_sec * 1000000000ULL + wallTime.tv_nsec;
+
+	addSample(boot, wall);
+}
+
+/**
+ * \brief Add a sample point to the clock recovery model, specifying the exact
+ * input and output clock values
+ * \param[in] input The input clock value
+ * \param[in] output The value of the output clock at the same moment, as far
+ * as possible, that the input clock was sampled
+ *
+ * This function should be used for corresponding clocks other than the Linux
+ * BOOTTIME and REALTIME clocks.
+ */
+void ClockRecovery::addSample(uint64_t input, uint64_t output)
+{
+	LOG(ClockRec, Debug) << "addSample " << input << " " << output;
+
+	if (count_ == 0) {
+		inputBase_ = input;
+		outputBase_ = output;
+	}
+
+	/*
+	 * We keep an eye on cumulative drift over the last several frames. If this exceeds a
+	 * threshold, then probably the system clock has been updated and we're going to have to
+	 * reset everything and start over.
+	 */
+	if (lastOutput_) {
+		int64_t inputDiff = getOutput(input) - getOutput(lastInput_);
+		int64_t outputDiff = output - lastOutput_;
+		error_ = error_ * 0.95 + (outputDiff - inputDiff);
+		if (std::abs(error_) > errorThreshold_) {
+			reset();
+			inputBase_ = input;
+			outputBase_ = output;
+		}
+	}
+	lastInput_ = input;
+	lastOutput_ = output;
+
+	/*
+	 * Never let the new output value be more than maxJitter_ away from what
+	 * we would have expected.  This is just to reduce the effect of sudden
+	 * large delays in the measured output.
+	 */
+	uint64_t expectedOutput = getOutput(input);
+	output = std::clamp(output, expectedOutput - maxJitter_, expectedOutput + maxJitter_);
+
+	/*
+	 * We use x, y, x^2 and x*y sums to calculate the best fit line. Here we
+	 * update them by pretending we have count_ samples at the previous fit,
+	 * and now one new one. Gradually the effect of the older values gets
+	 * lost. This is a very simple way of updating the fit (there are much
+	 * more complicated ones!), but it works well enough. Using averages
+	 * instead of sums makes the relative effect of old values and the new
+	 * sample clearer.
+	 */
+	double x = static_cast<int64_t>(input - inputBase_);
+	double y = static_cast<int64_t>(output - outputBase_) - x;
+	unsigned int count1 = count_ + 1;
+	xAve_ = (count_ * xAve_ + x) / count1;
+	yAve_ = (count_ * yAve_ + y) / count1;
+	x2Ave_ = (count_ * x2Ave_ + x * x) / count1;
+	xyAve_ = (count_ * xyAve_ + x * y) / count1;
+
+	/*
+	 * Don't update slope and offset until we've seen "enough" sample
+	 * points.  Note that the initial settings for slope_ and offset_
+	 * ensures that the wallclock advances at the same rate as the realtime
+	 * clock (but with their respective initial offsets).
+	 */
+	if (count_ > minSamples_) {
+		/* These are the standard equations for least squares linear regression. */
+		slope_ = (count1 * count1 * xyAve_ - count1 * xAve_ * count1 * yAve_) /
+			 (count1 * count1 * x2Ave_ - count1 * xAve_ * count1 * xAve_);
+		offset_ = yAve_ - slope_ * xAve_;
+	}
+
+	/*
+	 * Don't increase count_ above numSamples_, as this controls the long-term
+	 * amount of the residual fit.
+	 */
+	if (count1 < numSamples_)
+		count_++;
+}
+
+/**
+ * \brief Calculate the output clock value according to the model from an input
+ * clock value
+ * \param[in] input The input clock value
+ *
+ * \return Output clock value
+ */
+uint64_t ClockRecovery::getOutput(uint64_t input)
+{
+	double x = static_cast<int64_t>(input - inputBase_);
+	double y = slope_ * x + offset_;
+	uint64_t output = y + x + outputBase_;
+
+	LOG(ClockRec, Debug) << "getOutput " << input << " " << output;
+
+	return output;
+}
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/control_ids_core.yaml 0.6.0-2/src/libcamera/control_ids_core.yaml
--- 0.5.0-1/src/libcamera/control_ids_core.yaml	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/control_ids_core.yaml	2025-11-27 11:55:28.000000000 +0000
@@ -212,7 +212,7 @@ controls:
       description: |
         Exposure time for the frame applied in the sensor device.
 
-        This value is specified in micro-seconds.
+        This value is specified in microseconds.
 
         This control will only take effect if ExposureTimeMode is Manual. If
         this control is set when ExposureTimeMode is Auto, the value will be
@@ -1268,4 +1268,89 @@ controls:
       description: |
         Enable or disable the debug metadata.
 
+  - FrameWallClock:
+      type: int64_t
+      direction: out
+      description: |
+        This timestamp corresponds to the same moment in time as the
+        SensorTimestamp, but is represented as a wall clock time as measured by
+        the CLOCK_REALTIME clock. Like SensorTimestamp, the timestamp value is
+        expressed in nanoseconds.
+
+        Being a wall clock measurement, it can be used to synchronise timing
+        across different devices.
+
+        \sa SensorTimestamp
+
+        The FrameWallClock control can only be returned in metadata.
+  - WdrMode:
+      type: int32_t
+      direction: inout
+      description: |
+        Set the WDR mode.
+
+        The WDR mode is used to select the algorithm used for global tone
+        mapping. It will automatically reduce the exposure time of the sensor
+        so that there are only a small number of saturated pixels in the image.
+        The algorithm then compensates for the loss of brightness by applying a
+        global tone mapping curve to the image.
+      enum:
+        - name: WdrOff
+          value: 0
+          description: Wdr is disabled.
+        - name: WdrLinear
+          value: 1
+          description:
+            Apply a linear global tone mapping curve.
+
+            A curve with two linear sections is applied. This produces good
+            results at the expense of a slightly artificial look.
+        - name: WdrPower
+          value: 2
+          description: |
+            Apply a power global tone mapping curve.
+
+            This curve has high gain values on the dark areas of an image and
+            high compression values on the bright area. It therefore tends to
+            produce noticeable noise artifacts.
+        - name: WdrExponential
+          value: 3
+          description: |
+            Apply an exponential global tone mapping curve.
+
+            This curve has lower gain values in dark areas compared to the power
+            curve but produces a more natural look compared to the linear curve.
+            It is therefore the best choice for most scenes.
+        - name: WdrHistogramEqualization
+          value: 4
+          description: |
+            Apply histogram equalization.
+
+            This curve preserves most of the information of the image at the
+            expense of a very artificial look. It is therefore best suited for
+            technical analysis.
+  - WdrStrength:
+      type: float
+      direction: in
+      description: |
+        Specify the strength of the wdr algorithm. The exact meaning of this
+        value is specific to the algorithm in use. Usually a value of 0 means no
+        global tone mapping is applied. A values of 1 is the default value and
+        the correct value for most scenes. A value above 1 increases the global
+        tone mapping effect and can lead to unrealistic image effects.
+  - WdrMaxBrightPixels:
+      type: float
+      direction: in
+      description: |
+        Percentage of allowed (nearly) saturated pixels. The WDR algorithm
+        reduces the WdrExposureValue until the amount of pixels that are close
+        to saturation is lower than this value.
+
+  - LensDewarpEnable:
+      type: bool
+      direction: inout
+      description: |
+        Enable or disable lens dewarping. This control is only available if lens
+        dewarp parameters are configured in the tuning file.
+
 ...
diff -pruN 0.5.0-1/src/libcamera/control_ids_rpi.yaml 0.6.0-2/src/libcamera/control_ids_rpi.yaml
--- 0.5.0-1/src/libcamera/control_ids_rpi.yaml	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/control_ids_rpi.yaml	2025-11-27 11:55:28.000000000 +0000
@@ -71,4 +71,116 @@ controls:
 
         \sa StatsOutputEnable
 
+  - SyncMode:
+      type: int32_t
+      direction: in
+      description: |
+        Enable or disable camera synchronisation ("sync") mode.
+
+        When sync mode is enabled, a camera will synchronise frames temporally
+        with other cameras, either attached to the same device or a different
+        one. There should be one "server" device, which broadcasts timing
+        information to one or more "clients". Communication is one-way, from
+        server to clients only, and it is only clients that adjust their frame
+        timings to match the server.
+
+        Sync mode requires all cameras to be running at (as far as possible) the
+        same fixed framerate. Clients may continue to make adjustments to keep
+        their cameras synchronised with the server for the duration of the
+        session, though any updates after the initial ones should remain small.
+
+        \sa SyncReady
+        \sa SyncTimer
+        \sa SyncFrames
+
+      enum:
+        - name: SyncModeOff
+          value: 0
+          description: Disable sync mode.
+        - name: SyncModeServer
+          value: 1
+          description: |
+            Enable sync mode, act as server. The server broadcasts timing
+            messages to any clients that are listening, so that the clients can
+            synchronise their camera frames with the server's.
+        - name: SyncModeClient
+          value: 2
+          description: |
+            Enable sync mode, act as client. A client listens for any server
+            messages, and arranges for its camera frames to synchronise as
+            closely as possible with the server's. Many clients can listen out
+            for the same server. Clients can also be started ahead of any
+            servers, causing them merely to wait for the server to start.
+
+  - SyncReady:
+      type: bool
+      direction: out
+      description: |
+        When using the camera synchronisation algorithm, the server broadcasts
+        timing information to the clients. This also includes the time (some
+        number of frames in the future, called the "ready time") at which the
+        server will signal its controlling application, using this control, to
+        start using the image frames.
+
+        The client receives the "ready time" from the server, and will signal
+        its application to start using the frames at this same moment.
+
+        While this control value is false, applications (on both client and
+        server) should continue to wait, and not use the frames.
+
+        Once this value becomes true, it means that this is the first frame
+        where the server and its clients have agreed that they will both be
+        synchronised and that applications should begin consuming frames.
+        Thereafter, this control will continue to signal the value true for
+        the rest of the session.
+
+        \sa SyncMode
+        \sa SyncTimer
+        \sa SyncFrames
+
+  - SyncTimer:
+      type: int64_t
+      direction: out
+      description: |
+        This reports the amount of time, in microseconds, until the "ready
+        time", at which the server and client will signal their controlling
+        applications that the frames are now synchronised and should be
+        used. The value may be refined slightly over time, becoming more precise
+        as the "ready time" approaches.
+
+        Servers always report this value, whereas clients will omit this control
+        until they have received a message from the server that enables them to
+        calculate it.
+
+        Normally the value will start positive (the "ready time" is in the
+        future), and decrease towards zero, before becoming negative (the "ready
+        time" has elapsed). So there should be just one frame where the timer
+        value is, or is very close to, zero - the one for which the SyncReady
+        control becomes true. At this moment, the value indicates how closely
+        synchronised the client believes it is with the server.
+
+        But note that if frames are being dropped, then the "near zero" valued
+        frame, or indeed any other, could be skipped. In these cases the timer
+        value allows an application to deduce that this has happened.
+
+        \sa SyncMode
+        \sa SyncReady
+        \sa SyncFrames
+
+  - SyncFrames:
+      type: int32_t
+      direction: in
+      description: |
+        The number of frames the server should wait, after enabling
+        SyncModeServer, before signalling (via the SyncReady control) that
+        frames should be used. This therefore determines the "ready time" for
+        all synchronised cameras.
+
+        This control value should be set only for the device that is to act as
+        the server, before or at the same moment at which SyncModeServer is
+        enabled.
+
+        \sa SyncMode
+        \sa SyncReady
+        \sa SyncTimer
 ...
diff -pruN 0.5.0-1/src/libcamera/control_serializer.cpp 0.6.0-2/src/libcamera/control_serializer.cpp
--- 0.5.0-1/src/libcamera/control_serializer.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/control_serializer.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -144,7 +144,7 @@ void ControlSerializer::reset()
 
 size_t ControlSerializer::binarySize(const ControlValue &value)
 {
-	return sizeof(ControlType) + value.data().size_bytes();
+	return value.data().size_bytes();
 }
 
 size_t ControlSerializer::binarySize(const ControlInfo &info)
@@ -164,7 +164,8 @@ size_t ControlSerializer::binarySize(con
 size_t ControlSerializer::binarySize(const ControlInfoMap &infoMap)
 {
 	size_t size = sizeof(struct ipa_controls_header)
-		    + infoMap.size() * sizeof(struct ipa_control_info_entry);
+		    + infoMap.size() * (sizeof(struct ipa_control_info_entry) +
+					3 * sizeof(struct ipa_control_value_entry));
 
 	for (const auto &ctrl : infoMap)
 		size += binarySize(ctrl.second);
@@ -184,7 +185,7 @@ size_t ControlSerializer::binarySize(con
 size_t ControlSerializer::binarySize(const ControlList &list)
 {
 	size_t size = sizeof(struct ipa_controls_header)
-		    + list.size() * sizeof(struct ipa_control_value_entry);
+		    + list.size() * sizeof(struct ipa_control_list_entry);
 
 	for (const auto &ctrl : list)
 		size += binarySize(ctrl.second);
@@ -195,16 +196,17 @@ size_t ControlSerializer::binarySize(con
 void ControlSerializer::store(const ControlValue &value,
 			      ByteStreamBuffer &buffer)
 {
-	const ControlType type = value.type();
-	buffer.write(&type);
 	buffer.write(value.data());
 }
 
-void ControlSerializer::store(const ControlInfo &info, ByteStreamBuffer &buffer)
-{
-	store(info.min(), buffer);
-	store(info.max(), buffer);
-	store(info.def(), buffer);
+void ControlSerializer::populateControlValueEntry(struct ipa_control_value_entry &entry,
+						  const ControlValue &value,
+						  uint32_t offset)
+{
+	entry.type = value.type();
+	entry.is_array = value.isArray();
+	entry.count = value.numElements();
+	entry.offset = offset;
 }
 
 /**
@@ -232,7 +234,8 @@ int ControlSerializer::serialize(const C
 
 	/* Compute entries and data required sizes. */
 	size_t entriesSize = infoMap.size()
-			   * sizeof(struct ipa_control_info_entry);
+			   * (sizeof(struct ipa_control_info_entry) +
+			      3 * sizeof(struct ipa_control_value_entry));
 	size_t valuesSize = 0;
 	for (const auto &ctrl : infoMap)
 		valuesSize += binarySize(ctrl.second);
@@ -280,11 +283,18 @@ int ControlSerializer::serialize(const C
 		struct ipa_control_info_entry entry;
 		entry.id = id->id();
 		entry.type = id->type();
-		entry.offset = values.offset();
 		entry.direction = static_cast<ControlId::DirectionFlags::Type>(id->direction());
-		entries.write(&entry);
 
-		store(info, values);
+		populateControlValueEntry(entry.min, info.min(), values.offset());
+		store(info.min(), values);
+
+		populateControlValueEntry(entry.max, info.max(), values.offset());
+		store(info.max(), values);
+
+		populateControlValueEntry(entry.def, info.def(), values.offset());
+		store(info.def(), values);
+
+		entries.write(&entry);
 	}
 
 	if (buffer.overflow())
@@ -341,7 +351,7 @@ int ControlSerializer::serialize(const C
 	else
 		idMapType = IPA_CONTROL_ID_MAP_V4L2;
 
-	size_t entriesSize = list.size() * sizeof(struct ipa_control_value_entry);
+	size_t entriesSize = list.size() * sizeof(struct ipa_control_list_entry);
 	size_t valuesSize = 0;
 	for (const auto &ctrl : list)
 		valuesSize += binarySize(ctrl.second);
@@ -365,12 +375,9 @@ int ControlSerializer::serialize(const C
 		unsigned int id = ctrl.first;
 		const ControlValue &value = ctrl.second;
 
-		struct ipa_control_value_entry entry;
+		struct ipa_control_list_entry entry;
 		entry.id = id;
-		entry.type = value.type();
-		entry.is_array = value.isArray();
-		entry.count = value.numElements();
-		entry.offset = values.offset();
+		populateControlValueEntry(entry.value, value, values.offset());
 		entries.write(&entry);
 
 		store(value, values);
@@ -383,12 +390,10 @@ int ControlSerializer::serialize(const C
 }
 
 ControlValue ControlSerializer::loadControlValue(ByteStreamBuffer &buffer,
+						 ControlType type,
 						 bool isArray,
 						 unsigned int count)
 {
-	ControlType type;
-	buffer.read(&type);
-
 	ControlValue value;
 
 	value.reserve(type, isArray, count);
@@ -397,15 +402,6 @@ ControlValue ControlSerializer::loadCont
 	return value;
 }
 
-ControlInfo ControlSerializer::loadControlInfo(ByteStreamBuffer &b)
-{
-	ControlValue min = loadControlValue(b);
-	ControlValue max = loadControlValue(b);
-	ControlValue def = loadControlValue(b);
-
-	return ControlInfo(min, max, def);
-}
-
 /**
  * \fn template<typename T> T ControlSerializer::deserialize(ByteStreamBuffer &buffer)
  * \brief Deserialize an object from a binary buffer
@@ -483,8 +479,7 @@ ControlInfoMap ControlSerializer::deseri
 
 	ControlInfoMap::Map ctrls;
 	for (unsigned int i = 0; i < hdr->entries; ++i) {
-		const struct ipa_control_info_entry *entry =
-			entries.read<decltype(*entry)>();
+		const auto *entry = entries.read<const ipa_control_info_entry>();
 		if (!entry) {
 			LOG(Serializer, Error) << "Out of data";
 			return {};
@@ -511,15 +506,43 @@ ControlInfoMap ControlSerializer::deseri
 		const ControlId *controlId = idMap->at(entry->id);
 		ASSERT(controlId);
 
-		if (entry->offset != values.offset()) {
+		const ipa_control_value_entry &min_entry = entry->min;
+		const ipa_control_value_entry &max_entry = entry->max;
+		const ipa_control_value_entry &def_entry = entry->def;
+
+		if (min_entry.offset != values.offset()) {
 			LOG(Serializer, Error)
-				<< "Bad data, entry offset mismatch (entry "
+				<< "Bad data, entry offset mismatch (min entry "
 				<< i << ")";
 			return {};
 		}
+		ControlValue min =
+			loadControlValue(values, static_cast<ControlType>(min_entry.type),
+					 min_entry.is_array, min_entry.count);
+
+		if (max_entry.offset != values.offset()) {
+			LOG(Serializer, Error)
+				<< "Bad data, entry offset mismatch (max entry "
+				<< i << ")";
+			return {};
+		}
+		ControlValue max =
+			loadControlValue(values, static_cast<ControlType>(max_entry.type),
+					 max_entry.is_array, max_entry.count);
+
+		if (def_entry.offset != values.offset()) {
+			LOG(Serializer, Error)
+				<< "Bad data, entry offset mismatch (def entry "
+				<< i << ")";
+			return {};
+		}
+		ControlValue def =
+			loadControlValue(values, static_cast<ControlType>(def_entry.type),
+					 def_entry.is_array, def_entry.count);
+
 
 		/* Create and store the ControlInfo. */
-		ctrls.emplace(controlId, loadControlInfo(values));
+		ctrls.emplace(controlId, ControlInfo(min, max, def));
 	}
 
 	/*
@@ -601,8 +624,10 @@ ControlList ControlSerializer::deseriali
 
 		case IPA_CONTROL_ID_MAP_V4L2:
 		default:
-			LOG(Serializer, Fatal)
-				<< "A list of V4L2 controls requires an ControlInfoMap";
+			if (hdr->entries > 0)
+				LOG(Serializer, Fatal)
+					<< "A list of V4L2 controls requires a ControlInfoMap";
+
 			return {};
 		}
 	}
@@ -616,12 +641,12 @@ ControlList ControlSerializer::deseriali
 	ControlList ctrls(*idMap);
 
 	for (unsigned int i = 0; i < hdr->entries; ++i) {
-		const struct ipa_control_value_entry *entry =
-			entries.read<decltype(*entry)>();
-		if (!entry) {
+		auto *list_entry = entries.read<const ipa_control_list_entry>();
+		if (!list_entry) {
 			LOG(Serializer, Error) << "Out of data";
 			return {};
 		}
+		const ipa_control_value_entry *entry = &list_entry->value;
 
 		if (entry->offset != values.offset()) {
 			LOG(Serializer, Error)
@@ -630,8 +655,9 @@ ControlList ControlSerializer::deseriali
 			return {};
 		}
 
-		ctrls.set(entry->id,
-			  loadControlValue(values, entry->is_array, entry->count));
+		ctrls.set(list_entry->id,
+			  loadControlValue(values, static_cast<ControlType>(entry->type),
+					   entry->is_array, entry->count));
 	}
 
 	return ctrls;
diff -pruN 0.5.0-1/src/libcamera/controls.cpp 0.6.0-2/src/libcamera/controls.cpp
--- 0.5.0-1/src/libcamera/controls.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/controls.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -626,35 +626,6 @@ ControlInfo::ControlInfo(Span<const Cont
 }
 
 /**
- * \brief Construct a boolean ControlInfo with both boolean values
- * \param[in] values The control valid boolean values (both true and false)
- * \param[in] def The control default boolean value
- *
- * Construct a ControlInfo for a boolean control, where both true and false are
- * valid values. \a values must be { false, true } (the order is irrelevant).
- * The minimum value will always be false, and the maximum always true. The
- * default value is \a def.
- */
-ControlInfo::ControlInfo(std::set<bool> values, bool def)
-	: min_(false), max_(true), def_(def), values_({ false, true })
-{
-	ASSERT(values.count(def) && values.size() == 2);
-}
-
-/**
- * \brief Construct a boolean ControlInfo with only one valid value
- * \param[in] value The control valid boolean value
- *
- * Construct a ControlInfo for a boolean control, where there is only valid
- * value. The minimum, maximum, and default values will all be \a value.
- */
-ControlInfo::ControlInfo(bool value)
-	: min_(value), max_(value), def_(value)
-{
-	values_ = { value };
-}
-
-/**
  * \fn ControlInfo::min()
  * \brief Retrieve the minimum value of the control
  *
@@ -857,15 +828,7 @@ const ControlInfoMap::mapped_type &Contr
  */
 ControlInfoMap::size_type ControlInfoMap::count(unsigned int id) const
 {
-	if (!idmap_)
-		return 0;
-
-	/*
-	 * The ControlInfoMap and its idmap have a 1:1 mapping between their
-	 * entries, we can thus just count the matching entries in idmap to
-	 * avoid an additional lookup.
-	 */
-	return idmap_->count(id);
+	return find(id) != end();
 }
 
 /**
diff -pruN 0.5.0-1/src/libcamera/converter/converter_dw100.cpp 0.6.0-2/src/libcamera/converter/converter_dw100.cpp
--- 0.5.0-1/src/libcamera/converter/converter_dw100.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/libcamera/converter/converter_dw100.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,496 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ *
+ * DW100 Dewarp Engine integration
+ */
+
+#include "libcamera/internal/converter/converter_dw100.h"
+
+#include <linux/dw100.h>
+
+#include <libcamera/base/log.h>
+
+#include <libcamera/geometry.h>
+#include <libcamera/stream.h>
+
+#include "libcamera/internal/converter.h"
+#include "libcamera/internal/converter/converter_v4l2_m2m.h"
+#include "libcamera/internal/media_device.h"
+#include "libcamera/internal/v4l2_videodevice.h"
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(Converter)
+
+/**
+ * \class libcamera::ConverterDW100Module
+ * \brief A converter module for the dw100 dewarper
+ *
+ * This class implements a converter module with direct support for libcamera
+ * controls. Functionality wise it closely resembles the libcamera::Converter
+ * interface. The main difference is that V4L2 requests are handled internally
+ * and it has direct support for libcamera controls.
+ */
+
+ConverterDW100Module::ConverterDW100Module(std::shared_ptr<MediaDevice> media)
+	: converter_(media), running_(false)
+{
+	converter_.outputBufferReady.connect(&this->outputBufferReady, &Signal<FrameBuffer *>::emit);
+	converter_.inputBufferReady.connect(&this->inputBufferReady, &Signal<FrameBuffer *>::emit);
+}
+
+/**
+ * \brief Create a ConverterDW100Module
+ * \param[in] enumerator The enumerator
+ *
+ * Static factory function that searches for the dw100 device using the provided
+ * \a enumerator. If found, a ConverterDW100Module is instantiated and returned.
+ *
+ * \return A ConverterDW100Module or null if no converter was found
+ */
+std::unique_ptr<ConverterDW100Module>
+ConverterDW100Module::createModule(DeviceEnumerator *enumerator)
+{
+	DeviceMatch dwp("dw100");
+	dwp.add("dw100-source");
+	dwp.add("dw100-sink");
+
+	std::shared_ptr<MediaDevice> dwpMediaDevice = enumerator->search(dwp);
+	if (!dwpMediaDevice)
+		return {};
+
+	std::unique_ptr<ConverterDW100Module> dwpModule{ new ConverterDW100Module(dwpMediaDevice) };
+	if (dwpModule->converter_.isValid())
+		return dwpModule;
+
+	LOG(Converter, Warning)
+		<< "Found DW100 dewarper " << dwpMediaDevice->deviceNode()
+		<< " but invalid";
+	return {};
+}
+
+/**
+ * \brief Initialize the module with configuration data
+ * \param[in] params The config parameters
+ *
+ * This function shall be called from the pipeline handler to initialize the
+ * module with the provided parameters.
+ *
+ * A typical tuning file entry for the dewarper looks like this:
+ * \code{.unparsed}
+ * modules:
+ * - Dewarp:
+ *    cm: [
+ *      1.0, 0.0, 0.0,
+ *      0.0, 1.0, 0.0,
+ *      0.0, 0.0, 1.0,
+ *    ]
+ *    coefficients: [
+ *      0,0,0,0,0,
+ *    ]
+ * \endcode
+ *
+ * The \a cm and \a coefficients parameters are documented in
+ * Dw100VertexMap::setDewarpParams()
+ *
+ * \sa Dw100VertexMap::setDewarpParams()
+ * \return 0 if successful, an error code otherwise
+ */
+int ConverterDW100Module::init(const YamlObject &params)
+{
+	DewarpParms dp;
+
+	auto &cm = params["cm"];
+	auto &coefficients = params["coefficients"];
+
+	/* If nothing is provided, the dewarper is still functional */
+	if (!cm && !coefficients)
+		return 0;
+
+	if (!cm) {
+		LOG(Converter, Error) << "Dewarp parameters are missing 'cm' value";
+		return -EINVAL;
+	}
+
+	auto matrix = cm.get<Matrix<double, 3, 3>>();
+	if (!matrix) {
+		LOG(Converter, Error) << "Failed to load 'cm' value";
+		return -EINVAL;
+	}
+
+	dp.cm = *matrix;
+
+	if (!coefficients) {
+		LOG(Converter, Error) << "Dewarp parameters are missing 'coefficients' value";
+		return -EINVAL;
+	}
+
+	const auto coeffs = coefficients.getList<double>();
+	if (!coeffs) {
+		LOG(Converter, Error) << "Dewarp parameters 'coefficients' value is not a list";
+		return -EINVAL;
+	}
+	dp.coeffs = std::move(*coeffs);
+
+	dewarpParams_ = dp;
+
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::configure
+ */
+int ConverterDW100Module::configure(const StreamConfiguration &inputCfg,
+				    const std::vector<std::reference_wrapper<StreamConfiguration>>
+					    &outputCfgs)
+{
+	int ret;
+
+	vertexMaps_.clear();
+	ret = converter_.configure(inputCfg, outputCfgs);
+	if (ret)
+		return ret;
+
+	inputBufferCount_ = inputCfg.bufferCount;
+
+	for (auto &ref : outputCfgs) {
+		const auto &outputCfg = ref.get();
+		auto &info = vertexMaps_[outputCfg.stream()];
+		auto &vertexMap = info.map;
+		vertexMap.setInputSize(inputCfg.size);
+		vertexMap.setOutputSize(outputCfg.size);
+		vertexMap.setSensorCrop(sensorCrop_);
+
+		if (dewarpParams_)
+			vertexMap.setDewarpParams(dewarpParams_->cm, dewarpParams_->coeffs);
+		info.update = true;
+	}
+
+	return 0;
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::isConfigured
+ */
+bool ConverterDW100Module::isConfigured(const Stream *stream) const
+{
+	return vertexMaps_.find(stream) != vertexMaps_.end();
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::adjustInputSize
+ */
+Size ConverterDW100Module::adjustInputSize(const PixelFormat &pixFmt,
+					   const Size &size,
+					   Converter::Alignment align)
+{
+	return converter_.adjustInputSize(pixFmt, size, align);
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::adjustOutputSize
+ */
+Size ConverterDW100Module::adjustOutputSize(const PixelFormat &pixFmt,
+					    const Size &size,
+					    Converter::Alignment align)
+{
+	return converter_.adjustOutputSize(pixFmt, size, align);
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::exportBuffers
+ */
+int ConverterDW100Module::exportBuffers(const Stream *stream, unsigned int count,
+					std::vector<std::unique_ptr<FrameBuffer>> *buffers)
+{
+	return converter_.exportBuffers(stream, count, buffers);
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::validateOutput
+ */
+int ConverterDW100Module::validateOutput(StreamConfiguration *cfg,
+					 bool *adjusted,
+					 Converter::Alignment align)
+{
+	return converter_.validateOutput(cfg, adjusted, align);
+}
+
+/**
+ * \brief Queue buffers to converter device
+ * \param[in] input The frame buffer to apply the conversion
+ * \param[out] outputs The container holding the output stream pointers and
+ * their respective frame buffer outputs.
+ *
+ * This function queues the \a input frame buffer and the output frame buffers
+ * contained in \a outputs to the device for processing.
+ *
+ * Controls are automatically applied to the device before queuing buffers. V4L2
+ * requests are used to atomically apply the controls if the kernel supports it.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int ConverterDW100Module::queueBuffers(FrameBuffer *input,
+				       const std::map<const Stream *, FrameBuffer *> &outputs)
+{
+	int ret;
+
+	V4L2Request *request = nullptr;
+	if (!requests_.empty()) {
+		/* If we have requests support, there must be one available */
+		ASSERT(!availableRequests_.empty());
+		request = availableRequests_.front();
+		availableRequests_.pop();
+	}
+
+	for (auto &[stream, buffer] : outputs) {
+		ret = applyControls(stream, request);
+		if (ret) {
+			reinitRequest(request);
+			return ret;
+		}
+	}
+
+	ret = converter_.queueBuffers(input, outputs, request);
+	if (ret) {
+		reinitRequest(request);
+		return ret;
+	}
+
+	if (!request)
+		return 0;
+
+	ret = request->queue();
+	if (ret < 0) {
+		LOG(Converter, Error) << "Failed to queue dewarp request: -"
+				      << strerror(-ret);
+		/* Push it back into the queue. */
+		reinitRequest(request);
+	}
+
+	return ret;
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::start
+ */
+int ConverterDW100Module::start()
+{
+	int ret;
+
+	if (converter_.supportsRequests()) {
+		ret = converter_.allocateRequests(inputBufferCount_,
+						  &requests_);
+		if (ret < 0) {
+			LOG(Converter, Error) << "Failed to allocate requests.";
+			return ret;
+		}
+	}
+
+	for (std::unique_ptr<V4L2Request> &request : requests_) {
+		request->requestDone.connect(this, &ConverterDW100Module::reinitRequest);
+		availableRequests_.push(request.get());
+	}
+
+	/*
+	 * Apply controls on all streams, to support older kernels without
+	 * request and dynamic vertex map support.
+	 */
+	for (auto &[stream, info] : vertexMaps_)
+		applyControls(stream, nullptr);
+
+	ret = converter_.start();
+	if (!ret) {
+		running_ = true;
+		return 0;
+	}
+
+	availableRequests_ = {};
+	requests_.clear();
+	return ret;
+}
+
+/**
+ * \copydoc libcamera::V4L2M2MConverter::stop
+ */
+void ConverterDW100Module::stop()
+{
+	running_ = false;
+	converter_.stop();
+	availableRequests_ = {};
+	requests_.clear();
+}
+
+/**
+ * \brief Update the controls
+ * \param[in] stream The stream
+ * \param[inout] controls The controls info map to update
+ *
+ * Updated the \a controls map with all the controls and limits provided by this
+ * class.
+ */
+void ConverterDW100Module::updateControlInfos(const Stream *stream, ControlInfoMap::Map &controls)
+{
+	ControlValue scalerCropDefault = sensorCrop_;
+
+	if (isConfigured(stream)) {
+		auto &info = vertexMaps_[stream];
+		info.map.applyLimits();
+		scalerCropDefault = info.map.effectiveScalerCrop();
+	}
+
+	controls[&controls::ScalerCrop] = ControlInfo(Rectangle(sensorCrop_.x, sensorCrop_.y, 1, 1),
+						      sensorCrop_, sensorCrop_);
+
+	if (dewarpParams_.has_value())
+		controls[&controls::LensDewarpEnable] = ControlInfo(false, true, true);
+
+	if (!converter_.supportsRequests())
+		LOG(Converter, Warning)
+			<< "dw100 kernel driver has no requests support."
+			   " Dynamic configuration is not possible.";
+}
+
+/**
+ * \brief Set libcamera controls
+ * \param[in] stream The stream to update
+ * \param[in] controls The controls
+ *
+ * Looks up all supported controls in \a controls and sets them on stream \a
+ * stream. The controls will be applied to the device on the next call to
+ * queueBuffers().
+ */
+void ConverterDW100Module::setControls(const Stream *stream, const ControlList &controls)
+{
+	if (!isConfigured(stream))
+		return;
+
+	auto &info = vertexMaps_[stream];
+	auto &vertexMap = info.map;
+
+	const auto &lensDewarpEnable = controls.get(controls::LensDewarpEnable);
+	if (lensDewarpEnable) {
+		vertexMap.setLensDewarpEnable(*lensDewarpEnable);
+		info.update = true;
+	}
+
+	const auto &crop = controls.get(controls::ScalerCrop);
+	if (crop) {
+		vertexMap.setScalerCrop(*crop);
+		info.update = true;
+	}
+
+	if (info.update && running_ && !converter_.supportsRequests())
+		LOG(Converter, Error)
+			<< "Dynamically setting dw100 specific controls requires"
+			   " a dw100 kernel driver with requests support";
+}
+
+/**
+ * \brief Retrieve updated metadata
+ * \param[in] stream The stream
+ * \param[in] meta The metadata list
+ *
+ * This function retrieves the metadata for the provided \a stream and writes it
+ * to \a list. It shall be called after queueBuffers().
+ */
+void ConverterDW100Module::populateMetadata(const Stream *stream, ControlList &meta)
+{
+	if (!isConfigured(stream))
+		return;
+
+	auto &vertexMap = vertexMaps_[stream].map;
+
+	meta.set(controls::ScalerCrop, vertexMap.effectiveScalerCrop());
+
+	if (dewarpParams_.has_value())
+		meta.set(controls::LensDewarpEnable, vertexMap.lensDewarpEnable());
+}
+
+/**
+ * \var ConverterDW100Module::inputBufferReady
+ * \brief A signal emitted when the input frame buffer completes
+ */
+
+/**
+ * \var ConverterDW100Module::outputBufferReady
+ * \brief A signal emitted on each frame buffer completion of the output queue
+ */
+
+/**
+ * \brief Set sensor crop rectangle
+ * \param[in] rect The crop rectangle
+ *
+ * Set the sensor crop rectangle to \a rect. This rectangle describes the area
+ * covered by the input buffers in sensor coordinates. It is used internally
+ * to handle the ScalerCrop control and related metadata.
+ */
+void ConverterDW100Module::setSensorCrop(const Rectangle &rect)
+{
+	sensorCrop_ = rect;
+	for (auto &[stream, vertexMap] : vertexMaps_) {
+		vertexMap.map.setSensorCrop(rect);
+		vertexMap.update = true;
+	}
+}
+
+/**
+ * \brief Set transform
+ * \param[in] stream The stream
+ * \param[in] transform The transform
+ *
+ * Set the transform that shall be applied by the dewarper on the given stream.
+ * As orientation is a property of libcamera::CameraConfiguration, the transform
+ * needs to be set at configure time.
+ */
+void ConverterDW100Module::setTransform(const Stream *stream, const Transform &transform)
+{
+	if (!isConfigured(stream))
+		return;
+
+	vertexMaps_[stream].map.setTransform(transform);
+}
+
+void ConverterDW100Module::reinitRequest(V4L2Request *request)
+{
+	if (!request)
+		return;
+
+	request->reinit();
+	availableRequests_.push(request);
+}
+
+/**
+ * \brief Apply the vertex map for a given stream
+ * \param[in] stream The stream to update
+ * \param[in] request An optional request
+ *
+ * This function updates the vertex map on the stream \a stream. If \a request
+ * is provided, the update happens in that request.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int ConverterDW100Module::applyControls(const Stream *stream, const V4L2Request *request)
+{
+	if (!isConfigured(stream))
+		return -EINVAL;
+
+	auto &info = vertexMaps_[stream];
+	if (!info.update)
+		return 0;
+
+	std::vector<uint32_t> map = info.map.getVertexMap();
+	auto value = Span<const int32_t>(reinterpret_cast<const int32_t *>(&map[0]), map.size());
+
+	ControlList ctrls;
+	ctrls.set(V4L2_CID_DW100_DEWARPING_16x16_VERTEX_MAP, value);
+
+	int ret = converter_.applyControls(stream, ctrls, request);
+	if (!ret)
+		info.update = false;
+
+	return ret;
+}
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/converter/converter_dw100_vertexmap.cpp 0.6.0-2/src/libcamera/converter/converter_dw100_vertexmap.cpp
--- 0.5.0-1/src/libcamera/converter/converter_dw100_vertexmap.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/libcamera/converter/converter_dw100_vertexmap.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,657 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ *
+ * DW100 vertex map implementation
+ */
+
+#include "libcamera/internal/converter/converter_dw100_vertexmap.h"
+
+#include <algorithm>
+#include <assert.h>
+#include <cmath>
+#include <stdint.h>
+#include <utility>
+#include <vector>
+
+#include <libcamera/base/log.h>
+#include <libcamera/base/span.h>
+
+#include <libcamera/geometry.h>
+#include <libcamera/transform.h>
+
+#include "libcamera/internal/vector.h"
+
+constexpr int kDw100BlockSize = 16;
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(Converter)
+namespace {
+
+using Vector2d = Vector<double, 2>;
+using Vector3d = Vector<double, 3>;
+using Matrix3x3 = Matrix<double, 3, 3>;
+
+Matrix3x3 makeTranslate(const double tx, const double ty)
+{
+	Matrix3x3 m = Matrix3x3::identity();
+	m[0][2] = tx;
+	m[1][2] = ty;
+	return m;
+}
+
+Matrix3x3 makeTranslate(const Vector2d &t)
+{
+	return makeTranslate(t.x(), t.y());
+}
+
+Matrix3x3 makeRotate(const double degrees)
+{
+	double rad = degrees / 180.0 * M_PI;
+	double sa = std::sin(rad);
+	double ca = std::cos(rad);
+
+	Matrix3x3 m = Matrix3x3::identity();
+	m[0][0] = ca;
+	m[0][1] = -sa;
+	m[1][0] = sa;
+	m[1][1] = ca;
+	return m;
+}
+
+Matrix3x3 makeScale(const double sx, const double sy)
+{
+	Matrix3x3 m = Matrix3x3::identity();
+	m[0][0] = sx;
+	m[1][1] = sy;
+	return m;
+}
+
+/**
+ * \param t The transform to apply
+ * \param size The size of the rectangle that is transformed
+ *
+ * Create a matrix that represents the transform done by the \a t. It assumes
+ * that the origin of the coordinate system is at the top left corner of of the
+ * rectangle.
+ */
+Matrix3x3 makeTransform(const Transform &t, const Size &size)
+{
+	Matrix3x3 m = Matrix3x3::identity();
+	double wm = size.width * 0.5;
+	double hm = size.height * 0.5;
+	m = makeTranslate(-wm, -hm) * m;
+
+	if (!!(t & Transform::HFlip))
+		m = makeScale(-1, 1) * m;
+
+	if (!!(t & Transform::VFlip))
+		m = makeScale(1, -1) * m;
+
+	if (!!(t & Transform::Transpose)) {
+		m = makeRotate(-90) * m;
+		m = makeScale(1, -1) * m;
+		std::swap(wm, hm);
+	}
+
+	m = makeTranslate(wm, hm) * m;
+
+	return m;
+}
+
+/**
+ * \param from The source rectangle
+ * \param to The destination rectangle
+ *
+ * Create a matrix that transforms from the coordinate system of rectangle \a
+ * from into the coordinate system of rectangle \a to, by overlaying the
+ * rectangles.
+ *
+ * \see Rectangle::transformedBetween()
+ */
+Matrix3x3 makeTransform(const Rectangle &from, const Rectangle &to)
+{
+	Matrix3x3 m = Matrix3x3::identity();
+	double sx = to.width / static_cast<double>(from.width);
+	double sy = to.height / static_cast<double>(from.height);
+	m = makeTranslate(-from.x, -from.y) * m;
+	m = makeScale(sx, sy) * m;
+	m = makeTranslate(to.x, to.y) * m;
+	return m;
+}
+
+Vector2d transformPoint(const Matrix3x3 &m, const Vector2d &p)
+{
+	Vector3d p2{ { p.x(), p.y(), 1.0 } };
+	p2 = m * p2;
+	return { { p2.x() / p2.z(), p2.y() / p2.z() } };
+}
+
+Vector2d transformVector(const Matrix3x3 &m, const Vector2d &p)
+{
+	Vector3d p2{ { p.x(), p.y(), 0.0 } };
+	p2 = m * p2;
+	return { { p2.x(), p2.y() } };
+}
+
+Vector2d rotatedRectSize(const Vector2d &size, const double degrees)
+{
+	double rad = degrees / 180.0 * M_PI;
+	double sa = sin(rad);
+	double ca = cos(rad);
+
+	return { { std::abs(size.x() * ca) + std::abs(size.y() * sa),
+		   std::abs(size.x() * sa) + std::abs(size.y() * ca) } };
+}
+
+Vector2d point2Vec2d(const Point &p)
+{
+	return { { static_cast<double>(p.x), static_cast<double>(p.y) } };
+}
+
+int dw100VerticesForLength(const int length)
+{
+	return (length + kDw100BlockSize - 1) / kDw100BlockSize + 1;
+}
+
+} /* namespace */
+
+/**
+ * \class libcamera::Dw100VertexMap
+ * \brief Helper class to compute dw100 vertex maps
+ *
+ * The vertex map class represents a helper for handling dewarper vertex maps.
+ * There are 3 important sizes in the system:
+ *
+ * - The sensor size. The number of pixels of the whole sensor.
+ * - The input rectangle to the dewarper. Describes the pixel data flowing into
+ *   the dewarper in sensor coordinates.
+ * - ScalerCrop rectangle. The rectangle that shall be used for all further
+ *   stages. It is applied after lens dewarping but is in sensor coordinate
+ *   space.
+ * - The output size. This defines the size, the dewarper should output.
+ *
+ * +------------------------+
+ * |Sensor size             |
+ * |   +----------------+   |
+ * |   |  Input rect    |   |
+ * |   |  +-------------+   |
+ * |   |  | ScalerCrop  |   |
+ * |   |  |             |   |
+ * |   +--+-------------+   |
+ * +------------------------+
+ *
+ * This class implements a vertex map that forms the following pipeline:
+ *
+ * +-------------+    +-------------+    +------------+    +-----------------+
+ * |             |    |             |    | Transform  |    | Pan/Zoom        |
+ * | Lens Dewarp | -> | Scaler Crop | -> | (H/V Flip, | -> | (Offset, Scale, |
+ * |             |    |             |    | Transpose) |    | Rotate)         |
+ * +-------------+    +-------------+    +------------+    +-----------------+
+ *
+ * All parameters are clamped to valid values before creating the vertex map.
+ *
+ * The constraints process works as follows:
+ * - The ScalerCrop rectangle is clamped to the input rectangle
+ * - The ScalerCrop rectangle is transformed by the specified transform
+ *   forming ScalerCropT
+ * - A rectangle of output size is placed in the center of ScalerCropT
+ *   (OutputRect).
+ * - Rotate gets applied to OutputRect,
+ * - Scale is applied, but clamped so that the OutputRect fits completely into
+ *   ScalerCropT (Only regarding dimensions, not position)
+ * - Offset is clamped so that the OutputRect lies inside ScalerCropT
+ *
+ * After applying the limits, the actual values used for processing are stored
+ * effectiveXXX members and can be queried using the corresponding functions.
+ *
+ * The lens dewarp map is usually calibrated during tuning and is a map that
+ * maps from incoming pixels to dewarped pixels.
+ */
+
+/**
+ * \enum Dw100VertexMap::ScaleMode
+ * \brief The scale modes available for a vertex map
+ *
+ * \var Dw100VertexMap::Fill
+ * \brief Scale the input to fill the output
+ *
+ * This scale mode does not preserve aspect ratio. Offset and rotation are taken
+ * into account.
+ *
+ * \var Dw100VertexMap::Crop
+ * \brief Crop the input
+ *
+ * This scale mode preserves the aspect ratio. Offset, scale, rotation are taken
+ * into account within the possible limits.
+ */
+
+/**
+ * \brief Apply limits on scale and offset
+ *
+ * This function calculates \a effectiveScalerCrop_, \a effectiveScale_ and \a
+ * effectiveOffset_ based on the requested scaler crop, scale, rotation, offset
+ * and the selected scale mode, so that the whole output area is filled with
+ * valid input data.
+ */
+void Dw100VertexMap::applyLimits()
+{
+	int ow = outputSize_.width;
+	int oh = outputSize_.height;
+	effectiveScalerCrop_ = scalerCrop_.boundedTo(sensorCrop_);
+
+	/* Map the scalerCrop to the input pixel space */
+	Rectangle localScalerCrop = effectiveScalerCrop_.transformedBetween(
+		sensorCrop_, Rectangle(inputSize_));
+
+	Size localCropSizeT = localScalerCrop.size();
+	if (!!(transform_ & Transform::Transpose))
+		std::swap(localCropSizeT.width, localCropSizeT.height);
+
+	Vector2d size = rotatedRectSize(point2Vec2d({ ow, oh }), rotation_);
+
+	if (mode_ != Crop && mode_ != Fill) {
+		LOG(Converter, Error)
+			<< "Unknown mode " << mode_ << ". Default to 'Fill'";
+		mode_ = Fill;
+	}
+
+	/* Calculate constraints */
+	double scale = scale_;
+	if (mode_ == Crop) {
+		/* Scale up if needed */
+		scale = std::max(scale,
+				 std::max(size.x() / localCropSizeT.width,
+					  size.y() / localCropSizeT.height));
+		effectiveScaleX_ = scale;
+		effectiveScaleY_ = scale;
+
+		size = size / scale;
+
+	} else if (mode_ == Fill) {
+		effectiveScaleX_ = size.x() / localCropSizeT.width;
+		effectiveScaleY_ = size.y() / localCropSizeT.height;
+
+		size.x() /= effectiveScaleX_;
+		size.y() /= effectiveScaleY_;
+	}
+
+	/*
+	 * Clamp offset. Due to rounding errors, size might be slightly bigger
+	 * than scaler crop. Clamp the offset to 0 to prevent a crash in the
+	 * next clamp.
+	 */
+	double maxoffX, maxoffY;
+	maxoffX = std::max(0.0, (localCropSizeT.width - size.x())) * 0.5;
+	maxoffY = std::max(0.0, (localCropSizeT.height - size.y())) * 0.5;
+	if (!!(transform_ & Transform::Transpose))
+		std::swap(maxoffX, maxoffY);
+
+	/*
+	 * Transform the offset from sensor space to local space, apply the
+	 * limit and transform back.
+	 */
+	Vector2d offset = point2Vec2d(offset_);
+	Matrix3x3 m;
+
+	m = makeTransform(effectiveScalerCrop_, localScalerCrop);
+	offset = transformVector(m, offset);
+	offset.x() = std::clamp(offset.x(), -maxoffX, maxoffX);
+	offset.y() = std::clamp(offset.y(), -maxoffY, maxoffY);
+	m = makeTransform(localScalerCrop, effectiveScalerCrop_);
+	offset = transformVector(m, offset);
+	effectiveOffset_.x = offset.x();
+	effectiveOffset_.y = offset.y();
+}
+
+/**
+ * \fn Dw100VertexMap::setInputSize()
+ * \brief Set the size of the input data
+ * \param[in] size The input size
+ *
+ * To calculate a proper vertex map, the size of the input images must be set.
+ */
+
+/**
+ * \fn Dw100VertexMap::setSensorCrop()
+ * \brief Set the crop rectangle that represents the input data
+ * \param[in] rect
+ *
+ * Set the rectangle that represents the input data in sensor coordinates. This
+ * must be specified to properly calculate the vertex map.
+ */
+
+/**
+ * \fn Dw100VertexMap::setScalerCrop()
+ * \brief Set the requested scaler crop
+ * \param[in] rect
+ *
+ * Set the requested scaler crop. The actually applied scaler crop can be
+ * queried using \a Dw100VertexMap::effectiveScalerCrop() after calling
+ * Dw100VertexMap::applyLimits().
+ */
+
+/**
+ * \fn Dw100VertexMap::effectiveScalerCrop()
+ * \brief Get the effective scaler crop
+ *
+ * \return The effective scaler crop
+ */
+
+/**
+ * \fn Dw100VertexMap::setOutputSize()
+ * \brief Set the output size
+ * \param[in] size The size of the output images
+ */
+
+/**
+ * \fn Dw100VertexMap::outputSize()
+ * \brief Get the output size
+ * \return The output size
+ */
+
+/**
+ * \fn Dw100VertexMap::setTransform()
+ * \brief Sets the transform to apply
+ * \param[in] transform The transform
+ */
+
+/**
+ * \fn Dw100VertexMap::transform()
+ * \brief Get the transform
+ * \return The transform
+ */
+
+/**
+ * \fn Dw100VertexMap::setScale()
+ * \brief Sets the scale to apply
+ * \param[in] scale The scale
+ *
+ * Set the requested scale. The actually applied scale can be queried using \a
+ * Dw100VertexMap::effectiveScale() after calling \a
+ * Dw100VertexMap::applyLimits().
+ */
+
+/**
+ * \fn Dw100VertexMap::effectiveScale()
+ * \brief Get the effective scale
+ *
+ * Returns the actual scale applied to the input pixels in x and y direction. So
+ * a value of [2.0, 1.5] means that every input pixel is scaled to cover 2
+ * output pixels in x-direction and 1.5 in y-direction.
+ *
+ * \return The effective scale
+ */
+
+/**
+ * \fn Dw100VertexMap::setRotation()
+ * \brief Sets the rotation to apply
+ * \param[in] rotation The rotation in degrees
+ *
+ * The rotation is in clockwise direction to allow the same transform as
+ * CameraConfiguration::orientation
+ */
+
+/**
+ * \fn Dw100VertexMap::rotation()
+ * \brief Get the rotation
+ * \return The rotation in degrees
+ */
+
+/**
+ * \fn Dw100VertexMap::setOffset()
+ * \brief Sets the offset to apply
+ * \param[in] offset The offset
+ *
+ * Set the requested offset. The actually applied offset can be queried using \a
+ * Dw100VertexMap::effectiveOffset() after calling \a
+ * Dw100VertexMap::applyLimits().
+ */
+
+/**
+ * \fn Dw100VertexMap::effectiveOffset()
+ * \brief Get the effective offset
+ *
+ * Returns the actual offset applied to the input pixels in ScalerCrop
+ * coordinates.
+ *
+ * \return The effective offset
+ */
+
+/**
+ * \fn Dw100VertexMap::setMode()
+ * \brief Sets the scaling mode to apply
+ * \param[in] mode The mode
+ */
+
+/**
+ * \fn Dw100VertexMap::mode()
+ * \brief Get the scaling mode
+ * \return The scaling mode
+ */
+
+/**
+ * \brief Get the dw100 vertex map
+ *
+ * Calculates the vertex map as a vector of hardware specific entries.
+ *
+ * \return The vertex map
+ */
+std::vector<uint32_t> Dw100VertexMap::getVertexMap()
+{
+	int ow = outputSize_.width;
+	int oh = outputSize_.height;
+	int tileCountW = dw100VerticesForLength(ow);
+	int tileCountH = dw100VerticesForLength(oh);
+
+	applyLimits();
+
+	/*
+	 * libcamera handles all crop rectangles in sensor space. But the
+	 * dewarper "sees" only the pixels it gets passed. Note that these might
+	 * not cover exactly the max sensor crop, as there might be a crop
+	 * between ISP and dewarper to crop to a format supported by the
+	 * dewarper. effectiveScalerCrop_ is the crop in sensor space that gets
+	 * fed into the dewarper. localScalerCrop is the sensor crop mapped to
+	 * the data that is fed into the dewarper.
+	 */
+	Rectangle localScalerCrop = effectiveScalerCrop_.transformedBetween(
+		sensorCrop_, Rectangle(inputSize_));
+	Size localCropSizeT = localScalerCrop.size();
+	if (!!(transform_ & Transform::Transpose))
+		std::swap(localCropSizeT.width, localCropSizeT.height);
+
+	/*
+	 * The dw100 has a specialty in interpolation that has to be taken into
+	 * account to use in a pixel perfect manner. To explain this, I will
+	 * only use the x direction, the vertical axis behaves the same.
+	 *
+	 * Let's start with a pixel perfect 1:1 mapping of an image with a width
+	 * of 64pixels. The coordinates of the vertex map would then be:
+	 * 0 -- 16 -- 32 -- 48 -- 64
+	 * Note how the last coordinate lies outside the image (which ends at
+	 * 63) as it is basically the beginning of the next macro block.
+	 *
+	 * if we zoom out a bit we might end up with something like
+	 * -10 -- 0 -- 32 -- 64 -- 74
+	 * As the dewarper coordinates are unsigned it actually sees
+	 * 0 -- 0 -- 32 -- 64 -- 74
+	 * Leading to stretched pixels at the beginning and black for everything
+	 * > 63
+	 *
+	 * Now lets rotate the image by 180 degrees. A trivial rotation would
+	 * end up with:
+	 *
+	 * 64 -- 48 -- 32 -- 16 -- 0
+	 *
+	 * But as the first column now points to pixel 64 we get a single black
+	 * line. So for a proper 180* rotation, the coordinates need to be
+	 *
+	 * 63 -- 47 -- 31 -- 15 -- -1
+	 *
+	 * The -1 is clamped to 0 again, leading to a theoretical slight
+	 * interpolation error on the last 16 pixels.
+	 *
+	 * To create this proper transformation there are two things todo:
+	 *
+	 * 1. The rotation centers are offset by -0.5. This evens out for no
+	 *    rotation, and leads to a coordinate offset of -1 on 180 degree
+	 *    rotations.
+	 * 2. The transformation (flip and transpose) need to act on a size-1
+	 *    to get the same effect.
+	 */
+	Vector2d centerS{ { localCropSizeT.width * 0.5 - 0.5,
+			    localCropSizeT.height * 0.5 - 0.5 } };
+	Vector2d centerD{ { ow * 0.5 - 0.5,
+			    oh * 0.5 - 0.5 } };
+
+	LOG(Converter, Debug)
+		<< "Apply vertex map for"
+		<< " inputSize: " << inputSize_
+		<< " outputSize: " << outputSize_
+		<< " Transform: " << transformToString(transform_)
+		<< "\n effectiveScalerCrop: " << effectiveScalerCrop_
+		<< " localCropSizeT: " << localCropSizeT
+		<< " scaleX: " << effectiveScaleX_
+		<< " scaleY: " << effectiveScaleX_
+		<< " rotation: " << rotation_
+		<< " offset: " << effectiveOffset_;
+
+	Matrix3x3 outputToSensor = Matrix3x3::identity();
+	/* Move to center of output */
+	outputToSensor = makeTranslate(-centerD) * outputToSensor;
+	outputToSensor = makeRotate(-rotation_) * outputToSensor;
+	outputToSensor = makeScale(1.0 / effectiveScaleX_, 1.0 / effectiveScaleY_) * outputToSensor;
+	/* Move to top left of localScalerCropT */
+	outputToSensor = makeTranslate(centerS) * outputToSensor;
+	outputToSensor = makeTransform(-transform_, localCropSizeT.shrunkBy({ 1, 1 })) *
+			 outputToSensor;
+	/* Transform from "within localScalerCrop" to input reference frame */
+	outputToSensor = makeTranslate(localScalerCrop.x, localScalerCrop.y) * outputToSensor;
+	outputToSensor = makeTransform(localScalerCrop, effectiveScalerCrop_) * outputToSensor;
+	outputToSensor = makeTranslate(point2Vec2d(effectiveOffset_)) * outputToSensor;
+
+	Matrix3x3 sensorToInput = makeTransform(effectiveScalerCrop_, localScalerCrop);
+
+	/*
+	 * For every output tile, calculate the position of the corners in the
+	 * input image.
+	 */
+	std::vector<uint32_t> res;
+	res.reserve(tileCountW * tileCountH);
+	for (int y = 0; y < tileCountH; y++) {
+		for (int x = 0; x < tileCountW; x++) {
+			Vector2d p{ { static_cast<double>(x) * kDw100BlockSize,
+				      static_cast<double>(y) * kDw100BlockSize } };
+			p = p.max(0.0).min(Vector2d{ { static_cast<double>(ow),
+						       static_cast<double>(oh) } });
+
+			p = transformPoint(outputToSensor, p);
+
+			if (dewarpParamsValid_ && lensDewarpEnable_)
+				p = dewarpPoint(p);
+
+			p = transformPoint(sensorToInput, p);
+
+			/* Convert to fixed point */
+			uint32_t v = static_cast<uint32_t>(p.y() * 16) << 16 |
+				     (static_cast<uint32_t>(p.x() * 16) & 0xffff);
+			res.push_back(v);
+		}
+	}
+
+	return res;
+}
+
+/**
+ * \brief Set the dewarp parameters
+ * \param cm The camera matrix
+ * \param coeffs The dewarp coefficients
+ *
+ * Sets the dewarp parameters according to the commonly used dewarp model. See
+ * https://docs.opencv.org/4.12.0/d9/d0c/group__calib3d.html for further details
+ * on the model. The parameter \a coeffs must either hold 4,5,8 or 12 values.
+ * They represent the parameters k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4]]] in
+ * the model.
+ *
+ * \return A negative number on error, 0 otherwise
+ */
+int Dw100VertexMap::setDewarpParams(const Matrix<double, 3, 3> &cm,
+				    const Span<const double> &coeffs)
+{
+	dewarpM_ = cm;
+	dewarpCoeffs_.fill(0.0);
+
+	if (coeffs.size() != 4 && coeffs.size() != 5 &&
+	    coeffs.size() != 8 && coeffs.size() != 12) {
+		LOG(Converter, Error)
+			<< "Dewarp 'coefficients' must have 4, 5, 8 or 12 values";
+		dewarpParamsValid_ = false;
+		return -EINVAL;
+	}
+	std::copy(coeffs.begin(), coeffs.end(), dewarpCoeffs_.begin());
+
+	dewarpParamsValid_ = true;
+	return 0;
+}
+
+/**
+ * \fn Dw100VertexMap::dewarpParamsValid()
+ * \brief Returns if the dewarp parameters are valid
+ *
+ * \return True if the dewarp parameters are valid, false otherwise
+ */
+
+/**
+ * \fn Dw100VertexMap::setLensDewarpEnable()
+ * \brief Enables or disables lens dewarping
+ * \param[in] enable Enable or disable lens dewarping
+ */
+
+/**
+ * \fn Dw100VertexMap::lensDewarpEnable()
+ * \brief Returns if lens dewarping is enabled
+ */
+
+/**
+ * \brief Apply dewarp calculation to a point
+ * \param p The point to dewarp
+ *
+ * Applies the dewarp transformation to point \a p according to the commonly
+ * used dewarp model. See
+ * https://docs.opencv.org/4.12.0/d9/d0c/group__calib3d.html for further details
+ * on the model.
+ *
+ * \return The dewarped point
+ */
+Vector2d Dw100VertexMap::dewarpPoint(const Vector2d &p)
+{
+	double x, y;
+	double k1 = dewarpCoeffs_[0];
+	double k2 = dewarpCoeffs_[1];
+	double p1 = dewarpCoeffs_[2];
+	double p2 = dewarpCoeffs_[3];
+	double k3 = dewarpCoeffs_[4];
+	double k4 = dewarpCoeffs_[5];
+	double k5 = dewarpCoeffs_[6];
+	double k6 = dewarpCoeffs_[7];
+	double s1 = dewarpCoeffs_[8];
+	double s2 = dewarpCoeffs_[9];
+	double s3 = dewarpCoeffs_[10];
+	double s4 = dewarpCoeffs_[11];
+
+	y = (p.y() - dewarpM_[1][2]) / dewarpM_[1][1];
+	x = (p.x() - dewarpM_[0][2] - y * dewarpM_[0][1]) / dewarpM_[0][0];
+
+	double r2 = x * x + y * y;
+	double d = (1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2) /
+		   (1 + k4 * r2 + k5 * r2 * r2 + k6 * r2 * r2 * r2);
+	x = x * d + 2 * p1 * x * y + p2 * (r2 + 2 * x * x) + s1 * r2 + s2 * r2 * r2;
+	y = y * d + 2 * p2 * x * y + p1 * (r2 + 2 * y * y) + s3 * r2 + s4 * r2 * r2;
+
+	return { { x * dewarpM_[0][0] + y * dewarpM_[0][1] + dewarpM_[0][2],
+		   y * dewarpM_[1][1] + dewarpM_[1][2] } };
+}
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/converter/converter_v4l2_m2m.cpp 0.6.0-2/src/libcamera/converter/converter_v4l2_m2m.cpp
--- 0.5.0-1/src/libcamera/converter/converter_v4l2_m2m.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/converter/converter_v4l2_m2m.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -9,17 +9,22 @@
 #include "libcamera/internal/converter/converter_v4l2_m2m.h"
 
 #include <algorithm>
+#include <errno.h>
 #include <limits.h>
+#include <memory>
+#include <set>
 
 #include <libcamera/base/log.h>
 #include <libcamera/base/signal.h>
 #include <libcamera/base/utils.h>
 
+#include <libcamera/controls.h>
 #include <libcamera/framebuffer.h>
 #include <libcamera/geometry.h>
 #include <libcamera/stream.h>
 
 #include "libcamera/internal/media_device.h"
+#include "libcamera/internal/v4l2_request.h"
 #include "libcamera/internal/v4l2_videodevice.h"
 
 /**
@@ -106,6 +111,7 @@ int V4L2M2MConverter::V4L2M2MStream::con
 	format.planesCount = 1;
 	format.planes[0].bpl = inputCfg.stride;
 
+	LOG(Converter, Debug) << "Set input format to: " << format;
 	int ret = m2m_->output()->setFormat(&format);
 	if (ret < 0) {
 		LOG(Converter, Error)
@@ -128,6 +134,7 @@ int V4L2M2MConverter::V4L2M2MStream::con
 	format.fourcc = videoFormat;
 	format.size = outputCfg.size;
 
+	LOG(Converter, Debug) << "Set output format to: " << format;
 	ret = m2m_->capture()->setFormat(&format);
 	if (ret < 0) {
 		LOG(Converter, Error)
@@ -195,9 +202,11 @@ void V4L2M2MConverter::V4L2M2MStream::st
 	m2m_->output()->releaseBuffers();
 }
 
-int V4L2M2MConverter::V4L2M2MStream::queueBuffers(FrameBuffer *input, FrameBuffer *output)
+int V4L2M2MConverter::V4L2M2MStream::queueBuffers(FrameBuffer *input,
+						  FrameBuffer *output,
+						  const V4L2Request *request)
 {
-	int ret = m2m_->output()->queueBuffer(input);
+	int ret = m2m_->output()->queueBuffer(input, request);
 	if (ret < 0)
 		return ret;
 
@@ -245,6 +254,20 @@ void V4L2M2MConverter::V4L2M2MStream::ca
 	converter_->outputBufferReady.emit(buffer);
 }
 
+/**
+ * \brief Apply controls
+ * \param[in] ctrls The controls to apply
+ * \param[in] request An optional request
+ *
+ * \return 0 on success or a negative error code otherwise
+ * \see V4L2Device::setControls()
+ */
+int V4L2M2MConverter::V4L2M2MStream::applyControls(ControlList &ctrls,
+						   const V4L2Request *request)
+{
+	return m2m_->capture()->setControls(&ctrls, request);
+}
+
 /* -----------------------------------------------------------------------------
  * V4L2M2MConverter
  */
@@ -260,9 +283,8 @@ void V4L2M2MConverter::V4L2M2MStream::ca
  * \brief Construct a V4L2M2MConverter instance
  * \param[in] media The media device implementing the converter
  */
-
-V4L2M2MConverter::V4L2M2MConverter(MediaDevice *media)
-	: Converter(media)
+V4L2M2MConverter::V4L2M2MConverter(std::shared_ptr<MediaDevice> media)
+	: Converter(media), media_(media)
 {
 	if (deviceNode().empty())
 		return;
@@ -675,6 +697,7 @@ int V4L2M2MConverter::validateOutput(Str
 
 	const Size cfgSize = cfg->size;
 	cfg->size = adjustSizes(cfgSize, it->second, align);
+	cfg->stride = PixelFormatInfo::info(cfg->pixelFormat).stride(cfg->size.width, 0);
 
 	if (cfg->size.isNull())
 		return -EINVAL;
@@ -695,7 +718,8 @@ int V4L2M2MConverter::validateOutput(Str
  * \copydoc libcamera::Converter::queueBuffers
  */
 int V4L2M2MConverter::queueBuffers(FrameBuffer *input,
-				   const std::map<const Stream *, FrameBuffer *> &outputs)
+				   const std::map<const Stream *, FrameBuffer *> &outputs,
+				   const V4L2Request *request)
 {
 	std::set<FrameBuffer *> outputBufs;
 	int ret;
@@ -720,7 +744,7 @@ int V4L2M2MConverter::queueBuffers(Frame
 
 	/* Queue the input and output buffers to all the streams. */
 	for (auto [stream, buffer] : outputs) {
-		ret = streams_.at(stream)->queueBuffers(input, buffer);
+		ret = streams_.at(stream)->queueBuffers(input, buffer, request);
 		if (ret < 0)
 			return ret;
 	}
@@ -737,6 +761,56 @@ int V4L2M2MConverter::queueBuffers(Frame
 	return 0;
 }
 
+/**
+ * \brief Apply controls
+ * \param[in] stream The stream on which to apply the controls
+ * \param[in] ctrls The controls to apply
+ * \param[in] request An optional request
+ *
+ * \return 0 on success or a negative error code otherwise
+ * \see V4L2Device::setControls()
+ */
+int V4L2M2MConverter::applyControls(const Stream *stream, ControlList &ctrls,
+				    const V4L2Request *request)
+{
+	auto iter = streams_.find(stream);
+	if (iter == streams_.end())
+		return -EINVAL;
+
+	return iter->second->applyControls(ctrls, request);
+}
+
+/**
+ * \copydoc libcamera::MediaDevice::allocateRequests
+ */
+int V4L2M2MConverter::allocateRequests(unsigned int count,
+				       std::vector<std::unique_ptr<V4L2Request>> *requests)
+{
+	/* \todo The acquire() must be moved to the right place. */
+	media_->acquire();
+	if (!media_->busy())
+		LOG(Converter, Error)
+			<< "MediaDevice must be valid.";
+	int ret = media_->allocateRequests(count, requests);
+	media_->release();
+	return ret;
+}
+
+/**
+ * \copydoc libcamera::MediaDevice::supportsRequests
+ */
+bool V4L2M2MConverter::supportsRequests()
+{
+	/* \todo The acquire() must be moved to the right place. */
+	media_->acquire();
+	if (!media_->busy())
+		LOG(Converter, Error)
+			<< "MediaDevice must be valid.";
+	bool ret = media_->supportsRequests();
+	media_->release();
+	return ret;
+}
+
 /*
  * \todo This should be extended to include Feature::Flag to denote
  * what each converter supports feature-wise.
diff -pruN 0.5.0-1/src/libcamera/converter/meson.build 0.6.0-2/src/libcamera/converter/meson.build
--- 0.5.0-1/src/libcamera/converter/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/converter/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: CC0-1.0
 
 libcamera_internal_sources += files([
+        'converter_dw100.cpp',
+        'converter_dw100_vertexmap.cpp',
         'converter_v4l2_m2m.cpp'
 ])
diff -pruN 0.5.0-1/src/libcamera/converter.cpp 0.6.0-2/src/libcamera/converter.cpp
--- 0.5.0-1/src/libcamera/converter.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/converter.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -8,6 +8,7 @@
 #include "libcamera/internal/converter.h"
 
 #include <algorithm>
+#include <memory>
 
 #include <libcamera/base/log.h>
 
@@ -68,7 +69,7 @@ LOG_DEFINE_CATEGORY(Converter)
  * This searches for the entity implementing the data streaming function in the
  * media graph entities and use its device node as the converter device node.
  */
-Converter::Converter(MediaDevice *media, Features features)
+Converter::Converter(std::shared_ptr<MediaDevice> media, Features features)
 {
 	const std::vector<MediaEntity *> &entities = media->entities();
 	auto it = std::find_if(entities.begin(), entities.end(),
@@ -204,11 +205,14 @@ Converter::~Converter()
  * \param[in] input The frame buffer to apply the conversion
  * \param[out] outputs The container holding the output stream pointers and
  * their respective frame buffer outputs.
+ * \param[in] request An optional request
  *
  * This function queues the \a input frame buffer on the output streams of the
  * \a outputs map key and retrieve the output frame buffer indicated by the
  * buffer map value.
  *
+ * If \a request is provided the buffers are tied to that request.
+ *
  * \return 0 on success or a negative error code otherwise
  */
 
@@ -332,7 +336,7 @@ ConverterFactoryBase::ConverterFactoryBa
  * \return A new instance of the converter subclass corresponding to the media
  * device, or null if the media device driver name doesn't match anything
  */
-std::unique_ptr<Converter> ConverterFactoryBase::create(MediaDevice *media)
+std::unique_ptr<Converter> ConverterFactoryBase::create(std::shared_ptr<MediaDevice> media)
 {
 	const std::vector<ConverterFactoryBase *> &factories =
 		ConverterFactoryBase::factories();
diff -pruN 0.5.0-1/src/libcamera/framebuffer.cpp 0.6.0-2/src/libcamera/framebuffer.cpp
--- 0.5.0-1/src/libcamera/framebuffer.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/framebuffer.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -43,12 +43,19 @@ LOG_DEFINE_CATEGORY(Buffer)
  * The frame has been captured with success and contains valid data. All fields
  * of the FrameMetadata structure are valid.
  * \var FrameMetadata::FrameError
- * An error occurred during capture of the frame. The frame data may be partly
- * or fully invalid. The sequence and timestamp fields of the FrameMetadata
- * structure is valid, the other fields may be invalid.
+ * The frame data is partly or fully corrupted, missing or otherwise invalid.
+ * This can for instance indicate a hardware transmission error, or invalid data
+ * produced by the sensor during its startup phase. The sequence and timestamp
+ * fields of the FrameMetadata structure is valid, all the other fields may be
+ * invalid.
  * \var FrameMetadata::FrameCancelled
  * Capture stopped before the frame completed. The frame data is not valid. All
  * fields of the FrameMetadata structure but the status field are invalid.
+ * \var FrameMetadata::FrameStartup
+ * The frame has been successfully captured. However, the IPA is in a
+ * cold-start or reset phase and will result in image quality parameters
+ * producing unusable images. Applications are recommended to not consume these
+ * frames. All other fields of the FrameMetadata structure are valid.
  */
 
 /**
@@ -123,9 +130,9 @@ LOG_DEFINE_CATEGORY(Buffer)
  * \param[in] planes The frame memory planes
  * \param[in] cookie Cookie
  */
-FrameBuffer::Private::Private(const std::vector<Plane> &planes, uint64_t cookie)
-	: planes_(planes), cookie_(cookie), request_(nullptr),
-	  isContiguous_(true)
+FrameBuffer::Private::Private(Span<const Plane> planes, uint64_t cookie)
+	: planes_(planes.begin(), planes.end()), cookie_(cookie),
+	  request_(nullptr), isContiguous_(true)
 {
 	metadata_.planes_.resize(planes_.size());
 }
@@ -308,7 +315,7 @@ ino_t fileDescriptorInode(const SharedFD
  * \param[in] planes The frame memory planes
  * \param[in] cookie Cookie
  */
-FrameBuffer::FrameBuffer(const std::vector<Plane> &planes, unsigned int cookie)
+FrameBuffer::FrameBuffer(Span<const Plane> planes, unsigned int cookie)
 	: FrameBuffer(std::make_unique<Private>(planes, cookie))
 {
 }
@@ -358,7 +365,7 @@ FrameBuffer::FrameBuffer(std::unique_ptr
  * \brief Retrieve the static plane descriptors
  * \return Array of plane descriptors
  */
-const std::vector<FrameBuffer::Plane> &FrameBuffer::planes() const
+Span<const FrameBuffer::Plane> FrameBuffer::planes() const
 {
 	return _d()->planes_;
 }
diff -pruN 0.5.0-1/src/libcamera/geometry.cpp 0.6.0-2/src/libcamera/geometry.cpp
--- 0.5.0-1/src/libcamera/geometry.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/geometry.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -53,7 +53,7 @@ namespace libcamera {
  * \brief Assemble and return a string describing the point
  * \return A string describing the point
  */
-const std::string Point::toString() const
+std::string Point::toString() const
 {
 	std::stringstream ss;
 	ss << *this;
@@ -133,7 +133,7 @@ std::ostream &operator<<(std::ostream &o
  * \brief Assemble and return a string describing the size
  * \return A string describing the size
  */
-const std::string Size::toString() const
+std::string Size::toString() const
 {
 	std::stringstream ss;
 	ss << *this;
@@ -210,6 +210,16 @@ const std::string Size::toString() const
  */
 
 /**
+ * \fn Size::transpose()
+ * \brief Transpose the size in place
+ *
+ * This function swaps width and height of this size. This effectively applies
+ * the \a Transform::Transpose transformation on this size.
+ *
+ * \return A reference to this object
+ */
+
+/**
  * \fn Size::alignedDownTo(unsigned int hAlignment, unsigned int vAlignment)
  * \brief Align the size down horizontally and vertically
  * \param[in] hAlignment Horizontal alignment
@@ -676,7 +686,7 @@ std::ostream &operator<<(std::ostream &o
  * \brief Assemble and return a string describing the rectangle
  * \return A string describing the Rectangle
  */
-const std::string Rectangle::toString() const
+std::string Rectangle::toString() const
 {
 	std::stringstream ss;
 	ss << *this;
diff -pruN 0.5.0-1/src/libcamera/global_configuration.cpp 0.6.0-2/src/libcamera/global_configuration.cpp
--- 0.5.0-1/src/libcamera/global_configuration.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/libcamera/global_configuration.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,253 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024-2025 Red Hat, inc.
+ *
+ * Global configuration handling
+ */
+
+#include "libcamera/internal/global_configuration.h"
+
+#include <filesystem>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+#include <sys/types.h>
+#include <vector>
+
+#include <libcamera/base/file.h>
+#include <libcamera/base/log.h>
+#include <libcamera/base/utils.h>
+
+#include "libcamera/internal/yaml_parser.h"
+
+namespace libcamera {
+
+namespace {
+const std::vector<std::filesystem::path> globalConfigurationFiles = {
+	std::filesystem::path(LIBCAMERA_SYSCONF_DIR) / "configuration.yaml",
+	std::filesystem::path(LIBCAMERA_DATA_DIR) / "configuration.yaml",
+};
+}
+
+LOG_DEFINE_CATEGORY(Configuration)
+
+/**
+ * \class GlobalConfiguration
+ * \brief Support for global libcamera configuration
+ *
+ * The configuration file is a YAML file and the configuration itself is stored
+ * under a `%configuration` top-level item.
+ *
+ * The configuration file is looked up in the user's home directory first and,
+ * if it is not found, then in system-wide configuration directories. If
+ * multiple configuration files exist then only the first one found is used and
+ * no configuration merging is performed.
+ *
+ * If the first found configuration file cannot be opened or parsed, an error is
+ * reported and no configuration file is used. This is to prevent libcamera from
+ * using an unintended configuration file.
+ *
+ * The configuration can be accessed using the provided helpers, namely
+ * option(), envOption(), listOption() and envListOption() to access individual
+ * options, or configuration() to access the whole configuration.
+ */
+
+bool GlobalConfiguration::loadFile(const std::filesystem::path &fileName)
+{
+	File file(fileName);
+	if (!file.open(File::OpenModeFlag::ReadOnly)) {
+		if (file.error() == -ENOENT)
+			return false;
+
+		LOG(Configuration, Error)
+			<< "Failed to open configuration file " << fileName;
+		return true;
+	}
+
+	std::unique_ptr<YamlObject> configuration = YamlParser::parse(file);
+	if (!configuration) {
+		LOG(Configuration, Error)
+			<< "Failed to parse configuration file " << fileName;
+		return true;
+	}
+
+	const std::optional<int> version = (*configuration)["version"].get<int>();
+	if (version != 1) {
+		LOG(Configuration, Error)
+			<< "Failed to load configuration file due to unsupported version "
+			<< (version ? std::to_string(version.value()) : "\"unspecified\"")
+			<< ", expected version 1";
+		return true;
+	}
+
+	yamlConfiguration_ = std::move(configuration);
+	return true;
+}
+
+void GlobalConfiguration::load()
+{
+	std::filesystem::path userConfigurationDirectory;
+	const char *xdgConfigHome = utils::secure_getenv("XDG_CONFIG_HOME");
+	if (xdgConfigHome) {
+		userConfigurationDirectory = xdgConfigHome;
+	} else {
+		const char *home = utils::secure_getenv("HOME");
+		if (home)
+			userConfigurationDirectory =
+				std::filesystem::path(home) / ".config";
+	}
+
+	if (!userConfigurationDirectory.empty()) {
+		std::filesystem::path user_configuration_file =
+			userConfigurationDirectory / "libcamera" / "configuration.yaml";
+		if (loadFile(user_configuration_file))
+			return;
+	}
+
+	for (const auto &path : globalConfigurationFiles) {
+		if (loadFile(path))
+			return;
+	}
+}
+
+/**
+ * \brief Initialize the global configuration
+ */
+GlobalConfiguration::GlobalConfiguration()
+{
+	load();
+}
+
+/**
+ * \typedef GlobalConfiguration::Configuration
+ * \brief Type representing global libcamera configuration
+ *
+ * All code outside GlobalConfiguration must use this type declaration and not
+ * the underlying type.
+ */
+
+/**
+ * \fn std::optional<T> GlobalConfiguration::option(const std::initializer_list<std::string_view> &confPath) const
+ * \brief Retrieve the value of configuration option \a confPath
+ * \tparam T The type of the retrieved configuration value
+ * \param[in] confPath Sequence of the YAML section names (excluding
+ * `%configuration`) leading to the requested option
+ * \return The value of the configuration item corresponding to \a confPath if
+ * it exists in the configuration file, or no value otherwise
+ */
+
+/**
+ * \brief Retrieve the value of configuration option \a confPath
+ * \param[in] confPath Sequence of the YAML section names (excluding
+ * `%configuration`) leading to the requested list option, separated by dots
+ * \return A vector of strings or no value if not found
+ */
+std::optional<std::vector<std::string>> GlobalConfiguration::listOption(
+	const std::initializer_list<std::string_view> confPath) const
+{
+	const YamlObject *c = &configuration();
+	for (auto part : confPath) {
+		c = &(*c)[part];
+		if (!*c)
+			return {};
+	}
+	return c->getList<std::string>();
+}
+
+/**
+ * \brief Retrieve the value of environment variable with a fallback on the configuration file
+ * \param[in] envVariable Environment variable to get the value from
+ * \param[in] confPath The sequence of YAML section names to fall back on when
+ * \a envVariable is unavailable
+ *
+ * This helper looks first at the given environment variable and if it is
+ * defined then it returns its value (even if it is empty). Otherwise it looks
+ * for \a confPath the same way as in GlobalConfiguration::option. Only string
+ * values are supported.
+ *
+ * \note Support for using environment variables to configure libcamera behavior
+ * is provided here mostly for backward compatibility reasons. Introducing new
+ * configuration environment variables is discouraged.
+ *
+ * \return The value retrieved from the given environment if it is set,
+ * otherwise the value from the configuration file if it exists, or no value if
+ * it does not
+ */
+std::optional<std::string> GlobalConfiguration::envOption(
+	const char *envVariable,
+	const std::initializer_list<std::string_view> confPath) const
+{
+	const char *envValue = utils::secure_getenv(envVariable);
+	if (envValue)
+		return std::optional{ std::string{ envValue } };
+	return option<std::string>(confPath);
+}
+
+/**
+ * \brief Retrieve the value of the configuration option from a file or environment
+ * \param[in] envVariable Environment variable to get the value from
+ * \param[in] confPath The same as in GlobalConfiguration::option
+ * \param[in] delimiter Items separator in the environment variable
+ *
+ * This helper looks first at the given environment variable and if it is
+ * defined (even if it is empty) then it splits its value by semicolons and
+ * returns the resulting list of strings. Otherwise it looks for \a confPath the
+ * same way as in GlobalConfiguration::option, value of which must be a list of
+ * strings.
+ *
+ * \note Support for using environment variables to configure libcamera behavior
+ * is provided here mostly for backward compatibility reasons. Introducing new
+ * configuration environment variables is discouraged.
+ *
+ * \return A vector of strings retrieved from the given environment option or
+ * configuration file or no value if not found; the vector may be empty
+ */
+std::optional<std::vector<std::string>> GlobalConfiguration::envListOption(
+	const char *const envVariable,
+	const std::initializer_list<std::string_view> confPath,
+	const std::string delimiter) const
+{
+	const char *envValue = utils::secure_getenv(envVariable);
+	if (envValue) {
+		auto items = utils::split(envValue, delimiter);
+		return std::vector<std::string>(items.begin(), items.end());
+	}
+	return listOption(confPath);
+}
+
+/**
+ * \brief Retrieve the configuration version
+ *
+ * The version is declared in the configuration file in the top-level `%version`
+ * element, alongside `%configuration`. This has currently no real use but may be
+ * needed in future if configuration incompatibilities occur.
+ *
+ * \return Configuration version as declared in the configuration file or 0 if
+ * no global configuration is available
+ */
+unsigned int GlobalConfiguration::version() const
+{
+	return (*yamlConfiguration_)["version"].get<unsigned int>().value_or(0);
+}
+
+/**
+ * \brief Retrieve the libcamera global configuration
+ *
+ * This returns the whole configuration stored in the top-level section
+ * `%configuration` of the YAML configuration file.
+ *
+ * The requested part of the configuration can be accessed using \a YamlObject
+ * methods.
+ *
+ * \note \a YamlObject type itself shouldn't be used in type declarations to
+ * avoid trouble if we decide to change the underlying data objects in future.
+ *
+ * \return The whole configuration section
+ */
+GlobalConfiguration::Configuration GlobalConfiguration::configuration() const
+{
+	return (*yamlConfiguration_)["configuration"];
+}
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/ipa_controls.cpp 0.6.0-2/src/libcamera/ipa_controls.cpp
--- 0.5.0-1/src/libcamera/ipa_controls.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/ipa_controls.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -26,28 +26,28 @@
  * The following diagram describes the layout of the ControlList packet.
  *
  * ~~~~
- *           +-------------------------+    .                      .
- *  Header / | ipa_controls_header     |    |                      |
- *         | |                         |    |                      |
- *         \ |                         |    |                      |
- *           +-------------------------+    |                      |
- *         / | ipa_control_value_entry |    | hdr.data_offset      |
- *         | | #0                      |    |                      |
- * Control | +-------------------------+    |                      |
- *   value | | ...                     |    |                      |
- * entries | +-------------------------+    |                      |
- *         | | ipa_control_value_entry |    |             hdr.size |
- *         \ | #hdr.entries - 1        |    |                      |
- *           +-------------------------+    |                      |
- *           | empty space (optional)  |    |                      |
- *           +-------------------------+ <--´  .                   |
- *         / | ...                     |       | entry[n].offset   |
- *    Data | | ...                     |       |                   |
- * section | | value data for entry #n | <-----´                   |
- *         \ | ...                     |                           |
- *           +-------------------------+                           |
- *           | empty space (optional)  |                           |
- *           +-------------------------+ <-------------------------´
+ *           +-------------------------+    .                          .
+ *  Header / | ipa_controls_header     |    |                          |
+ *         | |                         |    |                          |
+ *         \ |                         |    |                          |
+ *           +-------------------------+    |                          |
+ *         / | ipa_control_list_entry  |    | hdr.data_offset          |
+ *         | | #0                      |    |                          |
+ * Control | +-------------------------+    |                          |
+ *   value | | ...                     |    |                          |
+ * entries | +-------------------------+    |                          |
+ *         | | ipa_control_list_entry  |    |             hdr.size     |
+ *         \ | #hdr.entries - 1        |    |                          |
+ *           +-------------------------+    |                          |
+ *           | empty space (optional)  |    |                          |
+ *           +-------------------------+ <--´  .                       |
+ *         / | ...                     |       | entry[n].value.offset |
+ *    Data | | ...                     |       |                       |
+ * section | | value data for entry #n | <-----´                       |
+ *         \ | ...                     |                               |
+ *           +-------------------------+                               |
+ *           | empty space (optional)  |                               |
+ *           +-------------------------+ <-----------------------------´
  * ~~~~
  *
  * The packet header contains the size of the packet, the number of entries, and
@@ -56,12 +56,14 @@
  * offset ipa_controls_header::data_offset from the beginning of the packet, and
  * shall be aligned to a multiple of 8 bytes.
  *
- * Entries are described by the ipa_control_value_entry structure. They contain
- * the numerical ID of the control, its type, and the number of control values.
- *
- * The control values are stored in the data section in the platform's native
- * format. The ipa_control_value_entry::offset field stores the offset from the
- * beginning of the data section to the values.
+ * Entries are described by the ipa_control_list_entry structure. They contain
+ * the numerical ID of the control and an ipa_control_value_entry structure,
+ * which contains the type and the number of control values.
+ *
+ * The control values are stored (as ipa_control_list_entry) in the data
+ * section in the platform's native format. The ipa_control_value_entry::offset
+ * field stores the offset from the beginning of the data section to the
+ * values.
  *
  * All control values in the data section shall be stored in the same order as
  * the respective control entries, shall be aligned to a multiple of 8 bytes,
@@ -74,59 +76,65 @@
  * The following diagram describes the layout of the ControlInfoMap packet.
  *
  * ~~~~
- *           +-------------------------+    .                      .
- *  Header / | ipa_controls_header     |    |                      |
- *         | |                         |    |                      |
- *         \ |                         |    |                      |
- *           +-------------------------+    |                      |
- *         / | ipa_control_info_entry  |    | hdr.data_offset      |
- *         | | #0                      |    |                      |
- * Control | +-------------------------+    |                      |
- *    info | | ...                     |    |                      |
- * entries | +-------------------------+    |                      |
- *         | | ipa_control_info_entry  |    |             hdr.size |
- *         \ | #hdr.entries - 1        |    |                      |
- *           +-------------------------+    |                      |
- *           | empty space (optional)  |    |                      |
- *           +-------------------------+ <--´  .                   |
- *         / | ...                     |       | entry[n].offset   |
- *    Data | | ...                     |       |                   |
- * section | | info data for entry #n  | <-----´                   |
- *         \ | ...                     |                           |
- *           +-------------------------+                           |
- *           | empty space (optional)  |                           |
- *           +-------------------------+ <-------------------------´
+ *           +------------------------------+    .                            .
+ *  Header / | ipa_controls_header          |    |                            |
+ *         | |                              |    |                            |
+ *         \ |                              |    |                            |
+ *           +------------------------------+    |                            |
+ *         / | ipa_control_info_entry       |    | hdr.data_offset            |
+ *         | | #0                           |    |                            |
+ * Control | +------------------------------+    |                            |
+ *    info | | ...                          |    |                            |
+ * entries | +------------------------------+    |                            |
+ *         | | ipa_control_info_entry       |    |                            |
+ *         \ | #hdr.entries - 1             |    |                            |
+ *           +------------------------------+    |                            |
+ *           | empty space (optional)       |    |                            |
+ *           +------------------------------+ <--´  . . .                     |
+ *         / | ...                          |       | entry[n].min.offset     |
+ *         | | ...                          |       | | |                     |
+ *    Data | | ...                          |       | | entry[n].max.offset   |
+ * section | | min value data for entry #n  | <-----´ | |                     |
+ *         | | max value data for entry #n  | <-------´ | entry[n].def.offset |
+ *         | | def value data for entry #n  | <---------´                     |
+ *         | | ...                          |                                 |
+ *         \ | ...                          |                                 |
+ *           +------------------------------+                                 |
+ *           | empty space (optional)       |                                 |
+ *           +------------------------------+ <-------------------------------´
  * ~~~~
  *
  * The packet header is identical to the ControlList packet header.
  *
  * Entries are described by the ipa_control_info_entry structure. They contain
- * the numerical ID and type of the control. The control info data is stored
- * in the data section as described by the following diagram.
- *
- * ~~~~
- *           +-------------------------+       .
- *         / | ...                     |       | entry[n].offset
- *         | +-------------------------+ <-----´
- *         | | minimum value (#n)      | \
- *    Data | +-------------------------+ |
- * section | | maximum value (#n)      | | Entry #n
- *         | +-------------------------+ |
- *         | | default value (#n)      | /
- *         | +-------------------------+
- *         \ | ...                     |
- *           +-------------------------+
- * ~~~~
+ * the numerical ID, direction (in/out) of the control, and three
+ * ipa_control_value_entry structures for the min, max, and def ControlValues
+ * that make up the ControlInfo.
+ *
+ * The control info has no associated data in the data section;
+ * instead the three control values for min, max, and def are stored in the data section
+ *
+ *
+ * The control values are stored (as ipa_control_list_entry) in the data
+ * section in the platform's native format. The ipa_control_value_entry::offset
+ * field stores the offset from the beginning of the data section to the
+ * values.
+ *
+ * ipa_control_value_entry structures contain the relevant
+ * ControlValue information for the ControlInfo's min, max, and def
+ * respectively, and their associated data is stored in the data section.
+ *
+ * The control info has no associated data in the data section. Instead the
+ * minimum, maximum, and default control values of the control info are stored
+ * n the data section in the platform's native data format. The
+ * ipa_control_value_entry::offset field stores the offset from the beginning
+ * of the data section to the control value data.
  *
- * The minimum, maximum and default values are stored in the platform's native
- * data format. The ipa_control_info_entry::offset field stores the offset from
- * the beginning of the data section to the info data.
- *
- * Info data in the data section shall be stored in the same order as the
- * entries array, shall be aligned to a multiple of 8 bytes, and shall be
- * contiguous in memory.
+ * All control values in the data section shall be stored in the same order as
+ * the respective control info entries, in the order of min, max, def, and shall be
+ * aligned to a multiple of 8 bytes, and shall be contiguous in memory.
  *
- * As for the ControlList packet, empty spaces may be present between the end of
+ * As with the ControlList packet, empty spaces may be present between the end of
  * the entries array and the data section, and after the data section. They
  * shall be ignored when parsing the packet.
  */
@@ -192,8 +200,6 @@ static_assert(sizeof(ipa_controls_header
 /**
  * \struct ipa_control_value_entry
  * \brief Description of a serialized ControlValue entry
- * \var ipa_control_value_entry::id
- * The numerical ID of the control
  * \var ipa_control_value_entry::type
  * The type of the control (defined by enum ControlType)
  * \var ipa_control_value_entry::is_array
@@ -203,22 +209,32 @@ static_assert(sizeof(ipa_controls_header
  * \var ipa_control_value_entry::offset
  * The offset in bytes from the beginning of the data section to the control
  * value data (shall be a multiple of 8 bytes).
- * \var ipa_control_value_entry::padding
- * Padding bytes (shall be set to 0)
+ * \var ipa_control_value_entry::reserved
+ * Reserved for future extensions
  */
 
 static_assert(sizeof(ipa_control_value_entry) == 16,
 	      "Invalid ABI size change for struct ipa_control_value_entry");
 
 /**
+ * \struct ipa_control_list_entry
+ * \brief Description of a serialized ControlList entry
+ * \var ipa_control_list_entry::id
+ * The numerical ID of the control
+ * \var ipa_control_list_entry::value
+ * The description of the serialized ControlValue
+ */
+
+static_assert(sizeof(ipa_control_list_entry) == 20,
+	      "Invalid ABI size change for struct ipa_control_list_entry");
+
+/**
  * \struct ipa_control_info_entry
  * \brief Description of a serialized ControlInfo entry
  * \var ipa_control_info_entry::id
  * The numerical ID of the control
  * \var ipa_control_info_entry::type
  * The type of the control (defined by enum ControlType)
- * \var ipa_control_info_entry::offset
- * The offset in bytes from the beginning of the data section to the control
  * info data (shall be a multiple of 8 bytes)
  * \var ipa_control_info_entry::direction
  * The directions in which the control is allowed to be sent. This is a flags
@@ -226,9 +242,15 @@ static_assert(sizeof(ipa_control_value_e
  * metadata). \sa ControlId::Direction
  * \var ipa_control_info_entry::padding
  * Padding bytes (shall be set to 0)
+ * \var ipa_control_info_entry::min
+ * The description of the serialized ControlValue (min)
+ * \var ipa_control_info_entry::max
+ * The description of the serialized ControlValue (max)
+ * \var ipa_control_info_entry::def
+ * The description of the serialized ControlValue (def)
  */
 
-static_assert(sizeof(ipa_control_info_entry) == 16,
+static_assert(sizeof(ipa_control_info_entry) == 64,
 	      "Invalid ABI size change for struct ipa_control_info_entry");
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/ipa_data_serializer.cpp 0.6.0-2/src/libcamera/ipa_data_serializer.cpp
--- 0.5.0-1/src/libcamera/ipa_data_serializer.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/ipa_data_serializer.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -196,7 +196,6 @@ IPADataSerializer<type>::serialize(const
 				  [[maybe_unused]] ControlSerializer *cs) \
 {									\
 	std::vector<uint8_t> dataVec;					\
-	dataVec.reserve(sizeof(type));					\
 	appendPOD<type>(dataVec, data);					\
 									\
 	return { dataVec, {} };						\
diff -pruN 0.5.0-1/src/libcamera/ipa_manager.cpp 0.6.0-2/src/libcamera/ipa_manager.cpp
--- 0.5.0-1/src/libcamera/ipa_manager.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/ipa_manager.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -10,12 +10,15 @@
 #include <algorithm>
 #include <dirent.h>
 #include <string.h>
+#include <string>
 #include <sys/types.h>
+#include <vector>
 
 #include <libcamera/base/file.h>
 #include <libcamera/base/log.h>
 #include <libcamera/base/utils.h>
 
+#include "libcamera/internal/global_configuration.h"
 #include "libcamera/internal/ipa_module.h"
 #include "libcamera/internal/ipa_proxy.h"
 #include "libcamera/internal/pipeline_handler.h"
@@ -101,30 +104,37 @@ LOG_DEFINE_CATEGORY(IPAManager)
  * The IPAManager class is meant to only be instantiated once, by the
  * CameraManager.
  */
-IPAManager::IPAManager()
+IPAManager::IPAManager(const GlobalConfiguration &configuration)
 {
 #if HAVE_IPA_PUBKEY
 	if (!pubKey_.isValid())
 		LOG(IPAManager, Warning) << "Public key not valid";
+
+	char *force = utils::secure_getenv("LIBCAMERA_IPA_FORCE_ISOLATION");
+	forceIsolation_ = (force && force[0] != '\0') ||
+			  (!force && configuration.option<bool>({ "ipa", "force_isolation" })
+					     .value_or(false));
 #endif
 
 	unsigned int ipaCount = 0;
 
 	/* User-specified paths take precedence. */
-	const char *modulePaths = utils::secure_getenv("LIBCAMERA_IPA_MODULE_PATH");
-	if (modulePaths) {
-		for (const auto &dir : utils::split(modulePaths, ":")) {
-			if (dir.empty())
-				continue;
-
-			ipaCount += addDir(dir.c_str());
-		}
+	const auto modulePaths =
+		configuration.envListOption(
+				     "LIBCAMERA_IPA_MODULE_PATH", { "ipa", "module_paths" })
+			.value_or(std::vector<std::string>());
+	for (const auto &dir : modulePaths) {
+		if (dir.empty())
+			continue;
 
-		if (!ipaCount)
-			LOG(IPAManager, Warning)
-				<< "No IPA found in '" << modulePaths << "'";
+		ipaCount += addDir(dir.c_str());
 	}
 
+	if (!modulePaths.empty() && !ipaCount)
+		LOG(IPAManager, Warning) << "No IPA found in '"
+					 << utils::join(modulePaths, ":")
+					 << "'";
+
 	/*
 	 * When libcamera is used before it is installed, load IPAs from the
 	 * same build directory as the libcamera library itself.
@@ -279,11 +289,10 @@ IPAModule *IPAManager::module(PipelineHa
 bool IPAManager::isSignatureValid([[maybe_unused]] IPAModule *ipa) const
 {
 #if HAVE_IPA_PUBKEY
-	char *force = utils::secure_getenv("LIBCAMERA_IPA_FORCE_ISOLATION");
-	if (force && force[0] != '\0') {
+	if (forceIsolation_) {
 		LOG(IPAManager, Debug)
 			<< "Isolation of IPA module " << ipa->path()
-			<< " forced through environment variable";
+			<< " forced through configuration";
 		return false;
 	}
 
diff -pruN 0.5.0-1/src/libcamera/ipa_module.cpp 0.6.0-2/src/libcamera/ipa_module.cpp
--- 0.5.0-1/src/libcamera/ipa_module.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/ipa_module.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -373,7 +373,7 @@ const struct IPAModuleInfo &IPAModule::i
  *
  * \return The IPA module signature
  */
-const std::vector<uint8_t> IPAModule::signature() const
+const std::vector<uint8_t> &IPAModule::signature() const
 {
 	return signature_;
 }
diff -pruN 0.5.0-1/src/libcamera/ipa_proxy.cpp 0.6.0-2/src/libcamera/ipa_proxy.cpp
--- 0.5.0-1/src/libcamera/ipa_proxy.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/ipa_proxy.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,13 +7,16 @@
 
 #include "libcamera/internal/ipa_proxy.h"
 
+#include <string>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
+#include <vector>
 
 #include <libcamera/base/log.h>
 #include <libcamera/base/utils.h>
 
+#include "libcamera/internal/global_configuration.h"
 #include "libcamera/internal/ipa_module.h"
 
 /**
@@ -25,6 +28,72 @@ namespace libcamera {
 
 LOG_DEFINE_CATEGORY(IPAProxy)
 
+namespace {
+
+std::string ipaConfigurationFile(const std::string &ipaName, const std::string &name,
+				 const std::vector<std::string> &configPaths)
+{
+	/*
+	 * Start with any user override through the module-specific environment
+	 * variable. Use the name of the IPA module up to the first '/' to
+	 * construct the variable name.
+	 */
+	std::string ipaEnvName = ipaName.substr(0, ipaName.find('/'));
+	std::transform(ipaEnvName.begin(), ipaEnvName.end(), ipaEnvName.begin(),
+		       [](unsigned char c) { return std::toupper(c); });
+	ipaEnvName = "LIBCAMERA_" + ipaEnvName + "_TUNING_FILE";
+
+	char const *configFromEnv = utils::secure_getenv(ipaEnvName.c_str());
+	if (configFromEnv && *configFromEnv != '\0')
+		return { configFromEnv };
+
+	struct stat statbuf;
+	int ret;
+
+	/* Check the directory pointed to by the IPA config path next. */
+	for (const auto &dir : configPaths) {
+		if (dir.empty())
+			continue;
+		std::string confPath = dir + "/" + ipaName + "/" + name;
+		ret = stat(confPath.c_str(), &statbuf);
+		if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
+			return confPath;
+	}
+
+	std::string root = utils::libcameraSourcePath();
+	if (!root.empty()) {
+		/*
+		 * When libcamera is used before it is installed, load
+		 * configuration files from the source directory. The
+		 * configuration files are then located in the 'data'
+		 * subdirectory of the corresponding IPA module.
+		 */
+		std::string ipaConfDir = root + "src/ipa/" + ipaName + "/data";
+
+		LOG(IPAProxy, Info)
+			<< "libcamera is not installed. Loading IPA configuration from '"
+			<< ipaConfDir << "'";
+
+		std::string confPath = ipaConfDir + "/" + name;
+		ret = stat(confPath.c_str(), &statbuf);
+		if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
+			return confPath;
+
+	} else {
+		/* Else look in the system locations. */
+		for (const auto &dir : utils::split(IPA_CONFIG_DIR, ":")) {
+			std::string confPath = dir + "/" + ipaName + "/" + name;
+			ret = stat(confPath.c_str(), &statbuf);
+			if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
+				return confPath;
+		}
+	}
+
+	return {};
+}
+
+} /* namespace */
+
 /**
  * \class IPAProxy
  * \brief IPA Proxy
@@ -48,9 +117,12 @@ LOG_DEFINE_CATEGORY(IPAProxy)
 /**
  * \brief Construct an IPAProxy instance
  * \param[in] ipam The IPA module
+ * \param[in] configuration The global configuration
  */
-IPAProxy::IPAProxy(IPAModule *ipam)
-	: valid_(false), state_(ProxyStopped), ipam_(ipam)
+IPAProxy::IPAProxy(IPAModule *ipam, const GlobalConfiguration &configuration)
+	: valid_(false), state_(ProxyStopped), ipam_(ipam),
+	  configPaths_(configuration.envListOption("LIBCAMERA_IPA_CONFIG_PATH", { "ipa", "config_paths" }).value_or(std::vector<std::string>())),
+	  execPaths_(configuration.envListOption("LIBCAMERA_IPA_PROXY_PATH", { "ipa", "proxy_paths" }).value_or(std::vector<std::string>()))
 {
 }
 
@@ -103,68 +175,10 @@ std::string IPAProxy::configurationFile(
 	 * has been validated when loading the module.
 	 */
 	const std::string ipaName = ipam_->info().name;
-
-	/*
-	 * Start with any user override through the module-specific environment
-	 * variable. Use the name of the IPA module up to the first '/' to
-	 * construct the variable name.
-	 */
-	std::string ipaEnvName = ipaName.substr(0, ipaName.find('/'));
-	std::transform(ipaEnvName.begin(), ipaEnvName.end(), ipaEnvName.begin(),
-		       [](unsigned char c) { return std::toupper(c); });
-	ipaEnvName = "LIBCAMERA_" + ipaEnvName + "_TUNING_FILE";
-
-	char const *configFromEnv = utils::secure_getenv(ipaEnvName.c_str());
-	if (configFromEnv && *configFromEnv != '\0')
-		return { configFromEnv };
-
-	struct stat statbuf;
-	int ret;
-
-	/*
-	 * Check the directory pointed to by the IPA config path environment
-	 * variable next.
-	 */
-	const char *confPaths = utils::secure_getenv("LIBCAMERA_IPA_CONFIG_PATH");
-	if (confPaths) {
-		for (const auto &dir : utils::split(confPaths, ":")) {
-			if (dir.empty())
-				continue;
-
-			std::string confPath = dir + "/" + ipaName + "/" + name;
-			ret = stat(confPath.c_str(), &statbuf);
-			if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
-				return confPath;
-		}
-	}
-
-	std::string root = utils::libcameraSourcePath();
-	if (!root.empty()) {
-		/*
-		 * When libcamera is used before it is installed, load
-		 * configuration files from the source directory. The
-		 * configuration files are then located in the 'data'
-		 * subdirectory of the corresponding IPA module.
-		 */
-		std::string ipaConfDir = root + "src/ipa/" + ipaName + "/data";
-
-		LOG(IPAProxy, Info)
-			<< "libcamera is not installed. Loading IPA configuration from '"
-			<< ipaConfDir << "'";
-
-		std::string confPath = ipaConfDir + "/" + name;
-		ret = stat(confPath.c_str(), &statbuf);
-		if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
-			return confPath;
-
-	} else {
-		/* Else look in the system locations. */
-		for (const auto &dir : utils::split(IPA_CONFIG_DIR, ":")) {
-			std::string confPath = dir + "/" + ipaName + "/" + name;
-			ret = stat(confPath.c_str(), &statbuf);
-			if (ret == 0 && (statbuf.st_mode & S_IFMT) == S_IFREG)
-				return confPath;
-		}
+	std::string confPath = ipaConfigurationFile(ipaName, name, configPaths_);
+	if (!confPath.empty()) {
+		LOG(IPAProxy, Info) << "Using tuning file " << confPath;
+		return confPath;
 	}
 
 	if (fallbackName.empty()) {
@@ -174,11 +188,12 @@ std::string IPAProxy::configurationFile(
 		return std::string();
 	}
 
+	confPath = ipaConfigurationFile(ipaName, fallbackName, configPaths_);
 	LOG(IPAProxy, Warning)
 		<< "Configuration file '" << name
 		<< "' not found for IPA module '" << ipaName
-		<< "', falling back to '" << fallbackName << "'";
-	return configurationFile(fallbackName);
+		<< "', falling back to '" << confPath << "'";
+	return confPath;
 }
 
 /**
@@ -199,18 +214,14 @@ std::string IPAProxy::resolvePath(const
 {
 	std::string proxyFile = "/" + file;
 
-	/* Check env variable first. */
-	const char *execPaths = utils::secure_getenv("LIBCAMERA_IPA_PROXY_PATH");
-	if (execPaths) {
-		for (const auto &dir : utils::split(execPaths, ":")) {
-			if (dir.empty())
-				continue;
-
-			std::string proxyPath = dir;
-			proxyPath += proxyFile;
-			if (!access(proxyPath.c_str(), X_OK))
-				return proxyPath;
-		}
+	/* Try paths from the configuration first. */
+	for (const auto &dir : execPaths_) {
+		if (dir.empty())
+			continue;
+
+		std::string proxyPath = dir + proxyFile;
+		if (!access(proxyPath.c_str(), X_OK))
+			return proxyPath;
 	}
 
 	/*
diff -pruN 0.5.0-1/src/libcamera/ipc_pipe_unixsocket.cpp 0.6.0-2/src/libcamera/ipc_pipe_unixsocket.cpp
--- 0.5.0-1/src/libcamera/ipc_pipe_unixsocket.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/ipc_pipe_unixsocket.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -28,10 +28,6 @@ IPCPipeUnixSocket::IPCPipeUnixSocket(con
 				     const char *ipaProxyWorkerPath)
 	: IPCPipe()
 {
-	std::vector<int> fds;
-	std::vector<std::string> args;
-	args.push_back(ipaModulePath);
-
 	socket_ = std::make_unique<IPCUnixSocket>();
 	UniqueFD fd = socket_->create();
 	if (!fd.isValid()) {
@@ -39,8 +35,9 @@ IPCPipeUnixSocket::IPCPipeUnixSocket(con
 		return;
 	}
 	socket_->readyRead.connect(this, &IPCPipeUnixSocket::readyRead);
-	args.push_back(std::to_string(fd.get()));
-	fds.push_back(fd.get());
+
+	std::array args{ std::string(ipaModulePath), std::to_string(fd.get()) };
+	std::array fds{ fd.get() };
 
 	proc_ = std::make_unique<Process>();
 	int ret = proc_->start(ipaProxyWorkerPath, args, fds);
diff -pruN 0.5.0-1/src/libcamera/matrix.cpp 0.6.0-2/src/libcamera/matrix.cpp
--- 0.5.0-1/src/libcamera/matrix.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/matrix.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,12 @@
 
 #include "libcamera/internal/matrix.h"
 
+#include <algorithm>
+#include <assert.h>
+#include <cmath>
+#include <numeric>
+#include <vector>
+
 #include <libcamera/base/log.h>
 
 /**
@@ -42,6 +48,16 @@ LOG_DEFINE_CATEGORY(Matrix)
  */
 
 /**
+ * \fn Matrix::Matrix(const Span<const T, Rows * Cols> data)
+ * \brief Construct a matrix from supplied data
+ * \param[in] data Data from which to construct a matrix
+ *
+ * \a data is a one-dimensional Span and will be turned into a matrix in
+ * row-major order. The size of \a data must be equal to the product of the
+ * number of rows and columns of the matrix (Rows x Cols).
+ */
+
+/**
  * \fn Matrix::identity()
  * \brief Construct an identity matrix
  */
@@ -78,6 +94,20 @@ LOG_DEFINE_CATEGORY(Matrix)
  */
 
 /**
+ * \fn Matrix::inverse(bool *ok) const
+ * \param[out] ok Indicate if the matrix was successfully inverted
+ * \brief Compute the inverse of the matrix
+ *
+ * This function computes the inverse of the matrix. It is only implemented for
+ * matrices of float and double types. If \a ok is provided it will be set to a
+ * boolean value to indicate of the inversion was successful. This can be used
+ * to check if the matrix is singular, in which case the function will return
+ * an identity matrix.
+ *
+ * \return The inverse of the matrix
+ */
+
+/**
  * \fn Matrix::operator[](size_t i)
  * \copydoc Matrix::operator[](size_t i) const
  */
@@ -108,11 +138,12 @@ LOG_DEFINE_CATEGORY(Matrix)
  */
 
 /**
- * \fn Matrix<T, R1, C2> operator*(const Matrix<T, R1, C1> &m1, const Matrix<T, R2, C2> &m2)
+ * \fn operator*(const Matrix<T1, R1, C1> &m1, const Matrix<T2, R2, C2> &m2)
  * \brief Matrix multiplication
- * \tparam T Type of numerical values in the matrices
+ * \tparam T1 Type of numerical values in the first matrix
  * \tparam R1 Number of rows in the first matrix
  * \tparam C1 Number of columns in the first matrix
+ * \tparam T2 Type of numerical values in the secont matrix
  * \tparam R2 Number of rows in the second matrix
  * \tparam C2 Number of columns in the second matrix
  * \param m1 Multiplicand matrix
@@ -132,6 +163,152 @@ LOG_DEFINE_CATEGORY(Matrix)
  */
 
 #ifndef __DOXYGEN__
+template<typename T>
+bool matrixInvert(Span<const T> dataIn, Span<T> dataOut, unsigned int dim,
+		  Span<T> scratchBuffer, Span<unsigned int> swapBuffer)
+{
+	/*
+	 * Convenience class to access matrix data, providing a row-major (i,j)
+	 * element accessor through the call operator, and the ability to swap
+	 * rows without modifying the backing storage.
+	 */
+	class MatrixAccessor
+	{
+	public:
+		MatrixAccessor(Span<T> data, Span<unsigned int> swapBuffer, unsigned int rows, unsigned int cols)
+			: data_(data), swap_(swapBuffer), rows_(rows), cols_(cols)
+		{
+			ASSERT(swap_.size() == rows);
+			std::iota(swap_.begin(), swap_.end(), T{ 0 });
+		}
+
+		T &operator()(unsigned int row, unsigned int col)
+		{
+			assert(row < rows_ && col < cols_);
+			return data_[index(row, col)];
+		}
+
+		void swap(unsigned int a, unsigned int b)
+		{
+			assert(a < rows_ && a < cols_);
+			std::swap(swap_[a], swap_[b]);
+		}
+
+	private:
+		unsigned int index(unsigned int row, unsigned int col) const
+		{
+			return swap_[row] * cols_ + col;
+		}
+
+		Span<T> data_;
+		Span<unsigned int> swap_;
+		unsigned int rows_;
+		unsigned int cols_;
+	};
+
+	/*
+	 * Matrix inversion using Gaussian elimination.
+	 *
+	 * Start by augmenting the original matrix with an identiy matrix of
+	 * the same size.
+	 */
+	ASSERT(scratchBuffer.size() == dim * dim * 2);
+	MatrixAccessor matrix(scratchBuffer, swapBuffer, dim, dim * 2);
+
+	for (unsigned int i = 0; i < dim; ++i) {
+		for (unsigned int j = 0; j < dim; ++j) {
+			matrix(i, j) = dataIn[i * dim + j];
+			matrix(i, j + dim) = T{ 0 };
+		}
+		matrix(i, i + dim) = T{ 1 };
+	}
+
+	/* Start by triangularizing the input . */
+	for (unsigned int pivot = 0; pivot < dim; ++pivot) {
+		/*
+		 * Locate the next pivot. To improve numerical stability, use
+		 * the row with the largest value in the pivot's column.
+		 */
+		unsigned int row = pivot;
+		T maxValue{ 0 };
+
+		for (unsigned int i = pivot; i < dim; ++i) {
+			T value = std::abs(matrix(i, pivot));
+			if (maxValue < value) {
+				maxValue = value;
+				row = i;
+			}
+		}
+
+		/*
+		 * If no pivot is found in the column, the matrix is not
+		 * invertible. Return an identity matrix.
+		 */
+		if (maxValue == 0) {
+			std::fill(dataOut.begin(), dataOut.end(), T{ 0 });
+			for (unsigned int i = 0; i < dim; ++i)
+				dataOut[i * dim + i] = T{ 1 };
+			return false;
+		}
+
+		/* Swap rows to bring the pivot in the right location. */
+		matrix.swap(pivot, row);
+
+		/* Process all rows below the pivot to zero the pivot column. */
+		const T pivotValue = matrix(pivot, pivot);
+
+		for (unsigned int i = pivot + 1; i < dim; ++i) {
+			const T factor = matrix(i, pivot) / pivotValue;
+
+			/*
+			 * We know the element in the pivot column will be 0,
+			 * hardcode it instead of computing it.
+			 */
+			matrix(i, pivot) = T{ 0 };
+
+			for (unsigned int j = pivot + 1; j < dim * 2; ++j)
+				matrix(i, j) -= matrix(pivot, j) * factor;
+		}
+	}
+
+	/*
+	 * Then diagonalize the input, walking the diagonal backwards. There's
+	 * no need to update the input matrix, as all the values we would write
+	 * in the top-right triangle aren't used in further calculations (and
+	 * would all by definition be zero).
+	 */
+	for (unsigned int pivot = dim - 1; pivot > 0; --pivot) {
+		const T pivotValue = matrix(pivot, pivot);
+
+		for (unsigned int i = 0; i < pivot; ++i) {
+			const T factor = matrix(i, pivot) / pivotValue;
+
+			for (unsigned int j = dim; j < dim * 2; ++j)
+				matrix(i, j) -= matrix(pivot, j) * factor;
+		}
+	}
+
+	/*
+	 * Finally, normalize the diagonal and store the result in the output
+	 * data.
+	 */
+	for (unsigned int i = 0; i < dim; ++i) {
+		const T factor = matrix(i, i);
+
+		for (unsigned int j = 0; j < dim; ++j)
+			dataOut[i * dim + j] = matrix(i, j + dim) / factor;
+	}
+
+	return true;
+}
+
+template bool matrixInvert<float>(Span<const float> dataIn, Span<float> dataOut,
+				  unsigned int dim, Span<float> scratchBuffer,
+				  Span<unsigned int> swapBuffer);
+template bool matrixInvert<double>(Span<const double> data, Span<double> dataOut,
+				   unsigned int dim, Span<double> scratchBuffer,
+				   Span<unsigned int> swapBuffer);
+
 /*
  * The YAML data shall be a list of numerical values. Its size shall be equal
  * to the product of the number of rows and columns of the matrix (Rows x
diff -pruN 0.5.0-1/src/libcamera/media_device.cpp 0.6.0-2/src/libcamera/media_device.cpp
--- 0.5.0-1/src/libcamera/media_device.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/media_device.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -20,6 +20,7 @@
 #include <linux/media.h>
 
 #include <libcamera/base/log.h>
+#include "libcamera/internal/v4l2_request.h"
 
 /**
  * \file media_device.h
@@ -794,7 +795,7 @@ void MediaDevice::fixupEntityFlags(struc
  * low-level link setup as it performs no checks on the validity of the \a
  * flags, and assumes that the supplied \a flags are valid for the link (e.g.
  * immutable links cannot be disabled).
-*
+ *
  * \sa MediaLink::setEnabled(bool enable)
  *
  * \return 0 on success or a negative error code otherwise
@@ -829,4 +830,72 @@ int MediaDevice::setupLink(const MediaLi
 	return 0;
 }
 
+/**
+ * \brief Identify all entities of a common function in the MediaDevice
+ * \param[in] function The entity function to search for
+ *
+ * Search all entities within the graph of the MediaDevice and return
+ * a vector of those which match the given function.
+ *
+ * \return A vector of matching entities
+ */
+std::vector<MediaEntity *> MediaDevice::locateEntities(unsigned int function)
+{
+	std::vector<MediaEntity *> found;
+
+	/* Gather all the entities matching the function they expose. */
+	for (MediaEntity *entity : entities()) {
+		if (entity->function() == function)
+			found.push_back(entity);
+	}
+
+	return found;
+}
+
+/**
+ * \brief Allocate requests
+ * \param[in] count Number of requests to allocate
+ * \param[out] requests Vector to store allocated requests
+ *
+ * Allocates and stores \a count requests in \a requests. If allocation fails,
+ * an error is returned and \a requests is cleared.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int MediaDevice::allocateRequests(unsigned int count,
+				  std::vector<std::unique_ptr<V4L2Request>> *requests)
+{
+	requests->resize(count);
+	for (unsigned int i = 0; i < count; i++) {
+		int requestFd;
+		int ret = ::ioctl(fd_.get(), MEDIA_IOC_REQUEST_ALLOC, &requestFd);
+		if (ret < 0) {
+			requests->clear();
+			return -errno;
+		}
+		(*requests)[i] = std::make_unique<V4L2Request>(UniqueFD(requestFd));
+	}
+
+	return 0;
+}
+
+/**
+ * \brief Check if requests are supported
+ *
+ * Checks if the device supports V4L2 requests by trying to allocate a single
+ * request. The result is cached, so the allocation is only tried once.
+ *
+ * \return True if the device supports requests, false otherwise
+ */
+bool MediaDevice::supportsRequests()
+{
+	if (supportsRequests_.has_value())
+		return supportsRequests_.value();
+
+	std::vector<std::unique_ptr<V4L2Request>> requests;
+	supportsRequests_ = (allocateRequests(1, &requests) == 0);
+
+	return supportsRequests_.value();
+}
+
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/media_pipeline.cpp 0.6.0-2/src/libcamera/media_pipeline.cpp
--- 0.5.0-1/src/libcamera/media_pipeline.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/libcamera/media_pipeline.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2024, Ideas on Board Oy
+ *
+ * Media pipeline support
+ */
+
+#include "libcamera/internal/media_pipeline.h"
+
+#include <algorithm>
+#include <errno.h>
+#include <queue>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+
+#include <linux/media.h>
+
+#include <libcamera/base/log.h>
+
+#include "libcamera/internal/camera_sensor.h"
+#include "libcamera/internal/media_device.h"
+#include "libcamera/internal/media_object.h"
+#include "libcamera/internal/v4l2_subdevice.h"
+
+/**
+ * \file media_pipeline.h
+ * \brief Provide a representation of a pipeline of devices using the Media
+ * Controller.
+ */
+
+namespace libcamera {
+
+LOG_DEFINE_CATEGORY(MediaPipeline)
+
+/**
+ * \class MediaPipeline
+ * \brief The MediaPipeline represents a set of entities that together form a
+ * data path for stream data.
+ *
+ * A MediaPipeline instance is constructed from a sink and a source between
+ * two entities in a media graph.
+ */
+
+/**
+ * \brief Retrieve all source pads connected to a sink pad through active routes
+ *
+ * Examine the entity using the V4L2 Subdevice Routing API to collect all the
+ * source pads which are connected with an active route to the sink pad.
+ *
+ * \return A vector of source MediaPads
+ */
+static std::vector<const MediaPad *> routedSourcePads(MediaPad *sink)
+{
+	MediaEntity *entity = sink->entity();
+	std::unique_ptr<V4L2Subdevice> subdev =
+		std::make_unique<V4L2Subdevice>(entity);
+
+	int ret = subdev->open();
+	if (ret < 0)
+		return {};
+
+	V4L2Subdevice::Routing routing = {};
+	ret = subdev->getRouting(&routing, V4L2Subdevice::ActiveFormat);
+	if (ret < 0)
+		return {};
+
+	std::vector<const MediaPad *> pads;
+
+	for (const V4L2Subdevice::Route &route : routing) {
+		if (sink->index() != route.sink.pad ||
+		    !(route.flags & V4L2_SUBDEV_ROUTE_FL_ACTIVE))
+			continue;
+
+		const MediaPad *pad = entity->getPadByIndex(route.source.pad);
+		if (!pad) {
+			LOG(MediaPipeline, Error)
+				<< "Entity " << entity->name()
+				<< " has invalid route source pad "
+				<< route.source.pad;
+			return {};
+		}
+
+		pads.push_back(pad);
+	}
+
+	return pads;
+}
+
+/**
+ * \brief Find the path from source to sink
+ *
+ * Starting from a source entity, determine the shortest path to the target
+ * described by \a sink.
+ *
+ * If \a sink can not be found, or a route from source to sink can not be
+ * achieved an error of -ENOLINK will be returned.
+ *
+ * When successful, the MediaPipeline will internally store the representation
+ * of entities and links to describe the path between the two entities.
+ *
+ * \return 0 on success, a negative errno otherwise
+ */
+int MediaPipeline::init(MediaEntity *source, std::string_view sink)
+{
+	/*
+	 * Find the shortest path between from the Camera Sensor and the
+	 * target entity.
+	 */
+	std::unordered_set<MediaEntity *> visited;
+	std::queue<std::tuple<MediaEntity *, MediaPad *>> queue;
+
+	/* Remember at each entity where we came from. */
+	std::unordered_map<MediaEntity *, Entity> parents;
+	MediaEntity *entity = nullptr;
+	MediaEntity *target = nullptr;
+	MediaPad *sinkPad;
+
+	queue.push({ source, nullptr });
+
+	while (!queue.empty()) {
+		std::tie(entity, sinkPad) = queue.front();
+		queue.pop();
+
+		/* Found the target device. */
+		if (entity->name() == sink) {
+			LOG(MediaPipeline, Debug)
+				<< "Found Pipeline target " << entity->name();
+			target = entity;
+			break;
+		}
+
+		visited.insert(entity);
+
+		/*
+		 * Add direct downstream entities to the search queue. If the
+		 * current entity supports the subdev internal routing API,
+		 * restrict the search to downstream entities reachable through
+		 * active routes.
+		 */
+
+		std::vector<const MediaPad *> pads;
+		bool supportsRouting = false;
+
+		if (sinkPad) {
+			pads = routedSourcePads(sinkPad);
+			if (!pads.empty())
+				supportsRouting = true;
+		}
+
+		if (pads.empty()) {
+			for (const MediaPad *pad : entity->pads()) {
+				if (!(pad->flags() & MEDIA_PAD_FL_SOURCE))
+					continue;
+				pads.push_back(pad);
+			}
+		}
+
+		for (const MediaPad *pad : pads) {
+			for (MediaLink *link : pad->links()) {
+				MediaEntity *next = link->sink()->entity();
+				if (visited.find(next) == visited.end()) {
+					queue.push({ next, link->sink() });
+
+					Entity e{ entity, supportsRouting, sinkPad, pad, link };
+					parents.insert({ next, e });
+				}
+			}
+		}
+	}
+
+	if (!target) {
+		LOG(MediaPipeline, Error)
+			<< "Failed to connect " << source->name()
+			<< " to " << sink;
+		return -ENOLINK;
+	}
+
+	/*
+	 * With the parents, we can follow back our way from the capture device
+	 * to the sensor. Store all the entities in the pipeline, from the
+	 * camera sensor to the video node, in entities_.
+	 */
+	entities_.push_front({ entity, false, sinkPad, nullptr, nullptr });
+
+	for (auto it = parents.find(entity); it != parents.end();
+	     it = parents.find(entity)) {
+		const Entity &e = it->second;
+		entities_.push_front(e);
+		entity = e.entity;
+	}
+
+	LOG(MediaPipeline, Info)
+		<< "Found pipeline: "
+		<< utils::join(entities_, " -> ",
+			       [](const Entity &e) {
+				       std::string s = "[";
+				       if (e.sink)
+					       s += std::to_string(e.sink->index()) + "|";
+				       s += e.entity->name();
+				       if (e.source)
+					       s += "|" + std::to_string(e.source->index());
+				       s += "]";
+				       return s;
+			       });
+
+	return 0;
+}
+
+/**
+ * \brief Initialise and enable all links through the MediaPipeline
+ * \return 0 on success, or a negative errno otherwise
+ */
+int MediaPipeline::initLinks()
+{
+	int ret = 0;
+
+	MediaLink *sinkLink = nullptr;
+	for (Entity &e : entities_) {
+		/* Sensor entities have no connected sink. */
+		if (!sinkLink) {
+			sinkLink = e.sourceLink;
+			continue;
+		}
+
+		LOG(MediaPipeline, Debug) << "Enabling : " << *sinkLink;
+
+		if (!(sinkLink->flags() & MEDIA_LNK_FL_ENABLED)) {
+			ret = sinkLink->setEnabled(true);
+			if (ret < 0)
+				return ret;
+		}
+
+		sinkLink = e.sourceLink;
+	}
+
+	return ret;
+}
+
+/**
+ * \brief Configure the entities of this MediaPipeline
+ *
+ * Propagate formats through each of the entities of the Pipeline, validating
+ * that each one was not adjusted by the driver from the desired format.
+ *
+ * \return 0 on success or a negative errno otherwise
+ */
+int MediaPipeline::configure(CameraSensor *sensor, V4L2SubdeviceFormat *format)
+{
+	int ret;
+
+	for (const Entity &e : entities_) {
+		/* The sensor is configured through the CameraSensor */
+		if (!e.sourceLink)
+			break;
+
+		MediaLink *link = e.sourceLink;
+		MediaPad *source = link->source();
+		MediaPad *sink = link->sink();
+
+		/* 'format' already contains the sensor configuration */
+		if (source->entity() != sensor->entity()) {
+			/* \todo Add MediaDevice cache to reduce FD pressure */
+			V4L2Subdevice subdev(source->entity());
+			ret = subdev.open();
+			if (ret)
+				return ret;
+
+			ret = subdev.getFormat(source->index(), format);
+			if (ret < 0)
+				return ret;
+		}
+
+		V4L2SubdeviceFormat sourceFormat = *format;
+		/* \todo Add MediaDevice cache to reduce FD pressure */
+		V4L2Subdevice subdev(sink->entity());
+		ret = subdev.open();
+		if (ret)
+			return ret;
+
+		ret = subdev.setFormat(sink->index(), format);
+		if (ret < 0)
+			return ret;
+
+		if (format->code != sourceFormat.code ||
+		    format->size != sourceFormat.size) {
+			LOG(MediaPipeline, Debug)
+				<< "Source '" << *source
+				<< " produces " << sourceFormat
+				<< ", sink '" << *sink
+				<< " requires " << *format;
+			return -EINVAL;
+		}
+
+		LOG(MediaPipeline, Debug)
+			<< "Link " << *link << " configured with format "
+			<< *format;
+	}
+
+	return 0;
+}
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/meson.build 0.6.0-2/src/libcamera/meson.build
--- 0.5.0-1/src/libcamera/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -21,6 +21,7 @@ libcamera_internal_sources = files([
     'byte_stream_buffer.cpp',
     'camera_controls.cpp',
     'camera_lens.cpp',
+    'clock_recovery.cpp',
     'control_serializer.cpp',
     'control_validator.cpp',
     'converter.cpp',
@@ -30,6 +31,7 @@ libcamera_internal_sources = files([
     'device_enumerator_sysfs.cpp',
     'dma_buf_allocator.cpp',
     'formats.cpp',
+    'global_configuration.cpp',
     'ipa_controls.cpp',
     'ipa_data_serializer.cpp',
     'ipa_interface.cpp',
@@ -43,6 +45,7 @@ libcamera_internal_sources = files([
     'matrix.cpp',
     'media_device.cpp',
     'media_object.cpp',
+    'media_pipeline.cpp',
     'pipeline_handler.cpp',
     'process.cpp',
     'pub_key.cpp',
@@ -51,6 +54,7 @@ libcamera_internal_sources = files([
     'sysfs.cpp',
     'v4l2_device.cpp',
     'v4l2_pixelformat.cpp',
+    'v4l2_request.cpp',
     'v4l2_subdevice.cpp',
     'v4l2_videodevice.cpp',
     'vector.cpp',
@@ -74,15 +78,12 @@ subdir('proxy')
 subdir('sensor')
 subdir('software_isp')
 
-null_dep = dependency('', required : false)
-
-# TODO: Use dependency('dl') when updating to meson 0.62.0 or newer.
-libdl = null_dep
-if not cc.has_function('dlopen')
-    libdl = cc.find_library('dl')
-endif
+libdl = dependency('dl')
 libudev = dependency('libudev', required : get_option('udev'))
-libyaml = dependency('yaml-0.1', required : false)
+libyaml = dependency('yaml-0.1', default_options : [
+    'default_library=static',
+    'werror=false',
+])
 
 # Use one of gnutls or libcrypto (provided by OpenSSL), trying gnutls first.
 libcrypto = dependency('gnutls', required : false)
@@ -118,17 +119,6 @@ if libudev.found()
     ])
 endif
 
-# Fallback to a subproject if libyaml isn't found, as it's not packaged in AOSP.
-if not libyaml.found()
-    cmake = import('cmake')
-
-    libyaml_vars = cmake.subproject_options()
-    libyaml_vars.add_cmake_defines({'CMAKE_POSITION_INDEPENDENT_CODE': 'ON'})
-    libyaml_vars.append_compile_args('c', '-Wno-unused-value')
-    libyaml_wrap = cmake.subproject('libyaml', options : libyaml_vars)
-    libyaml = libyaml_wrap.dependency('yaml')
-endif
-
 control_sources = []
 
 controls_mode_files = {
@@ -155,6 +145,7 @@ foreach mode, inout_files : controls_mod
                                      command : [gen_controls, '-o', '@OUTPUT@',
                                                 '--mode', mode, '-t', template_file,
                                                 '-r', ranges_file, '@INPUT@'],
+                                     depend_files : [py_mod_controls],
                                      env : py_build_env)
 endforeach
 
diff -pruN 0.5.0-1/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp 0.6.0-2/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp
--- 0.5.0-1/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/imx8-isi/imx8-isi.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -40,14 +40,13 @@ class PipelineHandlerISI;
 class ISICameraData : public Camera::Private
 {
 public:
-	ISICameraData(PipelineHandler *ph)
+	/* Maximum amount of streams (i.e. pipes) per camera. */
+	static constexpr unsigned int kNumStreams = 3;
+
+	ISICameraData(PipelineHandler *ph, unsigned int numStreams)
 		: Camera::Private(ph)
 	{
-		/*
-		 * \todo Assume 2 channels only for now, as that's the number of
-		 * available channels on i.MX8MP.
-		 */
-		streams_.resize(2);
+		streams_.resize(std::min(kNumStreams, numStreams));
 	}
 
 	PipelineHandlerISI *pipe();
@@ -56,7 +55,7 @@ public:
 
 	unsigned int pipeIndex(const Stream *stream)
 	{
-		return stream - &*streams_.begin();
+		return stream - &*streams_.begin() + xbarSourceOffset_;
 	}
 
 	unsigned int getRawMediaBusFormat(PixelFormat *pixelFormat) const;
@@ -70,7 +69,8 @@ public:
 
 	std::vector<Stream *> enabledStreams_;
 
-	unsigned int xbarSink_;
+	unsigned int xbarSink_ = 0;
+	unsigned int xbarSourceOffset_ = 0;
 };
 
 class ISICameraConfiguration : public CameraConfiguration
@@ -117,6 +117,8 @@ protected:
 
 	int queueRequestDevice(Camera *camera, Request *request) override;
 
+	bool acquireDevice(Camera *camera) override;
+
 private:
 	static constexpr Size kPreviewSize = { 1920, 1080 };
 	static constexpr Size kMinISISize = { 1, 1 };
@@ -139,10 +141,12 @@ private:
 
 	void bufferReady(FrameBuffer *buffer);
 
-	MediaDevice *isiDev_;
+	std::shared_ptr<MediaDevice> isiDev_;
 
 	std::unique_ptr<V4L2Subdevice> crossbar_;
 	std::vector<Pipe> pipes_;
+
+	V4L2Subdevice::Routing routing_ = {};
 };
 
 /* -----------------------------------------------------------------------------
@@ -366,7 +370,6 @@ ISICameraConfiguration::validateRaw(std:
 	 * Make sure the requested RAW format is supported by the
 	 * pipeline, otherwise adjust it.
 	 */
-	std::vector<unsigned int> mbusCodes = data_->sensor_->mbusCodes();
 	StreamConfiguration &rawConfig = config_[0];
 	PixelFormat rawFormat = rawConfig.pixelFormat;
 
@@ -762,30 +765,28 @@ PipelineHandlerISI::generateConfiguratio
 		 */
 		StreamConfiguration cfg;
 
-                switch (role) {
-                case StreamRole::StillCapture:
-                case StreamRole::Viewfinder:
-                case StreamRole::VideoRecording: {
-                        Size size = role == StreamRole::StillCapture
-                                  ? data->sensor_->resolution()
-                                  : PipelineHandlerISI::kPreviewSize;
-                        cfg = generateYUVConfiguration(camera, size);
-                        if (cfg.pixelFormat.isValid())
-                                break;
-
-
-                        /*
-                         * Fallback to use a Bayer format if that's what the
-                         * sensor supports.
-                         */
-                        [[fallthrough]];
-
-		 }
-
-                case StreamRole::Raw: {
-                        cfg = generateRawConfiguration(camera);
-                        break;
-                }
+		switch (role) {
+		case StreamRole::StillCapture:
+		case StreamRole::Viewfinder:
+		case StreamRole::VideoRecording: {
+			Size size = role == StreamRole::StillCapture
+				  ? data->sensor_->resolution()
+				  : PipelineHandlerISI::kPreviewSize;
+			cfg = generateYUVConfiguration(camera, size);
+			if (cfg.pixelFormat.isValid())
+				break;
+
+			/*
+			 * Fallback to use a Bayer format if that's what the
+			 * sensor supports.
+			 */
+			[[fallthrough]];
+		}
+
+		case StreamRole::Raw: {
+			cfg = generateRawConfiguration(camera);
+			break;
+		}
 
 		default:
 			LOG(ISI, Error) << "Requested stream role not supported: " << role;
@@ -811,34 +812,9 @@ int PipelineHandlerISI::configure(Camera
 	ISICameraConfiguration *camConfig = static_cast<ISICameraConfiguration *>(c);
 	ISICameraData *data = cameraData(camera);
 
-	/* All links are immutable except the sensor -> csis link. */
-	const MediaPad *sensorSrc = data->sensor_->entity()->getPadByIndex(0);
-	sensorSrc->links()[0]->setEnabled(true);
-
-	/*
-	 * Reset the crossbar switch routing and enable one route for each
-	 * requested stream configuration.
-	 *
-	 * \todo Handle concurrent usage of multiple cameras by adjusting the
-	 * routing table instead of resetting it.
-	 */
-	V4L2Subdevice::Routing routing = {};
-	unsigned int xbarFirstSource = crossbar_->entity()->pads().size() / 2 + 1;
-
-	for (const auto &[idx, config] : utils::enumerate(*c)) {
-		uint32_t sourcePad = xbarFirstSource + idx;
-		routing.emplace_back(V4L2Subdevice::Stream{ data->xbarSink_, 0 },
-				     V4L2Subdevice::Stream{ sourcePad, 0 },
-				     V4L2_SUBDEV_ROUTE_FL_ACTIVE);
-	}
-
-	int ret = crossbar_->setRouting(&routing, V4L2Subdevice::ActiveFormat);
-	if (ret)
-		return ret;
-
-	/* Apply format to the sensor and CSIS receiver. */
+	/* Apply format to the sensor, CSIS receiver and crossbar sink pad. */
 	V4L2SubdeviceFormat format = camConfig->sensorFormat_;
-	ret = data->sensor_->setFormat(&format);
+	int ret = data->sensor_->setFormat(&format);
 	if (ret)
 		return ret;
 
@@ -850,10 +826,17 @@ int PipelineHandlerISI::configure(Camera
 	if (ret)
 		return ret;
 
-	/* Now configure the ISI and video node instances, one per stream. */
-	data->enabledStreams_.clear();
-	for (const auto &config : *c) {
-		Pipe *pipe = pipeFromStream(camera, config.stream());
+	/*
+	 * As links on the output of the crossbar switch are immutable, the
+	 * routing table configured at match() time creates a media pipeline
+	 * that includes all the ISI pipelines corresponding to streams of this
+	 * camera, regardless of whether or not the streams are used in the
+	 * camera configuration. Set the format on the sink pad of all
+	 * corresponding ISI pipelines to avoid link validation failures when
+	 * starting streaming on the media pipeline.
+	 */
+	for (unsigned i = 0; i < data->streams_.size(); i++) {
+		Pipe *pipe = &pipes_.at(data->xbarSourceOffset_ + i);
 
 		/*
 		 * Set the format on the ISI sink pad: it must match what is
@@ -862,6 +845,15 @@ int PipelineHandlerISI::configure(Camera
 		ret = pipe->isi->setFormat(0, &format);
 		if (ret)
 			return ret;
+	}
+
+	/*
+	 * Now configure the ISI pipeline source pad and video node instances,
+	 * one per enabled stream.
+	 */
+	data->enabledStreams_.clear();
+	for (const auto &config : *c) {
+		Pipe *pipe = pipeFromStream(camera, config.stream());
 
 		/*
 		 * Configure the ISI sink compose rectangle to downscale the
@@ -962,6 +954,19 @@ int PipelineHandlerISI::queueRequestDevi
 	return 0;
 }
 
+bool PipelineHandlerISI::acquireDevice([[maybe_unused]] Camera *camera)
+{
+	if (useCount() > 0)
+		return true;
+
+	/* Enable routing for all available sensors once */
+	int ret = crossbar_->setRouting(&routing_, V4L2Subdevice::ActiveFormat);
+	if (ret)
+		return false;
+
+	return true;
+}
+
 bool PipelineHandlerISI::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch dm("mxc-isi");
@@ -973,11 +978,25 @@ bool PipelineHandlerISI::match(DeviceEnu
 	if (!isiDev_)
 		return false;
 
+	/* Count the number of sensors, to create one camera per sensor. */
+	unsigned cameraCount = 0;
+	for (MediaEntity *entity : isiDev_->entities()) {
+		if (entity->function() != MEDIA_ENT_F_CAM_SENSOR)
+			continue;
+
+		cameraCount++;
+	}
+
+	if (!cameraCount) {
+		LOG(ISI, Error) << "No camera sensor found";
+		return false;
+	}
+
 	/*
 	 * Acquire the subdevs and video nodes for the crossbar switch and the
 	 * processing pipelines.
 	 */
-	crossbar_ = V4L2Subdevice::fromEntityName(isiDev_, "crossbar");
+	crossbar_ = V4L2Subdevice::fromEntityName(isiDev_.get(), "crossbar");
 	if (!crossbar_)
 		return false;
 
@@ -988,7 +1007,7 @@ bool PipelineHandlerISI::match(DeviceEnu
 	for (unsigned int i = 0; ; ++i) {
 		std::string entityName = "mxc_isi." + std::to_string(i);
 		std::unique_ptr<V4L2Subdevice> isi =
-			V4L2Subdevice::fromEntityName(isiDev_, entityName);
+			V4L2Subdevice::fromEntityName(isiDev_.get(), entityName);
 		if (!isi)
 			break;
 
@@ -998,7 +1017,7 @@ bool PipelineHandlerISI::match(DeviceEnu
 
 		entityName += ".capture";
 		std::unique_ptr<V4L2VideoDevice> capture =
-			V4L2VideoDevice::fromEntityName(isiDev_, entityName);
+			V4L2VideoDevice::fromEntityName(isiDev_.get(), entityName);
 		if (!capture)
 			return false;
 
@@ -1006,7 +1025,7 @@ bool PipelineHandlerISI::match(DeviceEnu
 
 		ret = capture->open();
 		if (ret)
-			return ret;
+			return false;
 
 		pipes_.push_back({ std::move(isi), std::move(capture) });
 	}
@@ -1016,16 +1035,27 @@ bool PipelineHandlerISI::match(DeviceEnu
 		return false;
 	}
 
+	if (cameraCount > pipes_.size()) {
+		LOG(ISI, Error) << "Too many cameras";
+		return false;
+	}
+
 	/*
 	 * Loop over all the crossbar switch sink pads to find connected CSI-2
 	 * receivers and camera sensors.
+	 *
+	 * In multicamera case, limit maximum amount of streams to allow all
+	 * sensors to get at least one dedicated pipe.
 	 */
 	unsigned int numCameras = 0;
 	unsigned int numSinks = 0;
+	const unsigned int xbarFirstSource = crossbar_->entity()->pads().size() - pipes_.size();
+	const unsigned int maxStreams = pipes_.size() / cameraCount;
+
 	for (MediaPad *pad : crossbar_->entity()->pads()) {
 		unsigned int sink = numSinks;
 
-		if (!(pad->flags() & MEDIA_PAD_FL_SINK) || pad->links().empty())
+		if (!(pad->flags() & MEDIA_PAD_FL_SINK))
 			continue;
 
 		/*
@@ -1034,6 +1064,9 @@ bool PipelineHandlerISI::match(DeviceEnu
 		 */
 		numSinks++;
 
+		if (pad->links().empty())
+			continue;
+
 		MediaEntity *csi = pad->links()[0]->source()->entity();
 		if (csi->pads().size() != 2) {
 			LOG(ISI, Debug) << "Skip unsupported CSI-2 receiver "
@@ -1052,13 +1085,24 @@ bool PipelineHandlerISI::match(DeviceEnu
 			continue;
 		}
 
+		/* All links are immutable except the sensor -> csis link. */
+		const MediaPad *sensorSrc = sensor->getPadByIndex(0);
+		sensorSrc->links()[0]->setEnabled(true);
+
 		/* Create the camera data. */
 		std::unique_ptr<ISICameraData> data =
-			std::make_unique<ISICameraData>(this);
+			std::make_unique<ISICameraData>(this, maxStreams);
 
 		data->sensor_ = CameraSensorFactoryBase::create(sensor);
 		data->csis_ = std::make_unique<V4L2Subdevice>(csi);
 		data->xbarSink_ = sink;
+		data->xbarSourceOffset_ = numCameras * data->streams_.size();
+
+		LOG(ISI, Debug)
+			<< "cam" << numCameras
+			<< " streams " << data->streams_.size()
+			<< " sink " << data->xbarSink_
+			<< " offset " << data->xbarSourceOffset_;
 
 		ret = data->init();
 		if (ret) {
@@ -1073,6 +1117,14 @@ bool PipelineHandlerISI::match(DeviceEnu
 			       std::inserter(streams, streams.end()),
 			       [](Stream &s) { return &s; });
 
+		/*  Add routes to the crossbar switch routing table. */
+		for (unsigned i = 0; i < data->streams_.size(); i++) {
+			unsigned int sourcePad = xbarFirstSource + data->xbarSourceOffset_ + i;
+			routing_.emplace_back(V4L2Subdevice::Stream{ data->xbarSink_, 0 },
+					     V4L2Subdevice::Stream{ sourcePad, 0 },
+					     V4L2_SUBDEV_ROUTE_FL_ACTIVE);
+		}
+
 		std::shared_ptr<Camera> camera =
 			Camera::create(std::move(data), id, streams);
 
diff -pruN 0.5.0-1/src/libcamera/pipeline/ipu3/cio2.cpp 0.6.0-2/src/libcamera/pipeline/ipu3/cio2.cpp
--- 0.5.0-1/src/libcamera/pipeline/ipu3/cio2.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/ipu3/cio2.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -112,7 +112,7 @@ std::vector<SizeRange> CIO2Device::sizes
  * \return 0 on success or a negative error code otherwise
  * \retval -ENODEV No supported image sensor is connected to this CIO2 instance
  */
-int CIO2Device::init(const MediaDevice *media, unsigned int index)
+int CIO2Device::init(std::shared_ptr<const MediaDevice> media, unsigned int index)
 {
 	int ret;
 
@@ -170,7 +170,7 @@ int CIO2Device::init(const MediaDevice *
 		return ret;
 
 	std::string cio2Name = "ipu3-cio2 " + std::to_string(index);
-	output_ = V4L2VideoDevice::fromEntityName(media, cio2Name);
+	output_ = V4L2VideoDevice::fromEntityName(media.get(), cio2Name);
 	return output_->open();
 }
 
diff -pruN 0.5.0-1/src/libcamera/pipeline/ipu3/cio2.h 0.6.0-2/src/libcamera/pipeline/ipu3/cio2.h
--- 0.5.0-1/src/libcamera/pipeline/ipu3/cio2.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/ipu3/cio2.h	2025-11-27 11:55:28.000000000 +0000
@@ -38,7 +38,7 @@ public:
 	std::vector<PixelFormat> formats() const;
 	std::vector<SizeRange> sizes(const PixelFormat &format) const;
 
-	int init(const MediaDevice *media, unsigned int index);
+	int init(std::shared_ptr<const MediaDevice> media, unsigned int index);
 	int configure(const Size &size, const Transform &transform,
 		      V4L2DeviceFormat *outputFormat);
 
@@ -66,8 +66,6 @@ public:
 private:
 	void freeBuffers();
 
-	void cio2BufferReady(FrameBuffer *buffer);
-
 	std::unique_ptr<CameraSensor> sensor_;
 	std::unique_ptr<V4L2Subdevice> csi2_;
 	std::unique_ptr<V4L2VideoDevice> output_;
diff -pruN 0.5.0-1/src/libcamera/pipeline/ipu3/frames.cpp 0.6.0-2/src/libcamera/pipeline/ipu3/frames.cpp
--- 0.5.0-1/src/libcamera/pipeline/ipu3/frames.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/ipu3/frames.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -64,20 +64,20 @@ IPU3Frames::Info *IPU3Frames::create(Req
 	availableParamBuffers_.pop();
 	availableStatBuffers_.pop();
 
-	/* \todo Remove the dynamic allocation of Info */
-	std::unique_ptr<Info> info = std::make_unique<Info>();
+	auto [it, inserted] = frameInfo_.try_emplace(id);
+	ASSERT(inserted);
 
-	info->id = id;
-	info->request = request;
-	info->rawBuffer = nullptr;
-	info->paramBuffer = paramBuffer;
-	info->statBuffer = statBuffer;
-	info->paramDequeued = false;
-	info->metadataProcessed = false;
+	auto &info = it->second;
 
-	frameInfo_[id] = std::move(info);
+	info.id = id;
+	info.request = request;
+	info.rawBuffer = nullptr;
+	info.paramBuffer = paramBuffer;
+	info.statBuffer = statBuffer;
+	info.paramDequeued = false;
+	info.metadataProcessed = false;
 
-	return frameInfo_[id].get();
+	return &info;
 }
 
 void IPU3Frames::remove(IPU3Frames::Info *info)
@@ -115,7 +115,7 @@ IPU3Frames::Info *IPU3Frames::find(unsig
 	const auto &itInfo = frameInfo_.find(id);
 
 	if (itInfo != frameInfo_.end())
-		return itInfo->second.get();
+		return &itInfo->second;
 
 	LOG(IPU3, Fatal) << "Can't find tracking information for frame " << id;
 
@@ -124,16 +124,14 @@ IPU3Frames::Info *IPU3Frames::find(unsig
 
 IPU3Frames::Info *IPU3Frames::find(FrameBuffer *buffer)
 {
-	for (auto const &itInfo : frameInfo_) {
-		Info *info = itInfo.second.get();
-
-		for (auto const itBuffers : info->request->buffers())
-			if (itBuffers.second == buffer)
-				return info;
-
-		if (info->rawBuffer == buffer || info->paramBuffer == buffer ||
-		    info->statBuffer == buffer)
-			return info;
+	for (auto &[id, info] : frameInfo_) {
+		for (const auto &[stream, buf] : info.request->buffers())
+			if (buf == buffer)
+				return &info;
+
+		if (info.rawBuffer == buffer || info.paramBuffer == buffer ||
+		    info.statBuffer == buffer)
+			return &info;
 	}
 
 	LOG(IPU3, Fatal) << "Can't find tracking information from buffer";
diff -pruN 0.5.0-1/src/libcamera/pipeline/ipu3/frames.h 0.6.0-2/src/libcamera/pipeline/ipu3/frames.h
--- 0.5.0-1/src/libcamera/pipeline/ipu3/frames.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/ipu3/frames.h	2025-11-27 11:55:28.000000000 +0000
@@ -19,11 +19,7 @@
 namespace libcamera {
 
 class FrameBuffer;
-class IPAProxy;
-class PipelineHandler;
 class Request;
-class V4L2VideoDevice;
-struct IPABuffer;
 
 class IPU3Frames
 {
@@ -61,7 +57,7 @@ private:
 	std::queue<FrameBuffer *> availableParamBuffers_;
 	std::queue<FrameBuffer *> availableStatBuffers_;
 
-	std::map<unsigned int, std::unique_ptr<Info>> frameInfo_;
+	std::map<unsigned int, Info> frameInfo_;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/pipeline/ipu3/imgu.cpp 0.6.0-2/src/libcamera/pipeline/ipu3/imgu.cpp
--- 0.5.0-1/src/libcamera/pipeline/ipu3/imgu.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/ipu3/imgu.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -330,7 +330,8 @@ FOV calcFOV(const Size &in, const ImgUDe
  *
  * \return 0 on success or a negative error code otherwise
  */
-int ImgUDevice::init(MediaDevice *media, unsigned int index)
+int ImgUDevice::init(std::shared_ptr<libcamera::MediaDevice> media,
+		     unsigned int index)
 {
 	int ret;
 
@@ -342,32 +343,32 @@ int ImgUDevice::init(MediaDevice *media,
 	 * by the match() function: no need to check for newly created
 	 * video devices and subdevice validity here.
 	 */
-	imgu_ = V4L2Subdevice::fromEntityName(media, name_);
+	imgu_ = V4L2Subdevice::fromEntityName(media.get(), name_);
 	ret = imgu_->open();
 	if (ret)
 		return ret;
 
-	input_ = V4L2VideoDevice::fromEntityName(media, name_ + " input");
+	input_ = V4L2VideoDevice::fromEntityName(media.get(), name_ + " input");
 	ret = input_->open();
 	if (ret)
 		return ret;
 
-	output_ = V4L2VideoDevice::fromEntityName(media, name_ + " output");
+	output_ = V4L2VideoDevice::fromEntityName(media.get(), name_ + " output");
 	ret = output_->open();
 	if (ret)
 		return ret;
 
-	viewfinder_ = V4L2VideoDevice::fromEntityName(media, name_ + " viewfinder");
+	viewfinder_ = V4L2VideoDevice::fromEntityName(media.get(), name_ + " viewfinder");
 	ret = viewfinder_->open();
 	if (ret)
 		return ret;
 
-	param_ = V4L2VideoDevice::fromEntityName(media, name_ + " parameters");
+	param_ = V4L2VideoDevice::fromEntityName(media.get(), name_ + " parameters");
 	ret = param_->open();
 	if (ret)
 		return ret;
 
-	stat_ = V4L2VideoDevice::fromEntityName(media, name_ + " 3a stat");
+	stat_ = V4L2VideoDevice::fromEntityName(media.get(), name_ + " 3a stat");
 	ret = stat_->open();
 	if (ret)
 		return ret;
diff -pruN 0.5.0-1/src/libcamera/pipeline/ipu3/imgu.h 0.6.0-2/src/libcamera/pipeline/ipu3/imgu.h
--- 0.5.0-1/src/libcamera/pipeline/ipu3/imgu.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/ipu3/imgu.h	2025-11-27 11:55:28.000000000 +0000
@@ -64,7 +64,7 @@ public:
 		Size viewfinder;
 	};
 
-	int init(MediaDevice *media, unsigned int index);
+	int init(std::shared_ptr<MediaDevice> media, unsigned int index);
 
 	PipeConfig calculatePipeConfig(Pipe *pipe);
 
@@ -118,7 +118,7 @@ private:
 				 V4L2DeviceFormat *outputFormat);
 
 	std::string name_;
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/pipeline/ipu3/ipu3.cpp 0.6.0-2/src/libcamera/pipeline/ipu3/ipu3.cpp
--- 0.5.0-1/src/libcamera/pipeline/ipu3/ipu3.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/ipu3/ipu3.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -105,7 +105,7 @@ public:
 	Status validate() override;
 
 	const StreamConfiguration &cio2Format() const { return cio2Configuration_; }
-	const ImgUDevice::PipeConfig imguConfig() const { return pipeConfig_; }
+	const ImgUDevice::PipeConfig &imguConfig() const { return pipeConfig_; }
 
 	/* Cache the combinedTransform_ that will be applied to the sensor */
 	Transform combinedTransform_;
@@ -164,8 +164,8 @@ private:
 
 	ImgUDevice imgu0_;
 	ImgUDevice imgu1_;
-	MediaDevice *cio2MediaDev_;
-	MediaDevice *imguMediaDev_;
+	std::shared_ptr<MediaDevice> cio2MediaDev_;
+	std::shared_ptr<MediaDevice> imguMediaDev_;
 
 	std::vector<IPABuffer> ipaBuffers_;
 };
@@ -678,15 +678,19 @@ int PipelineHandlerIPU3::allocateBuffers
 	/* Map buffers to the IPA. */
 	unsigned int ipaBufferId = 1;
 
-	for (const std::unique_ptr<FrameBuffer> &buffer : imgu->paramBuffers_) {
-		buffer->setCookie(ipaBufferId++);
-		ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());
-	}
+	auto pushBuffers = [&](const std::vector<std::unique_ptr<FrameBuffer>> &buffers) {
+		for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
+			Span<const FrameBuffer::Plane> planes = buffer->planes();
+
+			buffer->setCookie(ipaBufferId++);
+			ipaBuffers_.emplace_back(buffer->cookie(),
+						 std::vector<FrameBuffer::Plane>{ planes.begin(),
+										  planes.end() });
+		}
+	};
 
-	for (const std::unique_ptr<FrameBuffer> &buffer : imgu->statBuffers_) {
-		buffer->setCookie(ipaBufferId++);
-		ipaBuffers_.emplace_back(buffer->cookie(), buffer->planes());
-	}
+	pushBuffers(imgu->paramBuffers_);
+	pushBuffers(imgu->statBuffers_);
 
 	data->ipa_->mapBuffers(ipaBuffers_);
 
diff -pruN 0.5.0-1/src/libcamera/pipeline/mali-c55/mali-c55.cpp 0.6.0-2/src/libcamera/pipeline/mali-c55/mali-c55.cpp
--- 0.5.0-1/src/libcamera/pipeline/mali-c55/mali-c55.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/mali-c55/mali-c55.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -101,8 +101,8 @@ public:
 	int loadIPA();
 
 	/* Deflect these functionalities to either TPG or CameraSensor. */
-	const std::vector<Size> sizes(unsigned int mbusCode) const;
-	const Size resolution() const;
+	std::vector<Size> sizes(unsigned int mbusCode) const;
+	Size resolution() const;
 
 	int pixfmtToMbusCode(const PixelFormat &pixFmt) const;
 	const PixelFormat &bestRawFormat() const;
@@ -131,8 +131,6 @@ private:
 	void setSensorControls(const ControlList &sensorControls);
 
 	std::string id_;
-	std::vector<unsigned int> tpgCodes_;
-	std::vector<Size> tpgSizes_;
 	Size tpgResolution_;
 };
 
@@ -159,15 +157,16 @@ int MaliC55CameraData::init()
 	 */
 	sensor_ = CameraSensorFactoryBase::create(entity_);
 	if (!sensor_)
-		return ret;
+		return -ENODEV;
 
 	const MediaPad *sourcePad = entity_->getPadByIndex(0);
 	MediaEntity *csiEntity = sourcePad->links()[0]->sink()->entity();
 
 	csi_ = std::make_unique<V4L2Subdevice>(csiEntity);
-	if (csi_->open()) {
+	ret = csi_->open();
+	if (ret) {
 		LOG(MaliC55, Error) << "Failed to open CSI-2 subdevice";
-		return false;
+		return ret;
 	}
 
 	return 0;
@@ -180,16 +179,15 @@ void MaliC55CameraData::initTPGData()
 	if (formats.empty())
 		return;
 
-	tpgCodes_ = utils::map_keys(formats);
-	std::sort(tpgCodes_.begin(), tpgCodes_.end());
+	std::vector<Size> tpgSizes;
 
 	for (const auto &format : formats) {
 		const std::vector<SizeRange> &ranges = format.second;
-		std::transform(ranges.begin(), ranges.end(), std::back_inserter(tpgSizes_),
+		std::transform(ranges.begin(), ranges.end(), std::back_inserter(tpgSizes),
 			       [](const SizeRange &range) { return range.max; });
 	}
 
-	tpgResolution_ = tpgSizes_.back();
+	tpgResolution_ = tpgSizes.back();
 }
 
 void MaliC55CameraData::setSensorControls(const ControlList &sensorControls)
@@ -197,7 +195,7 @@ void MaliC55CameraData::setSensorControl
 	delayedCtrls_->push(sensorControls);
 }
 
-const std::vector<Size> MaliC55CameraData::sizes(unsigned int mbusCode) const
+std::vector<Size> MaliC55CameraData::sizes(unsigned int mbusCode) const
 {
 	if (sensor_)
 		return sensor_->sizes(mbusCode);
@@ -220,7 +218,7 @@ const std::vector<Size> MaliC55CameraDat
 	return sizes;
 }
 
-const Size MaliC55CameraData::resolution() const
+Size MaliC55CameraData::resolution() const
 {
 	if (sensor_)
 		return sensor_->resolution();
@@ -620,7 +618,7 @@ public:
 	void imageBufferReady(FrameBuffer *buffer);
 	void paramsBufferReady(FrameBuffer *buffer);
 	void statsBufferReady(FrameBuffer *buffer);
-	void paramsComputed(unsigned int requestId);
+	void paramsComputed(unsigned int requestId, uint32_t bytesused);
 	void statsProcessed(unsigned int requestId, const ControlList &metadata);
 
 	bool match(DeviceEnumerator *enumerator) override;
@@ -684,7 +682,7 @@ private:
 	bool registerTPGCamera(MediaLink *link);
 	bool registerSensorCamera(MediaLink *link);
 
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 	std::unique_ptr<V4L2Subdevice> isp_;
 	std::unique_ptr<V4L2VideoDevice> stats_;
 	std::unique_ptr<V4L2VideoDevice> params_;
@@ -1135,27 +1133,33 @@ int PipelineHandlerMaliC55::allocateBuff
 		data->dsStream_.configuration().bufferCount,
 	});
 
+	auto pushBuffers = [&](const std::vector<std::unique_ptr<FrameBuffer>> &buffers,
+			       std::queue<FrameBuffer *> &queue,
+			       std::vector<IPABuffer> &ipaBuffers) {
+		for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
+			Span<const FrameBuffer::Plane> planes = buffer->planes();
+
+			buffer->setCookie(ipaBufferId++);
+			ipaBuffers.emplace_back(buffer->cookie(),
+						std::vector<FrameBuffer::Plane>{ planes.begin(),
+										 planes.end() });
+			queue.push(buffer.get());
+		}
+	};
+
 	ret = stats_->allocateBuffers(bufferCount, &statsBuffers_);
 	if (ret < 0)
 		return ret;
 
-	for (std::unique_ptr<FrameBuffer> &buffer : statsBuffers_) {
-		buffer->setCookie(ipaBufferId++);
-		data->ipaStatBuffers_.emplace_back(buffer->cookie(),
-						   buffer->planes());
-		availableStatsBuffers_.push(buffer.get());
-	}
+	pushBuffers(statsBuffers_, availableStatsBuffers_,
+		    data->ipaStatBuffers_);
 
 	ret = params_->allocateBuffers(bufferCount, &paramsBuffers_);
 	if (ret < 0)
 		return ret;
 
-	for (std::unique_ptr<FrameBuffer> &buffer : paramsBuffers_) {
-		buffer->setCookie(ipaBufferId++);
-		data->ipaParamBuffers_.emplace_back(buffer->cookie(),
-						    buffer->planes());
-		availableParamsBuffers_.push(buffer.get());
-	}
+	pushBuffers(paramsBuffers_, availableParamsBuffers_,
+		    data->ipaParamBuffers_);
 
 	if (data->ipa_) {
 		data->ipa_->mapBuffers(data->ipaStatBuffers_, true);
@@ -1496,7 +1500,7 @@ void PipelineHandlerMaliC55::statsBuffer
 				 sensorControls);
 }
 
-void PipelineHandlerMaliC55::paramsComputed(unsigned int requestId)
+void PipelineHandlerMaliC55::paramsComputed(unsigned int requestId, uint32_t bytesused)
 {
 	MaliC55FrameInfo &frameInfo = frameInfoMap_[requestId];
 	Request *request = frameInfo.request;
@@ -1507,8 +1511,7 @@ void PipelineHandlerMaliC55::paramsCompu
 	 * video devices.
 	 */
 
-	frameInfo.paramBuffer->_d()->metadata().planes()[0].bytesused =
-		sizeof(struct mali_c55_params_buffer);
+	frameInfo.paramBuffer->_d()->metadata().planes()[0].bytesused = bytesused;
 	params_->queueBuffer(frameInfo.paramBuffer);
 	stats_->queueBuffer(frameInfo.statBuffer);
 
@@ -1644,24 +1647,24 @@ bool PipelineHandlerMaliC55::match(Devic
 	if (!media_)
 		return false;
 
-	isp_ = V4L2Subdevice::fromEntityName(media_, "mali-c55 isp");
+	isp_ = V4L2Subdevice::fromEntityName(media_.get(), "mali-c55 isp");
 	if (isp_->open() < 0)
 		return false;
 
-	stats_ = V4L2VideoDevice::fromEntityName(media_, "mali-c55 3a stats");
+	stats_ = V4L2VideoDevice::fromEntityName(media_.get(), "mali-c55 3a stats");
 	if (stats_->open() < 0)
 		return false;
 
-	params_ = V4L2VideoDevice::fromEntityName(media_, "mali-c55 3a params");
+	params_ = V4L2VideoDevice::fromEntityName(media_.get(), "mali-c55 3a params");
 	if (params_->open() < 0)
 		return false;
 
 	MaliC55Pipe *frPipe = &pipes_[MaliC55FR];
-	frPipe->resizer = V4L2Subdevice::fromEntityName(media_, "mali-c55 resizer fr");
+	frPipe->resizer = V4L2Subdevice::fromEntityName(media_.get(), "mali-c55 resizer fr");
 	if (frPipe->resizer->open() < 0)
 		return false;
 
-	frPipe->cap = V4L2VideoDevice::fromEntityName(media_, "mali-c55 fr");
+	frPipe->cap = V4L2VideoDevice::fromEntityName(media_.get(), "mali-c55 fr");
 	if (frPipe->cap->open() < 0)
 		return false;
 
@@ -1679,11 +1682,11 @@ bool PipelineHandlerMaliC55::match(Devic
 
 		MaliC55Pipe *dsPipe = &pipes_[MaliC55DS];
 
-		dsPipe->resizer = V4L2Subdevice::fromEntityName(media_, "mali-c55 resizer ds");
+		dsPipe->resizer = V4L2Subdevice::fromEntityName(media_.get(), "mali-c55 resizer ds");
 		if (dsPipe->resizer->open() < 0)
 			return false;
 
-		dsPipe->cap = V4L2VideoDevice::fromEntityName(media_, "mali-c55 ds");
+		dsPipe->cap = V4L2VideoDevice::fromEntityName(media_.get(), "mali-c55 ds");
 		if (dsPipe->cap->open() < 0)
 			return false;
 
@@ -1712,7 +1715,7 @@ bool PipelineHandlerMaliC55::match(Devic
 	 *
 	 * MEDIA_ENT_F_CAM_SENSOR - The test pattern generator
 	 * MEDIA_ENT_F_VID_IF_BRIDGE - A CSI-2 receiver
-	 * MEDIA_ENT_F_IO_V4L - An input device
+	 * MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER - An input device
 	 *
 	 * The last one will be unsupported for now. The TPG is relatively easy,
 	 * we just register a Camera for it. If we have a CSI-2 receiver we need
@@ -1738,7 +1741,7 @@ bool PipelineHandlerMaliC55::match(Devic
 				return registered;
 
 			break;
-		case MEDIA_ENT_F_IO_V4L:
+		case MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER:
 			LOG(MaliC55, Warning) << "Memory input not yet supported";
 			break;
 		default:
diff -pruN 0.5.0-1/src/libcamera/pipeline/rkisp1/rkisp1.cpp 0.6.0-2/src/libcamera/pipeline/rkisp1/rkisp1.cpp
--- 0.5.0-1/src/libcamera/pipeline/rkisp1/rkisp1.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rkisp1/rkisp1.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -16,6 +16,7 @@
 #include <linux/media-bus-format.h>
 #include <linux/rkisp1-config.h>
 
+#include <libcamera/base/file.h>
 #include <libcamera/base/log.h>
 #include <libcamera/base/utils.h>
 
@@ -36,15 +37,17 @@
 #include "libcamera/internal/camera.h"
 #include "libcamera/internal/camera_sensor.h"
 #include "libcamera/internal/camera_sensor_properties.h"
-#include "libcamera/internal/converter/converter_v4l2_m2m.h"
+#include "libcamera/internal/converter/converter_dw100.h"
 #include "libcamera/internal/delayed_controls.h"
 #include "libcamera/internal/device_enumerator.h"
 #include "libcamera/internal/framebuffer.h"
 #include "libcamera/internal/ipa_manager.h"
 #include "libcamera/internal/media_device.h"
+#include "libcamera/internal/media_pipeline.h"
 #include "libcamera/internal/pipeline_handler.h"
 #include "libcamera/internal/v4l2_subdevice.h"
 #include "libcamera/internal/v4l2_videodevice.h"
+#include "libcamera/internal/yaml_parser.h"
 
 #include "rkisp1_path.h"
 
@@ -84,7 +87,7 @@ public:
 
 private:
 	PipelineHandlerRkISP1 *pipe_;
-	std::map<unsigned int, RkISP1FrameInfo *> frameInfo_;
+	std::map<unsigned int, RkISP1FrameInfo> frameInfo_;
 };
 
 class RkISP1CameraData : public Camera::Private
@@ -93,13 +96,14 @@ public:
 	RkISP1CameraData(PipelineHandler *pipe, RkISP1MainPath *mainPath,
 			 RkISP1SelfPath *selfPath)
 		: Camera::Private(pipe), frame_(0), frameInfo_(pipe),
-		  mainPath_(mainPath), selfPath_(selfPath)
+		  mainPath_(mainPath), selfPath_(selfPath),
+		  canUseDewarper_(false), usesDewarper_(false)
 	{
 	}
 
 	PipelineHandlerRkISP1 *pipe();
 	const PipelineHandlerRkISP1 *pipe() const;
-	int loadIPA(unsigned int hwRevision);
+	int loadIPA(unsigned int hwRevision, uint32_t supportedBlocks);
 
 	Stream mainPathStream_;
 	Stream selfPathStream_;
@@ -116,12 +120,21 @@ public:
 
 	ControlInfoMap ipaControls_;
 
+	/*
+	 * All entities in the pipeline, from the camera sensor to the RKISP1.
+	 */
+	MediaPipeline pipe_;
+
+	bool canUseDewarper_;
+	bool usesDewarper_;
+
 private:
 	void paramsComputed(unsigned int frame, unsigned int bytesused);
 	void setSensorControls(unsigned int frame,
 			       const ControlList &sensorControls);
 
 	void metadataReady(unsigned int frame, const ControlList &metadata);
+	int loadTuningFile(const std::string &file);
 };
 
 class RkISP1CameraConfiguration : public CameraConfiguration
@@ -149,6 +162,24 @@ private:
 	Transform combinedTransform_;
 };
 
+namespace {
+
+/*
+ * Maximum number of requests that shall be queued into the pipeline to keep
+ * the regulation fast.
+ * \todo This needs revisiting as soon as buffers got decoupled from requests
+ * and/or a fast path for controls was implemented.
+ */
+static constexpr unsigned int kRkISP1MaxQueuedRequests = 4;
+
+/*
+ * This many internal buffers (or rather parameter and statistics buffer
+ * pairs) ensures that the pipeline runs smoothly, without frame drops.
+ */
+static constexpr unsigned int kRkISP1MinBufferCount = 4;
+
+} /* namespace */
+
 class PipelineHandlerRkISP1 : public PipelineHandler
 {
 public:
@@ -180,10 +211,10 @@ private:
 	friend RkISP1CameraConfiguration;
 	friend RkISP1Frames;
 
-	int initLinks(Camera *camera, const CameraSensor *sensor,
-		      const RkISP1CameraConfiguration &config);
+	int initLinks(Camera *camera, const RkISP1CameraConfiguration &config);
 	int createCamera(MediaEntity *sensor);
 	void tryCompleteRequest(RkISP1FrameInfo *info);
+	void cancelDewarpRequest(RkISP1FrameInfo *info);
 	void imageBufferReady(FrameBuffer *buffer);
 	void paramBufferReady(FrameBuffer *buffer);
 	void statBufferReady(FrameBuffer *buffer);
@@ -195,11 +226,10 @@ private:
 
 	int updateControls(RkISP1CameraData *data);
 
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 	std::unique_ptr<V4L2Subdevice> isp_;
 	std::unique_ptr<V4L2VideoDevice> param_;
 	std::unique_ptr<V4L2VideoDevice> stat_;
-	std::unique_ptr<V4L2Subdevice> csi_;
 
 	bool hasSelfPath_;
 	bool isRaw_;
@@ -207,11 +237,7 @@ private:
 	RkISP1MainPath mainPath_;
 	RkISP1SelfPath selfPath_;
 
-	std::unique_ptr<V4L2M2MConverter> dewarper_;
-	Rectangle scalerMaxCrop_;
-	bool useDewarper_;
-
-	std::optional<Rectangle> activeCrop_;
+	std::unique_ptr<ConverterDW100Module> dewarper_;
 
 	/* Internal buffers used when dewarper is being used */
 	std::vector<std::unique_ptr<FrameBuffer>> mainPathBuffers_;
@@ -223,8 +249,6 @@ private:
 	std::queue<FrameBuffer *> availableStatBuffers_;
 
 	Camera *activeCamera_;
-
-	const MediaPad *ispSink_;
 };
 
 RkISP1Frames::RkISP1Frames(PipelineHandler *pipe)
@@ -259,7 +283,7 @@ RkISP1FrameInfo *RkISP1Frames::create(co
 		statBuffer = pipe_->availableStatBuffers_.front();
 		pipe_->availableStatBuffers_.pop();
 
-		if (pipe_->useDewarper_) {
+		if (data->usesDewarper_) {
 			mainPathBuffer = pipe_->availableMainPathBuffers_.front();
 			pipe_->availableMainPathBuffers_.pop();
 		}
@@ -269,49 +293,46 @@ RkISP1FrameInfo *RkISP1Frames::create(co
 		mainPathBuffer = request->findBuffer(&data->mainPathStream_);
 	selfPathBuffer = request->findBuffer(&data->selfPathStream_);
 
-	RkISP1FrameInfo *info = new RkISP1FrameInfo;
+	auto [it, inserted] = frameInfo_.try_emplace(frame);
+	ASSERT(inserted);
 
-	info->frame = frame;
-	info->request = request;
-	info->paramBuffer = paramBuffer;
-	info->mainPathBuffer = mainPathBuffer;
-	info->selfPathBuffer = selfPathBuffer;
-	info->statBuffer = statBuffer;
-	info->paramDequeued = false;
-	info->metadataProcessed = false;
+	auto &info = it->second;
 
-	frameInfo_[frame] = info;
+	info.frame = frame;
+	info.request = request;
+	info.paramBuffer = paramBuffer;
+	info.mainPathBuffer = mainPathBuffer;
+	info.selfPathBuffer = selfPathBuffer;
+	info.statBuffer = statBuffer;
+	info.paramDequeued = false;
+	info.metadataProcessed = false;
 
-	return info;
+	return &info;
 }
 
 int RkISP1Frames::destroy(unsigned int frame)
 {
-	RkISP1FrameInfo *info = find(frame);
-	if (!info)
+	auto it = frameInfo_.find(frame);
+	if (it == frameInfo_.end())
 		return -ENOENT;
 
-	pipe_->availableParamBuffers_.push(info->paramBuffer);
-	pipe_->availableStatBuffers_.push(info->statBuffer);
-	pipe_->availableMainPathBuffers_.push(info->mainPathBuffer);
+	auto &info = it->second;
 
-	frameInfo_.erase(info->frame);
+	pipe_->availableParamBuffers_.push(info.paramBuffer);
+	pipe_->availableStatBuffers_.push(info.statBuffer);
+	pipe_->availableMainPathBuffers_.push(info.mainPathBuffer);
 
-	delete info;
+	frameInfo_.erase(it);
 
 	return 0;
 }
 
 void RkISP1Frames::clear()
 {
-	for (const auto &entry : frameInfo_) {
-		RkISP1FrameInfo *info = entry.second;
-
-		pipe_->availableParamBuffers_.push(info->paramBuffer);
-		pipe_->availableStatBuffers_.push(info->statBuffer);
-		pipe_->availableMainPathBuffers_.push(info->mainPathBuffer);
-
-		delete info;
+	for (const auto &[frame, info] : frameInfo_) {
+		pipe_->availableParamBuffers_.push(info.paramBuffer);
+		pipe_->availableStatBuffers_.push(info.statBuffer);
+		pipe_->availableMainPathBuffers_.push(info.mainPathBuffer);
 	}
 
 	frameInfo_.clear();
@@ -322,7 +343,7 @@ RkISP1FrameInfo *RkISP1Frames::find(unsi
 	auto itInfo = frameInfo_.find(frame);
 
 	if (itInfo != frameInfo_.end())
-		return itInfo->second;
+		return &itInfo->second;
 
 	LOG(RkISP1, Fatal) << "Can't locate info from frame";
 
@@ -331,14 +352,12 @@ RkISP1FrameInfo *RkISP1Frames::find(unsi
 
 RkISP1FrameInfo *RkISP1Frames::find(FrameBuffer *buffer)
 {
-	for (auto &itInfo : frameInfo_) {
-		RkISP1FrameInfo *info = itInfo.second;
-
-		if (info->paramBuffer == buffer ||
-		    info->statBuffer == buffer ||
-		    info->mainPathBuffer == buffer ||
-		    info->selfPathBuffer == buffer)
-			return info;
+	for (auto &[frame, info] : frameInfo_) {
+		if (info.paramBuffer == buffer ||
+		    info.statBuffer == buffer ||
+		    info.mainPathBuffer == buffer ||
+		    info.selfPathBuffer == buffer)
+			return &info;
 	}
 
 	LOG(RkISP1, Fatal) << "Can't locate info from buffer";
@@ -348,11 +367,9 @@ RkISP1FrameInfo *RkISP1Frames::find(Fram
 
 RkISP1FrameInfo *RkISP1Frames::find(Request *request)
 {
-	for (auto &itInfo : frameInfo_) {
-		RkISP1FrameInfo *info = itInfo.second;
-
-		if (info->request == request)
-			return info;
+	for (auto &[frame, info] : frameInfo_) {
+		if (info.request == request)
+			return &info;
 	}
 
 	LOG(RkISP1, Fatal) << "Can't locate info from request";
@@ -370,7 +387,7 @@ const PipelineHandlerRkISP1 *RkISP1Camer
 	return static_cast<const PipelineHandlerRkISP1 *>(Camera::Private::pipe());
 }
 
-int RkISP1CameraData::loadIPA(unsigned int hwRevision)
+int RkISP1CameraData::loadIPA(unsigned int hwRevision, uint32_t supportedBlocks)
 {
 	ipa_ = IPAManager::createIPA<ipa::rkisp1::IPAProxyRkISP1>(pipe(), 1, 1);
 	if (!ipa_)
@@ -392,12 +409,64 @@ int RkISP1CameraData::loadIPA(unsigned i
 	}
 
 	ret = ipa_->init({ ipaTuningFile, sensor_->model() }, hwRevision,
-			 sensorInfo, sensor_->controls(), &ipaControls_);
+			 supportedBlocks, sensorInfo, sensor_->controls(),
+			 &ipaControls_);
 	if (ret < 0) {
 		LOG(RkISP1, Error) << "IPA initialization failure";
 		return ret;
 	}
 
+	ret = loadTuningFile(ipaTuningFile);
+	if (ret < 0) {
+		LOG(RkISP1, Error) << "Failed to load tuning file";
+		return ret;
+	}
+
+	return 0;
+}
+
+int RkISP1CameraData::loadTuningFile(const std::string &path)
+{
+	int ret;
+
+	if (!pipe()->dewarper_)
+		/* Nothing to do without dewarper */
+		return 0;
+
+	LOG(RkISP1, Debug) << "Load tuning file " << path;
+
+	File file(path);
+	if (!file.open(File::OpenModeFlag::ReadOnly)) {
+		ret = file.error();
+		LOG(RkISP1, Error)
+			<< "Failed to open tuning file "
+			<< path << ": " << strerror(-ret);
+		return ret;
+	}
+
+	std::unique_ptr<libcamera::YamlObject> data = YamlParser::parse(file);
+	if (!data)
+		return -EINVAL;
+
+	if (!data->contains("modules"))
+		return 0;
+
+	const auto &modules = (*data)["modules"].asList();
+	for (const auto &module : modules) {
+		const auto &params = module["Dewarp"];
+		if (!params)
+			continue;
+
+		ret = pipe()->dewarper_->init(params);
+		if (ret)
+			return ret;
+
+		LOG(RkISP1, Info) << "Dw100 dewarper initialized";
+
+		canUseDewarper_ = true;
+		return 0;
+	}
+
 	return 0;
 }
 
@@ -409,7 +478,14 @@ void RkISP1CameraData::paramsComputed(un
 		return;
 
 	info->paramBuffer->_d()->metadata().planes()[0].bytesused = bytesused;
-	pipe->param_->queueBuffer(info->paramBuffer);
+
+	int ret = pipe->param_->queueBuffer(info->paramBuffer);
+	if (ret < 0) {
+		LOG(RkISP1, Error) << "Failed to queue parameter buffer: "
+				   << strerror(-ret);
+		return;
+	}
+
 	pipe->stat_->queueBuffer(info->statBuffer);
 
 	if (info->mainPathBuffer)
@@ -525,36 +601,46 @@ CameraConfiguration::Status RkISP1Camera
 		status = Adjusted;
 	}
 
-	Orientation requestedOrientation = orientation;
-	combinedTransform_ = data_->sensor_->computeTransform(&orientation);
-	if (orientation != requestedOrientation)
-		status = Adjusted;
-
 	/*
-	 * Simultaneous capture of raw and processed streams isn't possible. If
-	 * there is any raw stream, cap the number of streams to one.
+	 * Simultaneous capture of raw and processed streams isn't possible.
+	 * Let the first stream decide on the type.
 	 */
-	if (config_.size() > 1) {
-		for (const auto &cfg : config_) {
-			if (PixelFormatInfo::info(cfg.pixelFormat).colourEncoding ==
+	bool isRaw = (PixelFormatInfo::info(config_[0].pixelFormat).colourEncoding ==
+		      PixelFormatInfo::ColourEncodingRAW);
+	if (isRaw) {
+		if (config_.size() > 1) {
+			config_.resize(1);
+			status = Adjusted;
+		}
+	} else {
+		/* Drop all raw configs. */
+		for (auto it = config_.begin(); it != config_.end();) {
+			if (PixelFormatInfo::info(it->pixelFormat).colourEncoding ==
 			    PixelFormatInfo::ColourEncodingRAW) {
-				config_.resize(1);
+				it = config_.erase(it);
 				status = Adjusted;
-				break;
+				continue;
 			}
+			++it;
 		}
 	}
 
-	bool useDewarper = false;
-	if (pipe->dewarper_) {
-		/*
-		 * Platforms with dewarper support, such as i.MX8MP, support
-		 * only a single stream. We can inspect config_[0] only here.
-		 */
-		bool isRaw = PixelFormatInfo::info(config_[0].pixelFormat).colourEncoding ==
-			     PixelFormatInfo::ColourEncodingRAW;
-		if (!isRaw)
-			useDewarper = true;
+	/*
+	 * If the dewarper supports orientation adjustments, apply that completely
+	 * there. Even if the sensor supports flips, it is beneficial to do that
+	 * in the dewarper so that lens dewarping happens on the unflipped image
+	 */
+	bool transposeAfterIsp = false;
+	bool useDewarper = (data_->canUseDewarper_ && !isRaw);
+	if (useDewarper) {
+		combinedTransform_ = orientation / data_->sensor_->mountingOrientation();
+		if (!!(combinedTransform_ & Transform::Transpose))
+			transposeAfterIsp = true;
+	} else {
+		Orientation requestedOrientation = orientation;
+		combinedTransform_ = data_->sensor_->computeTransform(&orientation);
+		if (orientation != requestedOrientation)
+			status = Adjusted;
 	}
 
 	/*
@@ -571,12 +657,18 @@ CameraConfiguration::Status RkISP1Camera
 
 	/*
 	 * Validate the configuration against the desired path and, if the
-	 * platform supports it, the dewarper.
+	 * platform supports it, the dewarper. While iterating over the
+	 * configurations collect the smallest common sensor format.
 	 */
+	Size accumulatedSensorSize;
 	auto validateConfig = [&](StreamConfiguration &cfg, RkISP1Path *path,
 				  Stream *stream, Status expectedStatus) {
 		StreamConfiguration tryCfg = cfg;
 
+		/* Need to validate the path before the transpose */
+		if (transposeAfterIsp)
+			tryCfg.size.transpose();
+
 		Status ret = path->validate(sensor, sensorConfig, &tryCfg);
 		if (ret == Invalid)
 			return false;
@@ -585,7 +677,14 @@ CameraConfiguration::Status RkISP1Camera
 		    (expectedStatus == Valid && ret == Adjusted))
 			return false;
 
+		Size sensorSize = tryCfg.size;
+
 		if (useDewarper) {
+			/*
+			 * The dewarper output is independent of the ISP path.
+			 * Reset to the originally requested size.
+			 */
+			tryCfg.size = cfg.size;
 			bool adjusted;
 
 			pipe->dewarper_->validateOutput(&tryCfg, &adjusted,
@@ -594,8 +693,16 @@ CameraConfiguration::Status RkISP1Camera
 				return false;
 		}
 
+		if (tryCfg.bufferCount < kRkISP1MinBufferCount) {
+			if (expectedStatus == Valid)
+				return false;
+			tryCfg.bufferCount = kRkISP1MinBufferCount;
+		}
+
 		cfg = tryCfg;
 		cfg.setStream(stream);
+
+		accumulatedSensorSize = std::max(accumulatedSensorSize, sensorSize);
 		return true;
 	};
 
@@ -646,29 +753,17 @@ CameraConfiguration::Status RkISP1Camera
 		return Invalid;
 	}
 
-	/* Select the sensor format. */
-	PixelFormat rawFormat;
-	Size maxSize;
-
-	for (const StreamConfiguration &cfg : config_) {
-		const PixelFormatInfo &info = PixelFormatInfo::info(cfg.pixelFormat);
-		if (info.colourEncoding == PixelFormatInfo::ColourEncodingRAW)
-			rawFormat = cfg.pixelFormat;
-
-		maxSize = std::max(maxSize, cfg.size);
-	}
-
 	std::vector<unsigned int> mbusCodes;
 
-	if (rawFormat.isValid()) {
-		mbusCodes = { rawFormats.at(rawFormat) };
+	if (isRaw) {
+		mbusCodes = { rawFormats.at(config_[0].pixelFormat) };
 	} else {
 		std::transform(rawFormats.begin(), rawFormats.end(),
 			       std::back_inserter(mbusCodes),
 			       [](const auto &value) { return value.second; });
 	}
 
-	sensorFormat_ = sensor->getFormat(mbusCodes, maxSize,
+	sensorFormat_ = sensor->getFormat(mbusCodes, accumulatedSensorSize,
 					  mainPath->maxResolution());
 
 	if (sensorFormat_.size.isNull())
@@ -682,7 +777,7 @@ CameraConfiguration::Status RkISP1Camera
  */
 
 PipelineHandlerRkISP1::PipelineHandlerRkISP1(CameraManager *manager)
-	: PipelineHandler(manager), hasSelfPath_(true), useDewarper_(false)
+	: PipelineHandler(manager, kRkISP1MaxQueuedRequests), hasSelfPath_(true)
 {
 }
 
@@ -703,6 +798,22 @@ PipelineHandlerRkISP1::generateConfigura
 	if (roles.empty())
 		return config;
 
+	Transform transform = Transform::Identity;
+	Size previewSize = kRkISP1PreviewSize;
+	bool transposeAfterIsp = false;
+	if (data->canUseDewarper_) {
+		transform = Orientation::Rotate0 / data->sensor_->mountingOrientation();
+		if (!!(transform & Transform::Transpose))
+			transposeAfterIsp = true;
+	}
+
+	/*
+	 * In case of a transpose transform we need to create a path for the
+	 * transposed size.
+	 */
+	if (transposeAfterIsp)
+		previewSize.transpose();
+
 	/*
 	 * As the ISP can't output different color spaces for the main and self
 	 * path, pick a sensible default color space based on the role of the
@@ -731,7 +842,7 @@ PipelineHandlerRkISP1::generateConfigura
 			if (!colorSpace)
 				colorSpace = ColorSpace::Sycc;
 
-			size = kRkISP1PreviewSize;
+			size = previewSize;
 			break;
 
 		case StreamRole::VideoRecording:
@@ -739,7 +850,7 @@ PipelineHandlerRkISP1::generateConfigura
 			if (!colorSpace)
 				colorSpace = ColorSpace::Rec709;
 
-			size = kRkISP1PreviewSize;
+			size = previewSize;
 			break;
 
 		case StreamRole::Raw:
@@ -781,7 +892,11 @@ PipelineHandlerRkISP1::generateConfigura
 		if (!cfg.pixelFormat.isValid())
 			return nullptr;
 
+		if (transposeAfterIsp && role != StreamRole::Raw)
+			cfg.size.transpose();
+
 		cfg.colorSpace = colorSpace;
+		cfg.bufferCount = kRkISP1MinBufferCount;
 		config->addConfiguration(cfg);
 	}
 
@@ -798,10 +913,23 @@ int PipelineHandlerRkISP1::configure(Cam
 	CameraSensor *sensor = data->sensor_.get();
 	int ret;
 
-	ret = initLinks(camera, sensor, *config);
+	ret = initLinks(camera, *config);
 	if (ret)
 		return ret;
 
+	const PixelFormat &streamFormat = config->at(0).pixelFormat;
+	const PixelFormatInfo &info = PixelFormatInfo::info(streamFormat);
+	isRaw_ = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW;
+	data->usesDewarper_ = data->canUseDewarper_ && !isRaw_;
+
+	Transform transform = config->combinedTransform();
+	bool transposeAfterIsp = false;
+	if (data->usesDewarper_) {
+		if (!!(transform & Transform::Transpose))
+			transposeAfterIsp = true;
+		transform = Transform::Identity;
+	}
+
 	/*
 	 * Configure the format on the sensor output and propagate it through
 	 * the pipeline.
@@ -811,22 +939,22 @@ int PipelineHandlerRkISP1::configure(Cam
 
 	if (config->sensorConfig)
 		ret = sensor->applyConfiguration(*config->sensorConfig,
-						 config->combinedTransform(),
+						 transform,
 						 &format);
 	else
-		ret = sensor->setFormat(&format, config->combinedTransform());
+		ret = sensor->setFormat(&format, transform);
 
 	if (ret < 0)
 		return ret;
 
 	LOG(RkISP1, Debug) << "Sensor configured with " << format;
 
-	if (csi_) {
-		ret = csi_->setFormat(0, &format);
-		if (ret < 0)
-			return ret;
-	}
+	/* Propagate format through the internal media pipeline up to the ISP */
+	ret = data->pipe_.configure(sensor, &format);
+	if (ret < 0)
+		return ret;
 
+	LOG(RkISP1, Debug) << "Configuring ISP with : " << format;
 	ret = isp_->setFormat(0, &format);
 	if (ret < 0)
 		return ret;
@@ -841,10 +969,6 @@ int PipelineHandlerRkISP1::configure(Cam
 		<< " crop " << inputCrop;
 
 	Rectangle outputCrop = inputCrop;
-	const PixelFormat &streamFormat = config->at(0).pixelFormat;
-	const PixelFormatInfo &info = PixelFormatInfo::info(streamFormat);
-	isRaw_ = info.colourEncoding == PixelFormatInfo::ColourEncodingRAW;
-	useDewarper_ = dewarper_ && !isRaw_;
 
 	/* YUYV8_2X8 is required on the ISP source path pad for YUV output. */
 	if (!isRaw_)
@@ -853,16 +977,31 @@ int PipelineHandlerRkISP1::configure(Cam
 	/*
 	 * On devices without DUAL_CROP (like the imx8mp) cropping needs to be
 	 * done on the ISP/IS output.
+	 *
+	 * If the dewarper is used, the cropping shall be done by the dewarper.
 	 */
 	if (media_->hwRevision() == RKISP1_V_IMX8MP) {
 		/* imx8mp has only a single path. */
 		const auto &cfg = config->at(0);
-		Size ispCrop = format.size.boundedToAspectRatio(cfg.size);
-		if (useDewarper_)
+		/*
+		 * If the dewarper is used, all cropping including aspect ratio
+		 * preservation shall be done there. To ensure that the output
+		 * format provided by the ISP is supported by the dewarper, a
+		 * minimal crop still needs to be applied on the ISP output.
+		 *
+		 * \todo It might be possible to allocate bigger buffers
+		 * (aligned to 8 pixels) with a stride matching format.size for
+		 * the ISP. The not-filled border could later be ignored by the
+		 * dewarper. This way we could skip the minimal crop here and
+		 * the MaximumScalerCrop would always match the isp output.
+		 */
+		Size ispCrop;
+		if (data->usesDewarper_)
 			ispCrop = dewarper_->adjustInputSize(cfg.pixelFormat,
-							     ispCrop);
+							     format.size);
 		else
-			ispCrop.alignUpTo(2, 2);
+			ispCrop = format.size.boundedToAspectRatio(cfg.size)
+					  .alignedUpTo(2, 2);
 
 		outputCrop = ispCrop.centeredTo(Rectangle(format.size).center());
 		format.size = ispCrop;
@@ -890,30 +1029,55 @@ int PipelineHandlerRkISP1::configure(Cam
 	if (ret)
 		return ret;
 
+	/* Apply the actual sensor crop for proper dewarp map calculation. */
+	Rectangle sensorCrop = outputCrop.transformedBetween(
+		inputCrop, sensorInfo.analogCrop);
+	if (data->usesDewarper_)
+		dewarper_->setSensorCrop(sensorCrop);
+	data->properties_.set(properties::ScalerCropMaximum, sensorCrop);
+
 	std::map<unsigned int, IPAStream> streamConfig;
 	std::vector<std::reference_wrapper<StreamConfiguration>> outputCfgs;
 
 	for (const StreamConfiguration &cfg : *config) {
 		if (cfg.stream() == &data->mainPathStream_) {
-			ret = mainPath_.configure(cfg, format);
-			streamConfig[0] = IPAStream(cfg.pixelFormat,
-						    cfg.size);
-			/* Configure dewarp */
-			if (dewarper_ && !isRaw_) {
+			/*
+			 * To allow for digital zoom, scaling down should happen
+			 * in the dewarper, instead of the resizer. Configure
+			 * the isp output to the same size as the sensor output.
+			 */
+			StreamConfiguration ispCfg = cfg;
+			if (data->usesDewarper_) {
 				outputCfgs.push_back(const_cast<StreamConfiguration &>(cfg));
-				ret = dewarper_->configure(cfg, outputCfgs);
+
+				ispCfg.bufferCount = kRkISP1MinBufferCount;
+				ispCfg.size = format.size;
+				ispCfg.stride =
+					PixelFormatInfo::info(ispCfg.pixelFormat)
+						.stride(ispCfg.size.width, 0);
+
+				ret = dewarper_->configure(ispCfg, outputCfgs);
 				if (ret)
 					return ret;
 
+				dewarper_->setTransform(cfg.stream(), config->combinedTransform());
 				/*
-				 * Calculate the crop rectangle of the data
-				 * flowing into the dewarper in sensor
-				 * coordinates.
+				 * Apply a default scaler crop that keeps the
+				 * aspect ratio.
 				 */
-				scalerMaxCrop_ =
-					outputCrop.transformedBetween(inputCrop,
-								      sensorInfo.analogCrop);
+				Size size = cfg.size;
+				if (transposeAfterIsp)
+					size.transpose();
+				size = sensorCrop.size().boundedToAspectRatio(size);
+
+				ControlList ctrls;
+				ctrls.set(controls::ScalerCrop, size.centeredTo(sensorCrop.center()));
+				dewarper_->setControls(cfg.stream(), ctrls);
 			}
+
+			ret = mainPath_.configure(ispCfg, format);
+			streamConfig[0] = IPAStream(cfg.pixelFormat,
+						    cfg.size);
 		} else if (hasSelfPath_) {
 			ret = selfPath_.configure(cfg, format);
 			streamConfig[1] = IPAStream(cfg.pixelFormat,
@@ -964,7 +1128,7 @@ int PipelineHandlerRkISP1::exportFrameBu
 		 * It has mainpath and no self path. Hence, export buffers from
 		 * dewarper just for the main path stream, for now.
 		 */
-		if (useDewarper_)
+		if (data->usesDewarper_)
 			return dewarper_->exportBuffers(&data->mainPathStream_, count, buffers);
 		else
 			return mainPath_.exportBuffers(count, buffers);
@@ -981,55 +1145,52 @@ int PipelineHandlerRkISP1::allocateBuffe
 	unsigned int ipaBufferId = 1;
 	int ret;
 
-	unsigned int maxCount = std::max({
-		data->mainPathStream_.configuration().bufferCount,
-		data->selfPathStream_.configuration().bufferCount,
-	});
+	auto errorCleanup = utils::scope_exit{ [&]() {
+		paramBuffers_.clear();
+		statBuffers_.clear();
+		mainPathBuffers_.clear();
+	} };
 
 	if (!isRaw_) {
-		ret = param_->allocateBuffers(maxCount, &paramBuffers_);
+		ret = param_->allocateBuffers(kRkISP1MinBufferCount, &paramBuffers_);
 		if (ret < 0)
-			goto error;
+			return ret;
 
-		ret = stat_->allocateBuffers(maxCount, &statBuffers_);
+		ret = stat_->allocateBuffers(kRkISP1MinBufferCount, &statBuffers_);
 		if (ret < 0)
-			goto error;
+			return ret;
 	}
 
 	/* If the dewarper is being used, allocate internal buffers for ISP. */
-	if (useDewarper_) {
-		ret = mainPath_.exportBuffers(maxCount, &mainPathBuffers_);
+	if (data->usesDewarper_) {
+		ret = mainPath_.exportBuffers(kRkISP1MinBufferCount, &mainPathBuffers_);
 		if (ret < 0)
-			goto error;
+			return ret;
 
 		for (std::unique_ptr<FrameBuffer> &buffer : mainPathBuffers_)
 			availableMainPathBuffers_.push(buffer.get());
 	}
 
-	for (std::unique_ptr<FrameBuffer> &buffer : paramBuffers_) {
-		buffer->setCookie(ipaBufferId++);
-		data->ipaBuffers_.emplace_back(buffer->cookie(),
-					       buffer->planes());
-		availableParamBuffers_.push(buffer.get());
-	}
+	auto pushBuffers = [&](const std::vector<std::unique_ptr<FrameBuffer>> &buffers,
+			       std::queue<FrameBuffer *> &queue) {
+		for (const std::unique_ptr<FrameBuffer> &buffer : buffers) {
+			Span<const FrameBuffer::Plane> planes = buffer->planes();
+
+			buffer->setCookie(ipaBufferId++);
+			data->ipaBuffers_.emplace_back(buffer->cookie(),
+						       std::vector<FrameBuffer::Plane>{ planes.begin(),
+											planes.end() });
+			queue.push(buffer.get());
+		}
+	};
 
-	for (std::unique_ptr<FrameBuffer> &buffer : statBuffers_) {
-		buffer->setCookie(ipaBufferId++);
-		data->ipaBuffers_.emplace_back(buffer->cookie(),
-					       buffer->planes());
-		availableStatBuffers_.push(buffer.get());
-	}
+	pushBuffers(paramBuffers_, availableParamBuffers_);
+	pushBuffers(statBuffers_, availableStatBuffers_);
 
 	data->ipa_->mapBuffers(data->ipaBuffers_);
 
+	errorCleanup.release();
 	return 0;
-
-error:
-	paramBuffers_.clear();
-	statBuffers_.clear();
-	mainPathBuffers_.clear();
-
-	return ret;
 }
 
 int PipelineHandlerRkISP1::freeBuffers(Camera *camera)
@@ -1104,7 +1265,10 @@ int PipelineHandlerRkISP1::start(Camera
 		}
 		actions += [&]() { stat_->streamOff(); };
 
-		if (useDewarper_) {
+		if (data->usesDewarper_) {
+			if (controls)
+				dewarper_->setControls(&data->mainPathStream_, *controls);
+
 			ret = dewarper_->start();
 			if (ret) {
 				LOG(RkISP1, Error) << "Failed to start dewarper";
@@ -1115,14 +1279,14 @@ int PipelineHandlerRkISP1::start(Camera
 	}
 
 	if (data->mainPath_->isEnabled()) {
-		ret = mainPath_.start();
+		ret = mainPath_.start(data->mainPathStream_.configuration().bufferCount);
 		if (ret)
 			return ret;
 		actions += [&]() { mainPath_.stop(); };
 	}
 
 	if (hasSelfPath_ && data->selfPath_->isEnabled()) {
-		ret = selfPath_.start();
+		ret = selfPath_.start(data->selfPathStream_.configuration().bufferCount);
 		if (ret)
 			return ret;
 	}
@@ -1159,7 +1323,7 @@ void PipelineHandlerRkISP1::stopDevice(C
 			LOG(RkISP1, Warning)
 				<< "Failed to stop parameters for " << camera->id();
 
-		if (useDewarper_)
+		if (data->usesDewarper_)
 			dewarper_->stop();
 	}
 
@@ -1201,7 +1365,6 @@ int PipelineHandlerRkISP1::queueRequestD
  */
 
 int PipelineHandlerRkISP1::initLinks(Camera *camera,
-				     const CameraSensor *sensor,
 				     const RkISP1CameraConfiguration &config)
 {
 	RkISP1CameraData *data = cameraData(camera);
@@ -1212,31 +1375,16 @@ int PipelineHandlerRkISP1::initLinks(Cam
 		return ret;
 
 	/*
-	 * Configure the sensor links: enable the link corresponding to this
-	 * camera.
+	 * Configure the sensor links: enable the links corresponding to this
+	 * pipeline all the way up to the ISP, through any connected CSI receiver.
 	 */
-	for (MediaLink *link : ispSink_->links()) {
-		if (link->source()->entity() != sensor->entity())
-			continue;
-
-		LOG(RkISP1, Debug)
-			<< "Enabling link from sensor '"
-			<< link->source()->entity()->name()
-			<< "' to ISP";
-
-		ret = link->setEnabled(true);
-		if (ret < 0)
-			return ret;
-	}
-
-	if (csi_) {
-		MediaLink *link = isp_->entity()->getPadByIndex(0)->links().at(0);
-
-		ret = link->setEnabled(true);
-		if (ret < 0)
-			return ret;
+	ret = data->pipe_.initLinks();
+	if (ret) {
+		LOG(RkISP1, Error) << "Failed to set up pipe links";
+		return ret;
 	}
 
+	/* Configure the paths after the ISP */
 	for (const StreamConfiguration &cfg : config) {
 		if (cfg.stream() == &data->mainPathStream_)
 			ret = data->mainPath_->setEnabled(true);
@@ -1271,28 +1419,8 @@ int PipelineHandlerRkISP1::updateControl
 {
 	ControlInfoMap::Map controls;
 
-	if (dewarper_) {
-		std::pair<Rectangle, Rectangle> cropLimits;
-		if (dewarper_->isConfigured(&data->mainPathStream_))
-			cropLimits = dewarper_->inputCropBounds(&data->mainPathStream_);
-		else
-			cropLimits = dewarper_->inputCropBounds();
-
-		/*
-		 * ScalerCrop is specified to be in Sensor coordinates.
-		 * So we need to transform the limits to sensor coordinates.
-		 * We can safely assume that the maximum crop limit contains the
-		 * full fov of the dewarper.
-		 */
-		Rectangle min = cropLimits.first.transformedBetween(cropLimits.second,
-								    scalerMaxCrop_);
-
-		controls[&controls::ScalerCrop] = ControlInfo(min,
-							      scalerMaxCrop_,
-							      scalerMaxCrop_);
-		data->properties_.set(properties::ScalerCropMaximum, scalerMaxCrop_);
-		activeCrop_ = scalerMaxCrop_;
-	}
+	if (data->usesDewarper_)
+		dewarper_->updateControlInfos(&data->mainPathStream_, controls);
 
 	/* Add the IPA registered controls to list of camera controls. */
 	for (const auto &ipaControl : data->ipaControls_)
@@ -1304,6 +1432,12 @@ int PipelineHandlerRkISP1::updateControl
 	return 0;
 }
 
+/*
+ * By default we assume all the blocks that were included in the first
+ * extensible parameters series are available. That is the lower 20bits.
+ */
+const uint32_t kDefaultExtParamsBlocks = 0xfffff;
+
 int PipelineHandlerRkISP1::createCamera(MediaEntity *sensor)
 {
 	int ret;
@@ -1312,6 +1446,13 @@ int PipelineHandlerRkISP1::createCamera(
 		std::make_unique<RkISP1CameraData>(this, &mainPath_,
 						   hasSelfPath_ ? &selfPath_ : nullptr);
 
+	/* Identify the pipeline path between the sensor and the rkisp1_isp */
+	ret = data->pipe_.init(sensor, "rkisp1_isp");
+	if (ret) {
+		LOG(RkISP1, Error) << "Failed to identify path from sensor to sink";
+		return ret;
+	}
+
 	data->sensor_ = CameraSensorFactoryBase::create(sensor);
 	if (!data->sensor_)
 		return -ENODEV;
@@ -1319,13 +1460,11 @@ int PipelineHandlerRkISP1::createCamera(
 	/* Initialize the camera properties. */
 	data->properties_ = data->sensor_->properties();
 
-	scalerMaxCrop_ = Rectangle(data->sensor_->resolution());
-
 	const CameraSensorProperties::SensorDelays &delays = data->sensor_->sensorDelays();
 	std::unordered_map<uint32_t, DelayedControls::ControlParams> params = {
 		{ V4L2_CID_ANALOGUE_GAIN, { delays.gainDelay, false } },
 		{ V4L2_CID_EXPOSURE, { delays.exposureDelay, false } },
-		{ V4L2_CID_VBLANK, { 1, false } },
+		{ V4L2_CID_VBLANK, { delays.vblankDelay, true } },
 	};
 
 	data->delayedCtrls_ =
@@ -1334,7 +1473,21 @@ int PipelineHandlerRkISP1::createCamera(
 	isp_->frameStart.connect(data->delayedCtrls_.get(),
 				 &DelayedControls::applyControls);
 
-	ret = data->loadIPA(media_->hwRevision());
+	uint32_t supportedBlocks = kDefaultExtParamsBlocks;
+
+	auto &controls = param_->controls();
+	if (controls.find(RKISP1_CID_SUPPORTED_PARAMS_BLOCKS) != controls.end()) {
+		auto list = param_->getControls({ { RKISP1_CID_SUPPORTED_PARAMS_BLOCKS } });
+		if (!list.empty())
+			supportedBlocks = static_cast<uint32_t>(
+				list.get(RKISP1_CID_SUPPORTED_PARAMS_BLOCKS)
+					.get<int32_t>());
+	} else {
+		LOG(RkISP1, Error)
+			<< "Failed to query supported params blocks. Falling back to defaults.";
+	}
+
+	ret = data->loadIPA(media_->hwRevision(), supportedBlocks);
 	if (ret)
 		return ret;
 
@@ -1347,6 +1500,7 @@ int PipelineHandlerRkISP1::createCamera(
 	const std::string &id = data->sensor_->id();
 	std::shared_ptr<Camera> camera =
 		Camera::create(std::move(data), id, streams);
+
 	registerCamera(std::move(camera));
 
 	return 0;
@@ -1354,8 +1508,6 @@ int PipelineHandlerRkISP1::createCamera(
 
 bool PipelineHandlerRkISP1::match(DeviceEnumerator *enumerator)
 {
-	const MediaPad *pad;
-
 	DeviceMatch dm("rkisp1");
 	dm.add("rkisp1_isp");
 	dm.add("rkisp1_resizer_mainpath");
@@ -1376,32 +1528,16 @@ bool PipelineHandlerRkISP1::match(Device
 	hasSelfPath_ = !!media_->getEntityByName("rkisp1_selfpath");
 
 	/* Create the V4L2 subdevices we will need. */
-	isp_ = V4L2Subdevice::fromEntityName(media_, "rkisp1_isp");
+	isp_ = V4L2Subdevice::fromEntityName(media_.get(), "rkisp1_isp");
 	if (isp_->open() < 0)
 		return false;
 
-	/* Locate and open the optional CSI-2 receiver. */
-	ispSink_ = isp_->entity()->getPadByIndex(0);
-	if (!ispSink_ || ispSink_->links().empty())
-		return false;
-
-	pad = ispSink_->links().at(0)->source();
-	if (pad->entity()->function() == MEDIA_ENT_F_VID_IF_BRIDGE) {
-		csi_ = std::make_unique<V4L2Subdevice>(pad->entity());
-		if (csi_->open() < 0)
-			return false;
-
-		ispSink_ = csi_->entity()->getPadByIndex(0);
-		if (!ispSink_)
-			return false;
-	}
-
 	/* Locate and open the stats and params video nodes. */
-	stat_ = V4L2VideoDevice::fromEntityName(media_, "rkisp1_stats");
+	stat_ = V4L2VideoDevice::fromEntityName(media_.get(), "rkisp1_stats");
 	if (stat_->open() < 0)
 		return false;
 
-	param_ = V4L2VideoDevice::fromEntityName(media_, "rkisp1_params");
+	param_ = V4L2VideoDevice::fromEntityName(media_.get(), "rkisp1_params");
 	if (param_->open() < 0)
 		return false;
 
@@ -1418,27 +1554,11 @@ bool PipelineHandlerRkISP1::match(Device
 	stat_->bufferReady.connect(this, &PipelineHandlerRkISP1::statBufferReady);
 	param_->bufferReady.connect(this, &PipelineHandlerRkISP1::paramBufferReady);
 
-	/* If dewarper is present, create its instance. */
-	DeviceMatch dwp("dw100");
-	dwp.add("dw100-source");
-	dwp.add("dw100-sink");
-
-	std::shared_ptr<MediaDevice> dwpMediaDevice = enumerator->search(dwp);
-	if (dwpMediaDevice) {
-		dewarper_ = std::make_unique<V4L2M2MConverter>(dwpMediaDevice.get());
-		if (dewarper_->isValid()) {
-			dewarper_->outputBufferReady.connect(
-				this, &PipelineHandlerRkISP1::dewarpBufferReady);
-
-			LOG(RkISP1, Info)
-				<< "Using DW100 dewarper " << dewarper_->deviceNode();
-		} else {
-			LOG(RkISP1, Warning)
-				<< "Found DW100 dewarper " << dewarper_->deviceNode()
-				<< " but invalid";
-
-			dewarper_.reset();
-		}
+	dewarper_ = ConverterDW100Module::createModule(enumerator);
+	if (dewarper_) {
+		dewarper_->outputBufferReady.connect(
+			this, &PipelineHandlerRkISP1::dewarpBufferReady);
+		LOG(RkISP1, Debug) << "Found DW100 dewarper";
 	}
 
 	/*
@@ -1446,8 +1566,10 @@ bool PipelineHandlerRkISP1::match(Device
 	 * camera instance for each of them.
 	 */
 	bool registered = false;
-	for (MediaLink *link : ispSink_->links()) {
-		if (!createCamera(link->source()->entity()))
+
+	for (MediaEntity *entity : media_->locateEntities(MEDIA_ENT_F_CAM_SENSOR)) {
+		LOG(RkISP1, Debug) << "Identified " << entity->name();
+		if (!createCamera(entity))
 			registered = true;
 	}
 
@@ -1477,6 +1599,31 @@ void PipelineHandlerRkISP1::tryCompleteR
 	completeRequest(request);
 }
 
+void PipelineHandlerRkISP1::cancelDewarpRequest(RkISP1FrameInfo *info)
+{
+	RkISP1CameraData *data = cameraData(activeCamera_);
+	Request *request = info->request;
+	/*
+	 * i.MX8MP is the only known platform with dewarper. It has
+	 * no self path. Hence, only main path buffer completion is
+	 * required.
+	 *
+	 * Also, we cannot completeBuffer(request, buffer) as buffer
+	 * here, is an internal buffer (between ISP and dewarper) and
+	 * is not associated to the any specific request. The request
+	 * buffer associated with main path stream is the one that
+	 * is required to be completed (not the internal buffer).
+	 */
+	for (auto [stream, buffer] : request->buffers()) {
+		if (stream == &data->mainPathStream_) {
+			buffer->_d()->cancel();
+			completeBuffer(request, buffer);
+		}
+	}
+
+	tryCompleteRequest(info);
+}
+
 void PipelineHandlerRkISP1::imageBufferReady(FrameBuffer *buffer)
 {
 	ASSERT(activeCamera_);
@@ -1509,7 +1656,7 @@ void PipelineHandlerRkISP1::imageBufferR
 			info->metadataProcessed = true;
 	}
 
-	if (!useDewarper_) {
+	if (!data->usesDewarper_) {
 		completeBuffer(request, buffer);
 		tryCompleteRequest(info);
 
@@ -1518,57 +1665,11 @@ void PipelineHandlerRkISP1::imageBufferR
 
 	/* Do not queue cancelled frames to dewarper. */
 	if (metadata.status == FrameMetadata::FrameCancelled) {
-		/*
-		 * i.MX8MP is the only known platform with dewarper. It has
-		 * no self path. Hence, only main path buffer completion is
-		 * required.
-		 *
-		 * Also, we cannot completeBuffer(request, buffer) as buffer
-		 * here, is an internal buffer (between ISP and dewarper) and
-		 * is not associated to the any specific request. The request
-		 * buffer associated with main path stream is the one that
-		 * is required to be completed (not the internal buffer).
-		 */
-		for (auto it : request->buffers()) {
-			if (it.first == &data->mainPathStream_)
-				completeBuffer(request, it.second);
-		}
-
-		tryCompleteRequest(info);
+		cancelDewarpRequest(info);
 		return;
 	}
 
-	/* Handle scaler crop control. */
-	const auto &crop = request->controls().get(controls::ScalerCrop);
-	if (crop) {
-		Rectangle rect = crop.value();
-
-		/*
-		 * ScalerCrop is specified to be in Sensor coordinates.
-		 * So we need to transform it into dewarper coordinates.
-		 * We can safely assume that the maximum crop limit contains the
-		 * full fov of the dewarper.
-		 */
-		std::pair<Rectangle, Rectangle> cropLimits =
-			dewarper_->inputCropBounds(&data->mainPathStream_);
-
-		rect = rect.transformedBetween(scalerMaxCrop_, cropLimits.second);
-		int ret = dewarper_->setInputCrop(&data->mainPathStream_,
-						  &rect);
-		rect = rect.transformedBetween(cropLimits.second, scalerMaxCrop_);
-		if (!ret && rect != crop.value()) {
-			/*
-			 * If the rectangle is changed by setInputCrop on the
-			 * dewarper, log a debug message and cache the actual
-			 * applied rectangle for metadata reporting.
-			 */
-			LOG(RkISP1, Debug)
-				<< "Applied rectangle " << rect.toString()
-				<< " differs from requested " << crop.value().toString();
-		}
-
-		activeCrop_ = rect;
-	}
+	dewarper_->setControls(&data->mainPathStream_, request->controls());
 
 	/*
 	 * Queue input and output buffers to the dewarper. The output
@@ -1576,11 +1677,16 @@ void PipelineHandlerRkISP1::imageBufferR
 	 * by the application.
 	 */
 	int ret = dewarper_->queueBuffers(buffer, request->buffers());
-	if (ret < 0)
-		LOG(RkISP1, Error) << "Cannot queue buffers to dewarper: "
+	if (ret < 0) {
+		LOG(RkISP1, Error) << "Failed to queue buffers to dewarper: -"
 				   << strerror(-ret);
 
-	request->metadata().set(controls::ScalerCrop, activeCrop_.value());
+		cancelDewarpRequest(info);
+
+		return;
+	}
+
+	dewarper_->populateMetadata(&data->mainPathStream_, request->metadata());
 }
 
 void PipelineHandlerRkISP1::dewarpBufferReady(FrameBuffer *buffer)
diff -pruN 0.5.0-1/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp 0.6.0-2/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp
--- 0.5.0-1/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rkisp1/rkisp1_path.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,8 @@
 
 #include "rkisp1_path.h"
 
+#include <array>
+
 #include <linux/media-bus-format.h>
 
 #include <libcamera/formats.h>
@@ -54,21 +56,24 @@ const std::map<PixelFormat, uint32_t> fo
 
 } /* namespace */
 
-RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats)
-	: name_(name), running_(false), formats_(formats), link_(nullptr)
+RkISP1Path::RkISP1Path(const char *name, const Span<const PixelFormat> &formats,
+		       const Size &minResolution, const Size &maxResolution)
+	: name_(name), running_(false), formats_(formats),
+	  minResolution_(minResolution), maxResolution_(maxResolution),
+	  link_(nullptr)
 {
 }
 
-bool RkISP1Path::init(MediaDevice *media)
+bool RkISP1Path::init(std::shared_ptr<MediaDevice> media)
 {
 	std::string resizer = std::string("rkisp1_resizer_") + name_ + "path";
 	std::string video = std::string("rkisp1_") + name_ + "path";
 
-	resizer_ = V4L2Subdevice::fromEntityName(media, resizer);
+	resizer_ = V4L2Subdevice::fromEntityName(media.get(), resizer);
 	if (resizer_->open() < 0)
 		return false;
 
-	video_ = V4L2VideoDevice::fromEntityName(media, video);
+	video_ = V4L2VideoDevice::fromEntityName(media.get(), video);
 	if (video_->open() < 0)
 		return false;
 
@@ -246,7 +251,6 @@ RkISP1Path::generateConfiguration(const
 	StreamConfiguration cfg(formats);
 	cfg.pixelFormat = format;
 	cfg.size = streamSize;
-	cfg.bufferCount = RKISP1_BUFFER_COUNT;
 
 	return cfg;
 }
@@ -339,7 +343,7 @@ RkISP1Path::validate(const CameraSensor
 					    : cfg->size;
 
 		V4L2SubdeviceFormat sensorFormat =
-			sensor->getFormat({ mbusCode }, rawSize);
+			sensor->getFormat(std::array{ mbusCode }, rawSize);
 
 		if (sensorConfig &&
 		    sensorConfig->outputSize != sensorFormat.size)
@@ -360,7 +364,7 @@ RkISP1Path::validate(const CameraSensor
 
 		uint32_t mbusCode = formatToMediaBus.at(rawFormat);
 		V4L2SubdeviceFormat sensorFormat =
-			sensor->getFormat({ mbusCode }, sensorSize);
+			sensor->getFormat(std::array{ mbusCode }, sensorSize);
 
 		if (sensorFormat.size != sensorSize)
 			return CameraConfiguration::Invalid;
@@ -380,7 +384,6 @@ RkISP1Path::validate(const CameraSensor
 
 	cfg->size.boundTo(maxResolution);
 	cfg->size.expandTo(minResolution);
-	cfg->bufferCount = RKISP1_BUFFER_COUNT;
 
 	V4L2DeviceFormat format;
 	format.fourcc = video_->toV4L2PixelFormat(cfg->pixelFormat);
@@ -477,15 +480,14 @@ int RkISP1Path::configure(const StreamCo
 	return 0;
 }
 
-int RkISP1Path::start()
+int RkISP1Path::start(unsigned int bufferCount)
 {
 	int ret;
 
 	if (running_)
 		return -EBUSY;
 
-	/* \todo Make buffer count user configurable. */
-	ret = video_->importBuffers(RKISP1_BUFFER_COUNT);
+	ret = video_->importBuffers(bufferCount);
 	if (ret)
 		return ret;
 
@@ -517,10 +519,12 @@ void RkISP1Path::stop()
 }
 
 /*
- * \todo Remove the hardcoded formats once all users will have migrated to a
- * recent enough kernel.
+ * \todo Remove the hardcoded resolutions and formats once kernels older than
+ * v6.4 will stop receiving LTS support (scheduled for December 2027 for v6.1).
  */
 namespace {
+constexpr Size RKISP1_RSZ_MP_SRC_MIN{ 32, 16 };
+constexpr Size RKISP1_RSZ_MP_SRC_MAX{ 4416, 3312 };
 constexpr std::array<PixelFormat, 18> RKISP1_RSZ_MP_FORMATS{
 	formats::YUYV,
 	formats::NV16,
@@ -542,6 +546,8 @@ constexpr std::array<PixelFormat, 18> RK
 	formats::SRGGB12,
 };
 
+constexpr Size RKISP1_RSZ_SP_SRC_MIN{ 32, 16 };
+constexpr Size RKISP1_RSZ_SP_SRC_MAX{ 1920, 1920 };
 constexpr std::array<PixelFormat, 8> RKISP1_RSZ_SP_FORMATS{
 	formats::YUYV,
 	formats::NV16,
@@ -555,12 +561,14 @@ constexpr std::array<PixelFormat, 8> RKI
 } /* namespace */
 
 RkISP1MainPath::RkISP1MainPath()
-	: RkISP1Path("main", RKISP1_RSZ_MP_FORMATS)
+	: RkISP1Path("main", RKISP1_RSZ_MP_FORMATS,
+		     RKISP1_RSZ_MP_SRC_MIN, RKISP1_RSZ_MP_SRC_MAX)
 {
 }
 
 RkISP1SelfPath::RkISP1SelfPath()
-	: RkISP1Path("self", RKISP1_RSZ_SP_FORMATS)
+	: RkISP1Path("self", RKISP1_RSZ_SP_FORMATS,
+		     RKISP1_RSZ_SP_SRC_MIN, RKISP1_RSZ_SP_SRC_MAX)
 {
 }
 
diff -pruN 0.5.0-1/src/libcamera/pipeline/rkisp1/rkisp1_path.h 0.6.0-2/src/libcamera/pipeline/rkisp1/rkisp1_path.h
--- 0.5.0-1/src/libcamera/pipeline/rkisp1/rkisp1_path.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rkisp1/rkisp1_path.h	2025-11-27 11:55:28.000000000 +0000
@@ -34,9 +34,10 @@ struct V4L2SubdeviceFormat;
 class RkISP1Path
 {
 public:
-	RkISP1Path(const char *name, const Span<const PixelFormat> &formats);
+	RkISP1Path(const char *name, const Span<const PixelFormat> &formats,
+		   const Size &minResolution, const Size &maxResolution);
 
-	bool init(MediaDevice *media);
+	bool init(std::shared_ptr<MediaDevice> media);
 
 	int setEnabled(bool enable) { return link_->setEnabled(enable); }
 	bool isEnabled() const { return link_->flags() & MEDIA_LNK_FL_ENABLED; }
@@ -57,7 +58,7 @@ public:
 		return video_->exportBuffers(bufferCount, buffers);
 	}
 
-	int start();
+	int start(unsigned int bufferCount);
 	void stop();
 
 	int queueBuffer(FrameBuffer *buffer) { return video_->queueBuffer(buffer); }
@@ -68,8 +69,6 @@ private:
 	void populateFormats();
 	Size filterSensorResolution(const CameraSensor *sensor);
 
-	static constexpr unsigned int RKISP1_BUFFER_COUNT = 4;
-
 	const char *name_;
 	bool running_;
 
diff -pruN 0.5.0-1/src/libcamera/pipeline/rpi/common/pipeline_base.cpp 0.6.0-2/src/libcamera/pipeline/rpi/common/pipeline_base.cpp
--- 0.5.0-1/src/libcamera/pipeline/rpi/common/pipeline_base.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rpi/common/pipeline_base.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -659,9 +659,9 @@ int PipelineHandlerBase::start(Camera *c
 	if (!result.controls.empty())
 		data->setSensorControls(result.controls);
 
-	/* Configure the number of dropped frames required on startup. */
-	data->dropFrameCount_ = data->config_.disableStartupFrameDrops
-			      ? 0 : result.dropFrameCount;
+	/* Configure the number of startup and invalid frames reported by the IPA. */
+	data->startupFrameCount_ = result.startupFrameCount;
+	data->invalidFrameCount_ = result.invalidFrameCount;
 
 	for (auto const stream : data->streams_)
 		stream->resetBuffers();
@@ -678,7 +678,6 @@ int PipelineHandlerBase::start(Camera *c
 		data->buffersAllocated_ = true;
 	}
 
-	/* We need to set the dropFrameCount_ before queueing buffers. */
 	ret = queueAllBuffers(camera);
 	if (ret) {
 		LOG(RPI, Error) << "Failed to queue buffers";
@@ -686,6 +685,9 @@ int PipelineHandlerBase::start(Camera *c
 		return ret;
 	}
 
+	/* A good moment to add an initial clock sample. */
+	data->wallClockRecovery_.addSample();
+
 	/*
 	 * Reset the delayed controls with the gain and exposure values set by
 	 * the IPA.
@@ -784,8 +786,10 @@ int PipelineHandlerBase::queueRequestDev
 }
 
 int PipelineHandlerBase::registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
-					MediaDevice *frontend, const std::string &frontendName,
-					MediaDevice *backend, MediaEntity *sensorEntity)
+					std::shared_ptr<MediaDevice> frontend,
+					const std::string &frontendName,
+					std::shared_ptr<MediaDevice> backend,
+					MediaEntity *sensorEntity)
 {
 	CameraData *data = cameraData.get();
 	int ret;
@@ -804,7 +808,8 @@ int PipelineHandlerBase::registerCamera(
 	 * chain. There may be a cascade of devices in this chain!
 	 */
 	MediaLink *link = sensorEntity->getPadByIndex(0)->links()[0];
-	data->enumerateVideoDevices(link, frontendName);
+	if (!data->enumerateVideoDevices(link, frontendName))
+		return -EINVAL;
 
 	ipa::RPi::InitResult result;
 	if (data->loadIPA(&result)) {
@@ -879,10 +884,12 @@ void PipelineHandlerBase::mapBuffers(Cam
 	 * This will allow us to identify buffers passed between the pipeline
 	 * handler and the IPA.
 	 */
-	for (auto const &it : buffers) {
-		bufferIds.push_back(IPABuffer(mask | it.first,
-					      it.second.buffer->planes()));
-		data->bufferIds_.insert(mask | it.first);
+	for (auto const &[id, buffer] : buffers) {
+		Span<const FrameBuffer::Plane> planes = buffer.buffer->planes();
+
+		bufferIds.emplace_back(mask | id,
+				       std::vector<FrameBuffer::Plane>{ planes.begin(), planes.end() });
+		data->bufferIds_.insert(mask | id);
 	}
 
 	data->ipa_->mapBuffers(bufferIds);
@@ -894,28 +901,12 @@ int PipelineHandlerBase::queueAllBuffers
 	int ret;
 
 	for (auto const stream : data->streams_) {
-		if (!(stream->getFlags() & StreamFlag::External)) {
-			ret = stream->queueAllBuffers();
-			if (ret < 0)
-				return ret;
-		} else {
-			/*
-			 * For external streams, we must queue up a set of internal
-			 * buffers to handle the number of drop frames requested by
-			 * the IPA. This is done by passing nullptr in queueBuffer().
-			 *
-			 * The below queueBuffer() call will do nothing if there
-			 * are not enough internal buffers allocated, but this will
-			 * be handled by queuing the request for buffers in the
-			 * RPiStream object.
-			 */
-			unsigned int i;
-			for (i = 0; i < data->dropFrameCount_; i++) {
-				ret = stream->queueBuffer(nullptr);
-				if (ret)
-					return ret;
-			}
-		}
+		if (stream->getFlags() & StreamFlag::External)
+			continue;
+
+		ret = stream->queueAllBuffers();
+		if (ret < 0)
+			return ret;
 	}
 
 	return 0;
@@ -1032,16 +1023,20 @@ void CameraData::freeBuffers()
  *          | Sensor2 |   | Sensor3 |
  *          +---------+   +---------+
  */
-void CameraData::enumerateVideoDevices(MediaLink *link, const std::string &frontend)
+bool CameraData::enumerateVideoDevices(MediaLink *link, const std::string &frontend)
 {
 	const MediaPad *sinkPad = link->sink();
 	const MediaEntity *entity = sinkPad->entity();
 	bool frontendFound = false;
 
+	/* Once we reach the Frontend entity, we are done. */
+	if (link->sink()->entity()->name() == frontend)
+		return true;
+
 	/* We only deal with Video Mux and Bridge devices in cascade. */
 	if (entity->function() != MEDIA_ENT_F_VID_MUX &&
 	    entity->function() != MEDIA_ENT_F_VID_IF_BRIDGE)
-		return;
+		return false;
 
 	/* Find the source pad for this Video Mux or Bridge device. */
 	const MediaPad *sourcePad = nullptr;
@@ -1053,7 +1048,7 @@ void CameraData::enumerateVideoDevices(M
 			 * and this branch in the cascade.
 			 */
 			if (sourcePad)
-				return;
+				return false;
 
 			sourcePad = pad;
 		}
@@ -1070,12 +1065,9 @@ void CameraData::enumerateVideoDevices(M
 	 * other Video Mux and Bridge devices.
 	 */
 	for (MediaLink *l : sourcePad->links()) {
-		enumerateVideoDevices(l, frontend);
-		/* Once we reach the Frontend entity, we are done. */
-		if (l->sink()->entity()->name() == frontend) {
-			frontendFound = true;
+		frontendFound = enumerateVideoDevices(l, frontend);
+		if (frontendFound)
 			break;
-		}
 	}
 
 	/* This identifies the end of our entity enumeration recursion. */
@@ -1090,12 +1082,13 @@ void CameraData::enumerateVideoDevices(M
 			bridgeDevices_.clear();
 		}
 	}
+
+	return frontendFound;
 }
 
 int CameraData::loadPipelineConfiguration()
 {
 	config_ = {
-		.disableStartupFrameDrops = false,
 		.cameraTimeoutValue = 0,
 	};
 
@@ -1132,8 +1125,10 @@ int CameraData::loadPipelineConfiguratio
 
 	const YamlObject &phConfig = (*root)["pipeline_handler"];
 
-	config_.disableStartupFrameDrops =
-		phConfig["disable_startup_frame_drops"].get<bool>(config_.disableStartupFrameDrops);
+	if (phConfig.contains("disable_startup_frame_drops"))
+		LOG(RPI, Warning)
+			<< "The disable_startup_frame_drops key is now deprecated, "
+			<< "startup frames are now identified by the FrameMetadata::Status::FrameStartup flag";
 
 	config_.cameraTimeoutValue =
 		phConfig["camera_timeout_value_ms"].get<unsigned int>(config_.cameraTimeoutValue);
@@ -1412,7 +1407,15 @@ void CameraData::handleStreamBuffer(Fram
 	 * buffer back to the stream.
 	 */
 	Request *request = requestQueue_.empty() ? nullptr : requestQueue_.front();
-	if (!dropFrameCount_ && request && request->findBuffer(stream) == buffer) {
+	if (request && request->findBuffer(stream) == buffer) {
+		FrameMetadata &md = buffer->_d()->metadata();
+
+		/* Mark the non-converged and invalid frames in the metadata. */
+		if (invalidFrameCount_)
+			md.status = FrameMetadata::Status::FrameError;
+		else if (startupFrameCount_)
+			md.status = FrameMetadata::Status::FrameStartup;
+
 		/*
 		 * Tag the buffer as completed, returning it to the
 		 * application.
@@ -1458,49 +1461,40 @@ void CameraData::handleState()
 
 void CameraData::checkRequestCompleted()
 {
-	bool requestCompleted = false;
-	/*
-	 * If we are dropping this frame, do not touch the request, simply
-	 * change the state to IDLE when ready.
-	 */
-	if (!dropFrameCount_) {
-		Request *request = requestQueue_.front();
-		if (request->hasPendingBuffers())
-			return;
+	Request *request = requestQueue_.front();
+	if (request->hasPendingBuffers())
+		return;
 
-		/* Must wait for metadata to be filled in before completing. */
-		if (state_ != State::IpaComplete)
-			return;
+	/* Must wait for metadata to be filled in before completing. */
+	if (state_ != State::IpaComplete)
+		return;
 
-		LOG(RPI, Debug) << "Completing request sequence: "
-				<< request->sequence();
+	LOG(RPI, Debug) << "Completing request sequence: "
+			<< request->sequence();
 
-		pipe()->completeRequest(request);
-		requestQueue_.pop();
-		requestCompleted = true;
-	}
+	pipe()->completeRequest(request);
+	requestQueue_.pop();
 
-	/*
-	 * Make sure we have three outputs completed in the case of a dropped
-	 * frame.
-	 */
-	if (state_ == State::IpaComplete &&
-	    ((ispOutputCount_ == ispOutputTotal_ && dropFrameCount_) ||
-	     requestCompleted)) {
-		LOG(RPI, Debug) << "Going into Idle state";
-		state_ = State::Idle;
-		if (dropFrameCount_) {
-			dropFrameCount_--;
-			LOG(RPI, Debug) << "Dropping frame at the request of the IPA ("
-					<< dropFrameCount_ << " left)";
-		}
+	LOG(RPI, Debug) << "Going into Idle state";
+	state_ = State::Idle;
+
+	if (invalidFrameCount_) {
+		invalidFrameCount_--;
+		LOG(RPI, Debug) << "Decrementing invalid frames to "
+				<< invalidFrameCount_;
+	} else if (startupFrameCount_) {
+		startupFrameCount_--;
+		LOG(RPI, Debug) << "Decrementing startup frames to "
+				<< startupFrameCount_;
 	}
 }
 
 void CameraData::fillRequestMetadata(const ControlList &bufferControls, Request *request)
 {
-	request->metadata().set(controls::SensorTimestamp,
-				bufferControls.get(controls::SensorTimestamp).value_or(0));
+	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);
 
 	if (cropParams_.size()) {
 		std::vector<Rectangle> crops;
diff -pruN 0.5.0-1/src/libcamera/pipeline/rpi/common/pipeline_base.h 0.6.0-2/src/libcamera/pipeline/rpi/common/pipeline_base.h
--- 0.5.0-1/src/libcamera/pipeline/rpi/common/pipeline_base.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rpi/common/pipeline_base.h	2025-11-27 11:55:28.000000000 +0000
@@ -20,6 +20,7 @@
 #include "libcamera/internal/bayer_format.h"
 #include "libcamera/internal/camera.h"
 #include "libcamera/internal/camera_sensor.h"
+#include "libcamera/internal/clock_recovery.h"
 #include "libcamera/internal/framebuffer.h"
 #include "libcamera/internal/media_device.h"
 #include "libcamera/internal/media_object.h"
@@ -48,8 +49,7 @@ class CameraData : public Camera::Privat
 public:
 	CameraData(PipelineHandler *pipe)
 		: Camera::Private(pipe), state_(State::Stopped),
-		  dropFrameCount_(0), buffersAllocated_(false),
-		  ispOutputCount_(0), ispOutputTotal_(0)
+		  startupFrameCount_(0), invalidFrameCount_(0), buffersAllocated_(false)
 	{
 	}
 
@@ -68,7 +68,7 @@ public:
 	void freeBuffers();
 	virtual void platformFreeBuffers() = 0;
 
-	void enumerateVideoDevices(MediaLink *link, const std::string &frontend);
+	bool enumerateVideoDevices(MediaLink *link, const std::string &frontend);
 
 	int loadPipelineConfiguration();
 	int loadIPA(ipa::RPi::InitResult *result);
@@ -151,7 +151,8 @@ public:
 	/* Mapping of CropParams keyed by the output stream order in CameraConfiguration */
 	std::map<unsigned int, CropParams> cropParams_;
 
-	unsigned int dropFrameCount_;
+	unsigned int startupFrameCount_;
+	unsigned int invalidFrameCount_;
 
 	/*
 	 * If set, this stores the value that represets a gain of one for
@@ -164,11 +165,6 @@ public:
 
 	struct Config {
 		/*
-		 * Override any request from the IPA to drop a number of startup
-		 * frames.
-		 */
-		bool disableStartupFrameDrops;
-		/*
 		 * Override the camera timeout value calculated by the IPA based
 		 * on frame durations.
 		 */
@@ -177,15 +173,14 @@ public:
 
 	Config config_;
 
+	ClockRecovery wallClockRecovery_;
+
 protected:
 	void fillRequestMetadata(const ControlList &bufferControls,
 				 Request *request);
 
 	virtual void tryRunPipeline() = 0;
 
-	unsigned int ispOutputCount_;
-	unsigned int ispOutputTotal_;
-
 private:
 	void checkRequestCompleted();
 };
@@ -229,13 +224,16 @@ public:
 
 protected:
 	int registerCamera(std::unique_ptr<RPi::CameraData> &cameraData,
-			   MediaDevice *frontent, const std::string &frontendName,
-			   MediaDevice *backend, MediaEntity *sensorEntity);
+			   std::shared_ptr<MediaDevice> frontend,
+			   const std::string &frontendName,
+			   std::shared_ptr<MediaDevice> backend,
+			   MediaEntity *sensorEntity);
 
 	void mapBuffers(Camera *camera, const BufferMap &buffers, unsigned int mask);
 
 	virtual int platformRegister(std::unique_ptr<CameraData> &cameraData,
-				     MediaDevice *unicam, MediaDevice *isp) = 0;
+				     std::shared_ptr<MediaDevice> unicam,
+				     std::shared_ptr<MediaDevice> isp) = 0;
 
 private:
 	CameraData *cameraData(Camera *camera)
diff -pruN 0.5.0-1/src/libcamera/pipeline/rpi/pisp/data/example.yaml 0.6.0-2/src/libcamera/pipeline/rpi/pisp/data/example.yaml
--- 0.5.0-1/src/libcamera/pipeline/rpi/pisp/data/example.yaml	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rpi/pisp/data/example.yaml	2025-11-27 11:55:28.000000000 +0000
@@ -16,11 +16,6 @@
                 #
                 # "num_cfe_config_queue": 2,
 
-                # Override any request from the IPA to drop a number of startup
-                # frames.
-                #
-                # "disable_startup_frame_drops": false,
-
                 # Custom timeout value (in ms) for camera to use. This overrides
                 # the value computed by the pipeline handler based on frame
                 # durations.
diff -pruN 0.5.0-1/src/libcamera/pipeline/rpi/pisp/pisp.cpp 0.6.0-2/src/libcamera/pipeline/rpi/pisp/pisp.cpp
--- 0.5.0-1/src/libcamera/pipeline/rpi/pisp/pisp.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rpi/pisp/pisp.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2023, Raspberry Pi Ltd
  *
- * pisp.cpp - Pipeline handler for PiSP based Raspberry Pi devices
+ * Pipeline handler for PiSP based Raspberry Pi devices
  */
 
 #include <algorithm>
@@ -866,7 +866,8 @@ private:
 
 	int prepareBuffers(Camera *camera) override;
 	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
-			     MediaDevice *cfe, MediaDevice *isp) override;
+			     std::shared_ptr<MediaDevice> cfe,
+			     std::shared_ptr<MediaDevice> isp) override;
 };
 
 bool PipelineHandlerPiSP::match(DeviceEnumerator *enumerator)
@@ -884,7 +885,7 @@ bool PipelineHandlerPiSP::match(DeviceEn
 		cfe.add("rp1-cfe-fe-image0");
 		cfe.add("rp1-cfe-fe-stats");
 		cfe.add("rp1-cfe-fe-config");
-		MediaDevice *cfeDevice = acquireMediaDevice(enumerator, cfe);
+		std::shared_ptr<MediaDevice> cfeDevice = acquireMediaDevice(enumerator, cfe);
 
 		if (!cfeDevice) {
 			LOG(RPI, Debug) << "Unable to acquire a CFE instance";
@@ -900,7 +901,7 @@ bool PipelineHandlerPiSP::match(DeviceEn
 		isp.add("pispbe-tdn_input");
 		isp.add("pispbe-stitch_output");
 		isp.add("pispbe-stitch_input");
-		MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
+		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
 
 		if (!ispDevice) {
 			LOG(RPI, Debug) << "Unable to acquire ISP instance";
@@ -1065,7 +1066,8 @@ int PipelineHandlerPiSP::prepareBuffers(
 }
 
 int PipelineHandlerPiSP::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
-					  MediaDevice *cfe, MediaDevice *isp)
+					  std::shared_ptr<MediaDevice> cfe,
+					  std::shared_ptr<MediaDevice> isp)
 {
 	PiSPCameraData *data = static_cast<PiSPCameraData *>(cameraData.get());
 	int ret;
@@ -1755,9 +1757,15 @@ void PiSPCameraData::cfeBufferDequeue(Fr
 		auto [ctrl, delayContext] = delayedCtrls_->get(buffer->metadata().sequence);
 		/*
 		 * Add the frame timestamp to the ControlList for the IPA to use
-		 * as it does not receive the FrameBuffer object.
+		 * as it does not receive the FrameBuffer object. Also derive a
+		 * corresponding wallclock value.
 		 */
-		ctrl.set(controls::SensorTimestamp, buffer->metadata().timestamp);
+		wallClockRecovery_.addSample();
+		uint64_t sensorTimestamp = buffer->metadata().timestamp;
+		uint64_t wallClockTimestamp = wallClockRecovery_.getOutput(sensorTimestamp);
+
+		ctrl.set(controls::SensorTimestamp, sensorTimestamp);
+		ctrl.set(controls::FrameWallClock, wallClockTimestamp);
 		job.sensorControls = std::move(ctrl);
 		job.delayContext = delayContext;
 	} else if (stream == &cfe_[Cfe::Config]) {
@@ -1834,12 +1842,6 @@ void PiSPCameraData::beOutputDequeue(Fra
 		dmabufSyncEnd(buffer->planes()[0].fd);
 
 	handleStreamBuffer(buffer, stream);
-
-	/*
-	 * Increment the number of ISP outputs generated.
-	 * This is needed to track dropped frames.
-	 */
-	ispOutputCount_++;
 	handleState();
 }
 
@@ -1885,7 +1887,6 @@ void PiSPCameraData::prepareIspComplete(
 		 * If there is no need to run the Backend, just signal that the
 		 * input buffer is completed and all Backend outputs are ready.
 		 */
-		ispOutputCount_ = ispOutputTotal_;
 		buffer = cfe_[Cfe::Output0].getBuffers().at(bayerId).buffer;
 		handleStreamBuffer(buffer, &cfe_[Cfe::Output0]);
 	} else
@@ -1994,7 +1995,6 @@ int PiSPCameraData::configureBe(const st
 	global.bayer_enables |= PISP_BE_BAYER_ENABLE_INPUT;
 	global.bayer_order = toPiSPBayerOrder(cfeFormat.fourcc);
 
-	ispOutputTotal_ = 1; /* Config buffer */
 	if (PISP_IMAGE_FORMAT_COMPRESSED(inputFormat.format)) {
 		pisp_decompress_config decompress;
 		decompress.offset = DefaultCompressionOffset;
@@ -2025,7 +2025,6 @@ int PiSPCameraData::configureBe(const st
 		setupOutputClipping(ispFormat0, outputFormat0);
 
 		be_->SetOutputFormat(0, outputFormat0);
-		ispOutputTotal_++;
 	}
 
 	if (global.rgb_enables & PISP_BE_RGB_ENABLE_OUTPUT1) {
@@ -2049,7 +2048,6 @@ int PiSPCameraData::configureBe(const st
 		setupOutputClipping(ispFormat1, outputFormat1);
 
 		be_->SetOutputFormat(1, outputFormat1);
-		ispOutputTotal_++;
 	}
 
 	/* Setup the TDN I/O blocks in case TDN gets turned on later. */
@@ -2256,8 +2254,6 @@ void PiSPCameraData::prepareCfe()
 
 void PiSPCameraData::prepareBe(uint32_t bufferId, bool stitchSwapBuffers)
 {
-	ispOutputCount_ = 0;
-
 	FrameBuffer *buffer = cfe_[Cfe::Output0].getBuffers().at(bufferId).buffer;
 
 	LOG(RPI, Debug) << "Input re-queue to ISP, buffer id " << bufferId
@@ -2319,16 +2315,11 @@ void PiSPCameraData::tryRunPipeline()
 
 	/* Take the first request from the queue and action the IPA. */
 	Request *request = requestQueue_.front();
+	ASSERT(request->metadata().empty());
 
 	/* See if a new ScalerCrop value needs to be applied. */
 	applyScalerCrop(request->controls());
 
-	/*
-	 * Clear the request metadata and fill it with some initial non-IPA
-	 * related controls. We clear it first because the request metadata
-	 * may have been populated if we have dropped the previous frame.
-	 */
-	request->metadata().clear();
 	fillRequestMetadata(job.sensorControls, request);
 
 	/* Set our state to say the pipeline is active. */
diff -pruN 0.5.0-1/src/libcamera/pipeline/rpi/vc4/data/example.yaml 0.6.0-2/src/libcamera/pipeline/rpi/vc4/data/example.yaml
--- 0.5.0-1/src/libcamera/pipeline/rpi/vc4/data/example.yaml	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rpi/vc4/data/example.yaml	2025-11-27 11:55:28.000000000 +0000
@@ -29,11 +29,6 @@
                 #
                 # "min_total_unicam_buffers": 4,
 
-                # Override any request from the IPA to drop a number of startup
-                # frames.
-                #
-                # "disable_startup_frame_drops": false,
-
                 # Custom timeout value (in ms) for camera to use. This overrides
                 # the value computed by the pipeline handler based on frame
                 # durations.
diff -pruN 0.5.0-1/src/libcamera/pipeline/rpi/vc4/vc4.cpp 0.6.0-2/src/libcamera/pipeline/rpi/vc4/vc4.cpp
--- 0.5.0-1/src/libcamera/pipeline/rpi/vc4/vc4.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/rpi/vc4/vc4.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -5,6 +5,8 @@
  * Pipeline handler for VC4-based Raspberry Pi devices
  */
 
+#include <memory>
+
 #include <linux/bcm2835-isp.h>
 #include <linux/v4l2-controls.h>
 #include <linux/videodev2.h>
@@ -158,7 +160,8 @@ private:
 
 	int prepareBuffers(Camera *camera) override;
 	int platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
-			     MediaDevice *unicam, MediaDevice *isp) override;
+			     std::shared_ptr<MediaDevice> unicam,
+			     std::shared_ptr<MediaDevice> isp) override;
 };
 
 bool PipelineHandlerVc4::match(DeviceEnumerator *enumerator)
@@ -173,7 +176,7 @@ bool PipelineHandlerVc4::match(DeviceEnu
 	 */
 	for (unsigned int i = 0; i < numUnicamDevices; i++) {
 		DeviceMatch unicam("unicam");
-		MediaDevice *unicamDevice = acquireMediaDevice(enumerator, unicam);
+		std::shared_ptr<MediaDevice> unicamDevice = acquireMediaDevice(enumerator, unicam);
 
 		if (!unicamDevice) {
 			LOG(RPI, Debug) << "Unable to acquire a Unicam instance";
@@ -181,7 +184,7 @@ bool PipelineHandlerVc4::match(DeviceEnu
 		}
 
 		DeviceMatch isp("bcm2835-isp");
-		MediaDevice *ispDevice = acquireMediaDevice(enumerator, isp);
+		std::shared_ptr<MediaDevice> ispDevice = acquireMediaDevice(enumerator, isp);
 
 		if (!ispDevice) {
 			LOG(RPI, Debug) << "Unable to acquire ISP instance";
@@ -303,7 +306,9 @@ int PipelineHandlerVc4::prepareBuffers(C
 	return 0;
 }
 
-int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData, MediaDevice *unicam, MediaDevice *isp)
+int PipelineHandlerVc4::platformRegister(std::unique_ptr<RPi::CameraData> &cameraData,
+					 std::shared_ptr<MediaDevice> unicam,
+					 std::shared_ptr<MediaDevice> isp)
 {
 	Vc4CameraData *data = static_cast<Vc4CameraData *>(cameraData.get());
 
@@ -597,8 +602,6 @@ int Vc4CameraData::platformConfigure(con
 		stream->setFlags(StreamFlag::External);
 	}
 
-	ispOutputTotal_ = outStreams.size();
-
 	/*
 	 * If ISP::Output0 stream has not been configured by the application,
 	 * we must allow the hardware to generate an output so that the data
@@ -625,8 +628,6 @@ int Vc4CameraData::platformConfigure(con
 			return -EINVAL;
 		}
 
-		ispOutputTotal_++;
-
 		LOG(RPI, Debug) << "Defaulting ISP Output0 format to "
 				<< format;
 	}
@@ -662,8 +663,6 @@ int Vc4CameraData::platformConfigure(con
 					<< ret;
 			return -EINVAL;
 		}
-
-		ispOutputTotal_++;
 	}
 
 	/* ISP statistics output format. */
@@ -676,8 +675,6 @@ int Vc4CameraData::platformConfigure(con
 		return ret;
 	}
 
-	ispOutputTotal_++;
-
 	/*
 	 * Configure the Unicam embedded data output format only if the sensor
 	 * supports it.
@@ -781,9 +778,15 @@ void Vc4CameraData::unicamBufferDequeue(
 		auto [ctrl, delayContext] = delayedCtrls_->get(buffer->metadata().sequence);
 		/*
 		 * Add the frame timestamp to the ControlList for the IPA to use
-		 * as it does not receive the FrameBuffer object.
+		 * as it does not receive the FrameBuffer object. Also derive a
+		 * corresponding wallclock value.
 		 */
-		ctrl.set(controls::SensorTimestamp, buffer->metadata().timestamp);
+		wallClockRecovery_.addSample();
+		uint64_t sensorTimestamp = buffer->metadata().timestamp;
+		uint64_t wallClockTimestamp = wallClockRecovery_.getOutput(sensorTimestamp);
+
+		ctrl.set(controls::SensorTimestamp, sensorTimestamp);
+		ctrl.set(controls::FrameWallClock, wallClockTimestamp);
 		bayerQueue_.push({ buffer, std::move(ctrl), delayContext });
 	} else {
 		embeddedQueue_.push(buffer);
@@ -843,12 +846,6 @@ void Vc4CameraData::ispOutputDequeue(Fra
 		handleStreamBuffer(buffer, stream);
 	}
 
-	/*
-	 * Increment the number of ISP outputs generated.
-	 * This is needed to track dropped frames.
-	 */
-	ispOutputCount_++;
-
 	handleState();
 }
 
@@ -880,7 +877,6 @@ void Vc4CameraData::prepareIspComplete(c
 			<< ", timestamp: " << buffer->metadata().timestamp;
 
 	isp_[Isp::Input].queueBuffer(buffer);
-	ispOutputCount_ = 0;
 
 	if (sensorMetadata_ && embeddedId) {
 		buffer = unicam_[Unicam::Embedded].getBuffers().at(embeddedId & RPi::MaskID).buffer;
@@ -936,16 +932,11 @@ void Vc4CameraData::tryRunPipeline()
 
 	/* Take the first request from the queue and action the IPA. */
 	Request *request = requestQueue_.front();
+	ASSERT(request->metadata().empty());
 
 	/* See if a new ScalerCrop value needs to be applied. */
 	applyScalerCrop(request->controls());
 
-	/*
-	 * Clear the request metadata and fill it with some initial non-IPA
-	 * related controls. We clear it first because the request metadata
-	 * may have been populated if we have dropped the previous frame.
-	 */
-	request->metadata().clear();
 	fillRequestMetadata(bayerFrame.controls, request);
 
 	/* Set our state to say the pipeline is active. */
diff -pruN 0.5.0-1/src/libcamera/pipeline/simple/simple.cpp 0.6.0-2/src/libcamera/pipeline/simple/simple.cpp
--- 0.5.0-1/src/libcamera/pipeline/simple/simple.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/simple/simple.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -25,16 +25,20 @@
 #include <libcamera/base/log.h>
 
 #include <libcamera/camera.h>
+#include <libcamera/color_space.h>
 #include <libcamera/control_ids.h>
 #include <libcamera/request.h>
 #include <libcamera/stream.h>
 
 #include "libcamera/internal/camera.h"
+#include "libcamera/internal/camera_manager.h"
 #include "libcamera/internal/camera_sensor.h"
 #include "libcamera/internal/camera_sensor_properties.h"
 #include "libcamera/internal/converter.h"
 #include "libcamera/internal/delayed_controls.h"
 #include "libcamera/internal/device_enumerator.h"
+#include "libcamera/internal/formats.h"
+#include "libcamera/internal/global_configuration.h"
 #include "libcamera/internal/media_device.h"
 #include "libcamera/internal/pipeline_handler.h"
 #include "libcamera/internal/software_isp/software_isp.h"
@@ -252,6 +256,7 @@ static const SimplePipelineInfo supporte
 	{ "dcmipp", {}, false },
 	{ "imx7-csi", { { "pxp", 1 } }, false },
 	{ "intel-ipu6", {}, true },
+	{ "intel-ipu7", {}, true },
 	{ "j721e-csi2rx", {}, true },
 	{ "mtk-seninf", { { "mtk-mdp", 3 } }, false },
 	{ "mxc-isi", {}, false },
@@ -375,6 +380,9 @@ public:
 	const Transform &combinedTransform() const { return combinedTransform_; }
 
 private:
+	static constexpr unsigned int kNumBuffersDefault = 4;
+	static constexpr unsigned int kNumBuffersMax = 32;
+
 	/*
 	 * The SimpleCameraData instance is guaranteed to be valid as long as
 	 * the corresponding Camera instance is valid. In order to borrow a
@@ -407,14 +415,15 @@ public:
 
 	V4L2VideoDevice *video(const MediaEntity *entity);
 	V4L2Subdevice *subdev(const MediaEntity *entity);
-	MediaDevice *converter() { return converter_; }
+	std::shared_ptr<MediaDevice> converter() { return converter_; }
 	bool swIspEnabled() const { return swIspEnabled_; }
 
 protected:
 	int queueRequestDevice(Camera *camera, Request *request) override;
 
 private:
-	static constexpr unsigned int kNumInternalBuffers = 3;
+	static constexpr unsigned int kMaxQueuedRequestsDevice = 4;
+	static constexpr unsigned int kNumInternalBuffers = 4;
 
 	struct EntityData {
 		std::unique_ptr<V4L2VideoDevice> video;
@@ -427,6 +436,10 @@ private:
 		return static_cast<SimpleCameraData *>(camera->_d());
 	}
 
+	bool matchDevice(std::shared_ptr<MediaDevice> media,
+			 const SimplePipelineInfo &info,
+			 DeviceEnumerator *enumerator);
+
 	std::vector<MediaEntity *> locateSensors(MediaDevice *media);
 	static int resetRoutingTable(V4L2Subdevice *subdev);
 
@@ -435,7 +448,7 @@ private:
 
 	std::map<const MediaEntity *, EntityData> entities_;
 
-	MediaDevice *converter_;
+	std::shared_ptr<MediaDevice> converter_;
 	bool swIspEnabled_;
 };
 
@@ -575,7 +588,7 @@ int SimpleCameraData::init()
 	int ret;
 
 	/* Open the converter, if any. */
-	MediaDevice *converter = pipe->converter();
+	std::shared_ptr<MediaDevice> converter = pipe->converter();
 	if (converter) {
 		converter_ = ConverterFactoryBase::create(converter);
 		if (!converter_) {
@@ -700,9 +713,14 @@ void SimpleCameraData::tryPipeline(unsig
 		<< " ]";
 
 	for (const auto &videoFormat : videoFormats) {
-		PixelFormat pixelFormat = videoFormat.first.toPixelFormat();
-		if (!pixelFormat)
+		PixelFormat pixelFormat = videoFormat.first.toPixelFormat(false);
+		if (!pixelFormat) {
+			LOG(SimplePipeline, Debug)
+				<< "Unsupported V4L2 pixel format "
+				<< videoFormat.first.toString();
+
 			continue;
+		}
 
 		Configuration config;
 		config.code = code;
@@ -1154,15 +1172,16 @@ CameraConfiguration::Status SimpleCamera
 	pipeConfig_ = nullptr;
 
 	for (const SimpleCameraData::Configuration *pipeConfig : *configs) {
-		const Size &size = pipeConfig->captureSize;
+		const Size &captureSize = pipeConfig->captureSize;
+		const Size &maxOutputSize = pipeConfig->outputSizes.max;
 
-		if (size.width >= maxStreamSize.width &&
-		    size.height >= maxStreamSize.height) {
-			if (!pipeConfig_ || size < pipeConfig_->captureSize)
+		if (maxOutputSize.width >= maxStreamSize.width &&
+		    maxOutputSize.height >= maxStreamSize.height) {
+			if (!pipeConfig_ || captureSize < pipeConfig_->captureSize)
 				pipeConfig_ = pipeConfig;
 		}
 
-		if (!maxPipeConfig || maxPipeConfig->captureSize < size)
+		if (!maxPipeConfig || maxPipeConfig->captureSize < captureSize)
 			maxPipeConfig = pipeConfig;
 	}
 
@@ -1204,11 +1223,51 @@ CameraConfiguration::Status SimpleCamera
 
 		PixelFormat pixelFormat = *it;
 		if (cfg.pixelFormat != pixelFormat) {
-			LOG(SimplePipeline, Debug) << "Adjusting pixel format";
+			LOG(SimplePipeline, Debug)
+				<< "Adjusting pixel format from "
+				<< cfg.pixelFormat << " to " << pixelFormat;
 			cfg.pixelFormat = pixelFormat;
 			status = Adjusted;
 		}
 
+		/*
+		 * Best effort to fix the color space. If the color space is not set,
+		 * set it according to the pixel format, which may not be correct (pixel
+		 * formats and color spaces are different things, although somewhat
+		 * related) but we don't have a better option at the moment. Then in any
+		 * case, perform the standard pixel format based color space adjustment.
+		 */
+		if (!cfg.colorSpace) {
+			const PixelFormatInfo &info = PixelFormatInfo::info(pixelFormat);
+			switch (info.colourEncoding) {
+			case PixelFormatInfo::ColourEncodingRGB:
+				cfg.colorSpace = ColorSpace::Srgb;
+				break;
+			case PixelFormatInfo::ColourEncodingYUV:
+				cfg.colorSpace = ColorSpace::Sycc;
+				break;
+			default:
+				cfg.colorSpace = ColorSpace::Raw;
+			}
+			LOG(SimplePipeline, Debug)
+				<< "Unspecified color space set to "
+				<< cfg.colorSpace.value().toString();
+			/*
+			 * Adjust the assigned color space to make sure everything is OK.
+			 * Since this is assigning an unspecified color space rather than
+			 * adjusting a requested one, changes here shouldn't set the status
+			 * to Adjusted.
+			 */
+			cfg.colorSpace->adjust(pixelFormat);
+		} else {
+			if (cfg.colorSpace->adjust(pixelFormat)) {
+				LOG(SimplePipeline, Debug)
+					<< "Color space adjusted to "
+					<< cfg.colorSpace.value().toString();
+				status = Adjusted;
+			}
+		}
+
 		if (!pipeConfig_->outputSizes.contains(cfg.size)) {
 			Size adjustedSize = pipeConfig_->captureSize;
 			/*
@@ -1231,7 +1290,7 @@ CameraConfiguration::Status SimpleCamera
 		    cfg.size != pipeConfig_->captureSize)
 			needConversion_ = true;
 
-		/* Set the stride, frameSize and bufferCount. */
+		/* Set the stride and frameSize. */
 		if (needConversion_) {
 			std::tie(cfg.stride, cfg.frameSize) =
 				data_->converter_
@@ -1254,7 +1313,18 @@ CameraConfiguration::Status SimpleCamera
 			cfg.frameSize = format.planes[0].size;
 		}
 
-		cfg.bufferCount = 4;
+		const unsigned int bufferCount = cfg.bufferCount;
+		if (!bufferCount)
+			cfg.bufferCount = kNumBuffersDefault;
+		else if (bufferCount > kNumBuffersMax)
+			cfg.bufferCount = kNumBuffersMax;
+
+		if (cfg.bufferCount != bufferCount) {
+			LOG(SimplePipeline, Debug)
+				<< "Adjusting bufferCount from " << bufferCount
+				<< " to " << cfg.bufferCount;
+			status = Adjusted;
+		}
 	}
 
 	return status;
@@ -1265,7 +1335,8 @@ CameraConfiguration::Status SimpleCamera
  */
 
 SimplePipelineHandler::SimplePipelineHandler(CameraManager *manager)
-	: PipelineHandler(manager), converter_(nullptr)
+	: PipelineHandler(manager, kMaxQueuedRequestsDevice),
+	  converter_(nullptr)
 {
 }
 
@@ -1353,8 +1424,20 @@ int SimplePipelineHandler::configure(Cam
 	if (ret < 0)
 		return ret;
 
-	/* Configure the video node. */
-	V4L2PixelFormat videoFormat = video->toV4L2PixelFormat(pipeConfig->captureFormat);
+	/* Configure the video node, taking into account any Bayer pattern change. */
+	V4L2PixelFormat videoFormat;
+	if (format.code == pipeConfig->code) {
+		videoFormat = video->toV4L2PixelFormat(pipeConfig->captureFormat);
+	} else {
+		/*
+		 * Bayer pattern has changed because of the transform that was applied on
+		 * the sensor. Get the V4L2PixelFormat corresponding to the configured Bayer
+		 * pattern.
+		 */
+		BayerFormat cfgBayer = BayerFormat::fromPixelFormat(pipeConfig->captureFormat);
+		cfgBayer.order = data->sensor_->bayerOrder(config->combinedTransform());
+		videoFormat = cfgBayer.toV4L2PixelFormat();
+	}
 
 	V4L2DeviceFormat captureFormat;
 	captureFormat.fourcc = videoFormat;
@@ -1396,7 +1479,7 @@ int SimplePipelineHandler::configure(Cam
 		return 0;
 
 	StreamConfiguration inputCfg;
-	inputCfg.pixelFormat = pipeConfig->captureFormat;
+	inputCfg.pixelFormat = videoFormat.toPixelFormat();
 	inputCfg.size = pipeConfig->captureSize;
 	inputCfg.stride = captureFormat.planes[0].bpl;
 	inputCfg.bufferCount = kNumInternalBuffers;
@@ -1660,25 +1743,13 @@ int SimplePipelineHandler::resetRoutingT
 	return 0;
 }
 
-bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
+bool SimplePipelineHandler::matchDevice(std::shared_ptr<MediaDevice> media,
+					const SimplePipelineInfo &info,
+					DeviceEnumerator *enumerator)
 {
-	const SimplePipelineInfo *info = nullptr;
 	unsigned int numStreams = 1;
-	MediaDevice *media;
 
-	for (const SimplePipelineInfo &inf : supportedDevices) {
-		DeviceMatch dm(inf.driver);
-		media = acquireMediaDevice(enumerator, dm);
-		if (media) {
-			info = &inf;
-			break;
-		}
-	}
-
-	if (!media)
-		return false;
-
-	for (const auto &[name, streams] : info->converters) {
+	for (const auto &[name, streams] : info.converters) {
 		DeviceMatch converterMatch(name);
 		converter_ = acquireMediaDevice(enumerator, converterMatch);
 		if (converter_) {
@@ -1687,10 +1758,23 @@ bool SimplePipelineHandler::match(Device
 		}
 	}
 
-	swIspEnabled_ = info->swIspEnabled;
+	swIspEnabled_ = info.swIspEnabled;
+	const GlobalConfiguration &configuration = cameraManager()->_d()->configuration();
+	for (GlobalConfiguration::Configuration entry :
+	     configuration.configuration()["pipelines"]["simple"]["supported_devices"]
+		     .asList()) {
+		auto name = entry["driver"].get<std::string>();
+		if (name == info.driver) {
+			swIspEnabled_ = entry["software_isp"].get<bool>().value_or(swIspEnabled_);
+			LOG(SimplePipeline, Debug)
+				<< "Configuration file overrides software ISP for "
+				<< info.driver << " to " << swIspEnabled_;
+			break;
+		}
+	}
 
 	/* Locate the sensors. */
-	std::vector<MediaEntity *> sensors = locateSensors(media);
+	std::vector<MediaEntity *> sensors = locateSensors(media.get());
 	if (sensors.empty()) {
 		LOG(SimplePipeline, Info) << "No sensor found for " << media->deviceNode();
 		return false;
@@ -1806,6 +1890,43 @@ bool SimplePipelineHandler::match(Device
 	return registered;
 }
 
+bool SimplePipelineHandler::match(DeviceEnumerator *enumerator)
+{
+	std::shared_ptr<MediaDevice> media;
+
+	for (const SimplePipelineInfo &inf : supportedDevices) {
+		DeviceMatch dm(inf.driver);
+		while ((media = acquireMediaDevice(enumerator, dm))) {
+			/*
+			 * If match succeeds, return true to let match() be
+			 * called again on a new instance of the pipeline
+			 * handler. Otherwise keep looping until we do
+			 * successfully match one (or run out).
+			 */
+			if (matchDevice(media, inf, enumerator)) {
+				LOG(SimplePipeline, Debug)
+					<< "Matched on device: "
+					<< media->deviceNode();
+				return true;
+			}
+
+			/*
+			 * \todo We need to clear the list of media devices
+			 * that we've already acquired in the event that we
+			 * fail to create a camera. This requires a rework of
+			 * DeviceEnumerator, or even how we create pipelines
+			 * handlers. This is because at the moment acquired
+			 * media devices are only released on pipeline handler
+			 * deconstruction, and if we release them any earlier
+			 * then DeviceEnumerator::search() will keep returning
+			 * the same media devices.
+			 */
+		}
+	}
+
+	return false;
+}
+
 V4L2VideoDevice *SimplePipelineHandler::video(const MediaEntity *entity)
 {
 	auto iter = entities_.find(entity);
diff -pruN 0.5.0-1/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp 0.6.0-2/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp
--- 0.5.0-1/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/uvcvideo/uvcvideo.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -46,7 +46,7 @@ public:
 	{
 	}
 
-	int init(MediaDevice *media);
+	int init(std::shared_ptr<MediaDevice> media);
 	void addControl(uint32_t cid, const ControlInfo &v4l2info,
 			ControlInfoMap::Map *ctrls);
 	void imageBufferReady(FrameBuffer *buffer);
@@ -100,7 +100,7 @@ public:
 private:
 	int processControl(const UVCCameraData *data, ControlList *controls,
 			   unsigned int id, const ControlValue &value);
-	int processControls(UVCCameraData *data, Request *request);
+	int processControls(UVCCameraData *data, const ControlList &reqControls);
 
 	bool acquireDevice(Camera *camera) override;
 	void releaseDevice(Camera *camera) override;
@@ -143,6 +143,9 @@ CameraConfiguration::Status UVCCameraCon
 	if (config_.empty())
 		return Invalid;
 
+	if (sensorConfig)
+		return Invalid;
+
 	if (orientation != Orientation::Rotate0) {
 		orientation = Orientation::Rotate0;
 		status = Adjusted;
@@ -287,7 +290,7 @@ int PipelineHandlerUVC::exportFrameBuffe
 	return data->video_->exportBuffers(count, buffers);
 }
 
-int PipelineHandlerUVC::start(Camera *camera, [[maybe_unused]] const ControlList *controls)
+int PipelineHandlerUVC::start(Camera *camera, const ControlList *controls)
 {
 	UVCCameraData *data = cameraData(camera);
 	unsigned int count = data->stream_.configuration().bufferCount;
@@ -296,13 +299,22 @@ int PipelineHandlerUVC::start(Camera *ca
 	if (ret < 0)
 		return ret;
 
-	ret = data->video_->streamOn();
-	if (ret < 0) {
-		data->video_->releaseBuffers();
-		return ret;
+	if (controls) {
+		ret = processControls(data, *controls);
+		if (ret < 0)
+			goto err_release_buffers;
 	}
 
+	ret = data->video_->streamOn();
+	if (ret < 0)
+		goto err_release_buffers;
+
 	return 0;
+
+err_release_buffers:
+	data->video_->releaseBuffers();
+
+	return ret;
 }
 
 void PipelineHandlerUVC::stopDevice(Camera *camera)
@@ -329,6 +341,10 @@ int PipelineHandlerUVC::processControl(c
 		cid = V4L2_CID_EXPOSURE_ABSOLUTE;
 	else if (id == controls::AnalogueGain)
 		cid = V4L2_CID_GAIN;
+	else if (id == controls::Gamma)
+		cid = V4L2_CID_GAMMA;
+	else if (id == controls::AeEnable)
+		return 0; /* Handled in `Camera::queueRequest()`. */
 	else
 		return -EINVAL;
 
@@ -394,6 +410,10 @@ int PipelineHandlerUVC::processControl(c
 		break;
 	}
 
+	case V4L2_CID_GAMMA:
+		controls->set(cid, static_cast<int32_t>(std::lround(value.get<float>() * 100)));
+		break;
+
 	default: {
 		int32_t ivalue = value.get<int32_t>();
 		controls->set(cid, ivalue);
@@ -404,11 +424,11 @@ int PipelineHandlerUVC::processControl(c
 	return 0;
 }
 
-int PipelineHandlerUVC::processControls(UVCCameraData *data, Request *request)
+int PipelineHandlerUVC::processControls(UVCCameraData *data, const ControlList &reqControls)
 {
 	ControlList controls(data->video_->controls());
 
-	for (const auto &[id, value] : request->controls())
+	for (const auto &[id, value] : reqControls)
 		processControl(data, &controls, id, value);
 
 	for (const auto &ctrl : controls)
@@ -436,7 +456,7 @@ int PipelineHandlerUVC::queueRequestDevi
 		return -ENOENT;
 	}
 
-	int ret = processControls(data, request);
+	int ret = processControls(data, request->controls());
 	if (ret < 0)
 		return ret;
 
@@ -449,7 +469,7 @@ int PipelineHandlerUVC::queueRequestDevi
 
 bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 {
-	MediaDevice *media;
+	std::shared_ptr<MediaDevice> media;
 	DeviceMatch dm("uvcvideo");
 
 	media = acquireMediaDevice(enumerator, dm);
@@ -491,7 +511,7 @@ void PipelineHandlerUVC::releaseDevice(C
 	data->video_->close();
 }
 
-int UVCCameraData::init(MediaDevice *media)
+int UVCCameraData::init(std::shared_ptr<MediaDevice> media)
 {
 	int ret;
 
@@ -590,6 +610,11 @@ int UVCCameraData::init(MediaDevice *med
 		addControl(cid, info, &ctrls);
 	}
 
+	if (autoExposureMode_ && manualExposureMode_) {
+		/* \todo Move this to the Camera class */
+		ctrls[&controls::AeEnable] = ControlInfo(false, true, true);
+	}
+
 	controlInfo_ = ControlInfoMap(std::move(ctrls), controls::controls);
 
 	/*
@@ -691,6 +716,9 @@ void UVCCameraData::addControl(uint32_t
 	case V4L2_CID_GAIN:
 		id = &controls::AnalogueGain;
 		break;
+	case V4L2_CID_GAMMA:
+		id = &controls::Gamma;
+		break;
 	default:
 		return;
 	}
@@ -845,6 +873,15 @@ void UVCCameraData::addControl(uint32_t
 		break;
 	}
 
+	case V4L2_CID_GAMMA:
+		/* UVC gamma is in units of 1/100 gamma. */
+		info = ControlInfo{
+			{ min / 100.0f },
+			{ max / 100.0f },
+			{ def / 100.0f }
+		};
+		break;
+
 	default:
 		info = v4l2Info;
 		break;
diff -pruN 0.5.0-1/src/libcamera/pipeline/vimc/vimc.cpp 0.6.0-2/src/libcamera/pipeline/vimc/vimc.cpp
--- 0.5.0-1/src/libcamera/pipeline/vimc/vimc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/vimc/vimc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -49,7 +49,7 @@ LOG_DEFINE_CATEGORY(VIMC)
 class VimcCameraData : public Camera::Private
 {
 public:
-	VimcCameraData(PipelineHandler *pipe, MediaDevice *media)
+	VimcCameraData(PipelineHandler *pipe, std::shared_ptr<MediaDevice> media)
 		: Camera::Private(pipe), media_(media)
 	{
 	}
@@ -59,7 +59,7 @@ public:
 	void imageBufferReady(FrameBuffer *buffer);
 	void paramsComputed(unsigned int id, const Flags<ipa::vimc::TestFlag> flags);
 
-	MediaDevice *media_;
+	std::shared_ptr<MediaDevice> media_;
 	std::unique_ptr<CameraSensor> sensor_;
 	std::unique_ptr<V4L2Subdevice> debayer_;
 	std::unique_ptr<V4L2Subdevice> scaler_;
@@ -363,8 +363,11 @@ int PipelineHandlerVimc::start(Camera *c
 	/* Map the mock IPA buffers to VIMC IPA to exercise IPC code paths. */
 	std::vector<IPABuffer> ipaBuffers;
 	for (auto [i, buffer] : utils::enumerate(data->mockIPABufs_)) {
+		Span<const FrameBuffer::Plane> planes = buffer->planes();
+
 		buffer->setCookie(i + 1);
-		ipaBuffers.emplace_back(buffer->cookie(), buffer->planes());
+		ipaBuffers.emplace_back(buffer->cookie(),
+					std::vector<FrameBuffer::Plane>{ planes.begin(), planes.end() });
 	}
 	data->ipa_->mapBuffers(ipaBuffers);
 
@@ -476,7 +479,7 @@ bool PipelineHandlerVimc::match(DeviceEn
 	dm.add("RGB/YUV Input");
 	dm.add("Scaler");
 
-	MediaDevice *media = acquireMediaDevice(enumerator, dm);
+	std::shared_ptr<MediaDevice> media = acquireMediaDevice(enumerator, dm);
 	if (!media)
 		return false;
 
@@ -536,21 +539,21 @@ int VimcCameraData::init()
 	if (!sensor_)
 		return -ENODEV;
 
-	debayer_ = V4L2Subdevice::fromEntityName(media_, "Debayer B");
+	debayer_ = V4L2Subdevice::fromEntityName(media_.get(), "Debayer B");
 	if (debayer_->open())
 		return -ENODEV;
 
-	scaler_ = V4L2Subdevice::fromEntityName(media_, "Scaler");
+	scaler_ = V4L2Subdevice::fromEntityName(media_.get(), "Scaler");
 	if (scaler_->open())
 		return -ENODEV;
 
-	video_ = V4L2VideoDevice::fromEntityName(media_, "RGB/YUV Capture");
+	video_ = V4L2VideoDevice::fromEntityName(media_.get(), "RGB/YUV Capture");
 	if (video_->open())
 		return -ENODEV;
 
 	video_->bufferReady.connect(this, &VimcCameraData::imageBufferReady);
 
-	raw_ = V4L2VideoDevice::fromEntityName(media_, "Raw Capture 1");
+	raw_ = V4L2VideoDevice::fromEntityName(media_.get(), "Raw Capture 1");
 	if (raw_->open())
 		return -ENODEV;
 
diff -pruN 0.5.0-1/src/libcamera/pipeline/virtual/config_parser.cpp 0.6.0-2/src/libcamera/pipeline/virtual/config_parser.cpp
--- 0.5.0-1/src/libcamera/pipeline/virtual/config_parser.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/virtual/config_parser.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -31,7 +31,7 @@ ConfigParser::parseConfigFile(File &file
 
 	std::unique_ptr<YamlObject> cameras = YamlParser::parse(file);
 	if (!cameras) {
-		LOG(Virtual, Error) << "Failed to pass config file.";
+		LOG(Virtual, Error) << "Failed to parse config file.";
 		return configurations;
 	}
 
@@ -233,17 +233,21 @@ int ConfigParser::parseFrameGenerator(co
 
 int ConfigParser::parseLocation(const YamlObject &cameraConfigData, VirtualCameraData *data)
 {
-	std::string location = cameraConfigData["location"].get<std::string>("CameraLocationFront");
-
 	/* Default value is properties::CameraLocationFront */
-	auto it = properties::LocationNameValueMap.find(location);
-	if (it == properties::LocationNameValueMap.end()) {
-		LOG(Virtual, Error)
-			<< "location: " << location << " is not supported";
-		return -EINVAL;
+	int32_t location = properties::CameraLocationFront;
+
+	if (auto l = cameraConfigData["location"].get<std::string>()) {
+		auto it = properties::LocationNameValueMap.find(*l);
+		if (it == properties::LocationNameValueMap.end()) {
+			LOG(Virtual, Error)
+				<< "location: " << *l << " is not supported";
+			return -EINVAL;
+		}
+
+		location = it->second;
 	}
 
-	data->properties_.set(properties::Location, it->second);
+	data->properties_.set(properties::Location, location);
 
 	return 0;
 }
diff -pruN 0.5.0-1/src/libcamera/pipeline/virtual/virtual.cpp 0.6.0-2/src/libcamera/pipeline/virtual/virtual.cpp
--- 0.5.0-1/src/libcamera/pipeline/virtual/virtual.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/virtual/virtual.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -106,6 +106,7 @@ private:
 	}
 
 	bool initFrameGenerator(Camera *camera);
+	void bufferCompleted(FrameBuffer *buffer);
 
 	DmaBufAllocator dmaBufAllocator_;
 
@@ -114,7 +115,7 @@ private:
 
 VirtualCameraData::VirtualCameraData(PipelineHandler *pipe,
 				     const std::vector<Resolution> &supportedResolutions)
-	: Camera::Private(pipe)
+	: Camera::Private(pipe), Thread("VirtualCamera")
 {
 	config_.resolutions = supportedResolutions;
 	for (const auto &resolution : config_.resolutions) {
@@ -129,6 +130,39 @@ VirtualCameraData::VirtualCameraData(Pip
 
 	/* \todo Support multiple streams and pass multi_stream_test */
 	streamConfigs_.resize(kMaxStream);
+
+	moveToThread(this);
+}
+
+void VirtualCameraData::processRequest(Request *request)
+{
+	for (auto const &[stream, buffer] : request->buffers()) {
+		bool found = false;
+		/* map buffer and fill test patterns */
+		for (auto &streamConfig : streamConfigs_) {
+			if (stream == &streamConfig.stream) {
+				FrameMetadata &fmd = buffer->_d()->metadata();
+
+				fmd.status = FrameMetadata::Status::FrameSuccess;
+				fmd.sequence = streamConfig.seq++;
+				fmd.timestamp = currentTimestamp();
+
+				Span<const FrameBuffer::Plane> planes = buffer->planes();
+				for (const auto [i, p] : utils::enumerate(planes))
+					fmd.planes()[i].bytesused = p.length;
+
+				found = true;
+
+				if (streamConfig.frameGenerator->generateFrame(
+					    stream->configuration().size, buffer))
+					fmd.status = FrameMetadata::Status::FrameError;
+
+				bufferCompleted.emit(buffer);
+				break;
+			}
+		}
+		ASSERT(found);
+	}
 }
 
 VirtualCameraConfiguration::VirtualCameraConfiguration(VirtualCameraData *data)
@@ -180,6 +214,17 @@ CameraConfiguration::Status VirtualCamer
 			adjusted = true;
 		}
 
+		if (cfg.colorSpace != ColorSpace::Rec709) {
+			cfg.colorSpace = ColorSpace::Rec709;
+			status = Adjusted;
+			adjusted = true;
+		}
+
+		if (validateColorSpaces() == Adjusted) {
+			status = Adjusted;
+			adjusted = true;
+		}
+
 		if (adjusted)
 			LOG(Virtual, Info)
 				<< "Stream configuration adjusted to " << cfg.toString();
@@ -244,6 +289,7 @@ PipelineHandlerVirtual::generateConfigur
 		cfg.pixelFormat = pixelFormat;
 		cfg.size = data->config_.maxResolutionSize;
 		cfg.bufferCount = VirtualCameraConfiguration::kBufferCount;
+		cfg.colorSpace = ColorSpace::Rec709;
 
 		config->addConfiguration(cfg);
 	}
@@ -291,11 +337,27 @@ int PipelineHandlerVirtual::start([[mayb
 	for (auto &s : data->streamConfigs_)
 		s.seq = 0;
 
+	data->bufferCompleted.connect(this, &PipelineHandlerVirtual::bufferCompleted);
+	data->start();
+
 	return 0;
 }
 
-void PipelineHandlerVirtual::stopDevice([[maybe_unused]] Camera *camera)
+void PipelineHandlerVirtual::stopDevice(Camera *camera)
 {
+	VirtualCameraData *data = cameraData(camera);
+
+	/* Cancel pending work. */
+	data->exit();
+	data->wait();
+	data->removeMessages(data);
+
+	/* Process pending `bufferCompleted` signals. */
+	thread()->dispatchMessages(Message::Type::InvokeMessage, this);
+	data->bufferCompleted.disconnect(this);
+
+	while (!data->queuedRequests_.empty())
+		cancelRequest(data->queuedRequests_.front());
 }
 
 int PipelineHandlerVirtual::queueRequestDevice([[maybe_unused]] Camera *camera,
@@ -304,35 +366,9 @@ int PipelineHandlerVirtual::queueRequest
 	VirtualCameraData *data = cameraData(camera);
 	const auto timestamp = currentTimestamp();
 
-	for (auto const &[stream, buffer] : request->buffers()) {
-		bool found = false;
-		/* map buffer and fill test patterns */
-		for (auto &streamConfig : data->streamConfigs_) {
-			if (stream == &streamConfig.stream) {
-				FrameMetadata &fmd = buffer->_d()->metadata();
-
-				fmd.status = FrameMetadata::Status::FrameSuccess;
-				fmd.sequence = streamConfig.seq++;
-				fmd.timestamp = timestamp;
-
-				for (const auto [i, p] : utils::enumerate(buffer->planes()))
-					fmd.planes()[i].bytesused = p.length;
-
-				found = true;
-
-				if (streamConfig.frameGenerator->generateFrame(
-					    stream->configuration().size, buffer))
-					fmd.status = FrameMetadata::Status::FrameError;
-
-				completeBuffer(request, buffer);
-				break;
-			}
-		}
-		ASSERT(found);
-	}
-
 	request->metadata().set(controls::SensorTimestamp, timestamp);
-	completeRequest(request);
+	data->invokeMethod(&VirtualCameraData::processRequest,
+			   ConnectionTypeQueued, request);
 
 	return 0;
 }
@@ -414,6 +450,14 @@ bool PipelineHandlerVirtual::initFrameGe
 	return true;
 }
 
+void PipelineHandlerVirtual::bufferCompleted(FrameBuffer *buffer)
+{
+	Request *request = buffer->request();
+
+	if (completeBuffer(request, buffer))
+		completeRequest(request);
+}
+
 REGISTER_PIPELINE_HANDLER(PipelineHandlerVirtual, "virtual")
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/pipeline/virtual/virtual.h 0.6.0-2/src/libcamera/pipeline/virtual/virtual.h
--- 0.5.0-1/src/libcamera/pipeline/virtual/virtual.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline/virtual/virtual.h	2025-11-27 11:55:28.000000000 +0000
@@ -11,6 +11,10 @@
 #include <variant>
 #include <vector>
 
+#include <libcamera/base/object.h>
+#include <libcamera/base/signal.h>
+#include <libcamera/base/thread.h>
+
 #include <libcamera/geometry.h>
 #include <libcamera/stream.h>
 
@@ -25,7 +29,9 @@ namespace libcamera {
 
 using VirtualFrame = std::variant<TestPattern, ImageFrames>;
 
-class VirtualCameraData : public Camera::Private
+class VirtualCameraData : public Camera::Private,
+			  public Thread,
+			  public Object
 {
 public:
 	const static unsigned int kMaxStream = 3;
@@ -54,9 +60,12 @@ public:
 
 	~VirtualCameraData() = default;
 
+	void processRequest(Request *request);
+
 	Configuration config_;
 
 	std::vector<StreamConfig> streamConfigs_;
+	Signal<FrameBuffer *> bufferCompleted;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/pipeline_handler.cpp 0.6.0-2/src/libcamera/pipeline_handler.cpp
--- 0.5.0-1/src/libcamera/pipeline_handler.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/pipeline_handler.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -62,13 +62,17 @@ LOG_DEFINE_CATEGORY(Pipeline)
 /**
  * \brief Construct a PipelineHandler instance
  * \param[in] manager The camera manager
+ * \param[in] maxQueuedRequestsDevice The maximum number of requests queued to
+ * the device
  *
  * In order to honour the std::enable_shared_from_this<> contract,
  * PipelineHandler instances shall never be constructed manually, but always
  * through the PipelineHandlerFactoryBase::create() function.
  */
-PipelineHandler::PipelineHandler(CameraManager *manager)
-	: manager_(manager), useCount_(0)
+PipelineHandler::PipelineHandler(CameraManager *manager,
+				 unsigned int maxQueuedRequestsDevice)
+	: manager_(manager), maxQueuedRequestsDevice_(maxQueuedRequestsDevice),
+	  useCount_(0)
 {
 }
 
@@ -125,10 +129,12 @@ PipelineHandler::~PipelineHandler()
  *
  * \context This function shall be called from the CameraManager thread.
  *
- * \return A pointer to the matching MediaDevice, or nullptr if no match is found
+ * \return A shared pointer to the matching MediaDevice, or nullptr if no match
+ * is found
  */
-MediaDevice *PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
-						 const DeviceMatch &dm)
+std::shared_ptr<MediaDevice>
+PipelineHandler::acquireMediaDevice(DeviceEnumerator *enumerator,
+				    const DeviceMatch &dm)
 {
 	std::shared_ptr<MediaDevice> media = enumerator->search(dm);
 	if (!media)
@@ -139,7 +145,7 @@ MediaDevice *PipelineHandler::acquireMed
 
 	mediaDevices_.push_back(media);
 
-	return media.get();
+	return media;
 }
 
 /**
@@ -360,19 +366,37 @@ void PipelineHandler::unlockMediaDevices
  */
 void PipelineHandler::stop(Camera *camera)
 {
+	/*
+	 * Take all waiting requests so that they are not requeued in response
+	 * to completeRequest() being called inside stopDevice(). Cancel them
+	 * after the device to keep them in order.
+	 */
+	Camera::Private *data = camera->_d();
+	std::queue<Request *> waitingRequests;
+	waitingRequests.swap(data->waitingRequests_);
+
 	/* Stop the pipeline handler and let the queued requests complete. */
 	stopDevice(camera);
 
 	/* Cancel and signal as complete all waiting requests. */
-	while (!waitingRequests_.empty()) {
-		Request *request = waitingRequests_.front();
-		waitingRequests_.pop();
-		cancelRequest(request);
+	while (!waitingRequests.empty()) {
+		Request *request = waitingRequests.front();
+		waitingRequests.pop();
+
+		/*
+		 * Cancel all requests by marking them as cancelled and calling
+		 * doQueueRequest() instead of cancelRequest(). This ensures
+		 * that the requests get a sequence number and are temporarily
+		 * added to queuedRequests_ so they can be properly completed in
+		 * completeRequest().
+		 */
+		request->_d()->cancel();
+		doQueueRequest(request);
 	}
 
 	/* Make sure no requests are pending. */
-	Camera::Private *data = camera->_d();
 	ASSERT(data->queuedRequests_.empty());
+	ASSERT(data->waitingRequests_.empty());
 
 	data->requestSequence_ = 0;
 }
@@ -414,7 +438,9 @@ void PipelineHandler::registerRequest(Re
 	 * Connect the request prepared signal to notify the pipeline handler
 	 * when a request is ready to be processed.
 	 */
-	request->_d()->prepared.connect(this, &PipelineHandler::doQueueRequests);
+	request->_d()->prepared.connect(this, [this, request]() {
+		doQueueRequests(request->_d()->camera());
+	});
 }
 
 /**
@@ -427,9 +453,9 @@ void PipelineHandler::registerRequest(Re
  * requests which have to be prepared to make sure they are ready for being
  * queued to the pipeline handler.
  *
- * The queue of waiting requests is iterated and all prepared requests are
- * passed to the pipeline handler in the same order they have been queued by
- * calling this function.
+ * The queue of waiting requests is iterated and up to \a
+ * maxQueuedRequestsDevice_ prepared requests are passed to the pipeline handler
+ * in the same order they have been queued by calling this function.
  *
  * If a Request fails during the preparation phase or if the pipeline handler
  * fails in queuing the request to the hardware the request is cancelled.
@@ -444,7 +470,9 @@ void PipelineHandler::queueRequest(Reque
 {
 	LIBCAMERA_TRACEPOINT(request_queue, request);
 
-	waitingRequests_.push(request);
+	Camera *camera = request->_d()->camera();
+	Camera::Private *data = camera->_d();
+	data->waitingRequests_.push(request);
 
 	request->_d()->prepare(300ms);
 }
@@ -478,15 +506,23 @@ void PipelineHandler::doQueueRequest(Req
  * Iterate the list of waiting requests and queue them to the device one
  * by one if they have been prepared.
  */
-void PipelineHandler::doQueueRequests()
+void PipelineHandler::doQueueRequests(Camera *camera)
 {
-	while (!waitingRequests_.empty()) {
-		Request *request = waitingRequests_.front();
+	Camera::Private *data = camera->_d();
+	while (!data->waitingRequests_.empty()) {
+		if (data->queuedRequests_.size() == maxQueuedRequestsDevice_)
+			break;
+
+		Request *request = data->waitingRequests_.front();
 		if (!request->_d()->prepared_)
 			break;
 
+		/*
+		 * Pop the request first, in case doQueueRequests() is called
+		 * recursively from within doQueueRequest()
+		 */
+		data->waitingRequests_.pop();
 		doQueueRequest(request);
-		waitingRequests_.pop();
 	}
 }
 
@@ -562,6 +598,9 @@ void PipelineHandler::completeRequest(Re
 		data->queuedRequests_.pop_front();
 		camera->requestComplete(req);
 	}
+
+	/* Allow any waiting requests to be queued to the pipeline. */
+	doQueueRequests(camera);
 }
 
 /**
@@ -697,7 +736,7 @@ void PipelineHandler::registerCamera(std
  * handler gets notified and automatically disconnects all the cameras it has
  * registered without requiring any manual intervention.
  */
-void PipelineHandler::hotplugMediaDevice(MediaDevice *media)
+void PipelineHandler::hotplugMediaDevice(std::shared_ptr<MediaDevice> media)
 {
 	media->disconnected.connect(this, [this, media] { mediaDeviceDisconnected(media); });
 }
@@ -705,7 +744,7 @@ void PipelineHandler::hotplugMediaDevice
 /**
  * \brief Slot for the MediaDevice disconnected signal
  */
-void PipelineHandler::mediaDeviceDisconnected(MediaDevice *media)
+void PipelineHandler::mediaDeviceDisconnected(std::shared_ptr<MediaDevice> media)
 {
 	media->disconnected.disconnect(this);
 
@@ -763,6 +802,20 @@ void PipelineHandler::disconnect()
  */
 
 /**
+ * \var PipelineHandler::maxQueuedRequestsDevice_
+ * \brief The maximum number of requests the pipeline handler shall queue to the
+ * device
+ *
+ * maxQueuedRequestsDevice_ limits the number of request that the
+ * pipeline handler shall queue to the underlying hardware, in order to
+ * saturate the pipeline with requests. The application may choose to queue
+ * as many requests as it desires, however only maxQueuedRequestsDevice_
+ * requests will be queued to the hardware at a given point in time. The
+ * remaining requests will be kept waiting in the internal waiting
+ * queue, to be queued at a later stage.
+ */
+
+/**
  * \fn PipelineHandler::name()
  * \brief Retrieve the pipeline handler name
  * \context This function shall be \threadsafe.
@@ -770,6 +823,12 @@ void PipelineHandler::disconnect()
  */
 
 /**
+ * \fn PipelineHandler::useCount()
+ * \brief Retrieve the pipeline handler's used camera count
+ * \return The number of acquired cameras of the pipeline handler
+ */
+
+/**
  * \fn PipelineHandler::cameraManager() const
  * \brief Retrieve the CameraManager that this pipeline handler belongs to
  * \context This function is \threadsafe.
diff -pruN 0.5.0-1/src/libcamera/process.cpp 0.6.0-2/src/libcamera/process.cpp
--- 0.5.0-1/src/libcamera/process.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/process.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -10,15 +10,19 @@
 #include <algorithm>
 #include <dirent.h>
 #include <fcntl.h>
-#include <list>
 #include <signal.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <sys/syscall.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
+#include <utility>
 #include <vector>
 
+#include <linux/sched.h>
+#include <linux/wait.h> /* glibc only provides `P_PIDFD` in `sys/wait.h` since 2.36 */
+
 #include <libcamera/base/event_notifier.h>
 #include <libcamera/base/log.h>
 #include <libcamera/base/utils.h>
@@ -32,161 +36,61 @@ namespace libcamera {
 
 LOG_DEFINE_CATEGORY(Process)
 
-/**
- * \class ProcessManager
- * \brief Manager of processes
- *
- * The ProcessManager singleton keeps track of all created Process instances,
- * and manages the signal handling involved in terminating processes.
- */
-
 namespace {
 
-void sigact(int signal, siginfo_t *info, void *ucontext)
+void closeAllFdsExcept(std::vector<int> v)
 {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-result"
+	sort(v.begin(), v.end());
+
+	ASSERT(v.empty() || v.front() >= 0);
+
+#if HAVE_CLOSE_RANGE
 	/*
-	 * We're in a signal handler so we can't log any message, and we need
-	 * to continue anyway.
+	 * At the moment libcamera does not require at least Linux 5.9,
+	 * which introduced the `close_range()` system call, so a runtime
+	 * check is also needed to make sure that it is supported.
 	 */
-	char data = 0;
-	write(ProcessManager::instance()->writePipe(), &data, sizeof(data));
-#pragma GCC diagnostic pop
-
-	const struct sigaction &oldsa = ProcessManager::instance()->oldsa();
-	if (oldsa.sa_flags & SA_SIGINFO) {
-		oldsa.sa_sigaction(signal, info, ucontext);
-	} else {
-		if (oldsa.sa_handler != SIG_IGN && oldsa.sa_handler != SIG_DFL)
-			oldsa.sa_handler(signal);
-	}
-}
-
-} /* namespace */
+	static const bool hasCloseRange = [] {
+		return close_range(~0u, 0, 0) < 0 && errno == EINVAL;
+	}();
+
+	if (hasCloseRange) {
+		unsigned int prev = 0;
+
+		for (unsigned int curr : v) {
+			ASSERT(prev <= curr + 1);
+			if (prev < curr)
+				close_range(prev, curr - 1, 0);
+			prev = curr + 1;
+		}
 
-void ProcessManager::sighandler()
-{
-	char data;
-	ssize_t ret = read(pipe_[0].get(), &data, sizeof(data));
-	if (ret < 0) {
-		LOG(Process, Error)
-			<< "Failed to read byte from signal handler pipe";
+		close_range(prev, ~0u, 0);
 		return;
 	}
+#endif
 
-	for (auto it = processes_.begin(); it != processes_.end();) {
-		Process *process = *it;
+	DIR *dir = opendir("/proc/self/fd");
+	if (!dir)
+		return;
+
+	int dfd = dirfd(dir);
 
-		int wstatus;
-		pid_t pid = waitpid(process->pid_, &wstatus, WNOHANG);
-		if (process->pid_ != pid) {
-			++it;
+	struct dirent *ent;
+	while ((ent = readdir(dir)) != nullptr) {
+		char *endp;
+		int fd = strtoul(ent->d_name, &endp, 10);
+		if (*endp)
 			continue;
-		}
 
-		it = processes_.erase(it);
-		process->died(wstatus);
+		if (fd >= 0 && fd != dfd &&
+		    !std::binary_search(v.begin(), v.end(), fd))
+			close(fd);
 	}
-}
 
-/**
- * \brief Register process with process manager
- * \param[in] proc Process to register
- *
- * This function registers the \a proc with the process manager. It
- * shall be called by the parent process after successfully forking, in
- * order to let the parent signal process termination.
- */
-void ProcessManager::registerProcess(Process *proc)
-{
-	processes_.push_back(proc);
-}
-
-ProcessManager *ProcessManager::self_ = nullptr;
-
-/**
- * \brief Construct a ProcessManager instance
- *
- * The ProcessManager class is meant to only be instantiated once, by the
- * CameraManager.
- */
-ProcessManager::ProcessManager()
-{
-	if (self_)
-		LOG(Process, Fatal)
-			<< "Multiple ProcessManager objects are not allowed";
-
-	sigaction(SIGCHLD, NULL, &oldsa_);
-
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = &sigact;
-	memcpy(&sa.sa_mask, &oldsa_.sa_mask, sizeof(sa.sa_mask));
-	sigaddset(&sa.sa_mask, SIGCHLD);
-	sa.sa_flags = oldsa_.sa_flags | SA_SIGINFO;
-
-	sigaction(SIGCHLD, &sa, NULL);
-
-	int pipe[2];
-	if (pipe2(pipe, O_CLOEXEC | O_DIRECT | O_NONBLOCK))
-		LOG(Process, Fatal)
-			<< "Failed to initialize pipe for signal handling";
-
-	pipe_[0] = UniqueFD(pipe[0]);
-	pipe_[1] = UniqueFD(pipe[1]);
-
-	sigEvent_ = new EventNotifier(pipe_[0].get(), EventNotifier::Read);
-	sigEvent_->activated.connect(this, &ProcessManager::sighandler);
-
-	self_ = this;
-}
-
-ProcessManager::~ProcessManager()
-{
-	sigaction(SIGCHLD, &oldsa_, NULL);
-
-	delete sigEvent_;
-
-	self_ = nullptr;
-}
-
-/**
- * \brief Retrieve the Process manager instance
- *
- * The ProcessManager is constructed by the CameraManager. This function shall
- * be used to retrieve the single instance of the manager.
- *
- * \return The Process manager instance
- */
-ProcessManager *ProcessManager::instance()
-{
-	return self_;
-}
-
-/**
- * \brief Retrieve the Process manager's write pipe
- *
- * This function is meant only to be used by the static signal handler.
- *
- * \return Pipe for writing
- */
-int ProcessManager::writePipe() const
-{
-	return pipe_[1].get();
+	closedir(dir);
 }
 
-/**
- * \brief Retrive the old signal action data
- *
- * This function is meant only to be used by the static signal handler.
- *
- * \return The old signal action data
- */
-const struct sigaction &ProcessManager::oldsa() const
-{
-	return oldsa_;
-}
+} /* namespace */
 
 /**
  * \class Process
@@ -208,7 +112,7 @@ const struct sigaction &ProcessManager::
  */
 
 Process::Process()
-	: pid_(-1), running_(false), exitStatus_(NotExited), exitCode_(0)
+	: pid_(-1), exitStatus_(NotExited), exitCode_(0)
 {
 }
 
@@ -235,102 +139,110 @@ Process::~Process()
  * or a negative error code otherwise
  */
 int Process::start(const std::string &path,
-		   const std::vector<std::string> &args,
-		   const std::vector<int> &fds)
+		   Span<const std::string> args,
+		   Span<const int> fds)
 {
-	int ret;
+	if (pid_ > 0)
+		return -EBUSY;
+
+	for (int fd : fds) {
+		if (fd < 0)
+			return -EINVAL;
+	}
 
-	if (running_)
-		return 0;
+	clone_args cargs = {};
+	int pidfd;
 
-	int childPid = fork();
-	if (childPid == -1) {
-		ret = -errno;
+	cargs.flags = CLONE_PIDFD | CLONE_NEWUSER | CLONE_NEWNET;
+	cargs.pidfd = reinterpret_cast<uintptr_t>(&pidfd);
+	cargs.exit_signal = SIGCHLD;
+
+	long childPid = syscall(SYS_clone3, &cargs, sizeof(cargs));
+	if (childPid < 0) {
+		int ret = -errno;
 		LOG(Process, Error) << "Failed to fork: " << strerror(-ret);
 		return ret;
-	} else if (childPid) {
-		pid_ = childPid;
-		ProcessManager::instance()->registerProcess(this);
+	}
 
-		running_ = true;
+	if (childPid) {
+		pid_ = childPid;
+		pidfd_ = UniqueFD(pidfd);
+		pidfdNotify_ = std::make_unique<EventNotifier>(pidfd_.get(), EventNotifier::Type::Read);
+		pidfdNotify_->activated.connect(this, &Process::onPidfdNotify);
 
-		return 0;
+		LOG(Process, Debug) << this << "[" << childPid << ':' << pidfd << "]"
+				    << " forked";
 	} else {
-		if (isolate())
-			_exit(EXIT_FAILURE);
-
-		closeAllFdsExcept(fds);
+		std::vector<int> v(fds.begin(), fds.end());
+		v.push_back(STDERR_FILENO);
+		closeAllFdsExcept(std::move(v));
+
+		const auto tryDevNullLowestFd = [](int expected, int oflag) {
+			int fd = open("/dev/null", oflag);
+			if (fd < 0)
+				_exit(EXIT_FAILURE);
+			if (fd != expected)
+				close(fd);
+		};
+
+		tryDevNullLowestFd(STDIN_FILENO, O_RDONLY);
+		tryDevNullLowestFd(STDOUT_FILENO, O_WRONLY);
+		tryDevNullLowestFd(STDERR_FILENO, O_WRONLY);
 
 		const char *file = utils::secure_getenv("LIBCAMERA_LOG_FILE");
 		if (file && strcmp(file, "syslog"))
 			unsetenv("LIBCAMERA_LOG_FILE");
 
-		const char **argv = new const char *[args.size() + 2];
-		unsigned int len = args.size();
+		const size_t len = args.size();
+		auto argv = std::make_unique<const char *[]>(len + 2);
+
 		argv[0] = path.c_str();
-		for (unsigned int i = 0; i < len; i++)
+		for (size_t i = 0; i < len; i++)
 			argv[i + 1] = args[i].c_str();
 		argv[len + 1] = nullptr;
 
-		execv(path.c_str(), (char **)argv);
+		execv(path.c_str(), const_cast<char **>(argv.get()));
 
-		exit(EXIT_FAILURE);
+		_exit(EXIT_FAILURE);
 	}
+
+	return 0;
 }
 
-void Process::closeAllFdsExcept(const std::vector<int> &fds)
+void Process::onPidfdNotify()
 {
-	std::vector<int> v(fds);
-	sort(v.begin(), v.end());
+	auto pidfdNotify = std::exchange(pidfdNotify_, {});
+	auto pidfd = std::exchange(pidfd_, {});
+	auto pid = std::exchange(pid_, -1);
 
-	DIR *dir = opendir("/proc/self/fd");
-	if (!dir)
-		return;
+	ASSERT(pidfdNotify);
+	ASSERT(pidfd.isValid());
+	ASSERT(pid > 0);
 
-	int dfd = dirfd(dir);
+	siginfo_t info;
 
-	struct dirent *ent;
-	while ((ent = readdir(dir)) != nullptr) {
-		char *endp;
-		int fd = strtoul(ent->d_name, &endp, 10);
-		if (*endp)
-			continue;
+	/*
+	 * `static_cast` is needed because `P_PIDFD` is not defined in `sys/wait.h` if the C standard library
+	 * is old enough. So `P_PIDFD` is taken from `linux/wait.h`, where it is just an integer #define.
+	 */
+	if (waitid(static_cast<idtype_t>(P_PIDFD), pidfd.get(), &info, WNOHANG | WEXITED) >= 0) {
+		ASSERT(info.si_pid == pid);
 
-		if (fd >= 0 && fd != dfd &&
-		    !std::binary_search(v.begin(), v.end(), fd))
-			close(fd);
-	}
+		LOG(Process, Debug)
+			<< this << "[" << pid << ':' << pidfd.get() << "]"
+			<< " code: " << info.si_code
+			<< " status: " << info.si_status;
 
-	closedir(dir);
-}
+		exitStatus_ = info.si_code == CLD_EXITED ? Process::NormalExit : Process::SignalExit;
+		exitCode_ = info.si_code == CLD_EXITED ? info.si_status : -1;
 
-int Process::isolate()
-{
-	int ret = unshare(CLONE_NEWUSER | CLONE_NEWNET);
-	if (ret) {
-		ret = -errno;
-		LOG(Process, Error) << "Failed to unshare execution context: "
-				    << strerror(-ret);
-		return ret;
+		finished.emit(exitStatus_, exitCode_);
+	} else {
+		int err = errno;
+		LOG(Process, Warning)
+			<< this << "[" << pid << ":" << pidfd.get() << "]"
+			<< " waitid() failed: " << strerror(err);
 	}
-
-	return 0;
-}
-
-/**
- * \brief SIGCHLD handler
- * \param[in] wstatus The status as output by waitpid()
- *
- * This function is called when the process associated with Process terminates.
- * It emits the Process::finished signal.
- */
-void Process::died(int wstatus)
-{
-	running_ = false;
-	exitStatus_ = WIFEXITED(wstatus) ? NormalExit : SignalExit;
-	exitCode_ = exitStatus_ == NormalExit ? WEXITSTATUS(wstatus) : -1;
-
-	finished.emit(exitStatus_, exitCode_);
 }
 
 /**
@@ -368,8 +280,8 @@ void Process::died(int wstatus)
  */
 void Process::kill()
 {
-	if (pid_ > 0)
-		::kill(pid_, SIGKILL);
+	if (pidfd_.isValid())
+		syscall(SYS_pidfd_send_signal, pidfd_.get(), SIGKILL, nullptr, 0);
 }
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/request.cpp 0.6.0-2/src/libcamera/request.cpp
--- 0.5.0-1/src/libcamera/request.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/request.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -228,15 +228,12 @@ void Request::Private::prepare(std::chro
 		if (!fence)
 			continue;
 
-		std::unique_ptr<EventNotifier> notifier =
-			std::make_unique<EventNotifier>(fence->fd().get(),
-							EventNotifier::Read);
-
-		notifier->activated.connect(this, [this, buffer] {
-							notifierActivated(buffer);
-					    });
+		auto [it, inserted] = notifiers_.try_emplace(buffer, fence->fd().get(), EventNotifier::Type::Read);
+		ASSERT(inserted);
 
-		notifiers_[buffer] = std::move(notifier);
+		it->second.activated.connect(this, [this, buffer] {
+			notifierActivated(buffer);
+		});
 	}
 
 	if (notifiers_.empty()) {
@@ -327,6 +324,9 @@ void Request::Private::timeout()
  * Don't reuse buffers
  * \var Request::ReuseBuffers
  * Reuse the buffers that were previously added by addBuffer()
+ *
+ * \note Fences associated with the buffers are not reused.
+ *  This flag should not be used if fences are used.
  */
 
 /**
@@ -452,7 +452,9 @@ void Request::reuse(ReuseFlag flags)
  *
  * When a valid Fence is provided to this function, \a fence is moved to \a
  * buffer and this Request will only be queued to the device once the
- * fences of all its buffers have been correctly signalled.
+ * fences of all its buffers have been correctly signalled. Ownership of the
+ * fence will only be taken in case of success, otherwise the fence will
+ * be left unmodified.
  *
  * If the \a fence associated with \a buffer isn't signalled, the request will
  * fail after a timeout. The buffer will still contain the fence, which
@@ -468,7 +470,7 @@ void Request::reuse(ReuseFlag flags)
  * \retval -EINVAL The buffer does not reference a valid Stream
  */
 int Request::addBuffer(const Stream *stream, FrameBuffer *buffer,
-		       std::unique_ptr<Fence> fence)
+		       std::unique_ptr<Fence> &&fence)
 {
 	if (!stream) {
 		LOG(Request, Error) << "Invalid stream reference";
@@ -484,15 +486,14 @@ int Request::addBuffer(const Stream *str
 		return -EEXIST;
 	}
 
-	auto it = bufferMap_.find(stream);
-	if (it != bufferMap_.end()) {
+	auto [it, inserted] = bufferMap_.try_emplace(stream, buffer);
+	if (!inserted) {
 		LOG(Request, Error) << "FrameBuffer already set for stream";
 		return -EEXIST;
 	}
 
 	buffer->_d()->setRequest(this);
 	_d()->pending_.insert(buffer);
-	bufferMap_[stream] = buffer;
 
 	if (fence && fence->isValid())
 		buffer->_d()->setFence(std::move(fence));
diff -pruN 0.5.0-1/src/libcamera/sensor/camera_sensor.cpp 0.6.0-2/src/libcamera/sensor/camera_sensor.cpp
--- 0.5.0-1/src/libcamera/sensor/camera_sensor.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/sensor/camera_sensor.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -302,8 +302,9 @@ int CameraSensor::setEmbeddedDataEnabled
  * camera sensor, likely at configure() time.
  *
  * If the requested \a orientation cannot be obtained, the \a orientation
- * parameter is adjusted to report the current image orientation and
- * Transform::Identity is returned.
+ * parameter is adjusted to report the native image orientation (i.e. resulting
+ * from the physical mounting rotation of the camera sensor, without any
+ * transformation) and Transform::Identity is returned.
  *
  * If the requested \a orientation can be obtained, the function computes a
  * Transform and does not adjust \a orientation.
@@ -331,6 +332,13 @@ int CameraSensor::setEmbeddedDataEnabled
  */
 
 /**
+ * \fn CameraSensor::mountingOrientation()
+ * \brief Fetch the mounting orientation of the sensor
+ *
+ * \return The mounting orientation of the sensor
+ */
+
+/**
  * \fn CameraSensor::controls()
  * \brief Retrieve the supported V4L2 controls and their information
  *
diff -pruN 0.5.0-1/src/libcamera/sensor/camera_sensor_legacy.cpp 0.6.0-2/src/libcamera/sensor/camera_sensor_legacy.cpp
--- 0.5.0-1/src/libcamera/sensor/camera_sensor_legacy.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/sensor/camera_sensor_legacy.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2019, Google Inc.
  *
- * camera_sensor_legacy.cpp - A V4L2-backed camera sensor
+ * A V4L2-backed camera sensor
  */
 
 #include <algorithm>
@@ -73,7 +73,7 @@ public:
 	std::vector<Size> sizes(unsigned int mbusCode) const override;
 	Size resolution() const override;
 
-	V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
+	V4L2SubdeviceFormat getFormat(Span<const unsigned int> mbusCodes,
 				      const Size &size,
 				      const Size maxSize) const override;
 	int setFormat(V4L2SubdeviceFormat *format,
@@ -88,9 +88,10 @@ public:
 	int sensorInfo(IPACameraSensorInfo *info) const override;
 	Transform computeTransform(Orientation *orientation) const override;
 	BayerFormat::Order bayerOrder(Transform t) const override;
+	Orientation mountingOrientation() const override { return mountingOrientation_; }
 
 	const ControlInfoMap &controls() const override;
-	ControlList getControls(const std::vector<uint32_t> &ids) override;
+	ControlList getControls(Span<const uint32_t> ids) override;
 	int setControls(ControlList *ctrls) override;
 
 	const std::vector<controls::draft::TestPatternModeEnum> &
@@ -699,7 +700,7 @@ Size CameraSensorLegacy::resolution() co
 }
 
 V4L2SubdeviceFormat
-CameraSensorLegacy::getFormat(const std::vector<unsigned int> &mbusCodes,
+CameraSensorLegacy::getFormat(Span<const unsigned int> mbusCodes,
 			      const Size &size, Size maxSize) const
 {
 	unsigned int desiredArea = size.width * size.height;
@@ -907,9 +908,13 @@ int CameraSensorLegacy::sensorInfo(IPACa
 	 * duration through V4L2 controls. Support for the V4L2_CID_PIXEL_RATE,
 	 * V4L2_CID_HBLANK and V4L2_CID_VBLANK controls is mandatory.
 	 */
-	ControlList ctrls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,
-						   V4L2_CID_HBLANK,
-						   V4L2_CID_VBLANK });
+	static constexpr uint32_t cids[] = {
+		V4L2_CID_PIXEL_RATE,
+		V4L2_CID_HBLANK,
+		V4L2_CID_VBLANK,
+	};
+
+	ControlList ctrls = subdev_->getControls(cids);
 	if (ctrls.empty()) {
 		LOG(CameraSensor, Error)
 			<< "Failed to retrieve camera info controls";
@@ -983,7 +988,7 @@ const ControlInfoMap &CameraSensorLegacy
 	return subdev_->controls();
 }
 
-ControlList CameraSensorLegacy::getControls(const std::vector<uint32_t> &ids)
+ControlList CameraSensorLegacy::getControls(Span<const uint32_t> ids)
 {
 	return subdev_->getControls(ids);
 }
diff -pruN 0.5.0-1/src/libcamera/sensor/camera_sensor_properties.cpp 0.6.0-2/src/libcamera/sensor/camera_sensor_properties.cpp
--- 0.5.0-1/src/libcamera/sensor/camera_sensor_properties.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/sensor/camera_sensor_properties.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -151,6 +151,38 @@ const CameraSensorProperties *CameraSens
 			},
 			.sensorDelays = { },
 		} },
+		{ "hm1246", {
+			.unitCellSize = { 3000, 3000 },
+			.testPatternModes =  {
+				{ controls::draft::TestPatternModeOff, 0 },
+				/* Solid white. */
+				{ controls::draft::TestPatternModeSolidColor, 6 },
+				/* The six vertical bars (left-to-right) are as follows: black,
+				 * blue, red, magenta, green and cyan.
+				 */
+				{ controls::draft::TestPatternModeCustom1, 5 },
+				/*
+				 * No corresponding test pattern mode for:
+				 *  1: "Checkboard"
+				 *  2: "Ramp"
+				 *  3: "Moving ones"
+				 *  4: "Blending color bars"
+				 *  7: "Solid black"
+				 *  8: "Solid red"
+				 *  9: "Solid green"
+				 * 10: "Solid blue"
+				 *
+				 * Even though the sensor supports color bars and faded color bars as test patterns, these are
+				 * not offered because these patterns do not meet the expected properties.
+				 */
+			},
+			.sensorDelays = {
+				.exposureDelay = 2,
+				.gainDelay = 2,
+				.vblankDelay = 2,
+				.hblankDelay = 2
+			},
+		} },
 		{ "imx214", {
 			.unitCellSize = { 1120, 1120 },
 			.testPatternModes = {
@@ -194,7 +226,7 @@ const CameraSensorProperties *CameraSens
 			.testPatternModes = {},
 			.sensorDelays = {
 				.exposureDelay = 2,
-				.gainDelay = 2,
+				.gainDelay = 1,
 				.vblankDelay = 2,
 				.hblankDelay = 2
 			},
@@ -242,7 +274,12 @@ const CameraSensorProperties *CameraSens
 		{ "imx462", {
 			.unitCellSize = { 2900, 2900 },
 			.testPatternModes = {},
-			.sensorDelays = { },
+			.sensorDelays = {
+				.exposureDelay = 2,
+				.gainDelay = 2,
+				.vblankDelay = 2,
+				.hblankDelay = 2
+			},
 		} },
 		{ "imx477", {
 			.unitCellSize = { 1550, 1550 },
@@ -456,6 +493,44 @@ const CameraSensorProperties *CameraSens
 			},
 			.sensorDelays = { },
 		} },
+		{ "vd55g1", {
+			.unitCellSize = { 2160, 2160 },
+			.testPatternModes = {
+				{ controls::draft::TestPatternModeOff, 0 },
+				{ controls::draft::TestPatternModePn9, 2},
+				/*
+				 * No corresponding test pattern mode for:
+				 * 1: "Diagonal Gray Scale"
+				 */
+			},
+			.sensorDelays = {
+				.exposureDelay = 2,
+				.gainDelay = 2,
+				.vblankDelay = 2,
+				.hblankDelay = 2
+			},
+		} },
+		{ "vd56g3", {
+			.unitCellSize = { 2610, 2610 },
+			.testPatternModes = {
+				{ controls::draft::TestPatternModeOff, 0 },
+				{ controls::draft::TestPatternModeSolidColor, 1 },
+				{ controls::draft::TestPatternModePn9, 6 },
+				/*
+				 * No corresponding test pattern mode for:
+				 * 2: "Vertical Color Bars"
+				 * 3: "Horizontal Gray Scale"
+				 * 4: "Vertical Gray Scale"
+				 * 5: "Diagonal Gray Scale"
+				 */
+			},
+			.sensorDelays = {
+				.exposureDelay = 2,
+				.gainDelay = 2,
+				.vblankDelay = 2,
+				.hblankDelay = 2
+			},
+		} },
 	};
 
 	const auto it = sensorProps.find(sensor);
diff -pruN 0.5.0-1/src/libcamera/sensor/camera_sensor_raw.cpp 0.6.0-2/src/libcamera/sensor/camera_sensor_raw.cpp
--- 0.5.0-1/src/libcamera/sensor/camera_sensor_raw.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/sensor/camera_sensor_raw.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Ideas on Board Oy.
  *
- * camera_sensor_raw.cpp - A raw camera sensor using the V4L2 streams API
+ * A raw camera sensor using the V4L2 streams API
  */
 
 #include <algorithm>
@@ -74,7 +74,7 @@ public:
 	std::vector<Size> sizes(unsigned int mbusCode) const override;
 	Size resolution() const override;
 
-	V4L2SubdeviceFormat getFormat(const std::vector<unsigned int> &mbusCodes,
+	V4L2SubdeviceFormat getFormat(Span<const unsigned int> mbusCodes,
 				      const Size &size,
 				      const Size maxSize) const override;
 	int setFormat(V4L2SubdeviceFormat *format,
@@ -94,9 +94,10 @@ public:
 	int sensorInfo(IPACameraSensorInfo *info) const override;
 	Transform computeTransform(Orientation *orientation) const override;
 	BayerFormat::Order bayerOrder(Transform t) const override;
+	Orientation mountingOrientation() const override { return mountingOrientation_; }
 
 	const ControlInfoMap &controls() const override;
-	ControlList getControls(const std::vector<uint32_t> &ids) override;
+	ControlList getControls(Span<const uint32_t> ids) override;
 	int setControls(ControlList *ctrls) override;
 
 	const std::vector<controls::draft::TestPatternModeEnum> &
@@ -757,7 +758,7 @@ Size CameraSensorRaw::resolution() const
 }
 
 V4L2SubdeviceFormat
-CameraSensorRaw::getFormat(const std::vector<unsigned int> &mbusCodes,
+CameraSensorRaw::getFormat(Span<const unsigned int> mbusCodes,
 			   const Size &size, Size maxSize) const
 {
 	unsigned int desiredArea = size.width * size.height;
@@ -1022,9 +1023,13 @@ int CameraSensorRaw::sensorInfo(IPACamer
 	 * duration through V4L2 controls. Support for the V4L2_CID_PIXEL_RATE,
 	 * V4L2_CID_HBLANK and V4L2_CID_VBLANK controls is mandatory.
 	 */
-	ControlList ctrls = subdev_->getControls({ V4L2_CID_PIXEL_RATE,
-						   V4L2_CID_HBLANK,
-						   V4L2_CID_VBLANK });
+	static constexpr uint32_t cids[] = {
+		V4L2_CID_PIXEL_RATE,
+		V4L2_CID_HBLANK,
+		V4L2_CID_VBLANK,
+	};
+
+	ControlList ctrls = subdev_->getControls(cids);
 	if (ctrls.empty()) {
 		LOG(CameraSensor, Error)
 			<< "Failed to retrieve camera info controls";
@@ -1095,7 +1100,7 @@ const ControlInfoMap &CameraSensorRaw::c
 	return subdev_->controls();
 }
 
-ControlList CameraSensorRaw::getControls(const std::vector<uint32_t> &ids)
+ControlList CameraSensorRaw::getControls(Span<const uint32_t> ids)
 {
 	return subdev_->getControls(ids);
 }
diff -pruN 0.5.0-1/src/libcamera/software_isp/TODO 0.6.0-2/src/libcamera/software_isp/TODO
--- 0.5.0-1/src/libcamera/software_isp/TODO	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/software_isp/TODO	2025-11-27 11:55:28.000000000 +0000
@@ -71,42 +71,6 @@ per-frame buffers like we do for hardwar
 
 ---
 
-6. Input buffer copying configuration
-
-> DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
-> 	: stats_(std::move(stats)), gammaCorrection_(1.0)
-> {
-> 	enableInputMemcpy_ = true;
-
-Set this appropriately and/or make it configurable.
-
----
-
-7. Performance measurement configuration
-
-> void DebayerCpu::process(FrameBuffer *input, FrameBuffer *output, DebayerParams params)
-> /* Measure before emitting signals */
-> if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
->     ++measuredFrames_ > DebayerCpu::kFramesToSkip) {
-> 	timespec frameEndTime = {};
-> 	clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);
-> 	frameProcessTime_ += timeDiff(frameEndTime, frameStartTime);
-> 	if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) {
-> 		const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure -
-> 						    DebayerCpu::kFramesToSkip;
-> 		LOG(Debayer, Info)
-> 			<< "Processed " << measuredFrames
-> 			<< " frames in " << frameProcessTime_ / 1000 << "us, "
-> 			<< frameProcessTime_ / (1000 * measuredFrames)
-> 			<< " us/frame";
-> 	}
-> }
-
-I wonder if there would be a way to control at runtime when/how to
-perform those measurements. Maybe that's a bit overkill.
-
----
-
 8. DebayerCpu cleanups
 
 > >> class DebayerCpu : public Debayer, public Object
diff -pruN 0.5.0-1/src/libcamera/software_isp/debayer_cpu.cpp 0.6.0-2/src/libcamera/software_isp/debayer_cpu.cpp
--- 0.5.0-1/src/libcamera/software_isp/debayer_cpu.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/software_isp/debayer_cpu.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -24,6 +24,7 @@
 #include "libcamera/internal/bayer_format.h"
 #include "libcamera/internal/dma_buf_allocator.h"
 #include "libcamera/internal/framebuffer.h"
+#include "libcamera/internal/global_configuration.h"
 #include "libcamera/internal/mapped_framebuffer.h"
 
 namespace libcamera {
@@ -38,8 +39,9 @@ namespace libcamera {
 /**
  * \brief Constructs a DebayerCpu object
  * \param[in] stats Pointer to the stats object to use
+ * \param[in] configuration The global configuration
  */
-DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats)
+DebayerCpu::DebayerCpu(std::unique_ptr<SwStatsCpu> stats, const GlobalConfiguration &configuration)
 	: stats_(std::move(stats))
 {
 	/*
@@ -49,8 +51,19 @@ DebayerCpu::DebayerCpu(std::unique_ptr<S
 	 * enable_input_memcpy_ makes this behavior configurable.  At the moment, we
 	 * always set it to true as the safer choice but this should be changed in
 	 * future.
+	 *
+	 * \todo Make memcpy automatic based on runtime detection of platform
+	 * capabilities.
 	 */
-	enableInputMemcpy_ = true;
+	enableInputMemcpy_ =
+		configuration.option<bool>({ "software_isp", "copy_input_buffer" }).value_or(true);
+
+	skipBeforeMeasure_ = configuration.option<unsigned int>(
+						  { "software_isp", "measure", "skip" })
+				     .value_or(skipBeforeMeasure_);
+	framesToMeasure_ = configuration.option<unsigned int>(
+						{ "software_isp", "measure", "number" })
+				   .value_or(framesToMeasure_);
 
 	/* Initialize color lookup tables */
 	for (unsigned int i = 0; i < DebayerParams::kRGBLookupSize; i++) {
@@ -541,7 +554,11 @@ int DebayerCpu::configure(const StreamCo
 	window_.width = outputCfg.size.width;
 	window_.height = outputCfg.size.height;
 
-	/* Don't pass x,y since process() already adjusts src before passing it */
+	/*
+	 * Set the stats window to the whole processed window. Its coordinates are
+	 * relative to the debayered area since debayering passes only the part of
+	 * data to be processed to the stats; see SwStatsCpu::setWindow.
+	 */
 	stats_->setWindow(Rectangle(window_.size()));
 
 	/* pad with patternSize.Width on both left and right side */
@@ -554,7 +571,7 @@ int DebayerCpu::configure(const StreamCo
 			lineBuffers_[i].resize(lineBufferLength_);
 	}
 
-	measuredFrames_ = 0;
+	encounteredFrames_ = 0;
 	frameProcessTime_ = 0;
 
 	return 0;
@@ -642,9 +659,9 @@ void DebayerCpu::memcpyNextLine(const ui
 	lineBufferIndex_ = (lineBufferIndex_ + 1) % (patternHeight + 1);
 }
 
-void DebayerCpu::process2(const uint8_t *src, uint8_t *dst)
+void DebayerCpu::process2(uint32_t frame, const uint8_t *src, uint8_t *dst)
 {
-	unsigned int yEnd = window_.y + window_.height;
+	unsigned int yEnd = window_.height;
 	/* Holds [0] previous- [1] current- [2] next-line */
 	const uint8_t *linePointers[3];
 
@@ -659,16 +676,19 @@ void DebayerCpu::process2(const uint8_t
 		/* window_.y == 0, use the next line as prev line */
 		linePointers[1] = src + inputConfig_.stride;
 		linePointers[2] = src;
-		/* Last 2 lines also need special handling */
+		/*
+		 * Last 2 lines also need special handling.
+		 * (And configure() ensures that yEnd >= 2.)
+		 */
 		yEnd -= 2;
 	}
 
 	setupInputMemcpy(linePointers);
 
-	for (unsigned int y = window_.y; y < yEnd; y += 2) {
+	for (unsigned int y = 0; y < yEnd; y += 2) {
 		shiftLinePointers(linePointers, src);
 		memcpyNextLine(linePointers);
-		stats_->processLine0(y, linePointers);
+		stats_->processLine0(frame, y, linePointers);
 		(this->*debayer0_)(dst, linePointers);
 		src += inputConfig_.stride;
 		dst += outputConfig_.stride;
@@ -683,7 +703,7 @@ void DebayerCpu::process2(const uint8_t
 	if (window_.y == 0) {
 		shiftLinePointers(linePointers, src);
 		memcpyNextLine(linePointers);
-		stats_->processLine0(yEnd, linePointers);
+		stats_->processLine0(frame, yEnd, linePointers);
 		(this->*debayer0_)(dst, linePointers);
 		src += inputConfig_.stride;
 		dst += outputConfig_.stride;
@@ -697,9 +717,8 @@ void DebayerCpu::process2(const uint8_t
 	}
 }
 
-void DebayerCpu::process4(const uint8_t *src, uint8_t *dst)
+void DebayerCpu::process4(uint32_t frame, const uint8_t *src, uint8_t *dst)
 {
-	const unsigned int yEnd = window_.y + window_.height;
 	/*
 	 * This holds pointers to [0] 2-lines-up [1] 1-line-up [2] current-line
 	 * [3] 1-line-down [4] 2-lines-down.
@@ -717,10 +736,10 @@ void DebayerCpu::process4(const uint8_t
 
 	setupInputMemcpy(linePointers);
 
-	for (unsigned int y = window_.y; y < yEnd; y += 4) {
+	for (unsigned int y = 0; y < window_.height; y += 4) {
 		shiftLinePointers(linePointers, src);
 		memcpyNextLine(linePointers);
-		stats_->processLine0(y, linePointers);
+		stats_->processLine0(frame, y, linePointers);
 		(this->*debayer0_)(dst, linePointers);
 		src += inputConfig_.stride;
 		dst += outputConfig_.stride;
@@ -733,7 +752,7 @@ void DebayerCpu::process4(const uint8_t
 
 		shiftLinePointers(linePointers, src);
 		memcpyNextLine(linePointers);
-		stats_->processLine2(y, linePointers);
+		stats_->processLine2(frame, y, linePointers);
 		(this->*debayer2_)(dst, linePointers);
 		src += inputConfig_.stride;
 		dst += outputConfig_.stride;
@@ -760,7 +779,10 @@ void DebayerCpu::process(uint32_t frame,
 {
 	timespec frameStartTime;
 
-	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure) {
+	bool measure = framesToMeasure_ > 0 &&
+		       encounteredFrames_ < skipBeforeMeasure_ + framesToMeasure_ &&
+		       ++encounteredFrames_ > skipBeforeMeasure_;
+	if (measure) {
 		frameStartTime = {};
 		clock_gettime(CLOCK_MONOTONIC_RAW, &frameStartTime);
 	}
@@ -781,6 +803,7 @@ void DebayerCpu::process(uint32_t frame,
 		blueCcm_ = params.redCcm;
 		for (unsigned int i = 0; i < 256; i++) {
 			std::swap(redCcm_[i].r, redCcm_[i].b);
+			std::swap(greenCcm_[i].r, greenCcm_[i].b);
 			std::swap(blueCcm_[i].r, blueCcm_[i].b);
 		}
 	} else {
@@ -805,30 +828,27 @@ void DebayerCpu::process(uint32_t frame,
 		return;
 	}
 
-	stats_->startFrame();
+	stats_->startFrame(frame);
 
 	if (inputConfig_.patternSize.height == 2)
-		process2(in.planes()[0].data(), out.planes()[0].data());
+		process2(frame, in.planes()[0].data(), out.planes()[0].data());
 	else
-		process4(in.planes()[0].data(), out.planes()[0].data());
+		process4(frame, in.planes()[0].data(), out.planes()[0].data());
 
 	metadata.planes()[0].bytesused = out.planes()[0].size();
 
 	dmaSyncers.clear();
 
 	/* Measure before emitting signals */
-	if (measuredFrames_ < DebayerCpu::kLastFrameToMeasure &&
-	    ++measuredFrames_ > DebayerCpu::kFramesToSkip) {
+	if (measure) {
 		timespec frameEndTime = {};
 		clock_gettime(CLOCK_MONOTONIC_RAW, &frameEndTime);
 		frameProcessTime_ += timeDiff(frameEndTime, frameStartTime);
-		if (measuredFrames_ == DebayerCpu::kLastFrameToMeasure) {
-			const unsigned int measuredFrames = DebayerCpu::kLastFrameToMeasure -
-							    DebayerCpu::kFramesToSkip;
+		if (encounteredFrames_ == skipBeforeMeasure_ + framesToMeasure_) {
 			LOG(Debayer, Info)
-				<< "Processed " << measuredFrames
+				<< "Processed " << framesToMeasure_
 				<< " frames in " << frameProcessTime_ / 1000 << "us, "
-				<< frameProcessTime_ / (1000 * measuredFrames)
+				<< frameProcessTime_ / (1000 * framesToMeasure_)
 				<< " us/frame";
 		}
 	}
diff -pruN 0.5.0-1/src/libcamera/software_isp/debayer_cpu.h 0.6.0-2/src/libcamera/software_isp/debayer_cpu.h
--- 0.5.0-1/src/libcamera/software_isp/debayer_cpu.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/software_isp/debayer_cpu.h	2025-11-27 11:55:28.000000000 +0000
@@ -18,6 +18,7 @@
 #include <libcamera/base/object.h>
 
 #include "libcamera/internal/bayer_format.h"
+#include "libcamera/internal/global_configuration.h"
 
 #include "debayer.h"
 #include "swstats_cpu.h"
@@ -27,7 +28,7 @@ namespace libcamera {
 class DebayerCpu : public Debayer, public Object
 {
 public:
-	DebayerCpu(std::unique_ptr<SwStatsCpu> stats);
+	DebayerCpu(std::unique_ptr<SwStatsCpu> stats, const GlobalConfiguration &configuration);
 	~DebayerCpu();
 
 	int configure(const StreamConfiguration &inputCfg,
@@ -132,8 +133,8 @@ private:
 	void setupInputMemcpy(const uint8_t *linePointers[]);
 	void shiftLinePointers(const uint8_t *linePointers[], const uint8_t *src);
 	void memcpyNextLine(const uint8_t *linePointers[]);
-	void process2(const uint8_t *src, uint8_t *dst);
-	void process4(const uint8_t *src, uint8_t *dst);
+	void process2(uint32_t frame, const uint8_t *src, uint8_t *dst);
+	void process4(uint32_t frame, const uint8_t *src, uint8_t *dst);
 
 	/* Max. supported Bayer pattern height is 4, debayering this requires 5 lines */
 	static constexpr unsigned int kMaxLineBuffers = 5;
@@ -160,11 +161,10 @@ private:
 	unsigned int xShift_; /* Offset of 0/1 applied to window_.x */
 	bool enableInputMemcpy_;
 	bool swapRedBlueGains_;
-	unsigned int measuredFrames_;
+	unsigned int encounteredFrames_;
 	int64_t frameProcessTime_;
-	/* Skip 30 frames for things to stabilize then measure 30 frames */
-	static constexpr unsigned int kFramesToSkip = 30;
-	static constexpr unsigned int kLastFrameToMeasure = 60;
+	unsigned int skipBeforeMeasure_ = 30;
+	unsigned int framesToMeasure_ = 30;
 };
 
 } /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/software_isp/software_isp.cpp 0.6.0-2/src/libcamera/software_isp/software_isp.cpp
--- 0.5.0-1/src/libcamera/software_isp/software_isp.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/software_isp/software_isp.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -75,7 +75,8 @@ LOG_DEFINE_CATEGORY(SoftwareIsp)
  */
 SoftwareIsp::SoftwareIsp(PipelineHandler *pipe, const CameraSensor *sensor,
 			 ControlInfoMap *ipaControls)
-	: dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
+	: ispWorkerThread_("SWIspWorker"),
+	  dmaHeap_(DmaBufAllocator::DmaBufAllocatorFlag::CmaHeap |
 		   DmaBufAllocator::DmaBufAllocatorFlag::SystemHeap |
 		   DmaBufAllocator::DmaBufAllocatorFlag::UDmaBuf)
 {
@@ -114,7 +115,8 @@ SoftwareIsp::SoftwareIsp(PipelineHandler
 	}
 	stats->statsReady.connect(this, &SoftwareIsp::statsReady);
 
-	debayer_ = std::make_unique<DebayerCpu>(std::move(stats));
+	const GlobalConfiguration &configuration = pipe->cameraManager()->_d()->configuration();
+	debayer_ = std::make_unique<DebayerCpu>(std::move(stats), configuration);
 	debayer_->inputBufferReady.connect(this, &SoftwareIsp::inputReady);
 	debayer_->outputBufferReady.connect(this, &SoftwareIsp::outputReady);
 
@@ -357,6 +359,7 @@ void SoftwareIsp::stop()
 {
 	ispWorkerThread_.exit();
 	ispWorkerThread_.wait();
+	ispWorkerThread_.removeMessages(debayer_.get());
 
 	Thread::current()->dispatchMessages(Message::Type::InvokeMessage, this);
 
diff -pruN 0.5.0-1/src/libcamera/software_isp/swstats_cpu.cpp 0.6.0-2/src/libcamera/software_isp/swstats_cpu.cpp
--- 0.5.0-1/src/libcamera/software_isp/swstats_cpu.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/software_isp/swstats_cpu.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -62,8 +62,9 @@ namespace libcamera {
  */
 
 /**
- * \fn void SwStatsCpu::processLine0(unsigned int y, const uint8_t *src[])
+ * \fn void SwStatsCpu::processLine0(uint32_t frame, unsigned int y, const uint8_t *src[])
  * \brief Process line 0
+ * \param[in] frame The frame number
  * \param[in] y The y coordinate.
  * \param[in] src The input data.
  *
@@ -74,8 +75,9 @@ namespace libcamera {
  */
 
 /**
- * \fn void SwStatsCpu::processLine2(unsigned int y, const uint8_t *src[])
+ * \fn void SwStatsCpu::processLine2(uint32_t frame, unsigned int y, const uint8_t *src[])
  * \brief Process line 2 and 3
+ * \param[in] frame The frame number
  * \param[in] y The y coordinate.
  * \param[in] src The input data.
  *
@@ -90,6 +92,11 @@ namespace libcamera {
  */
 
 /**
+ * \var SwStatsCpu::kStatPerNumFrames
+ * \brief Run stats once every kStatPerNumFrames frames
+ */
+
+/**
  * \typedef SwStatsCpu::statsProcessFn
  * \brief Called when there is data to get statistics from
  * \param[in] src The input data
@@ -175,7 +182,7 @@ void SwStatsCpu::statsBGGR8Line0(const u
 		std::swap(src0, src1);
 
 	/* x += 4 sample every other 2x2 block */
-	for (int x = 0; x < (int)window_.width; x += 4) {
+	for (unsigned int x = 0; x < window_.width; x += 4) {
 		b = src0[x];
 		g = src0[x + 1];
 		g2 = src1[x];
@@ -200,7 +207,7 @@ void SwStatsCpu::statsBGGR10Line0(const
 		std::swap(src0, src1);
 
 	/* x += 4 sample every other 2x2 block */
-	for (int x = 0; x < (int)window_.width; x += 4) {
+	for (unsigned int x = 0; x < window_.width; x += 4) {
 		b = src0[x];
 		g = src0[x + 1];
 		g2 = src1[x];
@@ -226,7 +233,7 @@ void SwStatsCpu::statsBGGR12Line0(const
 		std::swap(src0, src1);
 
 	/* x += 4 sample every other 2x2 block */
-	for (int x = 0; x < (int)window_.width; x += 4) {
+	for (unsigned int x = 0; x < window_.width; x += 4) {
 		b = src0[x];
 		g = src0[x + 1];
 		g2 = src1[x];
@@ -245,7 +252,7 @@ void SwStatsCpu::statsBGGR10PLine0(const
 {
 	const uint8_t *src0 = src[1] + window_.x * 5 / 4;
 	const uint8_t *src1 = src[2] + window_.x * 5 / 4;
-	const int widthInBytes = window_.width * 5 / 4;
+	const unsigned int widthInBytes = window_.width * 5 / 4;
 
 	if (swapLines_)
 		std::swap(src0, src1);
@@ -253,7 +260,7 @@ void SwStatsCpu::statsBGGR10PLine0(const
 	SWSTATS_START_LINE_STATS(uint8_t)
 
 	/* x += 5 sample every other 2x2 block */
-	for (int x = 0; x < widthInBytes; x += 5) {
+	for (unsigned int x = 0; x < widthInBytes; x += 5) {
 		/* BGGR */
 		b = src0[x];
 		g = src0[x + 1];
@@ -271,7 +278,7 @@ void SwStatsCpu::statsGBRG10PLine0(const
 {
 	const uint8_t *src0 = src[1] + window_.x * 5 / 4;
 	const uint8_t *src1 = src[2] + window_.x * 5 / 4;
-	const int widthInBytes = window_.width * 5 / 4;
+	const unsigned int widthInBytes = window_.width * 5 / 4;
 
 	if (swapLines_)
 		std::swap(src0, src1);
@@ -279,7 +286,7 @@ void SwStatsCpu::statsGBRG10PLine0(const
 	SWSTATS_START_LINE_STATS(uint8_t)
 
 	/* x += 5 sample every other 2x2 block */
-	for (int x = 0; x < widthInBytes; x += 5) {
+	for (unsigned int x = 0; x < widthInBytes; x += 5) {
 		/* GBRG */
 		g = src0[x];
 		b = src0[x + 1];
@@ -295,11 +302,15 @@ void SwStatsCpu::statsGBRG10PLine0(const
 
 /**
  * \brief Reset state to start statistics gathering for a new frame
+ * \param[in] frame The frame number
  *
  * This may only be called after a successful setWindow() call.
  */
-void SwStatsCpu::startFrame(void)
+void SwStatsCpu::startFrame(uint32_t frame)
 {
+	if (frame % kStatPerNumFrames)
+		return;
+
 	if (window_.width == 0)
 		LOG(SwStatsCpu, Error) << "Calling startFrame() without setWindow()";
 
@@ -318,6 +329,7 @@ void SwStatsCpu::startFrame(void)
  */
 void SwStatsCpu::finishFrame(uint32_t frame, uint32_t bufferId)
 {
+	stats_.valid = frame % kStatPerNumFrames == 0;
 	*sharedStats_ = stats_;
 	statsReady.emit(frame, bufferId);
 }
@@ -416,9 +428,33 @@ int SwStatsCpu::configure(const StreamCo
 /**
  * \brief Specify window coordinates over which to gather statistics
  * \param[in] window The window object.
+ *
+ * This method specifies the image area over which to gather the statistics.
+ * It must be called to set the area, otherwise the default zero-sized
+ * \a Rectangle is used and no statistics is gathered.
+ *
+ * The specified \a window is relative to what is passed to the processLine*
+ * methods. For example, if statistics are to be gathered from the entire
+ * processed area, then \a window should be a rectangle with the top-left corner
+ * of (0,0) and the same size as the processed area. If only a part of the
+ * processed area (e.g. its centre) is to be considered for statistics, then
+ * \a window should specify such a restriction accordingly.
+ *
+ * It is the responsibility of the callers to provide sensible \a window values,
+ * most notably not exceeding the original image boundaries. This means, among
+ * other, that neither coordinate of the top-left corner shall be negative.
+ *
+ * Due to limitations of the implementation, the method may adjust the window
+ * slightly if it is not aligned according to the bayer pattern determined in
+ * \a SwStatsCpu::configure(). In that case the window will be modified such that
+ * the sides are no larger than the original, and that the new bottom-left
+ * corner will be no further from (0,0) (along either axis) than the original
+ * was.
  */
 void SwStatsCpu::setWindow(const Rectangle &window)
 {
+	ASSERT(window.x >= 0 && window.y >= 0);
+
 	window_ = window;
 
 	window_.x &= ~(patternSize_.width - 1);
@@ -426,7 +462,7 @@ void SwStatsCpu::setWindow(const Rectang
 	window_.y &= ~(patternSize_.height - 1);
 
 	/* width_ - xShift_ to make sure the window fits */
-	window_.width -= xShift_;
+	window_.width = (window_.width > xShift_ ? window_.width - xShift_ : 0);
 	window_.width &= ~(patternSize_.width - 1);
 	window_.height &= ~(patternSize_.height - 1);
 }
diff -pruN 0.5.0-1/src/libcamera/software_isp/swstats_cpu.h 0.6.0-2/src/libcamera/software_isp/swstats_cpu.h
--- 0.5.0-1/src/libcamera/software_isp/swstats_cpu.h	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/software_isp/swstats_cpu.h	2025-11-27 11:55:28.000000000 +0000
@@ -32,6 +32,14 @@ public:
 	SwStatsCpu();
 	~SwStatsCpu() = default;
 
+	/*
+	 * The combination of pipeline + sensor delays means that
+	 * exposure changes can take up to 3 frames to get applied,
+	 * Run stats once every 4 frames to ensure any previous
+	 * exposure changes have been applied.
+	 */
+	static constexpr uint32_t kStatPerNumFrames = 4;
+
 	bool isValid() const { return sharedStats_.fd().isValid(); }
 
 	const SharedFD &getStatsFD() { return sharedStats_.fd(); }
@@ -40,11 +48,14 @@ public:
 
 	int configure(const StreamConfiguration &inputCfg);
 	void setWindow(const Rectangle &window);
-	void startFrame();
+	void startFrame(uint32_t frame);
 	void finishFrame(uint32_t frame, uint32_t bufferId);
 
-	void processLine0(unsigned int y, const uint8_t *src[])
+	void processLine0(uint32_t frame, unsigned int y, const uint8_t *src[])
 	{
+		if (frame % kStatPerNumFrames)
+			return;
+
 		if ((y & ySkipMask_) || y < static_cast<unsigned int>(window_.y) ||
 		    y >= (window_.y + window_.height))
 			return;
@@ -52,8 +63,11 @@ public:
 		(this->*stats0_)(src);
 	}
 
-	void processLine2(unsigned int y, const uint8_t *src[])
+	void processLine2(uint32_t frame, unsigned int y, const uint8_t *src[])
 	{
+		if (frame % kStatPerNumFrames)
+			return;
+
 		if ((y & ySkipMask_) || y < static_cast<unsigned int>(window_.y) ||
 		    y >= (window_.y + window_.height))
 			return;
diff -pruN 0.5.0-1/src/libcamera/stream.cpp 0.6.0-2/src/libcamera/stream.cpp
--- 0.5.0-1/src/libcamera/stream.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/stream.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -407,7 +407,8 @@ std::string StreamConfiguration::toStrin
  */
 std::ostream &operator<<(std::ostream &out, const StreamConfiguration &cfg)
 {
-	out << cfg.size << "-" << cfg.pixelFormat;
+	out << cfg.size << "-" << cfg.pixelFormat << "/"
+	    << ColorSpace::toString(cfg.colorSpace);
 	return out;
 }
 
diff -pruN 0.5.0-1/src/libcamera/v4l2_device.cpp 0.6.0-2/src/libcamera/v4l2_device.cpp
--- 0.5.0-1/src/libcamera/v4l2_device.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/v4l2_device.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -162,6 +162,7 @@ void V4L2Device::close()
 /**
  * \brief Read controls from the device
  * \param[in] ids The list of controls to read, specified by their ID
+ * \param[in] request An optional request
  *
  * This function reads the value of all controls contained in \a ids, and
  * returns their values as a ControlList.
@@ -171,10 +172,12 @@ void V4L2Device::close()
  * during validation of the requested controls, no control is read and this
  * function returns an empty control list.
  *
+ * If \a request is specified the controls tied to that request are read.
+ *
  * \return The control values in a ControlList on success, or an empty list on
  * error
  */
-ControlList V4L2Device::getControls(const std::vector<uint32_t> &ids)
+ControlList V4L2Device::getControls(Span<const uint32_t> ids, const V4L2Request *request)
 {
 	if (ids.empty())
 		return {};
@@ -242,10 +245,16 @@ ControlList V4L2Device::getControls(cons
 	}
 
 	struct v4l2_ext_controls v4l2ExtCtrls = {};
-	v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL;
 	v4l2ExtCtrls.controls = v4l2Ctrls.data();
 	v4l2ExtCtrls.count = v4l2Ctrls.size();
 
+	if (request) {
+		v4l2ExtCtrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
+		v4l2ExtCtrls.request_fd = request->fd();
+	} else {
+		v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL;
+	}
+
 	int ret = ioctl(VIDIOC_G_EXT_CTRLS, &v4l2ExtCtrls);
 	if (ret) {
 		unsigned int errorIdx = v4l2ExtCtrls.error_idx;
@@ -273,6 +282,7 @@ ControlList V4L2Device::getControls(cons
 /**
  * \brief Write controls to the device
  * \param[in] ctrls The list of controls to write
+ * \param[in] request An optional request
  *
  * This function writes the value of all controls contained in \a ctrls, and
  * stores the values actually applied to the device in the corresponding
@@ -288,11 +298,16 @@ ControlList V4L2Device::getControls(cons
  * are written and their values are updated in \a ctrls, while all other
  * controls are not written and their values are not changed.
  *
+ * If \a request is set, the controls will be applied to that request. If the
+ * device doesn't support requests, -EACCESS will be returned. If \a request is
+ * invalid, -EINVAL will be returned.
+ *
  * \return 0 on success or an error code otherwise
- * \retval -EINVAL One of the control is not supported or not accessible
+ * \retval -EINVAL One of the controls is not supported or not accessible
+ * \retval -EACCESS The device does not support requests
  * \retval i The index of the control that failed
  */
-int V4L2Device::setControls(ControlList *ctrls)
+int V4L2Device::setControls(ControlList *ctrls, const V4L2Request *request)
 {
 	if (ctrls->empty())
 		return 0;
@@ -377,10 +392,16 @@ int V4L2Device::setControls(ControlList
 	}
 
 	struct v4l2_ext_controls v4l2ExtCtrls = {};
-	v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL;
 	v4l2ExtCtrls.controls = v4l2Ctrls.data();
 	v4l2ExtCtrls.count = v4l2Ctrls.size();
 
+	if (request) {
+		v4l2ExtCtrls.which = V4L2_CTRL_WHICH_REQUEST_VAL;
+		v4l2ExtCtrls.request_fd = request->fd();
+	} else {
+		v4l2ExtCtrls.which = V4L2_CTRL_WHICH_CUR_VAL;
+	}
+
 	int ret = ioctl(VIDIOC_S_EXT_CTRLS, &v4l2ExtCtrls);
 	if (ret) {
 		unsigned int errorIdx = v4l2ExtCtrls.error_idx;
diff -pruN 0.5.0-1/src/libcamera/v4l2_request.cpp 0.6.0-2/src/libcamera/v4l2_request.cpp
--- 0.5.0-1/src/libcamera/v4l2_request.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/src/libcamera/v4l2_request.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+/*
+ * Copyright (C) 2025, Ideas On Board
+ *
+ * V4L2 Request
+ */
+
+#include "libcamera/internal/v4l2_request.h"
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+#include <linux/media.h>
+
+#include <libcamera/base/event_notifier.h>
+#include <libcamera/base/log.h>
+
+/**
+ * \file v4l2_request.h
+ * \brief V4L2 Request
+ */
+
+namespace libcamera {
+
+LOG_DECLARE_CATEGORY(V4L2)
+
+/**
+ * \class V4L2Request
+ * \brief V4L2Request object and API
+ *
+ * The V4L2Request class wraps a V4L2 request fd and provides some convenience
+ * functions to handle request.
+ *
+ * It is usually constructed by calling \a MediaDevice::allocateRequests().
+ *
+ * A request can then be passed to the V4L2Device::setControls(),
+ * V4L2Device::getControls() and V4L2VideoDevice::queueBuffer().
+ */
+
+/**
+ * \brief Construct a V4L2Request
+ * \param[in] fd The request fd
+ */
+V4L2Request::V4L2Request(UniqueFD &&fd)
+	: fd_(std::move(fd)), fdNotifier_(fd_.get(), EventNotifier::Exception)
+{
+	if (!fd_.isValid())
+		return;
+
+	fdNotifier_.activated.connect(this, &V4L2Request::requestReady);
+	fdNotifier_.setEnabled(false);
+}
+
+/**
+ * \fn V4L2Request::isValid()
+ * \brief Check if the request is valid
+ *
+ * Checks if the underlying fd is valid.
+ *
+ * \return True if the request is valid, false otherwise
+ */
+
+/**
+ * \fn V4L2Request::fd()
+ * \brief Get the file descriptor
+ *
+ * \return The file descriptor wrapped by this V4L2Request
+ */
+
+/**
+ * \var V4L2Request::requestDone
+ * \brief Signal that is emitted when the request is done
+ */
+
+/**
+ * \brief Reinit the request
+ *
+ * Calls MEDIA_REQUEST_IOC_REINIT on the request fd.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int V4L2Request::reinit()
+{
+	fdNotifier_.setEnabled(false);
+
+	if (::ioctl(fd_.get(), MEDIA_REQUEST_IOC_REINIT) < 0)
+		return -errno;
+
+	return 0;
+}
+
+/**
+ * \brief Queue the request
+ *
+ * Calls MEDIA_REQUEST_IOC_QUEUE on the request fd.
+ *
+ * \return 0 on success or a negative error code otherwise
+ */
+int V4L2Request::queue()
+{
+	if (::ioctl(fd_.get(), MEDIA_REQUEST_IOC_QUEUE) < 0)
+		return -errno;
+
+	fdNotifier_.setEnabled(true);
+
+	return 0;
+}
+
+std::string V4L2Request::logPrefix() const
+{
+	return "Request [" + std::to_string(fd()) + "]";
+}
+
+/**
+ * \brief Slot to handle request done events
+ *
+ * When this slot is called, the request is done and the requestDone will be
+ * emitted.
+ */
+void V4L2Request::requestReady()
+{
+	requestDone.emit(this);
+}
+
+} /* namespace libcamera */
diff -pruN 0.5.0-1/src/libcamera/v4l2_subdevice.cpp 0.6.0-2/src/libcamera/v4l2_subdevice.cpp
--- 0.5.0-1/src/libcamera/v4l2_subdevice.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/v4l2_subdevice.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -923,7 +923,7 @@ const MediaBusFormatInfo &MediaBusFormat
  * \brief Assemble and return a string describing the format
  * \return A string describing the V4L2SubdeviceFormat
  */
-const std::string V4L2SubdeviceFormat::toString() const
+std::string V4L2SubdeviceFormat::toString() const
 {
 	std::stringstream ss;
 	ss << *this;
@@ -949,6 +949,8 @@ std::ostream &operator<<(std::ostream &o
 	else
 		out << it->second.name;
 
+	out << "/" << ColorSpace::toString(f.colorSpace);
+
 	return out;
 }
 
diff -pruN 0.5.0-1/src/libcamera/v4l2_videodevice.cpp 0.6.0-2/src/libcamera/v4l2_videodevice.cpp
--- 0.5.0-1/src/libcamera/v4l2_videodevice.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/v4l2_videodevice.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -30,6 +30,7 @@
 #include "libcamera/internal/framebuffer.h"
 #include "libcamera/internal/media_device.h"
 #include "libcamera/internal/media_object.h"
+#include "libcamera/internal/v4l2_request.h"
 
 /**
  * \file v4l2_videodevice.h
@@ -288,7 +289,7 @@ V4L2BufferCache::Entry::Entry(bool free,
 
 bool V4L2BufferCache::Entry::operator==(const FrameBuffer &buffer) const
 {
-	const std::vector<FrameBuffer::Plane> &planes = buffer.planes();
+	Span<const FrameBuffer::Plane> planes = buffer.planes();
 
 	if (planes_.size() != planes.size())
 		return false;
@@ -429,7 +430,7 @@ bool V4L2BufferCache::Entry::operator==(
  * \brief Assemble and return a string describing the format
  * \return A string describing the V4L2DeviceFormat
  */
-const std::string V4L2DeviceFormat::toString() const
+std::string V4L2DeviceFormat::toString() const
 {
 	std::stringstream ss;
 	ss << *this;
@@ -446,7 +447,8 @@ const std::string V4L2DeviceFormat::toSt
  */
 std::ostream &operator<<(std::ostream &out, const V4L2DeviceFormat &f)
 {
-	out << f.size << "-" << f.fourcc;
+	out << f.size << "-" << f.fourcc << "/"
+	    << ColorSpace::toString(f.colorSpace);
 	return out;
 }
 
@@ -1326,7 +1328,8 @@ int V4L2VideoDevice::requestBuffers(unsi
 
 	if (rb.count < count) {
 		LOG(V4L2, Error)
-			<< "Not enough buffers provided by V4L2VideoDevice";
+			<< "Not enough buffers provided by V4L2VideoDevice. Wanted "
+			<< count << ", got " << rb.count;
 		requestBuffers(0, memoryType);
 		return -ENOMEM;
 	}
@@ -1627,6 +1630,7 @@ int V4L2VideoDevice::releaseBuffers()
 /**
  * \brief Queue a buffer to the video device
  * \param[in] buffer The buffer to be queued
+ * \param[in] request An optional request
  *
  * For capture video devices the \a buffer will be filled with data by the
  * device. For output video devices the \a buffer shall contain valid data and
@@ -1639,9 +1643,11 @@ int V4L2VideoDevice::releaseBuffers()
  * Note that queueBuffer() will fail if the device is in the process of being
  * stopped from a streaming state through streamOff().
  *
+ * If \a request is specified, the buffer will be tied to that request.
+ *
  * \return 0 on success or a negative error code otherwise
  */
-int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer)
+int V4L2VideoDevice::queueBuffer(FrameBuffer *buffer, const V4L2Request *request)
 {
 	struct v4l2_plane v4l2Planes[VIDEO_MAX_PLANES] = {};
 	struct v4l2_buffer buf = {};
@@ -1666,13 +1672,19 @@ int V4L2VideoDevice::queueBuffer(FrameBu
 	if (ret < 0)
 		return ret;
 
+	auto guard = utils::scope_exit{ [&]() { cache_->put(buf.index); } };
+
 	buf.index = ret;
 	buf.type = bufferType_;
 	buf.memory = memoryType_;
 	buf.field = V4L2_FIELD_NONE;
+	if (request) {
+		buf.flags = V4L2_BUF_FLAG_REQUEST_FD;
+		buf.request_fd = request->fd();
+	}
 
 	bool multiPlanar = V4L2_TYPE_IS_MULTIPLANAR(buf.type);
-	const std::vector<FrameBuffer::Plane> &planes = buffer->planes();
+	Span<const FrameBuffer::Plane> planes = buffer->planes();
 	const unsigned int numV4l2Planes = format_.planesCount;
 
 	/*
@@ -1788,6 +1800,7 @@ int V4L2VideoDevice::queueBuffer(FrameBu
 
 	queuedBuffers_[buf.index] = buffer;
 
+	guard.release();
 	return 0;
 }
 
@@ -1904,9 +1917,10 @@ FrameBuffer *V4L2VideoDevice::dequeueBuf
 	}
 	metadata.sequence -= firstFrame_.value();
 
+	Span<const FrameBuffer::Plane> framebufferPlanes = buffer->planes();
 	unsigned int numV4l2Planes = multiPlanar ? buf.length : 1;
 
-	if (numV4l2Planes != buffer->planes().size()) {
+	if (numV4l2Planes != framebufferPlanes.size()) {
 		/*
 		 * If we have a multi-planar buffer with a V4L2
 		 * single-planar format, split the V4L2 buffer across
@@ -1916,7 +1930,7 @@ FrameBuffer *V4L2VideoDevice::dequeueBuf
 		if (numV4l2Planes != 1) {
 			LOG(V4L2, Error)
 				<< "Invalid number of planes (" << numV4l2Planes
-				<< " != " << buffer->planes().size() << ")";
+				<< " != " << framebufferPlanes.size() << ")";
 
 			metadata.status = FrameMetadata::FrameError;
 			return buffer;
@@ -1933,12 +1947,12 @@ FrameBuffer *V4L2VideoDevice::dequeueBuf
 				       : buf.bytesused;
 		unsigned int remaining = bytesused;
 
-		for (auto [i, plane] : utils::enumerate(buffer->planes())) {
+		for (auto [i, plane] : utils::enumerate(framebufferPlanes)) {
 			if (!remaining) {
 				LOG(V4L2, Error)
 					<< "Dequeued buffer (" << bytesused
 					<< " bytes) too small for plane lengths "
-					<< utils::join(buffer->planes(), "/",
+					<< utils::join(framebufferPlanes, "/",
 						       [](const FrameBuffer::Plane &p) {
 							       return p.length;
 						       });
@@ -2030,10 +2044,9 @@ int V4L2VideoDevice::streamOff()
 	/* Send back all queued buffers. */
 	for (auto it : queuedBuffers_) {
 		FrameBuffer *buffer = it.second;
-		FrameMetadata &metadata = buffer->_d()->metadata();
 
 		cache_->put(it.first);
-		metadata.status = FrameMetadata::FrameCancelled;
+		buffer->_d()->cancel();
 		bufferReady.emit(buffer);
 	}
 
diff -pruN 0.5.0-1/src/libcamera/vector.cpp 0.6.0-2/src/libcamera/vector.cpp
--- 0.5.0-1/src/libcamera/vector.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/libcamera/vector.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -45,6 +45,14 @@ LOG_DEFINE_CATEGORY(Vector)
  */
 
 /**
+ * \fn Vector::Vector(const Span<const T, Rows> data)
+ * \brief Construct vector from supplied data
+ * \param data Data from which to construct a vector
+ *
+ * The size of \a data must be equal to the dimension size Rows of the vector.
+ */
+
+/**
  * \fn T Vector::operator[](size_t i) const
  * \brief Index to an element in the vector
  * \param i Index of element to retrieve
@@ -300,9 +308,10 @@ LOG_DEFINE_CATEGORY(Vector)
  */
 
 /**
- * \fn Vector<T, Rows> operator*(const Matrix<T, Rows, Cols> &m, const Vector<T, Cols> &v)
+ * \fn operator*(const Matrix<T, Rows, Cols> &m, const Vector<U, Cols> &v)
  * \brief Multiply a matrix by a vector
- * \tparam T Numerical type of the contents of the matrix and vector
+ * \tparam T Numerical type of the contents of the matrix
+ * \tparam U Numerical type of the contents of the vector
  * \tparam Rows The number of rows in the matrix
  * \tparam Cols The number of columns in the matrix (= rows in the vector)
  * \param m The matrix
diff -pruN 0.5.0-1/src/meson.build 0.6.0-2/src/meson.build
--- 0.5.0-1/src/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -55,7 +55,21 @@ if (pipelines.contains('virtual') or get
          '-Wno-unused-parameter')
     libyuv_vars.append_link_args('-ljpeg')
     libyuv = cmake.subproject('libyuv', options : libyuv_vars)
-    libyuv_dep = libyuv.dependency('yuv')
+
+    # Meson fails to apply the -fPIC flag to static libraries produced by CMake
+    # that wraps other static libraries without adding any source file, despite
+    # setting CMAKE_POSITION_INDEPENDENT_CODE to ON. See
+    # https://github.com/mesonbuild/meson/issues/10764.
+    #
+    # Work around the issue by wrapping the libyuv static library into another
+    # static library with 'pic' set to true.
+    libyuv_static = static_library('libyuv-static',
+                                   dependencies : libyuv.dependency('yuv'),
+                                   pic : true,
+                                   install : false)
+    libyuv_include = libyuv.include_directories('yuv')
+    libyuv_dep = declare_dependency(link_with : libyuv_static,
+                                    include_directories : libyuv_include)
 endif
 
 # libcamera must be built first as a dependency to the other components.
diff -pruN 0.5.0-1/src/py/libcamera/gen-py-controls.py 0.6.0-2/src/py/libcamera/gen-py-controls.py
--- 0.5.0-1/src/py/libcamera/gen-py-controls.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/py/libcamera/gen-py-controls.py	2025-11-27 11:55:28.000000000 +0000
@@ -60,11 +60,13 @@ def main(argv):
     parser = argparse.ArgumentParser()
     parser.add_argument('--mode', '-m', type=str, required=True,
                         help='Mode is either "controls" or "properties"')
-    parser.add_argument('--output', '-o', metavar='file', type=str,
+    parser.add_argument('--output', '-o', metavar='file', default=sys.stdout,
+                        type=argparse.FileType('w', encoding='utf-8'),
                         help='Output file name. Defaults to standard output if not specified.')
-    parser.add_argument('--template', '-t', type=str, required=True,
+    parser.add_argument('--template', '-t', required=True,
+                        type=argparse.FileType('r', encoding='utf-8'),
                         help='Template file name.')
-    parser.add_argument('input', type=str, nargs='+',
+    parser.add_argument('input', type=argparse.FileType('rb'), nargs='+',
                         help='Input file name.')
     args = parser.parse_args(argv[1:])
 
@@ -76,7 +78,7 @@ def main(argv):
     vendors = []
 
     for input in args.input:
-        data = yaml.safe_load(open(input, 'rb').read())
+        data = yaml.safe_load(input)
 
         vendor = data['vendor']
         if vendor != 'libcamera':
@@ -94,15 +96,10 @@ def main(argv):
     }
 
     env = jinja2.Environment()
-    template = env.from_string(open(args.template, 'r', encoding='utf-8').read())
+    template = env.from_string(args.template.read())
     string = template.render(data)
 
-    if args.output:
-        output = open(args.output, 'w', encoding='utf-8')
-        output.write(string)
-        output.close()
-    else:
-        sys.stdout.write(string)
+    args.output.write(string)
 
     return 0
 
diff -pruN 0.5.0-1/src/py/libcamera/gen-py-formats.py 0.6.0-2/src/py/libcamera/gen-py-formats.py
--- 0.5.0-1/src/py/libcamera/gen-py-formats.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/py/libcamera/gen-py-formats.py	2025-11-27 11:55:28.000000000 +0000
@@ -19,35 +19,23 @@ def generate(formats):
     return {'formats': '\n'.join(fmts)}
 
 
-def fill_template(template, data):
-    with open(template, encoding='utf-8') as f:
-        template = f.read()
-
-    template = string.Template(template)
-    return template.substitute(data)
-
-
 def main(argv):
     parser = argparse.ArgumentParser()
-    parser.add_argument('-o', dest='output', metavar='file', type=str,
+    parser.add_argument('-o', dest='output', metavar='file', default=sys.stdout,
+                        type=argparse.FileType('w', encoding='utf-8'),
                         help='Output file name. Defaults to standard output if not specified.')
-    parser.add_argument('input', type=str,
+    parser.add_argument('input', type=argparse.FileType('rb'),
                         help='Input file name.')
-    parser.add_argument('template', type=str,
+    parser.add_argument('template', type=argparse.FileType('r', encoding='utf-8'),
                         help='Template file name.')
     args = parser.parse_args(argv[1:])
 
-    with open(args.input, encoding='utf-8') as f:
-        formats = yaml.safe_load(f)['formats']
+    formats = yaml.safe_load(args.input)['formats']
 
     data = generate(formats)
-    data = fill_template(args.template, data)
+    data = string.Template(args.template.read()).substitute(data)
 
-    if args.output:
-        with open(args.output, 'w', encoding='utf-8') as f:
-            f.write(data)
-    else:
-        sys.stdout.write(data)
+    args.output.write(data)
 
     return 0
 
diff -pruN 0.5.0-1/src/py/libcamera/meson.build 0.6.0-2/src/py/libcamera/meson.build
--- 0.5.0-1/src/py/libcamera/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/py/libcamera/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -1,21 +1,5 @@
 # SPDX-License-Identifier: CC0-1.0
 
-py3_dep = dependency('python3', required : get_option('pycamera'))
-
-if not py3_dep.found()
-    pycamera_enabled = false
-    subdir_done()
-endif
-
-pybind11_dep = dependency('pybind11', required : get_option('pycamera'))
-
-if not pybind11_dep.found()
-    pycamera_enabled = false
-    subdir_done()
-endif
-
-pycamera_enabled = true
-
 pycamera_sources = files([
     'py_camera_manager.cpp',
     'py_color_space.cpp',
@@ -36,6 +20,7 @@ pycamera_sources += custom_target('py_ge
                                   output : ['py_controls_generated.cpp'],
                                   command : [gen_py_controls, '--mode', 'controls', '-o', '@OUTPUT@',
                                              '-t', gen_py_controls_template, '@INPUT@'],
+                                  depend_files : [py_mod_controls],
                                   env : py_build_env)
 
 pycamera_sources += custom_target('py_gen_properties',
@@ -43,6 +28,7 @@ pycamera_sources += custom_target('py_ge
                                   output : ['py_properties_generated.cpp'],
                                   command : [gen_py_controls, '--mode', 'properties', '-o', '@OUTPUT@',
                                              '-t', gen_py_controls_template, '@INPUT@'],
+                                  depend_files : [py_mod_controls],
                                   env : py_build_env)
 
 # Generate formats
@@ -61,7 +47,7 @@ pycamera_sources += custom_target('py_ge
 
 pycamera_deps = [
     libcamera_private,
-    py3_dep,
+    py3.dependency(),
     pybind11_dep,
 ]
 
@@ -71,16 +57,33 @@ pycamera_args = [
     '-DPYBIND11_USE_SMART_HOLDER_AS_DEFAULT',
 ]
 
-destdir = get_option('libdir') / ('python' + py3_dep.version()) / 'site-packages' / 'libcamera'
+if meson.is_cross_build()
+    # Meson doesn't correctly support cross-compilation through the python
+    # module. There's work in progress to fix this, based on PEP 739
+    # (https://github.com/mesonbuild/meson/pull/14657). While waiting for this
+    # to become available, work around the issue by using shared_module().
+    destdir = py3.get_install_dir(subdir : 'libcamera', pure : false)
+
+    pycamera = shared_module('_libcamera',
+                             pycamera_sources,
+                             install : true,
+                             install_dir : destdir,
+                             install_tag : 'python-runtime',
+                             name_prefix : '',
+                             dependencies : pycamera_deps,
+                             cpp_args : pycamera_args)
+else
+    pycamera = py3.extension_module('_libcamera',
+                                    pycamera_sources,
+                                    install : true,
+                                    subdir : 'libcamera',
+                                    dependencies : pycamera_deps,
+                                    cpp_args : pycamera_args)
+endif
 
-pycamera = shared_module('_libcamera',
-                         pycamera_sources,
-                         install : true,
-                         install_dir : destdir,
-                         install_tag : 'python-runtime',
-                         name_prefix : '',
-                         dependencies : pycamera_deps,
-                         cpp_args : pycamera_args)
+py3.install_sources(['__init__.py'],
+                    subdir : 'libcamera',
+                    pure : false)
 
 # Create symlinks from the build dir to the source dir so that we can use the
 # Python module directly from the build dir.
@@ -93,10 +96,6 @@ run_command('ln', '-fsrT', meson.current
             meson.current_build_dir() / 'utils',
             check : true)
 
-install_data(['__init__.py'],
-             install_dir : destdir,
-             install_tag : 'python-runtime')
-
 # \todo Generate stubs when building. See https://peps.python.org/pep-0484/#stub-files
 # Note: Depends on pybind11-stubgen. To generate pylibcamera stubs:
 # $ PYTHONPATH=build/src/py pybind11-stubgen --no-setup-py -o build/src/py libcamera
diff -pruN 0.5.0-1/src/py/libcamera/py_helpers.cpp 0.6.0-2/src/py/libcamera/py_helpers.cpp
--- 0.5.0-1/src/py/libcamera/py_helpers.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/py/libcamera/py_helpers.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -47,7 +47,7 @@ py::object controlValueToPy(const Contro
 	case ControlTypeFloat:
 		return valueOrTuple<float>(cv);
 	case ControlTypeString:
-		return py::cast(cv.get<std::string>());
+		return py::cast(cv.get<std::string_view>());
 	case ControlTypeSize: {
 		const Size *v = reinterpret_cast<const Size *>(cv.data().data());
 		return py::cast(v);
@@ -88,7 +88,7 @@ ControlValue pyToControlValue(const py::
 	case ControlTypeFloat:
 		return controlValueMaybeArray<float>(ob);
 	case ControlTypeString:
-		return ControlValue(ob.cast<std::string>());
+		return ControlValue(ob.cast<std::string_view>());
 	case ControlTypeRectangle:
 		return controlValueMaybeArray<Rectangle>(ob);
 	case ControlTypeSize:
diff -pruN 0.5.0-1/src/py/libcamera/py_main.cpp 0.6.0-2/src/py/libcamera/py_main.cpp
--- 0.5.0-1/src/py/libcamera/py_main.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/py/libcamera/py_main.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -372,7 +372,13 @@ PYBIND11_MODULE(_libcamera, m)
 		.def(py::init<std::vector<FrameBuffer::Plane>, unsigned int>(),
 		     py::arg("planes"), py::arg("cookie") = 0)
 		.def_property_readonly("metadata", &FrameBuffer::metadata, py::return_value_policy::reference_internal)
-		.def_property_readonly("planes", &FrameBuffer::planes)
+		.def_property_readonly("planes", [](const FrameBuffer &self) {
+			/* Convert from Span<> to std::vector<> */
+			/* Note: this creates copies */
+			auto planes = self.planes();
+			std::vector<FrameBuffer::Plane> v(planes.begin(), planes.end());
+			return v;
+		})
 		.def_property("cookie", &FrameBuffer::cookie, &FrameBuffer::setCookie);
 
 	pyFrameBufferPlane
@@ -495,7 +501,8 @@ PYBIND11_MODULE(_libcamera, m)
 		.def_property_readonly("planes", [](const FrameMetadata &self) {
 			/* Convert from Span<> to std::vector<> */
 			/* Note: this creates a copy */
-			std::vector<FrameMetadata::Plane> v(self.planes().begin(), self.planes().end());
+			auto planes = self.planes();
+			std::vector<FrameMetadata::Plane> v(planes.begin(), planes.end());
 			return v;
 		});
 
diff -pruN 0.5.0-1/src/py/meson.build 0.6.0-2/src/py/meson.build
--- 0.5.0-1/src/py/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/src/py/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -1,3 +1,16 @@
 # SPDX-License-Identifier: CC0-1.0
 
+py_mod = import('python')
+py3 = py_mod.find_installation('python3', required : get_option('pycamera'))
+pybind11_dep = dependency('pybind11', required : get_option('pycamera'))
+
+pycamera_enabled = py3.found() and pybind11_dep.found()
+if not pycamera_enabled
+    subdir_done()
+endif
+
 subdir('libcamera')
+
+pycamera_devenv = environment()
+pycamera_devenv.prepend('PYTHONPATH', meson.current_build_dir())
+meson.add_devenv(pycamera_devenv)
diff -pruN 0.5.0-1/subprojects/.gitignore 0.6.0-2/subprojects/.gitignore
--- 0.5.0-1/subprojects/.gitignore	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/subprojects/.gitignore	2025-11-27 11:55:28.000000000 +0000
@@ -2,6 +2,6 @@
 
 /googletest-release*
 /libpisp
-/libyaml
 /libyuv
 /packagecache
+/yaml-0.2.5
diff -pruN 0.5.0-1/subprojects/libpisp.wrap 0.6.0-2/subprojects/libpisp.wrap
--- 0.5.0-1/subprojects/libpisp.wrap	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/subprojects/libpisp.wrap	2025-11-27 11:55:28.000000000 +0000
@@ -2,5 +2,5 @@
 
 [wrap-git]
 url = https://github.com/raspberrypi/libpisp.git
-revision = v1.2.0
+revision = v1.3.0
 depth = 1
diff -pruN 0.5.0-1/subprojects/libyaml.wrap 0.6.0-2/subprojects/libyaml.wrap
--- 0.5.0-1/subprojects/libyaml.wrap	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/subprojects/libyaml.wrap	2025-11-27 11:55:28.000000000 +0000
@@ -1,7 +1,13 @@
 # SPDX-License-Identifier: CC0-1.0
 
-[wrap-git]
-directory = libyaml
-url = https://github.com/yaml/libyaml
-# tags/0.2.5
-revision = 2c891fc7a770e8ba2fec34fc6b545c672beb37e6
+[wrap-file]
+directory = yaml-0.2.5
+source_url = https://pyyaml.org/download/libyaml/yaml-0.2.5.tar.gz
+source_filename = yaml-0.2.5.tar.gz
+source_hash = c642ae9b75fee120b2d96c712538bd2cf283228d2337df2cf2988e3c02678ef4
+patch_filename = libyaml_0.2.5-1_patch.zip
+patch_url = https://wrapdb.mesonbuild.com/v2/libyaml_0.2.5-1/get_patch
+patch_hash = bf2e9b922be00b6b00c5fce29d9fb8dc83f0431c77239f3b73e8b254d3f3f5b5
+
+[provide]
+yaml-0.1 = yaml_dep
diff -pruN 0.5.0-1/subprojects/libyuv.wrap 0.6.0-2/subprojects/libyuv.wrap
--- 0.5.0-1/subprojects/libyuv.wrap	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/subprojects/libyuv.wrap	2025-11-27 11:55:28.000000000 +0000
@@ -3,4 +3,5 @@
 [wrap-git]
 directory = libyuv
 url = https://chromium.googlesource.com/libyuv/libyuv.git
-revision = 93b1b332cd60b56ab90aea14182755e379c28a80
+revision = 500f45652c459cfccd20f83f297eb66cb7b015cb
+diff_files = libyuv/0004-CMakeLists.txt-Do-not-enable-NEON-for-armel-armhf.patch
diff -pruN 0.5.0-1/subprojects/packagefiles/libyuv/0004-CMakeLists.txt-Do-not-enable-NEON-for-armel-armhf.patch 0.6.0-2/subprojects/packagefiles/libyuv/0004-CMakeLists.txt-Do-not-enable-NEON-for-armel-armhf.patch
--- 0.5.0-1/subprojects/packagefiles/libyuv/0004-CMakeLists.txt-Do-not-enable-NEON-for-armel-armhf.patch	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/subprojects/packagefiles/libyuv/0004-CMakeLists.txt-Do-not-enable-NEON-for-armel-armhf.patch	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,42 @@
+From: Boyuan Yang <byang@debian.org>
+Date: Fri, 8 Nov 2024 08:07:01 -0500
+Subject: CMakeLists.txt: Do not enable NEON for armel armhf
+
+According to https://wiki.debian.org/ArchitectureSpecificsMemo#armel
+the armhf architecture does not guarantee NEON. Do not enable NEON
+on armhf. Also disable NEON for armel to prevent FTBFS
+---
+ CMakeLists.txt | 19 ++++++++++---------
+ 1 file changed, 10 insertions(+), 9 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index bf8be36..783c3d4 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -95,16 +95,17 @@ endif()
+ if(NOT MSVC)
+   string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" arch_lowercase)
+ 
++# Debian-specific: Do not enable Arm Neon kernels on non-arm64 architectures.
+   if(arch_lowercase MATCHES "^arm" AND NOT arch_lowercase STREQUAL "arm64")
+-    # Enable Arm Neon kernels.
+-    add_definitions(-DLIBYUV_NEON=1)
+-    add_library(${ly_lib_name}_neon OBJECT
+-      ${ly_src_dir}/compare_neon.cc
+-      ${ly_src_dir}/rotate_neon.cc
+-      ${ly_src_dir}/row_neon.cc
+-      ${ly_src_dir}/scale_neon.cc)
+-    target_compile_options(${ly_lib_name}_neon PRIVATE -mfpu=neon)
+-    list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_neon>)
++    message("Debian-specific: Not enabling NEON on ${arch_lowercase}.")
++#    add_definitions(-DLIBYUV_NEON=1)
++#    add_library(${ly_lib_name}_neon OBJECT
++#      ${ly_src_dir}/compare_neon.cc
++#      ${ly_src_dir}/rotate_neon.cc
++#      ${ly_src_dir}/row_neon.cc
++#      ${ly_src_dir}/scale_neon.cc)
++#    target_compile_options(${ly_lib_name}_neon PRIVATE -mfpu=neon)
++#    list(APPEND ly_lib_parts $<TARGET_OBJECTS:${ly_lib_name}_neon>)
+   endif()
+ 
+   if(arch_lowercase STREQUAL "aarch64" OR arch_lowercase STREQUAL "arm64")
diff -pruN 0.5.0-1/test/camera/buffer_import.cpp 0.6.0-2/test/camera/buffer_import.cpp
--- 0.5.0-1/test/camera/buffer_import.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/camera/buffer_import.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -52,16 +52,9 @@ protected:
 		if (request->status() != Request::RequestComplete)
 			return;
 
-		const Request::BufferMap &buffers = request->buffers();
-
 		completeRequestsCount_++;
 
-		/* Create a new request. */
-		const Stream *stream = buffers.begin()->first;
-		FrameBuffer *buffer = buffers.begin()->second;
-
-		request->reuse();
-		request->addBuffer(stream, buffer);
+		request->reuse(Request::ReuseBuffers);
 		camera_->queueRequest(request);
 
 		dispatcher_->interrupt();
diff -pruN 0.5.0-1/test/camera/camera_reconfigure.cpp 0.6.0-2/test/camera/camera_reconfigure.cpp
--- 0.5.0-1/test/camera/camera_reconfigure.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/camera/camera_reconfigure.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -46,14 +46,8 @@ private:
 		if (request->status() != Request::RequestComplete)
 			return;
 
-		const Request::BufferMap &buffers = request->buffers();
-
-		const Stream *stream = buffers.begin()->first;
-		FrameBuffer *buffer = buffers.begin()->second;
-
 		/* Reuse the request and re-queue it with the same buffers. */
-		request->reuse();
-		request->addBuffer(stream, buffer);
+		request->reuse(Request::ReuseBuffers);
 		camera_->queueRequest(request);
 	}
 
diff -pruN 0.5.0-1/test/camera/capture.cpp 0.6.0-2/test/camera/capture.cpp
--- 0.5.0-1/test/camera/capture.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/camera/capture.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -48,16 +48,9 @@ protected:
 		if (request->status() != Request::RequestComplete)
 			return;
 
-		const Request::BufferMap &buffers = request->buffers();
-
 		completeRequestsCount_++;
 
-		/* Create a new request. */
-		const Stream *stream = buffers.begin()->first;
-		FrameBuffer *buffer = buffers.begin()->second;
-
-		request->reuse();
-		request->addBuffer(stream, buffer);
+		request->reuse(Request::ReuseBuffers);
 		camera_->queueRequest(request);
 
 		dispatcher_->interrupt();
diff -pruN 0.5.0-1/test/camera-sensor.cpp 0.6.0-2/test/camera-sensor.cpp
--- 0.5.0-1/test/camera-sensor.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/camera-sensor.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -96,10 +96,13 @@ protected:
 		}
 
 		/* Use an invalid format and make sure it's not selected. */
-		V4L2SubdeviceFormat format = sensor_->getFormat({ 0xdeadbeef,
-								  MEDIA_BUS_FMT_SBGGR10_1X10,
-								  MEDIA_BUS_FMT_BGR888_1X24 },
-								Size(1024, 768));
+		static constexpr uint32_t mbusCodes[] = {
+			0xdeadbeef,
+			MEDIA_BUS_FMT_SBGGR10_1X10,
+			MEDIA_BUS_FMT_BGR888_1X24,
+		};
+
+		V4L2SubdeviceFormat format = sensor_->getFormat(mbusCodes, Size(1024, 768));
 		if (format.code != MEDIA_BUS_FMT_SBGGR10_1X10 ||
 		    format.size != Size(4096, 2160)) {
 			cerr << "Failed to get a suitable format, expected 4096x2160-0x"
diff -pruN 0.5.0-1/test/controls/control_info.cpp 0.6.0-2/test/controls/control_info.cpp
--- 0.5.0-1/test/controls/control_info.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/controls/control_info.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -50,7 +50,7 @@ protected:
 		 * Test information retrieval from a control with boolean
 		 * values.
 		 */
-		ControlInfo aeEnable({ false, true }, false);
+		ControlInfo aeEnable(false, true, false);
 
 		if (aeEnable.min().get<bool>() != false ||
 		    aeEnable.def().get<bool>() != false ||
@@ -59,13 +59,12 @@ protected:
 			return TestFail;
 		}
 
-		if (aeEnable.values()[0].get<bool>() != false ||
-		    aeEnable.values()[1].get<bool>() != true) {
+		if (!aeEnable.values().empty()) {
 			cout << "Invalid control values for AeEnable" << endl;
 			return TestFail;
 		}
 
-		ControlInfo awbEnable(true);
+		ControlInfo awbEnable(true, true, true);
 
 		if (awbEnable.min().get<bool>() != true ||
 		    awbEnable.def().get<bool>() != true ||
@@ -74,7 +73,7 @@ protected:
 			return TestFail;
 		}
 
-		if (awbEnable.values()[0].get<bool>() != true) {
+		if (!awbEnable.values().empty()) {
 			cout << "Invalid control values for AwbEnable" << endl;
 			return TestFail;
 		}
diff -pruN 0.5.0-1/test/controls/control_value.cpp 0.6.0-2/test/controls/control_value.cpp
--- 0.5.0-1/test/controls/control_value.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/controls/control_value.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -318,7 +318,7 @@ protected:
 		/*
 		 * String type.
 		 */
-		std::string string{ "libcamera" };
+		std::string_view string{ "libcamera" };
 		value.set(string);
 		if (value.isNone() || !value.isArray() ||
 		    value.type() != ControlTypeString ||
@@ -327,7 +327,7 @@ protected:
 			return TestFail;
 		}
 
-		if (value.get<std::string>() != string) {
+		if (value.get<std::string_view>() != string) {
 			cerr << "Control value mismatch after setting to string" << endl;
 			return TestFail;
 		}
diff -pruN 0.5.0-1/test/geometry.cpp 0.6.0-2/test/geometry.cpp
--- 0.5.0-1/test/geometry.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/geometry.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -203,6 +203,11 @@ protected:
 			return TestFail;
 		}
 
+		if (Size(200, 50).transpose() != Size(50, 200)) {
+			cout << "Size::transpose() test failed" << endl;
+			return TestFail;
+		}
+
 		/* Aspect ratio tests */
 		if (Size(0, 0).boundedToAspectRatio(Size(4, 3)) != Size(0, 0) ||
 		    Size(1920, 1440).boundedToAspectRatio(Size(16, 9)) != Size(1920, 1080) ||
diff -pruN 0.5.0-1/test/gstreamer/gstreamer_memory_lifetime_test.cpp 0.6.0-2/test/gstreamer/gstreamer_memory_lifetime_test.cpp
--- 0.5.0-1/test/gstreamer/gstreamer_memory_lifetime_test.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/gstreamer/gstreamer_memory_lifetime_test.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2024, Nicolas Dufresne
  *
- * gstreamer_memory_lifetime_test.cpp - GStreamer memory lifetime test
+ * GStreamer memory lifetime test
  */
 
 #include <iostream>
diff -pruN 0.5.0-1/test/ipa/libipa/meson.build 0.6.0-2/test/ipa/libipa/meson.build
--- 0.5.0-1/test/ipa/libipa/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/ipa/libipa/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -4,6 +4,7 @@ libipa_test = [
     {'name': 'fixedpoint', 'sources': ['fixedpoint.cpp']},
     {'name': 'histogram', 'sources': ['histogram.cpp']},
     {'name': 'interpolator', 'sources': ['interpolator.cpp']},
+    {'name': 'pwl', 'sources': ['pwl.cpp'] },
 ]
 
 foreach test : libipa_test
diff -pruN 0.5.0-1/test/ipa/libipa/pwl.cpp 0.6.0-2/test/ipa/libipa/pwl.cpp
--- 0.5.0-1/test/ipa/libipa/pwl.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/test/ipa/libipa/pwl.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2025, Ideas on Board Oy
+ *
+ * PWL tests
+ */
+
+#include "../src/ipa/libipa/pwl.h"
+
+#include <cmath>
+#include <iostream>
+#include <map>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "test.h"
+
+using namespace std;
+using namespace libcamera;
+using namespace ipa;
+
+#define ASSERT_EQ(a, b)                                                 \
+	if ((a) != (b)) {                                               \
+		std::cout << #a " != " #b " (" << a << " ," << b << ")" \
+			  << std::endl;                                 \
+		return TestFail;                                        \
+	}
+
+class PwlTest : public Test
+{
+protected:
+	int run()
+	{
+		Pwl pwl;
+		pwl.append(0, 0);
+		pwl.append(1, 1);
+
+		ASSERT_EQ(pwl.eval(-1), -1);
+		ASSERT_EQ(pwl.eval(0), 0);
+		ASSERT_EQ(pwl.eval(0.5), 0.5);
+		ASSERT_EQ(pwl.eval(1), 1);
+		ASSERT_EQ(pwl.eval(2), 2);
+
+		ASSERT_EQ(pwl.size(), 2);
+
+		/* Test degenerate PWL. */
+		pwl.clear();
+		pwl.append(1, 1);
+		ASSERT_EQ(pwl.eval(0), 1);
+		ASSERT_EQ(pwl.eval(1), 1);
+		ASSERT_EQ(pwl.eval(2), 1);
+
+		return TestPass;
+	}
+};
+
+TEST_REGISTER(PwlTest)
diff -pruN 0.5.0-1/test/ipc/unixsocket_ipc.cpp 0.6.0-2/test/ipc/unixsocket_ipc.cpp
--- 0.5.0-1/test/ipc/unixsocket_ipc.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/ipc/unixsocket_ipc.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -209,8 +209,6 @@ protected:
 	}
 
 private:
-	ProcessManager processManager_;
-
 	unique_ptr<IPCPipeUnixSocket> ipc_;
 };
 
diff -pruN 0.5.0-1/test/libtest/buffer_source.cpp 0.6.0-2/test/libtest/buffer_source.cpp
--- 0.5.0-1/test/libtest/buffer_source.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/libtest/buffer_source.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -52,7 +52,8 @@ int BufferSource::allocate(const StreamC
 		return TestSkip;
 	}
 
-	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_.get(), videoDeviceName);
+	std::unique_ptr<V4L2VideoDevice> video = V4L2VideoDevice::fromEntityName(media_.get(),
+										 videoDeviceName);
 	if (!video) {
 		std::cout << "Failed to get video device from entity "
 			  << videoDeviceName << std::endl;
diff -pruN 0.5.0-1/test/libtest/camera_test.cpp 0.6.0-2/test/libtest/camera_test.cpp
--- 0.5.0-1/test/libtest/camera_test.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/libtest/camera_test.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -15,11 +15,11 @@ using namespace std;
 
 CameraTest::CameraTest(const char *name, bool isolate)
 {
-	cm_ = new CameraManager();
-
 	if (isolate)
 		setenv("LIBCAMERA_IPA_FORCE_ISOLATION", "1", 1);
 
+	cm_ = new CameraManager();
+
 	if (cm_->start()) {
 		cerr << "Failed to start camera manager" << endl;
 		status_ = TestFail;
diff -pruN 0.5.0-1/test/log/log_api.cpp 0.6.0-2/test/log/log_api.cpp
--- 0.5.0-1/test/log/log_api.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/log/log_api.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -26,6 +26,11 @@ using namespace std;
 using namespace libcamera;
 
 LOG_DEFINE_CATEGORY(LogAPITest)
+LOG_DEFINE_CATEGORY(Cat0)
+LOG_DEFINE_CATEGORY(Cat1)
+LOG_DEFINE_CATEGORY(Cat2)
+LOG_DEFINE_CATEGORY(Cat3)
+LOG_DEFINE_CATEGORY(Cat4)
 
 class LogAPITest : public Test
 {
@@ -74,6 +79,34 @@ protected:
 		return TestPass;
 	}
 
+	int testEnvLevels()
+	{
+		setenv("LIBCAMERA_LOG_LEVELS",
+		       "Cat0:0,Cat0:9999,Cat1:INFO,Cat1:INVALID,Cat2:2,Cat2:-1,"
+		       "Cat3:ERROR,Cat3:{[]},Cat4:4,Cat4:rubbish",
+		       true);
+		logSetTarget(libcamera::LoggingTargetNone);
+
+		const std::pair<const LogCategory &, libcamera::LogSeverity> expected[] = {
+			{ _LOG_CATEGORY(Cat0)(), libcamera::LogDebug },
+			{ _LOG_CATEGORY(Cat1)(), libcamera::LogInfo },
+			{ _LOG_CATEGORY(Cat2)(), libcamera::LogWarning },
+			{ _LOG_CATEGORY(Cat3)(), libcamera::LogError },
+			{ _LOG_CATEGORY(Cat4)(), libcamera::LogFatal },
+		};
+		bool ok = true;
+
+		for (const auto &[c, s] : expected) {
+			if (c.severity() != s) {
+				ok = false;
+				cerr << "Severity of " << c.name() << " (" << c.severity() << ") "
+				     << "does not equal " << s << endl;
+			}
+		}
+
+		return ok ? TestPass : TestFail;
+	}
+
 	int testFile()
 	{
 		int fd = open("/tmp", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
@@ -135,7 +168,11 @@ protected:
 
 	int run() override
 	{
-		int ret = testFile();
+		int ret = testEnvLevels();
+		if (ret != TestPass)
+			return TestFail;
+
+		ret = testFile();
 		if (ret != TestPass)
 			return TestFail;
 
diff -pruN 0.5.0-1/test/log/log_process.cpp 0.6.0-2/test/log/log_process.cpp
--- 0.5.0-1/test/log/log_process.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/log/log_process.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -137,8 +137,6 @@ private:
 		exitCode_ = exitCode;
 	}
 
-	ProcessManager processManager_;
-
 	Process proc_;
 	Process::ExitStatus exitStatus_ = Process::NotExited;
 	string logPath_;
diff -pruN 0.5.0-1/test/log/meson.build 0.6.0-2/test/log/meson.build
--- 0.5.0-1/test/log/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/log/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -11,5 +11,6 @@ foreach test : log_test
                      link_with : test_libraries,
                      include_directories : test_includes_internal)
 
-    test(test['name'], exe, suite : 'log')
+    test(test['name'], exe, suite : 'log',
+         should_fail : test.get('should_fail', false))
 endforeach
diff -pruN 0.5.0-1/test/matrix.cpp 0.6.0-2/test/matrix.cpp
--- 0.5.0-1/test/matrix.cpp	1970-01-01 00:00:00.000000000 +0000
+++ 0.6.0-2/test/matrix.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2024, Ideas on Board Oy
+ *
+ * Matrix tests
+ */
+
+#include "libcamera/internal/matrix.h"
+
+#include <cmath>
+#include <iostream>
+
+#include "test.h"
+
+using namespace libcamera;
+
+#define ASSERT_EQ(a, b)                                                   \
+	if ((a) != (b)) {                                                 \
+		std::cout << #a " != " #b << " (line " << __LINE__ << ")" \
+			  << std::endl;                                   \
+		return TestFail;                                          \
+	}
+
+class MatrixTest : public Test
+{
+protected:
+	int run()
+	{
+		Matrix<double, 3, 3> m1;
+
+		ASSERT_EQ(m1[0][0], 0.0);
+		ASSERT_EQ(m1[0][1], 0.0);
+
+		constexpr Matrix<float, 2, 2> m2 = Matrix<float, 2, 2>().identity();
+		ASSERT_EQ(m2[0][0], 1.0);
+		ASSERT_EQ(m2[0][1], 0.0);
+		ASSERT_EQ(m2[1][0], 0.0);
+		ASSERT_EQ(m2[1][1], 1.0);
+
+		Matrix<float, 2, 2> m3{ { 2.0, 0.0, 0.0, 2.0 } };
+		Matrix<float, 2, 2> m4 = m3.inverse();
+
+		Matrix<float, 2, 2> m5 = m3 * m4;
+		ASSERT_EQ(m5[0][0], 1.0);
+		ASSERT_EQ(m5[0][1], 0.0);
+		ASSERT_EQ(m5[1][0], 0.0);
+		ASSERT_EQ(m5[1][1], 1.0);
+
+		return TestPass;
+	}
+};
+
+TEST_REGISTER(MatrixTest)
diff -pruN 0.5.0-1/test/meson.build 0.6.0-2/test/meson.build
--- 0.5.0-1/test/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -60,6 +60,7 @@ internal_tests = [
     {'name': 'file', 'sources': ['file.cpp']},
     {'name': 'flags', 'sources': ['flags.cpp']},
     {'name': 'hotplug-cameras', 'sources': ['hotplug-cameras.cpp']},
+    {'name': 'matrix', 'sources': ['matrix.cpp']},
     {'name': 'message', 'sources': ['message.cpp']},
     {'name': 'object', 'sources': ['object.cpp']},
     {'name': 'object-delete', 'sources': ['object-delete.cpp']},
diff -pruN 0.5.0-1/test/object-invoke.cpp 0.6.0-2/test/object-invoke.cpp
--- 0.5.0-1/test/object-invoke.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/object-invoke.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -58,6 +58,19 @@ public:
 		return 42;
 	}
 
+	struct MoveOnly {
+		MoveOnly() = default;
+		MoveOnly(const MoveOnly &) = delete;
+		MoveOnly &operator=(const MoveOnly &) = delete;
+		MoveOnly(MoveOnly &&) = default;
+		MoveOnly &operator=(MoveOnly &&) = default;
+	};
+
+	MoveOnly methodWithReturnMoveOnly()
+	{
+		return {};
+	}
+
 private:
 	Status status_;
 	int value_;
@@ -186,6 +199,10 @@ protected:
 			return TestFail;
 		}
 
+		/* Test invoking a method that returns type with no copy ctor/assignment. */
+		object_.invokeMethod(&InvokedObject::methodWithReturnMoveOnly,
+				     ConnectionTypeBlocking);
+
 		return TestPass;
 	}
 
diff -pruN 0.5.0-1/test/process/process_test.cpp 0.6.0-2/test/process/process_test.cpp
--- 0.5.0-1/test/process/process_test.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/process/process_test.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -5,9 +5,9 @@
  * Process test
  */
 
+#include <array>
 #include <iostream>
 #include <unistd.h>
-#include <vector>
 
 #include <libcamera/base/event_dispatcher.h>
 #include <libcamera/base/thread.h>
@@ -48,8 +48,7 @@ protected:
 		Timer timeout;
 
 		int exitCode = 42;
-		vector<std::string> args;
-		args.push_back(to_string(exitCode));
+		std::array args{ to_string(exitCode) };
 		proc_.finished.connect(this, &ProcessTest::procFinished);
 
 		/* Test that kill() on an unstarted process is safe. */
@@ -87,8 +86,6 @@ private:
 		exitCode_ = exitCode;
 	}
 
-	ProcessManager processManager_;
-
 	Process proc_;
 	enum Process::ExitStatus exitStatus_;
 	int exitCode_;
diff -pruN 0.5.0-1/test/py/meson.build 0.6.0-2/test/py/meson.build
--- 0.5.0-1/test/py/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/py/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -15,9 +15,6 @@ endif
 
 py_env = environment()
 
-pymod = import('python')
-py3 = pymod.find_installation('python3')
-
 pypathdir = meson.project_build_root() / 'src' / 'py'
 py_env.append('PYTHONPATH', pypathdir)
 
diff -pruN 0.5.0-1/test/utils.cpp 0.6.0-2/test/utils.cpp
--- 0.5.0-1/test/utils.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/utils.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -85,7 +85,7 @@ protected:
 			if (index != i || value != i + 1) {
 				cerr << "utils::enumerate(<vector>) test failed: i=" << i
 				     << ", index=" << index << ", value=" << value
-				     << std::endl;
+				     << endl;
 				return TestFail;
 			}
 
@@ -106,7 +106,7 @@ protected:
 			if (index != i || value != i) {
 				cerr << "utils::enumerate(<span>) test failed: i=" << i
 				     << ", index=" << index << ", value=" << value
-				     << std::endl;
+				     << endl;
 				return TestFail;
 			}
 
@@ -120,7 +120,7 @@ protected:
 			if (index != i || value != i * 2) {
 				cerr << "utils::enumerate(<array>) test failed: i=" << i
 				     << ", index=" << index << ", value=" << value
-				     << std::endl;
+				     << endl;
 				return TestFail;
 			}
 
@@ -138,32 +138,40 @@ protected:
 
 		exposure = 25ms + 25ms;
 		if (exposure.get<std::micro>() != 50000.0) {
-			cerr << "utils::Duration failed to return microsecond count";
+			cerr << "utils::Duration failed "
+			     << "to return microsecond count" << endl;
 			return TestFail;
 		}
 
 		exposure = 1.0s / 4;
 		if (exposure != 250ms) {
-			cerr << "utils::Duration failed scalar divide test";
+			cerr << "utils::Duration failed "
+			     << "scalar divide test" << endl;
 			return TestFail;
 		}
 
 		exposure = 5000.5us;
 		if (!exposure) {
-			cerr << "utils::Duration failed boolean test";
+			cerr << "utils::Duration failed boolean test" << endl;
 			return TestFail;
 		}
 
 		os << exposure;
 		if (os.str() != "5000.50us") {
-			cerr << "utils::Duration operator << failed";
+			cerr << "utils::Duration operator << failed" << endl;
 			return TestFail;
 		}
 
 		exposure = 100ms;
 		ratio = exposure / 25ms;
 		if (ratio != 4.0) {
-			cerr << "utils::Duration failed ratio test";
+			cerr << "utils::Duration failed ratio test" << endl;
+			return TestFail;
+		}
+
+		exposure = 100ms;
+		if ((-exposure).get<std::milli>() != -100) {
+			cerr << "utils::Duration failed negation" << endl;
 			return TestFail;
 		}
 
@@ -210,10 +218,27 @@ protected:
 		os << utils::hex(static_cast<uint64_t>(0x42), 1) << " ";
 		ref += "0x42 ";
 
+		os << utils::hex(static_cast<int8_t>(-1)) << " ";
+		ref += "0xff ";
+		os << utils::hex(static_cast<uint8_t>(-1)) << " ";
+		ref += "0xff ";
+		os << utils::hex(static_cast<int16_t>(-1)) << " ";
+		ref += "0xffff ";
+		os << utils::hex(static_cast<uint16_t>(-1)) << " ";
+		ref += "0xffff ";
+		os << utils::hex(static_cast<int32_t>(-1)) << " ";
+		ref += "0xffffffff ";
+		os << utils::hex(static_cast<uint32_t>(-1)) << " ";
+		ref += "0xffffffff ";
+		os << utils::hex(static_cast<int64_t>(-1)) << " ";
+		ref += "0xffffffffffffffff ";
+		os << utils::hex(static_cast<uint64_t>(-1)) << " ";
+		ref += "0xffffffffffffffff ";
+
 		std::string s = os.str();
 		if (s != ref) {
 			cerr << "utils::hex() test failed, expected '" << ref
-			     << "', got '" << s << "'";
+			     << "', got '" << s << "'" << endl;
 			return TestFail;
 		}
 
diff -pruN 0.5.0-1/test/v4l2_videodevice/controls.cpp 0.6.0-2/test/v4l2_videodevice/controls.cpp
--- 0.5.0-1/test/v4l2_videodevice/controls.cpp	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/test/v4l2_videodevice/controls.cpp	2025-11-27 11:55:28.000000000 +0000
@@ -60,11 +60,15 @@ protected:
 		const ControlInfo &u8 = infoMap.find(VIVID_CID_U8_4D_ARRAY)->second;
 
 		/* Test getting controls. */
-		ControlList ctrls = capture_->getControls({ V4L2_CID_BRIGHTNESS,
-							    V4L2_CID_CONTRAST,
-							    V4L2_CID_SATURATION,
-							    VIVID_CID_INTEGER64,
-							    VIVID_CID_U8_4D_ARRAY });
+		static constexpr uint32_t cids[] = {
+			V4L2_CID_BRIGHTNESS,
+			V4L2_CID_CONTRAST,
+			V4L2_CID_SATURATION,
+			VIVID_CID_INTEGER64,
+			VIVID_CID_U8_4D_ARRAY,
+		};
+
+		ControlList ctrls = capture_->getControls(cids);
 		if (ctrls.empty()) {
 			cerr << "Failed to get controls" << endl;
 			return TestFail;
diff -pruN 0.5.0-1/utils/checkstyle.py 0.6.0-2/utils/checkstyle.py
--- 0.5.0-1/utils/checkstyle.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/checkstyle.py	2025-11-27 11:55:28.000000000 +0000
@@ -541,7 +541,7 @@ class TrailersChecker(CommitChecker):
 
     known_trailers = {
         'Acked-by': email_regex,
-        'Bug': link_regex,
+        'Closes': link_regex,
         'Co-developed-by': email_regex,
         'Fixes': commit_regex,
         'Link': link_regex,
diff -pruN 0.5.0-1/utils/codegen/controls.py 0.6.0-2/utils/codegen/controls.py
--- 0.5.0-1/utils/codegen/controls.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/controls.py	2025-11-27 11:55:28.000000000 +0000
@@ -111,7 +111,7 @@ class Control(object):
         size = self.__data.get('size')
 
         if typ == 'string':
-            return 'std::string'
+            return 'std::string_view'
 
         if self.__size is None:
             return typ
diff -pruN 0.5.0-1/utils/codegen/gen-controls.py 0.6.0-2/utils/codegen/gen-controls.py
--- 0.5.0-1/utils/codegen/gen-controls.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/gen-controls.py	2025-11-27 11:55:28.000000000 +0000
@@ -44,25 +44,25 @@ def main(argv):
     parser = argparse.ArgumentParser()
     parser.add_argument('--mode', '-m', type=str, required=True, choices=['controls', 'properties'],
                         help='Mode of operation')
-    parser.add_argument('--output', '-o', metavar='file', type=str,
+    parser.add_argument('--output', '-o', metavar='file', default=sys.stdout,
+                        type=argparse.FileType('w', encoding='utf-8'),
                         help='Output file name. Defaults to standard output if not specified.')
-    parser.add_argument('--ranges', '-r', type=str, required=True,
+    parser.add_argument('--ranges', '-r', required=True, type=argparse.FileType('rb'),
                         help='Control id range reservation file.')
-    parser.add_argument('--template', '-t', dest='template', type=str, required=True,
+    parser.add_argument('--template', '-t', dest='template', required=True,
+                        type=argparse.FileType('r', encoding='utf-8'),
                         help='Template file name.')
-    parser.add_argument('input', type=str, nargs='+',
+    parser.add_argument('input', nargs='+',
+                        type=argparse.FileType('rb'),
                         help='Input file name.')
 
     args = parser.parse_args(argv[1:])
 
-    ranges = {}
-    with open(args.ranges, 'rb') as f:
-        data = open(args.ranges, 'rb').read()
-        ranges = yaml.safe_load(data)['ranges']
+    ranges = yaml.safe_load(args.ranges)['ranges']
 
     controls = {}
     for input in args.input:
-        data = yaml.safe_load(open(input, 'rb').read())
+        data = yaml.safe_load(input)
 
         vendor = data['vendor']
         if vendor not in ranges.keys():
@@ -92,15 +92,10 @@ def main(argv):
     env = jinja2.Environment()
     env.filters['format_description'] = format_description
     env.filters['snake_case'] = snake_case
-    template = env.from_string(open(args.template, 'r', encoding='utf-8').read())
+    template = env.from_string(args.template.read())
     string = template.render(data)
 
-    if args.output:
-        output = open(args.output, 'w', encoding='utf-8')
-        output.write(string)
-        output.close()
-    else:
-        sys.stdout.write(string)
+    args.output.write(string)
 
     return 0
 
diff -pruN 0.5.0-1/utils/codegen/gen-formats.py 0.6.0-2/utils/codegen/gen-formats.py
--- 0.5.0-1/utils/codegen/gen-formats.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/gen-formats.py	2025-11-27 11:55:28.000000000 +0000
@@ -7,6 +7,7 @@
 # Generate formats definitions from YAML
 
 import argparse
+import jinja2
 import re
 import string
 import sys
@@ -18,14 +19,12 @@ class DRMFourCC(object):
     mod_vendor_regex = re.compile(r"#define DRM_FORMAT_MOD_VENDOR_([A-Z0-9_]+)[ \t]+([0-9a-fA-Fx]+)")
     mod_regex = re.compile(r"#define ([A-Za-z0-9_]+)[ \t]+fourcc_mod_code\(([A-Z0-9_]+), ([0-9a-fA-Fx]+)\)")
 
-    def __init__(self, filename):
+    def __init__(self, file):
         self.formats = {}
         self.vendors = {}
         self.mods = {}
 
-        for line in open(filename, 'rb').readlines():
-            line = line.decode('utf-8')
-
+        for line in file:
             match = DRMFourCC.format_regex.match(line)
             if match:
                 format, fourcc = match.groups()
@@ -52,67 +51,54 @@ class DRMFourCC(object):
         return self.vendors[vendor], value
 
 
-def generate_h(formats, drm_fourcc):
-    template = string.Template('constexpr PixelFormat ${name}{ __fourcc(${fourcc}), __mod(${mod}) };')
-
+def generate_formats(formats, drm_fourcc):
     fmts = []
 
     for format in formats:
         name, format = format.popitem()
         fourcc = drm_fourcc.fourcc(format['fourcc'])
-        if format.get('big-endian'):
-            fourcc += '| DRM_FORMAT_BIG_ENDIAN'
 
         data = {
             'name': name,
             'fourcc': fourcc,
             'mod': '0, 0',
+            'big_endian': format.get('big_endian'),
         }
 
         mod = format.get('mod')
         if mod:
             data['mod'] = '%u, %u' % drm_fourcc.mod(mod)
 
-        fmts.append(template.substitute(data))
-
-    return {'formats': '\n'.join(fmts)}
-
-
-def fill_template(template, data):
+        fmts.append(data)
 
-    template = open(template, 'rb').read()
-    template = template.decode('utf-8')
-    template = string.Template(template)
-    return template.substitute(data)
+    return fmts
 
 
 def main(argv):
 
     # Parse command line arguments
     parser = argparse.ArgumentParser()
-    parser.add_argument('-o', dest='output', metavar='file', type=str,
+    parser.add_argument('-o', dest='output', metavar='file', default=sys.stdout,
+                        type=argparse.FileType('w', encoding='utf-8'),
                         help='Output file name. Defaults to standard output if not specified.')
-    parser.add_argument('input', type=str,
+    parser.add_argument('input', type=argparse.FileType('rb'),
                         help='Input file name.')
-    parser.add_argument('template', type=str,
+    parser.add_argument('template', type=argparse.FileType('r', encoding='utf-8'),
                         help='Template file name.')
-    parser.add_argument('drm_fourcc', type=str,
+    parser.add_argument('drm_fourcc', type=argparse.FileType('r', encoding='utf-8'),
                         help='Path to drm_fourcc.h.')
     args = parser.parse_args(argv[1:])
 
-    data = open(args.input, 'rb').read()
-    formats = yaml.safe_load(data)['formats']
+    formats = yaml.safe_load(args.input)['formats']
     drm_fourcc = DRMFourCC(args.drm_fourcc)
 
-    data = generate_h(formats, drm_fourcc)
-    data = fill_template(args.template, data)
+    env = jinja2.Environment()
+    template = env.from_string(args.template.read())
+    string = template.render({
+        'formats': generate_formats(formats, drm_fourcc),
+    })
 
-    if args.output:
-        output = open(args.output, 'wb')
-        output.write(data.encode('utf-8'))
-        output.close()
-    else:
-        sys.stdout.write(data)
+    args.output.write(string)
 
     return 0
 
diff -pruN 0.5.0-1/utils/codegen/gen-gst-controls.py 0.6.0-2/utils/codegen/gen-gst-controls.py
--- 0.5.0-1/utils/codegen/gen-gst-controls.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/gen-gst-controls.py	2025-11-27 11:55:28.000000000 +0000
@@ -138,18 +138,20 @@ def extend_control(ctrl):
 def main(argv):
     # Parse command line arguments
     parser = argparse.ArgumentParser()
-    parser.add_argument('--output', '-o', metavar='file', type=str,
+    parser.add_argument('--output', '-o', metavar='file', default=sys.stdout,
+                        type=argparse.FileType('w', encoding='utf-8'),
                         help='Output file name. Defaults to standard output if not specified.')
-    parser.add_argument('--template', '-t', dest='template', type=str, required=True,
+    parser.add_argument('--template', '-t', dest='template', required=True,
+                        type=argparse.FileType('r', encoding='utf-8'),
                         help='Template file name.')
-    parser.add_argument('input', type=str, nargs='+',
+    parser.add_argument('input', nargs='+', type=argparse.FileType('rb'),
                         help='Input file name.')
 
     args = parser.parse_args(argv[1:])
 
     controls = {}
     for input in args.input:
-        data = yaml.safe_load(open(input, 'rb').read())
+        data = yaml.safe_load(input)
 
         vendor = data['vendor']
         ctrls = controls.setdefault(vendor, [])
@@ -167,14 +169,10 @@ def main(argv):
     env.filters['indent_str'] = indent_str
     env.filters['snake_case'] = snake_case
     env.filters['kebab_case'] = kebab_case
-    template = env.from_string(open(args.template, 'r', encoding='utf-8').read())
+    template = env.from_string(args.template.read())
     string = template.render(data)
 
-    if args.output:
-        with open(args.output, 'w', encoding='utf-8') as output:
-            output.write(string)
-    else:
-        sys.stdout.write(string)
+    args.output.write(string)
 
     return 0
 
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/core_ipa_interface.h.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -16,6 +16,8 @@
 
 {% if has_map %}#include <map>{% endif %}
 {% if has_string %}#include <string>{% endif %}
+#include <type_traits>
+#include <utility>
 {% if has_array %}#include <vector>{% endif %}
 
 #include <libcamera/controls.h>
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/core_ipa_serializer.h.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/core_ipa_serializer.h.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/core_ipa_serializer.h.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/core_ipa_serializer.h.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -31,13 +31,8 @@ template<>
 class IPADataSerializer<{{struct|name}}>
 {
 public:
-{{- serializer.serializer(struct, "")}}
-{%- if struct|has_fd %}
-{{serializer.deserializer_fd(struct, "")}}
-{%- else %}
-{{serializer.deserializer_no_fd(struct, "")}}
-{{serializer.deserializer_fd_simple(struct, "")}}
-{%- endif %}
+{{- serializer.serializer(struct)}}
+{{- serializer.deserializer(struct)}}
 };
 {% endfor %}
 
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/definition_functions.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/definition_functions.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/definition_functions.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/definition_functions.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -26,31 +26,30 @@ struct {{struct.mojom_name}}
 {
 public:
 #ifndef __DOXYGEN__
-	{{struct.mojom_name}}() {%- if struct|has_default_fields %}
-		:{% endif %}
-{%- for field in struct.fields|with_default_values -%}
-{{" " if loop.first}}{{field.mojom_name}}({{field|default_value}}){{", " if not loop.last}}
-{%- endfor %}
-	{
-	}
+	{{struct.mojom_name}}() = default;
 
+	template<
+	{%- for field in struct.fields %}
+		typename T{{loop.index}} = {{field|name}},
+	{%- endfor %}
+	{%- for field in struct.fields %}
+		std::enable_if_t<std::is_convertible_v<T{{loop.index}}&&, {{field|name}}>> * = nullptr{{"," if not loop.last}}
+	{%- endfor %}
+	>
 	{{struct.mojom_name}}(
 {%- for field in struct.fields -%}
-{{"const " if not field|is_pod}}{{field|name}} {{"&" if not field|is_pod}}_{{field.mojom_name}}{{", " if not loop.last}}
+		T{{loop.index}} &&_{{field.mojom_name}}{{ ", " if not loop.last }}
 {%- endfor -%}
 )
-		:
-{%- for field in struct.fields -%}
-{{" " if loop.first}}{{field.mojom_name}}(_{{field.mojom_name}}){{", " if not loop.last}}
+{%- for field in struct.fields %}
+		{{": " if loop.first else ", "}}{{field.mojom_name}}(std::forward<T{{loop.index}}>(_{{field.mojom_name}}))
 {%- endfor %}
 	{
 	}
 #endif
 
 {% for field in struct.fields %}
-	{{field|name}} {{field.mojom_name}};
+	{{field|name}} {{field.mojom_name}}{% if field|default_value %}{ {{field|default_value}} }{% endif %};
 {%- endfor %}
 };
 {%- endmacro -%}
-
-
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_interface.h.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -16,6 +16,8 @@
 
 {% if has_map %}#include <map>{% endif %}
 {% if has_string %}#include <string>{% endif %}
+#include <type_traits>
+#include <utility>
 {% if has_array %}#include <vector>{% endif %}
 
 #include <libcamera/base/flags.h>
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.cpp.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -45,35 +45,13 @@ namespace {{ns}} {
 {% endfor %}
 {%- endif %}
 
-{{proxy_name}}::{{proxy_name}}(IPAModule *ipam, bool isolate)
-	: IPAProxy(ipam), isolate_(isolate),
-	  controlSerializer_(ControlSerializer::Role::Proxy), seq_(0)
+{{proxy_name}}Threaded::{{proxy_name}}Threaded(IPAModule *ipam, const GlobalConfiguration &configuration)
+	: {{proxy_name}}(ipam, configuration), thread_("{{proxy_name}}")
 {
 	LOG(IPAProxy, Debug)
-		<< "initializing {{module_name}} proxy: loading IPA from "
+		<< "initializing {{module_name}} proxy in thread: loading IPA from "
 		<< ipam->path();
 
-	if (isolate_) {
-		const std::string proxyWorkerPath = resolvePath("{{module_name}}_ipa_proxy");
-		if (proxyWorkerPath.empty()) {
-			LOG(IPAProxy, Error)
-				<< "Failed to get proxy worker path";
-			return;
-		}
-
-		ipc_ = std::make_unique<IPCPipeUnixSocket>(ipam->path().c_str(),
-							   proxyWorkerPath.c_str());
-		if (!ipc_->isConnected()) {
-			LOG(IPAProxy, Error) << "Failed to create IPCPipe";
-			return;
-		}
-
-		ipc_->recv.connect(this, &{{proxy_name}}::recvMessage);
-
-		valid_ = true;
-		return;
-	}
-
 	if (!ipam->load())
 		return;
 
@@ -88,59 +66,16 @@ namespace {{ns}} {
 	proxy_.setIPA(ipa_.get());
 
 {% for method in interface_event.methods %}
-	ipa_->{{method.mojom_name}}.connect(this, &{{proxy_name}}::{{method.mojom_name}}Thread);
+	ipa_->{{method.mojom_name}}.connect(this, &{{proxy_name}}Threaded::{{method.mojom_name}}Handler);
 {%- endfor %}
 
 	valid_ = true;
 }
 
-{{proxy_name}}::~{{proxy_name}}()
-{
-	if (isolate_) {
-		IPCMessage::Header header =
-			{ static_cast<uint32_t>({{cmd_enum_name}}::Exit), seq_++ };
-		IPCMessage msg(header);
-		ipc_->sendAsync(msg);
-	}
-}
-
-{% if interface_event.methods|length > 0 %}
-void {{proxy_name}}::recvMessage(const IPCMessage &data)
-{
-	size_t dataSize = data.data().size();
-	{{cmd_event_enum_name}} _cmd = static_cast<{{cmd_event_enum_name}}>(data.header().cmd);
-
-	switch (_cmd) {
-{%- for method in interface_event.methods %}
-	case {{cmd_event_enum_name}}::{{method.mojom_name|cap}}: {
-		{{method.mojom_name}}IPC(data.data().cbegin(), dataSize, data.fds());
-		break;
-	}
-{%- endfor %}
-	default:
-		LOG(IPAProxy, Error) << "Unknown command " << static_cast<uint32_t>(_cmd);
-	}
-}
-{%- endif %}
+{{proxy_name}}Threaded::~{{proxy_name}}Threaded() = default;
 
 {% for method in interface_main.methods %}
-{{proxy_funcs.func_sig(proxy_name, method)}}
-{
-	if (isolate_)
-		{{"return " if method|method_return_value != "void"}}{{method.mojom_name}}IPC(
-{%- for param in method|method_param_names -%}
-		{{param}}{{- ", " if not loop.last}}
-{%- endfor -%}
-);
-	else
-		{{"return " if method|method_return_value != "void"}}{{method.mojom_name}}Thread(
-{%- for param in method|method_param_names -%}
-		{{param}}{{- ", " if not loop.last}}
-{%- endfor -%}
-);
-}
-
-{{proxy_funcs.func_sig(proxy_name, method, "Thread")}}
+{{proxy_funcs.func_sig(proxy_name + "Threaded", method)}}
 {
 {%- if method.mojom_name == "stop" %}
 	{{proxy_funcs.stop_thread_body()}}
@@ -159,16 +94,14 @@ void {{proxy_name}}::recvMessage(const I
 	state_ = ProxyRunning;
 	thread_.start();
 
-	{{ "return " if method|method_return_value != "void" -}}
-	proxy_.invokeMethod(&ThreadProxy::start, ConnectionTypeBlocking
+	return proxy_.invokeMethod(&ThreadProxy::start, ConnectionTypeBlocking
 	{{- ", " if method|method_param_names}}
 	{%- for param in method|method_param_names -%}
 		{{param}}{{- ", " if not loop.last}}
 	{%- endfor -%}
 );
 {%- elif not method|is_async %}
-	{{ "return " if method|method_return_value != "void" -}}
-	ipa_->{{method.mojom_name}}(
+	return ipa_->{{method.mojom_name}}(
 	{%- for param in method|method_param_names -%}
 		{{param}}{{- ", " if not loop.last}}
 	{%- endfor -%}
@@ -182,8 +115,57 @@ void {{proxy_name}}::recvMessage(const I
 );
 {%- endif %}
 }
+{% endfor %}
 
-{{proxy_funcs.func_sig(proxy_name, method, "IPC")}}
+{% for method in interface_event.methods %}
+{{proxy_funcs.func_sig(proxy_name + "Threaded", method, "Handler")}}
+{
+	ASSERT(state_ != ProxyStopped);
+	{{method.mojom_name}}.emit({{method.parameters|params_comma_sep}});
+}
+{% endfor %}
+
+/* ========================================================================== */
+
+{{proxy_name}}Isolated::{{proxy_name}}Isolated(IPAModule *ipam, const GlobalConfiguration &configuration)
+	: {{proxy_name}}(ipam, configuration),
+	  controlSerializer_(ControlSerializer::Role::Proxy), seq_(0)
+{
+	LOG(IPAProxy, Debug)
+		<< "initializing {{module_name}} proxy in isolation: loading IPA from "
+		<< ipam->path();
+
+	const std::string proxyWorkerPath = resolvePath("{{module_name}}_ipa_proxy");
+	if (proxyWorkerPath.empty()) {
+		LOG(IPAProxy, Error) << "Failed to get proxy worker path";
+		return;
+	}
+
+	auto ipc = std::make_unique<IPCPipeUnixSocket>(ipam->path().c_str(),
+						       proxyWorkerPath.c_str());
+	if (!ipc->isConnected()) {
+		LOG(IPAProxy, Error) << "Failed to create IPCPipe";
+		return;
+	}
+
+	ipc->recv.connect(this, &{{proxy_name}}Isolated::recvMessage);
+
+	ipc_ = std::move(ipc);
+	valid_ = true;
+}
+
+{{proxy_name}}Isolated::~{{proxy_name}}Isolated()
+{
+	if (ipc_) {
+		IPCMessage::Header header =
+			{ static_cast<uint32_t>({{cmd_enum_name}}::Exit), seq_++ };
+		IPCMessage msg(header);
+		ipc_->sendAsync(msg);
+	}
+}
+
+{% for method in interface_main.methods %}
+{{proxy_funcs.func_sig(proxy_name + "Isolated", method)}}
 {
 {%- if method.mojom_name == "configure" %}
 	controlSerializer_.reset();
@@ -206,7 +188,7 @@ void {{proxy_name}}::recvMessage(const I
 );
 {%- endif %}
 	if (_ret < 0) {
-		LOG(IPAProxy, Error) << "Failed to call {{method.mojom_name}}";
+		LOG(IPAProxy, Error) << "Failed to call {{method.mojom_name}}: " << _ret;
 {%- if method|method_return_value != "void" %}
 		return static_cast<{{method|method_return_value}}>(_ret);
 {%- else %}
@@ -227,22 +209,30 @@ void {{proxy_name}}::recvMessage(const I
 
 {% endfor %}
 
-{% for method in interface_event.methods %}
-{{proxy_funcs.func_sig(proxy_name, method, "Thread")}}
+void {{proxy_name}}Isolated::recvMessage(const IPCMessage &data)
 {
-	ASSERT(state_ != ProxyStopped);
-	{{method.mojom_name}}.emit({{method.parameters|params_comma_sep}});
+	size_t dataSize = data.data().size();
+	{{cmd_event_enum_name}} _cmd = static_cast<{{cmd_event_enum_name}}>(data.header().cmd);
+
+	switch (_cmd) {
+{%- for method in interface_event.methods %}
+	case {{cmd_event_enum_name}}::{{method.mojom_name|cap}}: {
+		{{method.mojom_name}}Handler(data.data().cbegin(), dataSize, data.fds());
+		break;
+	}
+{%- endfor %}
+	default:
+		LOG(IPAProxy, Error) << "Unknown command " << static_cast<uint32_t>(_cmd);
+	}
 }
 
-void {{proxy_name}}::{{method.mojom_name}}IPC(
+{% for method in interface_event.methods %}
+void {{proxy_name}}Isolated::{{method.mojom_name}}Handler(
 	[[maybe_unused]] std::vector<uint8_t>::const_iterator data,
 	[[maybe_unused]] size_t dataSize,
 	[[maybe_unused]] const std::vector<SharedFD> &fds)
 {
-{%- for param in method.parameters %}
-	{{param|name}} {{param.mojom_name}};
-{%- endfor %}
-{{proxy_funcs.deserialize_call(method.parameters, 'data', 'fds', false, false, true, 'dataSize')}}
+{{proxy_funcs.deserialize_call(method.parameters, 'data', 'fds', false, true, true, 'dataSize')}}
 	{{method.mojom_name}}.emit({{method.parameters|params_comma_sep}});
 }
 {% endfor %}
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_proxy.h.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -34,38 +34,32 @@ namespace {{ns}} {
 {% endfor %}
 {%- endif %}
 
+class {{proxy_name}}Threaded;
+class {{proxy_name}}Isolated;
+
 class {{proxy_name}} : public IPAProxy, public {{interface_name}}, public Object
 {
 public:
-	{{proxy_name}}(IPAModule *ipam, bool isolate);
-	~{{proxy_name}}();
+	using Threaded = {{proxy_name}}Threaded;
+	using Isolated = {{proxy_name}}Isolated;
 
-{% for method in interface_main.methods %}
-{{proxy_funcs.func_sig(proxy_name, method, "", false, true)|indent(8, true)}};
-{% endfor %}
+protected:
+	using IPAProxy::IPAProxy;
+};
 
-{%- for method in interface_event.methods %}
-	Signal<
-{%- for param in method.parameters -%}
-		{{"const " if not param|is_pod}}{{param|name}}{{" &" if not param|is_pod and not param|is_enum}}
-		{{- ", " if not loop.last}}
-{%- endfor -%}
-> {{method.mojom_name}};
-{% endfor %}
-
-private:
-	void recvMessage(const IPCMessage &data);
+class {{proxy_name}}Threaded : public {{proxy_name}}
+{
+public:
+	{{proxy_name}}Threaded(IPAModule *ipam, const GlobalConfiguration &configuration);
+	~{{proxy_name}}Threaded();
 
 {% for method in interface_main.methods %}
-{{proxy_funcs.func_sig(proxy_name, method, "Thread", false)|indent(8, true)}};
-{{proxy_funcs.func_sig(proxy_name, method, "IPC", false)|indent(8, true)}};
+{{proxy_funcs.func_sig(proxy_name + "Threaded", method, "", false, true)|indent(8, true)}};
 {% endfor %}
+
+private:
 {% for method in interface_event.methods %}
-{{proxy_funcs.func_sig(proxy_name, method, "Thread", false)|indent(8, true)}};
-	void {{method.mojom_name}}IPC(
-		std::vector<uint8_t>::const_iterator data,
-		size_t dataSize,
-		const std::vector<SharedFD> &fds);
+{{proxy_funcs.func_sig(proxy_name + "Threaded", method, "Handler", false)|indent(8, true)}};
 {% endfor %}
 
 	/* Helper class to invoke async functions in another thread. */
@@ -88,12 +82,12 @@ private:
 		}
 {% for method in interface_main.methods %}
 {%- if method|is_async %}
-		{{proxy_funcs.func_sig(proxy_name, method, "", false)|indent(16)}}
+		{{proxy_funcs.func_sig(proxy_name + "Threaded", method, "", false)|indent(16)}}
 		{
 			ipa_->{{method.mojom_name}}({{method.parameters|params_comma_sep}});
 		}
 {%- elif method.mojom_name == "start" %}
-		{{proxy_funcs.func_sig(proxy_name, method, "", false)|indent(16)}}
+		{{proxy_funcs.func_sig(proxy_name + "Threaded", method, "", false)|indent(16)}}
 		{
 {%- if method|method_return_value != "void" %}
 			return ipa_->{{method.mojom_name}}({{method.parameters|params_comma_sep}});
@@ -113,8 +107,27 @@ private:
 	Thread thread_;
 	ThreadProxy proxy_;
 	std::unique_ptr<{{interface_name}}> ipa_;
+};
 
-	const bool isolate_;
+class {{proxy_name}}Isolated : public {{proxy_name}}
+{
+public:
+	{{proxy_name}}Isolated(IPAModule *ipam, const GlobalConfiguration &configuration);
+	~{{proxy_name}}Isolated();
+
+{% for method in interface_main.methods %}
+{{proxy_funcs.func_sig(proxy_name + "Isolated", method, "", false, true)|indent(8, true)}};
+{% endfor %}
+
+private:
+	void recvMessage(const IPCMessage &data);
+
+{% for method in interface_event.methods %}
+	void {{method.mojom_name}}Handler(
+		std::vector<uint8_t>::const_iterator data,
+		size_t dataSize,
+		const std::vector<SharedFD> &fds);
+{% endfor %}
 
 	std::unique_ptr<IPCPipeUnixSocket> ipc_;
 
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_serializer.h.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_serializer.h.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/module_ipa_serializer.h.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/module_ipa_serializer.h.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -32,13 +32,8 @@ template<>
 class IPADataSerializer<{{struct|name_full}}>
 {
 public:
-{{- serializer.serializer(struct, namespace_str)}}
-{%- if struct|has_fd %}
-{{serializer.deserializer_fd(struct, namespace_str)}}
-{%- else %}
-{{serializer.deserializer_no_fd(struct, namespace_str)}}
-{{serializer.deserializer_fd_simple(struct, namespace_str)}}
-{%- endif %}
+{{- serializer.serializer(struct)}}
+{{- serializer.deserializer(struct)}}
 };
 {% endfor %}
 
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/proxy_functions.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -52,9 +52,6 @@
  #}
 {%- macro serialize_call(params, buf, fds) %}
 {%- for param in params %}
-{%- if param|is_enum %}
-	static_assert(sizeof({{param|name_full}}) <= 4);
-{%- endif %}
 	std::vector<uint8_t> {{param.mojom_name}}Buf;
 {%- if param|has_fd %}
 	std::vector<SharedFD> {{param.mojom_name}}Fds;
@@ -62,13 +59,7 @@
 {%- else %}
 	std::tie({{param.mojom_name}}Buf, std::ignore) =
 {%- endif %}
-{%- if param|is_flags %}
 		IPADataSerializer<{{param|name_full}}>::serialize({{param.mojom_name}}
-{%- elif param|is_enum %}
-		IPADataSerializer<uint32_t>::serialize(static_cast<uint32_t>({{param.mojom_name}})
-{%- else %}
-		IPADataSerializer<{{param|name}}>::serialize({{param.mojom_name}}
-{% endif -%}
 {{- ", &controlSerializer_" if param|needs_control_serializer -}}
 );
 {%- endfor %}
@@ -107,13 +98,7 @@
  #}
 {%- macro deserialize_param(param, pointer, loop, buf, fds, iter, data_size) -%}
 {{"*" if pointer}}{{param.mojom_name}} =
-{%- if param|is_flags %}
 IPADataSerializer<{{param|name_full}}>::deserialize(
-{%- elif param|is_enum %}
-static_cast<{{param|name_full}}>(IPADataSerializer<uint32_t>::deserialize(
-{%- else %}
-IPADataSerializer<{{param|name}}>::deserialize(
-{%- endif %}
 	{{buf}}{{- ".cbegin()" if not iter}} + {{param.mojom_name}}Start,
 {%- if loop.last and not iter %}
 	{{buf}}.cend()
@@ -137,7 +122,7 @@ IPADataSerializer<{{param|name}}>::deser
 {%- if param|needs_control_serializer %}
 	&controlSerializer_
 {%- endif -%}
-){{")" if param|is_enum and not param|is_flags}};
+);
 {%- endmacro -%}
 
 
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl
--- 0.5.0-1/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/libcamera_templates/serializer.tmpl	2025-11-27 11:55:28.000000000 +0000
@@ -28,19 +28,11 @@
  #
  # \todo Avoid intermediate vectors
  #}
-{%- macro serializer_field(field, namespace, loop) %}
+{%- macro serializer_field(field, loop) %}
 {%- if field|is_pod or field|is_enum %}
 		std::vector<uint8_t> {{field.mojom_name}};
 		std::tie({{field.mojom_name}}, std::ignore) =
-	{%- if field|is_pod %}
-			IPADataSerializer<{{field|name}}>::serialize(data.{{field.mojom_name}});
-	{%- elif field|is_flags %}
 			IPADataSerializer<{{field|name_full}}>::serialize(data.{{field.mojom_name}});
-	{%- elif field|is_enum_scoped %}
-			IPADataSerializer<uint{{field|bit_width}}_t>::serialize(static_cast<uint{{field|bit_width}}_t>(data.{{field.mojom_name}}));
-	{%- elif field|is_enum %}
-			IPADataSerializer<uint{{field|bit_width}}_t>::serialize(data.{{field.mojom_name}});
-	{%- endif %}
 		retData.insert(retData.end(), {{field.mojom_name}}.begin(), {{field.mojom_name}}.end());
 {%- elif field|is_fd %}
 		std::vector<uint8_t> {{field.mojom_name}};
@@ -94,17 +86,11 @@
  # Generate code to deserialize \a field into object ret.
  # This code is meant to be used by the IPADataSerializer specialization.
  #}
-{%- macro deserializer_field(field, namespace, loop) %}
+{%- macro deserializer_field(field, loop) %}
 {% if field|is_pod or field|is_enum %}
 	{%- set field_size = (field|bit_width|int / 8)|int %}
 		{{- check_data_size(field_size, 'dataSize', field.mojom_name, 'data')}}
-		{%- if field|is_pod %}
-		ret.{{field.mojom_name}} = IPADataSerializer<{{field|name}}>::deserialize(m, m + {{field_size}});
-		{%- elif field|is_flags %}
 		ret.{{field.mojom_name}} = IPADataSerializer<{{field|name_full}}>::deserialize(m, m + {{field_size}});
-		{%- else %}
-		ret.{{field.mojom_name}} = static_cast<{{field|name_full}}>(IPADataSerializer<uint{{field|bit_width}}_t>::deserialize(m, m + {{field_size}}));
-		{%- endif %}
 	{%- if not loop.last %}
 		m += {{field_size}};
 		dataSize -= {{field_size}};
@@ -182,7 +168,7 @@
  # Generate code for IPADataSerializer specialization, for serializing
  # \a struct.
  #}
-{%- macro serializer(struct, namespace) %}
+{%- macro serializer(struct) %}
 	static std::tuple<std::vector<uint8_t>, std::vector<SharedFD>>
 	serialize(const {{struct|name_full}} &data,
 {%- if struct|needs_control_serializer %}
@@ -196,7 +182,7 @@
 		std::vector<SharedFD> retFds;
 {%- endif %}
 {%- for field in struct.fields %}
-{{serializer_field(field, namespace, loop)}}
+{{serializer_field(field, loop)}}
 {%- endfor %}
 {% if struct|has_fd %}
 		return {retData, retFds};
@@ -213,7 +199,7 @@
  # Generate code for IPADataSerializer specialization, for deserializing
  # \a struct, in the case that \a struct has file descriptors.
  #}
-{%- macro deserializer_fd(struct, namespace) %}
+{%- macro deserializer_fd(struct) %}
 	static {{struct|name_full}}
 	deserialize(std::vector<uint8_t> &data,
 		    std::vector<SharedFD> &fds,
@@ -245,7 +231,7 @@
 		size_t dataSize = std::distance(dataBegin, dataEnd);
 		[[maybe_unused]] size_t fdsSize = std::distance(fdsBegin, fdsEnd);
 {%- for field in struct.fields -%}
-{{deserializer_field(field, namespace, loop)}}
+{{deserializer_field(field, loop)}}
 {%- endfor %}
 		return ret;
 	}
@@ -258,7 +244,7 @@
  # \a struct, in the case that \a struct has no file descriptors but requires
  # deserializers with file descriptors.
  #}
-{%- macro deserializer_fd_simple(struct, namespace) %}
+{%- macro deserializer_fd_simple(struct) %}
 	static {{struct|name_full}}
 	deserialize(std::vector<uint8_t> &data,
 		    [[maybe_unused]] std::vector<SharedFD> &fds,
@@ -285,7 +271,7 @@
  # Generate code for IPADataSerializer specialization, for deserializing
  # \a struct, in the case that \a struct does not have file descriptors.
  #}
-{%- macro deserializer_no_fd(struct, namespace) %}
+{%- macro deserializer_no_fd(struct) %}
 	static {{struct|name_full}}
 	deserialize(std::vector<uint8_t> &data,
 {%- if struct|needs_control_serializer %}
@@ -312,8 +298,22 @@
 
 		size_t dataSize = std::distance(dataBegin, dataEnd);
 {%- for field in struct.fields -%}
-{{deserializer_field(field, namespace, loop)}}
+{{deserializer_field(field, loop)}}
 {%- endfor %}
 		return ret;
 	}
 {%- endmacro %}
+
+{#
+ # \brief Deserialize a struct
+ #
+ # Generate code for IPADataSerializer specialization, for deserializing \a struct.
+ #}
+{%- macro deserializer(struct) %}
+{%- if struct|has_fd %}
+{{deserializer_fd(struct)}}
+{%- else %}
+{{deserializer_no_fd(struct)}}
+{{deserializer_fd_simple(struct)}}
+{%- endif %}
+{%- endmacro %}
diff -pruN 0.5.0-1/utils/codegen/ipc/generators/mojom_libcamera_generator.py 0.6.0-2/utils/codegen/ipc/generators/mojom_libcamera_generator.py
--- 0.5.0-1/utils/codegen/ipc/generators/mojom_libcamera_generator.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/ipc/generators/mojom_libcamera_generator.py	2025-11-27 11:55:28.000000000 +0000
@@ -166,7 +166,7 @@ def MethodParamOutputs(method):
     return method.response_parameters[1:]
 
 def MethodParamsHaveFd(parameters):
-    return len([x for x in parameters if HasFd(x)]) > 0
+    return any(x for x in parameters if HasFd(x))
 
 def MethodInputHasFd(method):
     return MethodParamsHaveFd(method.parameters)
@@ -465,9 +465,9 @@ class Generator(generator.Generator):
             'cmd_event_enum_name': '_%sEventCmd' % self.module_name,
             'consts': self.module.constants,
             'enums': self.module.enums,
-            'has_array': len([x for x in self.module.kinds.keys() if x[0] == 'a']) > 0,
-            'has_map': len([x for x in self.module.kinds.keys() if x[0] == 'm']) > 0,
-            'has_string': len([x for x in self.module.kinds.keys() if x[0] == 's']) > 0,
+            'has_array': any(x for x in self.module.kinds.keys() if x[0] == 'a'),
+            'has_map': any(x for x in self.module.kinds.keys() if x[0] == 'm'),
+            'has_string': any(x for x in self.module.kinds.keys() if x[0] == 's'),
             'has_namespace': self.module.mojom_namespace != '',
             'interface_event': GetEventInterface(self.module.interfaces),
             'interface_main': GetMainInterface(self.module.interfaces),
@@ -485,9 +485,9 @@ class Generator(generator.Generator):
         return {
             'consts': self.module.constants,
             'enums_gen_header': [x for x in self.module.enums if x.attributes is None or 'skipHeader' not in x.attributes],
-            'has_array': len([x for x in self.module.kinds.keys() if x[0] == 'a']) > 0,
-            'has_map': len([x for x in self.module.kinds.keys() if x[0] == 'm']) > 0,
-            'has_string': len([x for x in self.module.kinds.keys() if x[0] == 's']) > 0,
+            'has_array': any(x for x in self.module.kinds.keys() if x[0] == 'a'),
+            'has_map': any(x for x in self.module.kinds.keys() if x[0] == 'm'),
+            'has_string': any(x for x in self.module.kinds.keys() if x[0] == 's'),
             'structs_gen_header': [x for x in self.module.structs if x.attributes is None or 'skipHeader' not in x.attributes],
             'structs_gen_serializer': [x for x in self.module.structs if x.attributes is None or 'skipSerdes' not in x.attributes],
         }
diff -pruN 0.5.0-1/utils/codegen/meson.build 0.6.0-2/utils/codegen/meson.build
--- 0.5.0-1/utils/codegen/meson.build	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/codegen/meson.build	2025-11-27 11:55:28.000000000 +0000
@@ -16,4 +16,6 @@ gen_header = files('gen-header.sh')
 gen_ipa_pub_key = files('gen-ipa-pub-key.py')
 gen_tracepoints = files('gen-tp-header.py')
 
+py_mod_controls = files('controls.py')
+
 subdir('ipc')
diff -pruN 0.5.0-1/utils/gen-debug-controls.py 0.6.0-2/utils/gen-debug-controls.py
--- 0.5.0-1/utils/gen-debug-controls.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/gen-debug-controls.py	2025-11-27 11:55:28.000000000 +0000
@@ -17,8 +17,13 @@ import sys
 from dataclasses import dataclass
 from pathlib import Path
 
-logger = logging.getLogger(__name__)
-logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
+fmt = '%(levelname)s: %(message)s'
+try:
+    import coloredlogs
+    coloredlogs.install(level=logging.INFO, fmt=fmt)
+except ImportError:
+    logging.basicConfig(level=logging.INFO, format=fmt)
+
 
 try:
     import ruamel.yaml as ruyaml
@@ -27,6 +32,8 @@ except:
         f'Failed to import ruamel.yaml. Please install the ruamel.yaml package.')
     sys.exit(1)
 
+logger = logging.getLogger(__name__)
+
 @dataclass
 class FoundMatch:
     file: os.PathLike
@@ -96,6 +103,7 @@ def main(argv):
             controls_map[k] = v
 
     obsolete_names = list(controls_map.keys())
+    found_by_name = {}
 
     for m in matches:
         if not m.type:
@@ -105,12 +113,19 @@ def main(argv):
             continue
 
         p = m.file.relative_to(root_dir)
+        logger.info(f"Found control {m.name} in {p}")
         desc = {'type': m.type,
                 'direction': 'out',
-                'description': f'Debug control {m.name} found in {p}:{m.line}'}
+                'description': f'Debug control {m.name} found in {p}'}
         if m.size is not None:
             desc['size'] = m.size
 
+        c = found_by_name.setdefault(m.name, m)
+        if c.type != m.type or c.size != m.size:
+            logger.error(
+                f"Found multiple entries for control '{m.name}' with differing type or size")
+            return 1
+
         if m.name in controls_map:
             # Can't use == for modified check because of the special yaml dicts.
             update_needed = False
@@ -127,7 +142,9 @@ def main(argv):
                 controls_map[m.name].clear()
                 controls_map[m.name].update(desc)
 
-            obsolete_names.remove(m.name)
+            # Don't try to remove more than once in case control was found multiple files.
+            if m.name in obsolete_names:
+                obsolete_names.remove(m.name)
         else:
             logger.info(f"Add control '{m.name}'")
             insert_before = len(controls)
@@ -156,6 +173,9 @@ def main(argv):
                  "#\n"))
         yaml.dump(doc, f)
 
+    p = ctrl_file.relative_to(Path.cwd(), walk_up=True)
+    logger.info(f"Sucessfully updated {p}")
+
     return 0
 
 
diff -pruN 0.5.0-1/utils/raspberrypi/ctt/ctt.py 0.6.0-2/utils/raspberrypi/ctt/ctt.py
--- 0.5.0-1/utils/raspberrypi/ctt/ctt.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/raspberrypi/ctt/ctt.py	2025-11-27 11:55:28.000000000 +0000
@@ -198,9 +198,12 @@ class Camera:
         """
         Write output to json
         """
-        self.json['rpi.cac']['cac'] = cacs
-        self.log += '\nCAC calibration written to json file'
-        print('Finished CAC calibration')
+        if cacs:
+            self.json['rpi.cac']['cac'] = cacs
+            self.log += '\nCAC calibration written to json file'
+            print('Finished CAC calibration')
+        else:
+            self.log += "\nCAC calibration failed"
 
 
     """
@@ -433,7 +436,8 @@ class Camera:
         write to json
         """
         self.json['rpi.noise']['reference_constant'] = int(noise_out[1])
-        self.json['rpi.noise']['reference_slope'] = round(noise_out[0], 3)
+        # Results are better with about 40% higher deviation.
+        self.json['rpi.noise']['reference_slope'] = round(1.4 * noise_out[0], 3)
         self.log += '\nNOISE calibrations written to json'
         print('Finished NOISE calibrations')
 
diff -pruN 0.5.0-1/utils/raspberrypi/ctt/ctt_alsc.py 0.6.0-2/utils/raspberrypi/ctt/ctt_alsc.py
--- 0.5.0-1/utils/raspberrypi/ctt/ctt_alsc.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/raspberrypi/ctt/ctt_alsc.py	2025-11-27 11:55:28.000000000 +0000
@@ -127,11 +127,12 @@ def alsc(Cam, Img, do_alsc_colour, plot=
     channels = [Img.channels[i] for i in Img.order]
     """
     calculate size of single rectangle.
-    -(-(w-1)//32) is a ceiling division. w-1 is to deal robustly with the case
-    where w is a multiple of 32.
+    The divisions here must ensure the final row/column of cells has a non-zero number of
+    pixels.
     """
     w, h = Img.w/2, Img.h/2
-    dx, dy = int(-(-(w-1)//grid_w)), int(-(-(h-1)//grid_h))
+    dx, dy = int((w - 1) // (grid_w - 1)), int((h - 1) // (grid_h - 1))
+
     """
     average the green channels into one
     """
diff -pruN 0.5.0-1/utils/raspberrypi/ctt/ctt_cac.py 0.6.0-2/utils/raspberrypi/ctt/ctt_cac.py
--- 0.5.0-1/utils/raspberrypi/ctt/ctt_cac.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/raspberrypi/ctt/ctt_cac.py	2025-11-27 11:55:28.000000000 +0000
@@ -108,12 +108,29 @@ def shifts_to_yaml(red_shift, blue_shift
         ybsgrid[xgridloc][ygridloc].append(blue_shift[3])
 
     # Now calculate the average pixel shift for each square in the grid
+    grid_incomplete = False
     for x in range(output_grid_size - 1):
         for y in range(output_grid_size - 1):
-            xrgrid[x, y] = np.mean(xrsgrid[x][y])
-            yrgrid[x, y] = np.mean(yrsgrid[x][y])
-            xbgrid[x, y] = np.mean(xbsgrid[x][y])
-            ybgrid[x, y] = np.mean(ybsgrid[x][y])
+            if xrsgrid[x][y]:
+                xrgrid[x, y] = np.mean(xrsgrid[x][y])
+            else:
+                grid_incomplete = True
+            if yrsgrid[x][y]:
+                yrgrid[x, y] = np.mean(yrsgrid[x][y])
+            else:
+                grid_incomplete = True
+            if xbsgrid[x][y]:
+                xbgrid[x, y] = np.mean(xbsgrid[x][y])
+            else:
+                grid_incomplete = True
+            if ybsgrid[x][y]:
+                ybgrid[x, y] = np.mean(ybsgrid[x][y])
+            else:
+                grid_incomplete = True
+
+    if grid_incomplete:
+        raise RuntimeError("\nERROR: CAC measurements do not span the image!"
+                           "\nConsider using improved CAC images, or remove them entirely.\n")
 
     # Next, we start to interpolate the central points of the grid that gets passed to the tuning file
     input_grids = np.array([xrgrid, yrgrid, xbgrid, ybgrid])
@@ -219,7 +236,12 @@ def cac(Cam):
     # tuning file
     print("\nCreating output grid")
     Cam.log += '\nCreating output grid'
-    rx, ry, bx, by = shifts_to_yaml(red_shift, blue_shift, image_size)
+    try:
+        rx, ry, bx, by = shifts_to_yaml(red_shift, blue_shift, image_size)
+    except RuntimeError as e:
+        print(str(e))
+        Cam.log += "\nCAC correction failed! CAC will not be enabled."
+        return {}
 
     print("CAC correction complete!")
     Cam.log += '\nCAC correction complete!'
diff -pruN 0.5.0-1/utils/raspberrypi/ctt/ctt_pisp.py 0.6.0-2/utils/raspberrypi/ctt/ctt_pisp.py
--- 0.5.0-1/utils/raspberrypi/ctt/ctt_pisp.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/raspberrypi/ctt/ctt_pisp.py	2025-11-27 11:55:28.000000000 +0000
@@ -29,11 +29,11 @@ json_template = {
         {
             "sdn":
             {
-                "deviation": 1.6,
-                "strength": 0.5,
+                "deviation": 0.6,
+                "strength": 0.95,
                 "deviation2": 3.2,
                 "deviation_no_tdn": 3.2,
-                "strength_no_tdn": 0.75
+                "strength_no_tdn": 0.95
             },
             "cdn":
             {
@@ -42,7 +42,7 @@ json_template = {
             },
             "tdn":
             {
-                "deviation": 0.8,
+                "deviation": 1.0,
                 "threshold": 0.05
             }
         },
@@ -50,11 +50,11 @@ json_template = {
         {
             "sdn":
             {
-                "deviation": 1.6,
-                "strength": 0.5,
+                "deviation": 0.6,
+                "strength": 0.95,
                 "deviation2": 3.2,
                 "deviation_no_tdn": 3.2,
-                "strength_no_tdn": 0.75
+                "strength_no_tdn": 0.95
             },
             "cdn":
             {
@@ -71,11 +71,11 @@ json_template = {
         {
             "sdn":
             {
-                "deviation": 1.6,
-                "strength": 0.5,
+                "deviation": 0.6,
+                "strength": 0.95,
                 "deviation2": 3.2,
                 "deviation_no_tdn": 3.2,
-                "strength_no_tdn": 0.75
+                "strength_no_tdn": 0.95
             },
             "cdn":
             {
@@ -714,38 +714,56 @@ json_template = {
     "rpi.contrast": {
         "ce_enable": 1,
         "gamma_curve": [
-            0,     0,
-            1024,  5040,
-            2048,  9338,
-            3072,  12356,
-            4096,  15312,
-            5120,  18051,
-            6144,  20790,
-            7168,  23193,
-            8192,  25744,
-            9216,  27942,
-            10240, 30035,
-            11264, 32005,
-            12288, 33975,
-            13312, 35815,
-            14336, 37600,
-            15360, 39168,
-            16384, 40642,
-            18432, 43379,
-            20480, 45749,
-            22528, 47753,
-            24576, 49621,
-            26624, 51253,
-            28672, 52698,
-            30720, 53796,
-            32768, 54876,
-            36864, 57012,
-            40960, 58656,
-            45056, 59954,
-            49152, 61183,
-            53248, 62355,
-            57344, 63419,
-            61440, 64476,
+            0, 0,
+            512, 2518,
+            1024, 5033,
+            1536, 7175,
+            2048, 9309,
+            2560, 10814,
+            3072, 12312,
+            3584, 13773,
+            4096, 15225,
+            4608, 16566,
+            5120, 17899,
+            5632, 19221,
+            6144, 20534,
+            6656, 21684,
+            7168, 22826,
+            7680, 24024,
+            8192, 25212,
+            9216, 27251,
+            10240, 29167,
+            11264, 30947,
+            12288, 32696,
+            13312, 34309,
+            14336, 35849,
+            15360, 37194,
+            16384, 38445,
+            17408, 39598,
+            18432, 40732,
+            19456, 41717,
+            20480, 42687,
+            22528, 44343,
+            24576, 45871,
+            26624, 47222,
+            28672, 48441,
+            30720, 49460,
+            32768, 50470,
+            34816, 51476,
+            36864, 52480,
+            38912, 53382,
+            40960, 54294,
+            43008, 55155,
+            45056, 56035,
+            47104, 56920,
+            49152, 57824,
+            51200, 58737,
+            53248, 59666,
+            55296, 60604,
+            57344, 61558,
+            59392, 62529,
+            61440, 63516,
+            63488, 64519,
             65535, 65535
         ]
     },
@@ -754,8 +772,8 @@ json_template = {
     "rpi.cac": {
     },
     "rpi.sharpen": {
-	"threshold": 0.25,
-	"limit": 1.0,
+	"threshold": 0.75,
+	"limit": 0.5,
 	"strength": 1.0
     },
     "rpi.hdr":
diff -pruN 0.5.0-1/utils/raspberrypi/ctt/ctt_vc4.py 0.6.0-2/utils/raspberrypi/ctt/ctt_vc4.py
--- 0.5.0-1/utils/raspberrypi/ctt/ctt_vc4.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/raspberrypi/ctt/ctt_vc4.py	2025-11-27 11:55:28.000000000 +0000
@@ -55,12 +55,16 @@ json_template = {
         },
         "exposure_modes": {
             "normal": {
-                "shutter": [100, 10000, 30000, 60000, 120000],
-                "gain": [1.0, 2.0, 4.0, 6.0, 6.0]
+                "shutter": [100, 10000, 30000, 60000, 66666],
+                "gain": [1.0, 2.0, 4.0, 6.0, 8.0]
             },
             "short": {
-                "shutter": [100, 5000, 10000, 20000, 120000],
-                "gain": [1.0, 2.0, 4.0, 6.0, 6.0]
+                "shutter": [100, 5000, 10000, 20000, 66666],
+                "gain": [1.0, 2.0, 4.0, 6.0, 8.0]
+            },
+            "long": {
+                "shutter": [ 100, 10000, 30000, 60000, 120000 ],
+                "gain": [ 1.0, 2.0, 4.0, 6.0, 8.0 ]
             }
         },
         "constraint_modes": {
@@ -120,6 +124,9 @@ json_template = {
     "rpi.ccm": {
     },
     "rpi.sharpen": {
+        "threshold": 0.75,
+        "limit": 0.5,
+        "strength": 1.0
     }
 }
 
diff -pruN 0.5.0-1/utils/rkisp1/gen-csc-table.py 0.6.0-2/utils/rkisp1/gen-csc-table.py
--- 0.5.0-1/utils/rkisp1/gen-csc-table.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/rkisp1/gen-csc-table.py	2025-11-27 11:55:28.000000000 +0000
@@ -147,6 +147,8 @@ def main(argv):
         description='Generate color space conversion table coefficients with '
         'configurable fixed-point precision.'
     )
+    parser.add_argument('--format', '-f', choices=['dec', 'hex'], default='hex',
+                        help='Number format')
     parser.add_argument('--invert', '-i', action='store_true',
                         help='Invert the color space conversion (YUV -> RGB)')
     parser.add_argument('--precision', '-p', default='Q1.7',
@@ -190,19 +192,29 @@ def main(argv):
         else:
             line = round_array(line)
 
-        # Convert coefficients to the number of bits selected by the precision.
-        # Negative values will be turned into positive integers using 2's
-        # complement.
-        line = [coeff & ((1 << precision.total) - 1) for coeff in line]
+        if args.format == 'hex':
+            # Convert coefficients to the number of bits selected by the precision.
+            # Negative values will be turned into positive integers using 2's
+            # complement.
+            line = [coeff & ((1 << precision.total) - 1) for coeff in line]
+
         rounded_coeffs.append(line)
 
     # Print the result as C code.
     nbits = 1 << (precision.total - 1).bit_length()
     nbytes = nbits // 4
-    print(f'static const u{nbits} {"yuv2rgb" if args.invert else "rgb2yuv"}_{args.encoding}_{quantization.name.lower()}_coeffs[] = {{')
+
+    if args.format == 'hex':
+        coeff_fmt = '0x{0:0' + str(nbytes) + 'x}'
+        sign = 'u'
+    else:
+        coeff_fmt = '{0}'
+        sign = 's'
+
+    print(f'static const {sign}{nbits} {"yuv2rgb" if args.invert else "rgb2yuv"}_{args.encoding}_{quantization.name.lower()}_coeffs[] = {{')
 
     for line in rounded_coeffs:
-        line = [f'0x{coeff:0{nbytes}x}' for coeff in line]
+        line = [coeff_fmt.format(coeff) for coeff in line]
 
         print(f'\t{", ".join(line)},')
 
diff -pruN 0.5.0-1/utils/tuning/rkisp1.py 0.6.0-2/utils/tuning/rkisp1.py
--- 0.5.0-1/utils/tuning/rkisp1.py	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/tuning/rkisp1.py	2025-11-27 11:55:28.000000000 +0000
@@ -27,6 +27,7 @@ awb = AWBRkISP1(debug=[lt.Debug.Plot])
 blc = StaticModule('BlackLevelCorrection')
 ccm = CCMRkISP1(debug=[lt.Debug.Plot])
 color_processing = StaticModule('ColorProcessing')
+compress = StaticModule('Compress')
 filter = StaticModule('Filter')
 gamma_out = StaticModule('GammaOutCorrection', {'gamma': 2.2})
 lsc = LSCRkISP1(debug=[lt.Debug.Plot],
@@ -47,15 +48,18 @@ lsc = LSCRkISP1(debug=[lt.Debug.Plot],
                 # values.  This can also be a custom function.
                 smoothing_function=lt.smoothing.MedianBlur(3),)
 lux = LuxRkISP1(debug=[lt.Debug.Plot])
+wdr = StaticModule('WideDynamicRange',
+                   {'ExposureConstraint': {'MaxBrightPixels': 0.02, 'yTarget': 0.95}})
 
 tuner = lt.Tuner('RkISP1')
-tuner.add([agc, awb, blc, ccm, color_processing, filter, gamma_out, lsc, lux])
+tuner.add([agc, awb, blc, ccm, color_processing, filter, gamma_out, lsc, lux, wdr, compress])
 tuner.set_input_parser(YamlParser())
 tuner.set_output_formatter(YamlOutput())
 
 # Bayesian AWB uses the lux value, so insert the lux algorithm before AWB.
+# Compress is parameterized by others, so add it at the end.
 tuner.set_output_order([agc, lux, awb, blc, ccm, color_processing,
-                        filter, gamma_out, lsc])
+                        filter, gamma_out, lsc, wdr, compress])
 
 if __name__ == '__main__':
     sys.exit(tuner.run(sys.argv))
diff -pruN 0.5.0-1/utils/update-kernel-headers.sh 0.6.0-2/utils/update-kernel-headers.sh
--- 0.5.0-1/utils/update-kernel-headers.sh	2025-04-03 13:38:25.000000000 +0000
+++ 0.6.0-2/utils/update-kernel-headers.sh	2025-11-27 11:55:28.000000000 +0000
@@ -49,6 +49,7 @@ headers="
 	drm/drm_fourcc.h
 	linux/dma-buf.h
 	linux/dma-heap.h
+	linux/dw100.h
 	linux/media-bus-format.h
 	linux/media.h
 	linux/rkisp1-config.h
