[{"id":32769,"web_url":"https://patchwork.libcamera.org/comment/32769/","msgid":"<20241216131206.GR32204@pendragon.ideasonboard.com>","date":"2024-12-16T13:12:06","subject":"Re: [PATCH v4] gstreamer: keep same transfer with that in negotiated\n\tcaps","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Hou,\n\nThank you for the patch.\n\nOn Mon, Dec 16, 2024 at 01:30:44PM +0900, Hou Qi wrote:\n> The conversions back and forth between GStreamer colorimetry and\n> libcamera color space are not invariant for the bt601 colorimetry.\n> The reason is that Rec709 transfer function defined in GStreamer\n> as GST_VIDEO_TRANSFER_BT709 (5), is to be replaced by its alias\n> GST_VIDEO_TRANSFER_BT601 (16) only for the case of bt601 (aka 2:4:16:4)\n> colorimetry - see [1].\n> \n> Currently the composition of the GStreamer/libcamera conversions:\n> colorimetry_from_colorspace (colorspace_from_colorimetry (bt601))\n> returns 2:4:5:4 instead of the expected 2:4:16:4 (bt601). This\n> causes negotiation error when the downstream element explicitly\n> expects bt601 colorimetry.\n> \n> Minimal example to reproduce the issue is with a pipeline handler\n> that do not set the optional color space in the stream configuration,\n> for instance vimc or imx8-isi:\n> export LIBCAMERA_PIPELINES_MATCH_LIST=\"vimc,imx8-isi\"\n> gst-launch-1.0 -v libcamerasrc ! video/x-raw,colorimetry=bt601 ! fakesink\n> \n> Above pipeline fails to start. This change memorizes downstream required\n> transfer function when mapped libcamera transfer is Rec709 in\n> gst_libcamera_configure_stream_from_caps(), and restores the transfer\n> function in gst_libcamera_stream_formats_to_caps().\n> \n> [1] https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/724\n> \n> Bug: https://bugs.libcamera.org/show_bug.cgi?id=150\n> Signed-off-by: Hou Qi <qi.hou@nxp.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nNicolas has also provided a R-b tag in v2, which I think is still\napplicable, so I'll add it to the commit.\n\n> ---\n>  src/gstreamer/gstlibcamera-utils.cpp | 20 ++++++++++++--------\n>  src/gstreamer/gstlibcamera-utils.h   |  5 +++--\n>  src/gstreamer/gstlibcamerasrc.cpp    |  6 ++++--\n>  3 files changed, 19 insertions(+), 12 deletions(-)\n> \n> diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp\n> index 732987ef..a466b305 100644\n> --- a/src/gstreamer/gstlibcamera-utils.cpp\n> +++ b/src/gstreamer/gstlibcamera-utils.cpp\n> @@ -85,7 +85,7 @@ static struct {\n>  };\n>  \n>  static GstVideoColorimetry\n> -colorimetry_from_colorspace(const ColorSpace &colorSpace)\n> +colorimetry_from_colorspace(const ColorSpace &colorSpace, GstVideoTransferFunction transfer)\n>  {\n>  \tGstVideoColorimetry colorimetry;\n>  \n> @@ -113,6 +113,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)\n>  \t\tbreak;\n>  \tcase ColorSpace::TransferFunction::Rec709:\n>  \t\tcolorimetry.transfer = GST_VIDEO_TRANSFER_BT709;\n> +\t\tif (transfer != GST_VIDEO_TRANSFER_UNKNOWN)\n> +\t\t\tcolorimetry.transfer = transfer;\n>  \t\tbreak;\n>  \t}\n>  \n> @@ -144,7 +146,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)\n>  }\n>  \n>  static std::optional<ColorSpace>\n> -colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)\n> +colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry,\n> +\t\t\t    GstVideoTransferFunction *transfer)\n>  {\n>  \tstd::optional<ColorSpace> colorspace = ColorSpace::Raw;\n>  \n> @@ -188,6 +191,7 @@ colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)\n>  \tcase GST_VIDEO_TRANSFER_BT2020_12:\n>  \tcase GST_VIDEO_TRANSFER_BT709:\n>  \t\tcolorspace->transferFunction = ColorSpace::TransferFunction::Rec709;\n> +\t\t*transfer = colorimetry.transfer;\n>  \t\tbreak;\n>  \tdefault:\n>  \t\tGST_WARNING(\"Colorimetry transfer function %d not mapped in gstlibcamera\",\n> @@ -379,7 +383,8 @@ gst_libcamera_stream_formats_to_caps(const StreamFormats &formats)\n>  }\n>  \n>  GstCaps *\n> -gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg)\n> +gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg,\n> +\t\t\t\t\t   GstVideoTransferFunction transfer)\n>  {\n>  \tGstCaps *caps = gst_caps_new_empty();\n>  \tGstStructure *s = bare_structure_from_format(stream_cfg.pixelFormat);\n> @@ -390,7 +395,7 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg\n>  \t\t\t  nullptr);\n>  \n>  \tif (stream_cfg.colorSpace) {\n> -\t\tGstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value());\n> +\t\tGstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value(), transfer);\n>  \t\tg_autofree gchar *colorimetry_str = gst_video_colorimetry_to_string(&colorimetry);\n>  \n>  \t\tif (colorimetry_str)\n> @@ -405,9 +410,8 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg\n>  \treturn caps;\n>  }\n>  \n> -void\n> -gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,\n> -\t\t\t\t\t GstCaps *caps)\n> +void gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,\n> +\t\t\t\t\t      GstCaps *caps, GstVideoTransferFunction *transfer)\n>  {\n>  \tGstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat);\n>  \tguint i;\n> @@ -495,7 +499,7 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,\n>  \t\tif (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str))\n>  \t\t\tg_critical(\"Invalid colorimetry %s\", colorimetry_str);\n>  \n> -\t\tstream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry);\n> +\t\tstream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry, transfer);\n>  \t}\n>  }\n>  \n> diff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h\n> index cab1c814..4978987c 100644\n> --- a/src/gstreamer/gstlibcamera-utils.h\n> +++ b/src/gstreamer/gstlibcamera-utils.h\n> @@ -16,9 +16,10 @@\n>  #include <gst/video/video.h>\n>  \n>  GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);\n> -GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg);\n> +GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg,\n> +\t\t\t\t\t\t    GstVideoTransferFunction transfer);\n>  void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg,\n> -\t\t\t\t\t      GstCaps *caps);\n> +\t\t\t\t\t      GstCaps *caps, GstVideoTransferFunction *transfer);\n>  void gst_libcamera_get_framerate_from_caps(GstCaps *caps, GstStructure *element_caps);\n>  void gst_libcamera_clamp_and_set_frameduration(libcamera::ControlList &controls,\n>  \t\t\t\t\t       const libcamera::ControlInfoMap &camera_controls,\n> diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> index 8efa25f4..5e9e843d 100644\n> --- a/src/gstreamer/gstlibcamerasrc.cpp\n> +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> @@ -433,6 +433,8 @@ static bool\n>  gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n>  {\n>  \tGstLibcameraSrcState *state = self->state;\n> +\tstd::vector<GstVideoTransferFunction> transfer(state->srcpads_.size(),\n> +\t\t\t\t\t\t       GST_VIDEO_TRANSFER_UNKNOWN);\n>  \n>  \tg_autoptr(GstStructure) element_caps = gst_structure_new_empty(\"caps\");\n>  \n> @@ -448,7 +450,7 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n>  \n>  \t\t/* Fixate caps and configure the stream. */\n>  \t\tcaps = gst_caps_make_writable(caps);\n> -\t\tgst_libcamera_configure_stream_from_caps(stream_cfg, caps);\n> +\t\tgst_libcamera_configure_stream_from_caps(stream_cfg, caps, &transfer[i]);\n>  \t\tgst_libcamera_get_framerate_from_caps(caps, element_caps);\n>  \t}\n>  \n> @@ -476,7 +478,7 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n>  \t\tGstPad *srcpad = state->srcpads_[i];\n>  \t\tconst StreamConfiguration &stream_cfg = state->config_->at(i);\n>  \n> -\t\tg_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg);\n> +\t\tg_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg, transfer[i]);\n>  \t\tgst_libcamera_framerate_to_caps(caps, element_caps);\n>  \n>  \t\tif (!gst_pad_push_event(srcpad, gst_event_new_caps(caps)))","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id CC772C32DA\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 16 Dec 2024 13:12:24 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E217567F5F;\n\tMon, 16 Dec 2024 14:12:23 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A97C862C8B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 16 Dec 2024 14:12:22 +0100 (CET)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id F06C3675;\n\tMon, 16 Dec 2024 14:11:45 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"i/bHVS1o\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1734354706;\n\tbh=sD/yqQiulTFBMjLVHUEdfjhk2gWzrzOZyqt9WkdLCjw=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=i/bHVS1oFVARAiGcECrnpTP0Cx5snAvoZtt+s53+KBBLI6EBTlNaiatf4nuoqXQbY\n\tcq4JungDoVfi5XjcOUoDjX8OpdFSIBIH9jBUKtlBR9W+cLySsoX7lTTfVnbs67IrHC\n\tn/tEhrPHKCE3gmruaqEs1O7Tilm0yWLZZWjB+Szc=","Date":"Mon, 16 Dec 2024 15:12:06 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Hou Qi <qi.hou@nxp.com>","Cc":"libcamera-devel@lists.libcamera.org, jared.hu@nxp.com,\n\tjulien.vuillaumier@nxp.com","Subject":"Re: [PATCH v4] gstreamer: keep same transfer with that in negotiated\n\tcaps","Message-ID":"<20241216131206.GR32204@pendragon.ideasonboard.com>","References":"<20241216043044.1760345-1-qi.hou@nxp.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20241216043044.1760345-1-qi.hou@nxp.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":32770,"web_url":"https://patchwork.libcamera.org/comment/32770/","msgid":"<20241216132715.GS32204@pendragon.ideasonboard.com>","date":"2024-12-16T13:27:15","subject":"Re: [PATCH v4] gstreamer: keep same transfer with that in negotiated\n\tcaps","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Mon, Dec 16, 2024 at 03:12:06PM +0200, Laurent Pinchart wrote:\n> Hi Hou,\n> \n> Thank you for the patch.\n> \n> On Mon, Dec 16, 2024 at 01:30:44PM +0900, Hou Qi wrote:\n> > The conversions back and forth between GStreamer colorimetry and\n> > libcamera color space are not invariant for the bt601 colorimetry.\n> > The reason is that Rec709 transfer function defined in GStreamer\n> > as GST_VIDEO_TRANSFER_BT709 (5), is to be replaced by its alias\n> > GST_VIDEO_TRANSFER_BT601 (16) only for the case of bt601 (aka 2:4:16:4)\n> > colorimetry - see [1].\n> > \n> > Currently the composition of the GStreamer/libcamera conversions:\n> > colorimetry_from_colorspace (colorspace_from_colorimetry (bt601))\n> > returns 2:4:5:4 instead of the expected 2:4:16:4 (bt601). This\n> > causes negotiation error when the downstream element explicitly\n> > expects bt601 colorimetry.\n> > \n> > Minimal example to reproduce the issue is with a pipeline handler\n> > that do not set the optional color space in the stream configuration,\n> > for instance vimc or imx8-isi:\n> > export LIBCAMERA_PIPELINES_MATCH_LIST=\"vimc,imx8-isi\"\n> > gst-launch-1.0 -v libcamerasrc ! video/x-raw,colorimetry=bt601 ! fakesink\n> > \n> > Above pipeline fails to start. This change memorizes downstream required\n> > transfer function when mapped libcamera transfer is Rec709 in\n> > gst_libcamera_configure_stream_from_caps(), and restores the transfer\n> > function in gst_libcamera_stream_formats_to_caps().\n> > \n> > [1] https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/724\n> > \n> > Bug: https://bugs.libcamera.org/show_bug.cgi?id=150\n> > Signed-off-by: Hou Qi <qi.hou@nxp.com>\n> \n> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n> \n> Nicolas has also provided a R-b tag in v2, which I think is still\n> applicable, so I'll add it to the commit.\n\nPatch merged in the master branch.\n\n> > ---\n> >  src/gstreamer/gstlibcamera-utils.cpp | 20 ++++++++++++--------\n> >  src/gstreamer/gstlibcamera-utils.h   |  5 +++--\n> >  src/gstreamer/gstlibcamerasrc.cpp    |  6 ++++--\n> >  3 files changed, 19 insertions(+), 12 deletions(-)\n> > \n> > diff --git a/src/gstreamer/gstlibcamera-utils.cpp b/src/gstreamer/gstlibcamera-utils.cpp\n> > index 732987ef..a466b305 100644\n> > --- a/src/gstreamer/gstlibcamera-utils.cpp\n> > +++ b/src/gstreamer/gstlibcamera-utils.cpp\n> > @@ -85,7 +85,7 @@ static struct {\n> >  };\n> >  \n> >  static GstVideoColorimetry\n> > -colorimetry_from_colorspace(const ColorSpace &colorSpace)\n> > +colorimetry_from_colorspace(const ColorSpace &colorSpace, GstVideoTransferFunction transfer)\n> >  {\n> >  \tGstVideoColorimetry colorimetry;\n> >  \n> > @@ -113,6 +113,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)\n> >  \t\tbreak;\n> >  \tcase ColorSpace::TransferFunction::Rec709:\n> >  \t\tcolorimetry.transfer = GST_VIDEO_TRANSFER_BT709;\n> > +\t\tif (transfer != GST_VIDEO_TRANSFER_UNKNOWN)\n> > +\t\t\tcolorimetry.transfer = transfer;\n> >  \t\tbreak;\n> >  \t}\n> >  \n> > @@ -144,7 +146,8 @@ colorimetry_from_colorspace(const ColorSpace &colorSpace)\n> >  }\n> >  \n> >  static std::optional<ColorSpace>\n> > -colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)\n> > +colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry,\n> > +\t\t\t    GstVideoTransferFunction *transfer)\n> >  {\n> >  \tstd::optional<ColorSpace> colorspace = ColorSpace::Raw;\n> >  \n> > @@ -188,6 +191,7 @@ colorspace_from_colorimetry(const GstVideoColorimetry &colorimetry)\n> >  \tcase GST_VIDEO_TRANSFER_BT2020_12:\n> >  \tcase GST_VIDEO_TRANSFER_BT709:\n> >  \t\tcolorspace->transferFunction = ColorSpace::TransferFunction::Rec709;\n> > +\t\t*transfer = colorimetry.transfer;\n> >  \t\tbreak;\n> >  \tdefault:\n> >  \t\tGST_WARNING(\"Colorimetry transfer function %d not mapped in gstlibcamera\",\n> > @@ -379,7 +383,8 @@ gst_libcamera_stream_formats_to_caps(const StreamFormats &formats)\n> >  }\n> >  \n> >  GstCaps *\n> > -gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg)\n> > +gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg,\n> > +\t\t\t\t\t   GstVideoTransferFunction transfer)\n> >  {\n> >  \tGstCaps *caps = gst_caps_new_empty();\n> >  \tGstStructure *s = bare_structure_from_format(stream_cfg.pixelFormat);\n> > @@ -390,7 +395,7 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg\n> >  \t\t\t  nullptr);\n> >  \n> >  \tif (stream_cfg.colorSpace) {\n> > -\t\tGstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value());\n> > +\t\tGstVideoColorimetry colorimetry = colorimetry_from_colorspace(stream_cfg.colorSpace.value(), transfer);\n> >  \t\tg_autofree gchar *colorimetry_str = gst_video_colorimetry_to_string(&colorimetry);\n> >  \n> >  \t\tif (colorimetry_str)\n> > @@ -405,9 +410,8 @@ gst_libcamera_stream_configuration_to_caps(const StreamConfiguration &stream_cfg\n> >  \treturn caps;\n> >  }\n> >  \n> > -void\n> > -gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,\n> > -\t\t\t\t\t GstCaps *caps)\n> > +void gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,\n> > +\t\t\t\t\t      GstCaps *caps, GstVideoTransferFunction *transfer)\n> >  {\n> >  \tGstVideoFormat gst_format = pixel_format_to_gst_format(stream_cfg.pixelFormat);\n> >  \tguint i;\n> > @@ -495,7 +499,7 @@ gst_libcamera_configure_stream_from_caps(StreamConfiguration &stream_cfg,\n> >  \t\tif (!gst_video_colorimetry_from_string(&colorimetry, colorimetry_str))\n> >  \t\t\tg_critical(\"Invalid colorimetry %s\", colorimetry_str);\n> >  \n> > -\t\tstream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry);\n> > +\t\tstream_cfg.colorSpace = colorspace_from_colorimetry(colorimetry, transfer);\n> >  \t}\n> >  }\n> >  \n> > diff --git a/src/gstreamer/gstlibcamera-utils.h b/src/gstreamer/gstlibcamera-utils.h\n> > index cab1c814..4978987c 100644\n> > --- a/src/gstreamer/gstlibcamera-utils.h\n> > +++ b/src/gstreamer/gstlibcamera-utils.h\n> > @@ -16,9 +16,10 @@\n> >  #include <gst/video/video.h>\n> >  \n> >  GstCaps *gst_libcamera_stream_formats_to_caps(const libcamera::StreamFormats &formats);\n> > -GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg);\n> > +GstCaps *gst_libcamera_stream_configuration_to_caps(const libcamera::StreamConfiguration &stream_cfg,\n> > +\t\t\t\t\t\t    GstVideoTransferFunction transfer);\n> >  void gst_libcamera_configure_stream_from_caps(libcamera::StreamConfiguration &stream_cfg,\n> > -\t\t\t\t\t      GstCaps *caps);\n> > +\t\t\t\t\t      GstCaps *caps, GstVideoTransferFunction *transfer);\n> >  void gst_libcamera_get_framerate_from_caps(GstCaps *caps, GstStructure *element_caps);\n> >  void gst_libcamera_clamp_and_set_frameduration(libcamera::ControlList &controls,\n> >  \t\t\t\t\t       const libcamera::ControlInfoMap &camera_controls,\n> > diff --git a/src/gstreamer/gstlibcamerasrc.cpp b/src/gstreamer/gstlibcamerasrc.cpp\n> > index 8efa25f4..5e9e843d 100644\n> > --- a/src/gstreamer/gstlibcamerasrc.cpp\n> > +++ b/src/gstreamer/gstlibcamerasrc.cpp\n> > @@ -433,6 +433,8 @@ static bool\n> >  gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n> >  {\n> >  \tGstLibcameraSrcState *state = self->state;\n> > +\tstd::vector<GstVideoTransferFunction> transfer(state->srcpads_.size(),\n> > +\t\t\t\t\t\t       GST_VIDEO_TRANSFER_UNKNOWN);\n> >  \n> >  \tg_autoptr(GstStructure) element_caps = gst_structure_new_empty(\"caps\");\n> >  \n> > @@ -448,7 +450,7 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n> >  \n> >  \t\t/* Fixate caps and configure the stream. */\n> >  \t\tcaps = gst_caps_make_writable(caps);\n> > -\t\tgst_libcamera_configure_stream_from_caps(stream_cfg, caps);\n> > +\t\tgst_libcamera_configure_stream_from_caps(stream_cfg, caps, &transfer[i]);\n> >  \t\tgst_libcamera_get_framerate_from_caps(caps, element_caps);\n> >  \t}\n> >  \n> > @@ -476,7 +478,7 @@ gst_libcamera_src_negotiate(GstLibcameraSrc *self)\n> >  \t\tGstPad *srcpad = state->srcpads_[i];\n> >  \t\tconst StreamConfiguration &stream_cfg = state->config_->at(i);\n> >  \n> > -\t\tg_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg);\n> > +\t\tg_autoptr(GstCaps) caps = gst_libcamera_stream_configuration_to_caps(stream_cfg, transfer[i]);\n> >  \t\tgst_libcamera_framerate_to_caps(caps, element_caps);\n> >  \n> >  \t\tif (!gst_pad_push_event(srcpad, gst_event_new_caps(caps)))","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E4518C32F6\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 16 Dec 2024 13:27:35 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 7B86F67F67;\n\tMon, 16 Dec 2024 14:27:34 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id D33E467F56\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 16 Dec 2024 14:27:31 +0100 (CET)","from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi\n\t[81.175.209.231])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 24C8A675;\n\tMon, 16 Dec 2024 14:26:55 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"soG1DVzR\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1734355615;\n\tbh=b+clb7KVG4D1NNDEo9mtctT+gmFet6hNsXSIClIliWQ=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=soG1DVzR6iOBCpExolhgi7UUMiHFJWrlxNHlqMJ/etA5whFeNbuiwIdjuF7MdIHr8\n\tdewPDg4B4yu+lekl9e+yXLeHLh5IGyBxo6BShEarouuIu9ISmm4Aa7CY3qV56yeDy4\n\tCZWIAn51pjgqlB5s03bMFhag/jVZbksdW756lQ0g=","Date":"Mon, 16 Dec 2024 15:27:15 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Hou Qi <qi.hou@nxp.com>","Cc":"libcamera-devel@lists.libcamera.org, jared.hu@nxp.com,\n\tjulien.vuillaumier@nxp.com","Subject":"Re: [PATCH v4] gstreamer: keep same transfer with that in negotiated\n\tcaps","Message-ID":"<20241216132715.GS32204@pendragon.ideasonboard.com>","References":"<20241216043044.1760345-1-qi.hou@nxp.com>\n\t<20241216131206.GR32204@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20241216131206.GR32204@pendragon.ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]