[{"id":34019,"web_url":"https://patchwork.libcamera.org/comment/34019/","msgid":"<174541476482.2882969.16888861057763666056@ping.linuxembedded.co.uk>","date":"2025-04-23T13:26:04","subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Paul Elder (2025-04-23 10:12:08)\n> cam currently defaults to the viewfinder role when no role is specified.\n> This means that on platforms that only support the raw role (such as a\n> raw sensor with no softISP on a simple pipeline platform),\n> generateConfiguration() would return nullptr and cam would bail out.\n> \n> At least this is what is supposed to happen based on the little\n> documentation that we have written regarding generateConfiguration(),\n> specifically in the application writer's guide, which is probably the\n> most influential piece of documentation:\n> \n>   The ``Camera::generateConfiguration()`` function accepts a list of\n>   desired roles and generates a ``CameraConfiguration`` with the best\n>   stream parameters configuration for each of the requested roles. If the\n>   camera can handle the requested roles, it returns an initialized\n>   ``CameraConfiguration`` and a null pointer if it can't.\n> \n> Currently the simple pipeline handler will return a raw configuration\n> anyway (if it only supports raw) even if a non-raw role was requested.\n> Thus cam receives a raw configuration instead of a nullptr when no role\n> is specified and viewfinder is requested.\n> \n> However, in the near future, support for raw streams with softISP on the\n> simple pipeline handler will be merged. This will notably change the\n> behavior of the simple pipeline handler to return nullptr if a non-raw\n> role was requested on a platform that only supports raw. This is proper\n> behavior according to documentation, but changes cam's behavior as it\n> used to capture fine with no parameters but will no longer be able to.\n> \n> Technically this is an issue with the roles API, as we are mixing\n> roles in the sense of \"configuration hints\" (eg. viewfinder vs recording\n> vs still capture) with roles in the sense of \"platform capabilities\"\n> (raw vs everything else). In the long term the proper solution is to\n> rework the roles API.\n> \n> In the meantime, fix cam so that it will try the raw role if the default\n> viewfinder role returns no configuration. cam is an app that is capable\n> of using the raw stream, so this is appropriate behavior. If roles are\n> specified, then do not retry, as in this situation the user knows what\n> streams they can use and what they want.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> ---\n>  src/apps/cam/camera_session.cpp    | 29 +++++++++++++++++++++++++----\n>  src/apps/common/stream_options.cpp |  3 +--\n>  src/apps/qcam/main_window.cpp      |  3 +++\n>  3 files changed, 29 insertions(+), 6 deletions(-)\n> \n> diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp\n> index 97c1ae44995e..f63fcb228519 100644\n> --- a/src/apps/cam/camera_session.cpp\n> +++ b/src/apps/cam/camera_session.cpp\n> @@ -62,11 +62,32 @@ CameraSession::CameraSession(CameraManager *cm,\n>                 return;\n>         }\n>  \n> -       std::vector<StreamRole> roles = StreamKeyValueParser::roles(options_[OptStream]);\n> +       std::vector<StreamRole> roles =\n> +               StreamKeyValueParser::roles(options_[OptStream]);\n> +       std::vector<std::vector<StreamRole>> tryRoles;\n> +       if (!roles.empty()) {\n> +               /*\n> +                * If the roles are explicitly specified then there's no need\n> +                * to try other roles\n> +                */\n> +               tryRoles.push_back(roles);\n> +       } else {\n> +               tryRoles.push_back({ StreamRole::Viewfinder });\n> +               tryRoles.push_back({ StreamRole::Raw });\n> +       }\n> +\n> +       std::unique_ptr<CameraConfiguration> config;\n> +       bool valid = false;\n> +       for (std::vector<StreamRole> &rolesIt : tryRoles) {\n> +               config = camera_->generateConfiguration(rolesIt);\n> +               if (config && config->size() == rolesIt.size()) {\n> +                       roles = rolesIt;\n> +                       valid = true;\n> +                       break;\n> +               }\n> +       }\n>  \n> -       std::unique_ptr<CameraConfiguration> config =\n> -               camera_->generateConfiguration(roles);\n> -       if (!config || config->size() != roles.size()) {\n> +       if (!valid) {\n>                 std::cerr << \"Failed to get default stream configuration\"\n>                           << std::endl;\n>                 return;\n> diff --git a/src/apps/common/stream_options.cpp b/src/apps/common/stream_options.cpp\n> index 99239e07e302..288f86530351 100644\n> --- a/src/apps/common/stream_options.cpp\n> +++ b/src/apps/common/stream_options.cpp\n> @@ -42,9 +42,8 @@ KeyValueParser::Options StreamKeyValueParser::parse(const char *arguments)\n>  \n>  std::vector<StreamRole> StreamKeyValueParser::roles(const OptionValue &values)\n>  {\n> -       /* If no configuration values to examine default to viewfinder. */\n>         if (values.empty())\n> -               return { StreamRole::Viewfinder };\n> +               return {};\n>  \n>         const std::vector<OptionValue> &streamParameters = values.toArray();\n>  \n> diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\n> index d2ccbd2318fa..224a7e5a693a 100644\n> --- a/src/apps/qcam/main_window.cpp\n> +++ b/src/apps/qcam/main_window.cpp\n> @@ -356,6 +356,9 @@ int MainWindow::startCapture()\n>  \n>         /* Verify roles are supported. */\n>         switch (roles.size()) {\n> +       case 0:\n> +               roles[0] = StreamRole::Viewfinder;\n> +               break;\n\nIs this necessary? Doesn't it stop the raw stream being handled in qcam\nwhich could be supported with Milans' series ? Or perhaps this just\ncontinues default behaviour ?\n\n>         case 1:\n>                 if (roles[0] != StreamRole::Viewfinder) {\n>                         qWarning() << \"Only viewfinder supported for single stream\";\n\nThis all looks good - except here - do we need to change this ?\n\nqcam /is/ capable of displaying RAW streams as a single stream for quite\nsome time now.\n\nBut that could be on top anyway.\n\nReviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n> -- \n> 2.47.2\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 57330BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 23 Apr 2025 13:26:09 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 61F0F68ACD;\n\tWed, 23 Apr 2025 15:26:08 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 7073968AC6\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 23 Apr 2025 15:26:07 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CD1C216A;\n\tWed, 23 Apr 2025 15:26:05 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"mk5uodwE\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1745414765;\n\tbh=Uwe31z4eYTqiPZexGSD/qKcW7YgmEX4EATzMauuo6zU=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=mk5uodwE+07jZOp33HGjcdIhSQAU2glFglG2RTVgOLB2SgeVXOd8G7xHfrzkIuKd2\n\tJ6D4Lxld63LGlOfhxcm8LPvmhhaFEsYZR3nyfpe97J1K6liYrXwKkPFlX0oIdIL1LP\n\t7gCrXaLSyApBjkJsB00Oh/lsYFr5cxaK9HUBoNx4=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20250423091208.2935632-1-paul.elder@ideasonboard.com>","References":"<20250423091208.2935632-1-paul.elder@ideasonboard.com>","Subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Paul Elder <paul.elder@ideasonboard.com>","To":"Paul Elder <paul.elder@ideasonboard.com>,\n\tlibcamera-devel@lists.libcamera.org","Date":"Wed, 23 Apr 2025 14:26:04 +0100","Message-ID":"<174541476482.2882969.16888861057763666056@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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":34022,"web_url":"https://patchwork.libcamera.org/comment/34022/","msgid":"<aAn8pXE-4SUdFJIg@pyrite.rasen.tech>","date":"2025-04-24T08:56:05","subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","submitter":{"id":17,"url":"https://patchwork.libcamera.org/api/people/17/","name":"Paul Elder","email":"paul.elder@ideasonboard.com"},"content":"On Wed, Apr 23, 2025 at 02:26:04PM +0100, Kieran Bingham wrote:\n> Quoting Paul Elder (2025-04-23 10:12:08)\n> > cam currently defaults to the viewfinder role when no role is specified.\n> > This means that on platforms that only support the raw role (such as a\n> > raw sensor with no softISP on a simple pipeline platform),\n> > generateConfiguration() would return nullptr and cam would bail out.\n> > \n> > At least this is what is supposed to happen based on the little\n> > documentation that we have written regarding generateConfiguration(),\n> > specifically in the application writer's guide, which is probably the\n> > most influential piece of documentation:\n> > \n> >   The ``Camera::generateConfiguration()`` function accepts a list of\n> >   desired roles and generates a ``CameraConfiguration`` with the best\n> >   stream parameters configuration for each of the requested roles. If the\n> >   camera can handle the requested roles, it returns an initialized\n> >   ``CameraConfiguration`` and a null pointer if it can't.\n> > \n> > Currently the simple pipeline handler will return a raw configuration\n> > anyway (if it only supports raw) even if a non-raw role was requested.\n> > Thus cam receives a raw configuration instead of a nullptr when no role\n> > is specified and viewfinder is requested.\n> > \n> > However, in the near future, support for raw streams with softISP on the\n> > simple pipeline handler will be merged. This will notably change the\n> > behavior of the simple pipeline handler to return nullptr if a non-raw\n> > role was requested on a platform that only supports raw. This is proper\n> > behavior according to documentation, but changes cam's behavior as it\n> > used to capture fine with no parameters but will no longer be able to.\n> > \n> > Technically this is an issue with the roles API, as we are mixing\n> > roles in the sense of \"configuration hints\" (eg. viewfinder vs recording\n> > vs still capture) with roles in the sense of \"platform capabilities\"\n> > (raw vs everything else). In the long term the proper solution is to\n> > rework the roles API.\n> > \n> > In the meantime, fix cam so that it will try the raw role if the default\n> > viewfinder role returns no configuration. cam is an app that is capable\n> > of using the raw stream, so this is appropriate behavior. If roles are\n> > specified, then do not retry, as in this situation the user knows what\n> > streams they can use and what they want.\n> > \n> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> > ---\n> >  src/apps/cam/camera_session.cpp    | 29 +++++++++++++++++++++++++----\n> >  src/apps/common/stream_options.cpp |  3 +--\n> >  src/apps/qcam/main_window.cpp      |  3 +++\n> >  3 files changed, 29 insertions(+), 6 deletions(-)\n> > \n> > diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp\n> > index 97c1ae44995e..f63fcb228519 100644\n> > --- a/src/apps/cam/camera_session.cpp\n> > +++ b/src/apps/cam/camera_session.cpp\n> > @@ -62,11 +62,32 @@ CameraSession::CameraSession(CameraManager *cm,\n> >                 return;\n> >         }\n> >  \n> > -       std::vector<StreamRole> roles = StreamKeyValueParser::roles(options_[OptStream]);\n> > +       std::vector<StreamRole> roles =\n> > +               StreamKeyValueParser::roles(options_[OptStream]);\n> > +       std::vector<std::vector<StreamRole>> tryRoles;\n> > +       if (!roles.empty()) {\n> > +               /*\n> > +                * If the roles are explicitly specified then there's no need\n> > +                * to try other roles\n> > +                */\n> > +               tryRoles.push_back(roles);\n> > +       } else {\n> > +               tryRoles.push_back({ StreamRole::Viewfinder });\n> > +               tryRoles.push_back({ StreamRole::Raw });\n> > +       }\n> > +\n> > +       std::unique_ptr<CameraConfiguration> config;\n> > +       bool valid = false;\n> > +       for (std::vector<StreamRole> &rolesIt : tryRoles) {\n> > +               config = camera_->generateConfiguration(rolesIt);\n> > +               if (config && config->size() == rolesIt.size()) {\n> > +                       roles = rolesIt;\n> > +                       valid = true;\n> > +                       break;\n> > +               }\n> > +       }\n> >  \n> > -       std::unique_ptr<CameraConfiguration> config =\n> > -               camera_->generateConfiguration(roles);\n> > -       if (!config || config->size() != roles.size()) {\n> > +       if (!valid) {\n> >                 std::cerr << \"Failed to get default stream configuration\"\n> >                           << std::endl;\n> >                 return;\n> > diff --git a/src/apps/common/stream_options.cpp b/src/apps/common/stream_options.cpp\n> > index 99239e07e302..288f86530351 100644\n> > --- a/src/apps/common/stream_options.cpp\n> > +++ b/src/apps/common/stream_options.cpp\n> > @@ -42,9 +42,8 @@ KeyValueParser::Options StreamKeyValueParser::parse(const char *arguments)\n> >  \n> >  std::vector<StreamRole> StreamKeyValueParser::roles(const OptionValue &values)\n> >  {\n> > -       /* If no configuration values to examine default to viewfinder. */\n> >         if (values.empty())\n> > -               return { StreamRole::Viewfinder };\n> > +               return {};\n> >  \n> >         const std::vector<OptionValue> &streamParameters = values.toArray();\n> >  \n> > diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\n> > index d2ccbd2318fa..224a7e5a693a 100644\n> > --- a/src/apps/qcam/main_window.cpp\n> > +++ b/src/apps/qcam/main_window.cpp\n> > @@ -356,6 +356,9 @@ int MainWindow::startCapture()\n> >  \n> >         /* Verify roles are supported. */\n> >         switch (roles.size()) {\n> > +       case 0:\n> > +               roles[0] = StreamRole::Viewfinder;\n> > +               break;\n> \n> Is this necessary? Doesn't it stop the raw stream being handled in qcam\n> which could be supported with Milans' series ? Or perhaps this just\n> continues default behaviour ?\n\nIt's the retain the previous behavior. If no role is specified it\ndefaults to viewfinder.\n\n> \n> >         case 1:\n> >                 if (roles[0] != StreamRole::Viewfinder) {\n> >                         qWarning() << \"Only viewfinder supported for single stream\";\n> \n> This all looks good - except here - do we need to change this ?\n> \n> qcam /is/ capable of displaying RAW streams as a single stream for quite\n> some time now.\n\nGood point, I think we can do this.\n\n> \n> But that could be on top anyway.\n\nYes :)\n\n> \n> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\n\nThanks,\n\nPaul\n\n> \n> > -- \n> > 2.47.2\n> >","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 87D51BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 24 Apr 2025 08:56:16 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8639E68ACD;\n\tThu, 24 Apr 2025 10:56:15 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 4F826617E4\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 24 Apr 2025 10:56:13 +0200 (CEST)","from pyrite.rasen.tech (unknown\n\t[IPv6:2404:7a81:160:2100:7bb4:ac30:75b1:f030])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 4E1BE9CE;\n\tThu, 24 Apr 2025 10:56:10 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"LSPvAxkp\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1745484971;\n\tbh=PZHSiA72bsjPGtHTEEWYJRBNpNayXVUeRNIYPjTvXs4=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=LSPvAxkp64+t5GnGQgc5SmZCP1Upz4H4+9WuaD5+UWbq1Z7HNvwQZ+9LOvKYFc7gs\n\tUStV44zxjyiFRulm4tWIENclROJfhGGeD8nB8raEFW3nr9QSg3gLzwrVkJfQXa16+q\n\t/2Z8jfYay6z97j8EXzSN0V0+4t1SEsVhjiIT/M6I=","Date":"Thu, 24 Apr 2025 17:56:05 +0900","From":"Paul Elder <paul.elder@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","Message-ID":"<aAn8pXE-4SUdFJIg@pyrite.rasen.tech>","References":"<20250423091208.2935632-1-paul.elder@ideasonboard.com>\n\t<174541476482.2882969.16888861057763666056@ping.linuxembedded.co.uk>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<174541476482.2882969.16888861057763666056@ping.linuxembedded.co.uk>","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":34059,"web_url":"https://patchwork.libcamera.org/comment/34059/","msgid":"<85jz76zv07.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","date":"2025-04-26T17:35:04","subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","submitter":{"id":177,"url":"https://patchwork.libcamera.org/api/people/177/","name":"Milan Zamazal","email":"mzamazal@redhat.com"},"content":"Hi Paul,\n\nthank you for the patch.\n\nPaul Elder <paul.elder@ideasonboard.com> writes:\n\n> cam currently defaults to the viewfinder role when no role is specified.\n> This means that on platforms that only support the raw role (such as a\n> raw sensor with no softISP on a simple pipeline platform),\n> generateConfiguration() would return nullptr and cam would bail out.\n>\n> At least this is what is supposed to happen based on the little\n> documentation that we have written regarding generateConfiguration(),\n> specifically in the application writer's guide, which is probably the\n> most influential piece of documentation:\n>\n>   The ``Camera::generateConfiguration()`` function accepts a list of\n>   desired roles and generates a ``CameraConfiguration`` with the best\n>   stream parameters configuration for each of the requested roles. If the\n>   camera can handle the requested roles, it returns an initialized\n>   ``CameraConfiguration`` and a null pointer if it can't.\n>\n> Currently the simple pipeline handler will return a raw configuration\n> anyway (if it only supports raw) even if a non-raw role was requested.\n> Thus cam receives a raw configuration instead of a nullptr when no role\n> is specified and viewfinder is requested.\n>\n> However, in the near future, support for raw streams with softISP on the\n> simple pipeline handler will be merged. This will notably change the\n> behavior of the simple pipeline handler to return nullptr if a non-raw\n> role was requested on a platform that only supports raw. This is proper\n> behavior according to documentation, but changes cam's behavior as it\n> used to capture fine with no parameters but will no longer be able to.\n>\n> Technically this is an issue with the roles API, as we are mixing\n> roles in the sense of \"configuration hints\" (eg. viewfinder vs recording\n> vs still capture) with roles in the sense of \"platform capabilities\"\n> (raw vs everything else). In the long term the proper solution is to\n> rework the roles API.\n>\n> In the meantime, fix cam so that it will try the raw role if the default\n> viewfinder role returns no configuration. cam is an app that is capable\n> of using the raw stream, so this is appropriate behavior. If roles are\n> specified, then do not retry, as in this situation the user knows what\n> streams they can use and what they want.\n\nMakes sense to me and I cannot see any problem related to my work on raw\nstreams.\n\nReviewed-by: Milan Zamazal <mzamazal@redhat.com>\n\n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> ---\n>  src/apps/cam/camera_session.cpp    | 29 +++++++++++++++++++++++++----\n>  src/apps/common/stream_options.cpp |  3 +--\n>  src/apps/qcam/main_window.cpp      |  3 +++\n>  3 files changed, 29 insertions(+), 6 deletions(-)\n>\n> diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp\n> index 97c1ae44995e..f63fcb228519 100644\n> --- a/src/apps/cam/camera_session.cpp\n> +++ b/src/apps/cam/camera_session.cpp\n> @@ -62,11 +62,32 @@ CameraSession::CameraSession(CameraManager *cm,\n>  \t\treturn;\n>  \t}\n>  \n> -\tstd::vector<StreamRole> roles = StreamKeyValueParser::roles(options_[OptStream]);\n> +\tstd::vector<StreamRole> roles =\n> +\t\tStreamKeyValueParser::roles(options_[OptStream]);\n> +\tstd::vector<std::vector<StreamRole>> tryRoles;\n> +\tif (!roles.empty()) {\n> +\t\t/*\n> +\t\t * If the roles are explicitly specified then there's no need\n> +\t\t * to try other roles\n> +\t\t */\n> +\t\ttryRoles.push_back(roles);\n> +\t} else {\n> +\t\ttryRoles.push_back({ StreamRole::Viewfinder });\n> +\t\ttryRoles.push_back({ StreamRole::Raw });\n> +\t}\n> +\n> +\tstd::unique_ptr<CameraConfiguration> config;\n> +\tbool valid = false;\n> +\tfor (std::vector<StreamRole> &rolesIt : tryRoles) {\n> +\t\tconfig = camera_->generateConfiguration(rolesIt);\n> +\t\tif (config && config->size() == rolesIt.size()) {\n> +\t\t\troles = rolesIt;\n> +\t\t\tvalid = true;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n>  \n> -\tstd::unique_ptr<CameraConfiguration> config =\n> -\t\tcamera_->generateConfiguration(roles);\n> -\tif (!config || config->size() != roles.size()) {\n> +\tif (!valid) {\n>  \t\tstd::cerr << \"Failed to get default stream configuration\"\n>  \t\t\t  << std::endl;\n>  \t\treturn;\n> diff --git a/src/apps/common/stream_options.cpp b/src/apps/common/stream_options.cpp\n> index 99239e07e302..288f86530351 100644\n> --- a/src/apps/common/stream_options.cpp\n> +++ b/src/apps/common/stream_options.cpp\n> @@ -42,9 +42,8 @@ KeyValueParser::Options StreamKeyValueParser::parse(const char *arguments)\n>  \n>  std::vector<StreamRole> StreamKeyValueParser::roles(const OptionValue &values)\n>  {\n> -\t/* If no configuration values to examine default to viewfinder. */\n>  \tif (values.empty())\n> -\t\treturn { StreamRole::Viewfinder };\n> +\t\treturn {};\n>  \n>  \tconst std::vector<OptionValue> &streamParameters = values.toArray();\n>  \n> diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\n> index d2ccbd2318fa..224a7e5a693a 100644\n> --- a/src/apps/qcam/main_window.cpp\n> +++ b/src/apps/qcam/main_window.cpp\n> @@ -356,6 +356,9 @@ int MainWindow::startCapture()\n>  \n>  \t/* Verify roles are supported. */\n>  \tswitch (roles.size()) {\n> +\tcase 0:\n> +\t\troles[0] = StreamRole::Viewfinder;\n> +\t\tbreak;\n>  \tcase 1:\n>  \t\tif (roles[0] != StreamRole::Viewfinder) {\n>  \t\t\tqWarning() << \"Only viewfinder supported for single stream\";","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 51BB5BE08B\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 26 Apr 2025 17:35:15 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 62E4B68ACD;\n\tSat, 26 Apr 2025 19:35:14 +0200 (CEST)","from us-smtp-delivery-124.mimecast.com\n\t(us-smtp-delivery-124.mimecast.com [170.10.129.124])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 009B0617E3\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 26 Apr 2025 19:35:11 +0200 (CEST)","from mail-ej1-f71.google.com (mail-ej1-f71.google.com\n\t[209.85.218.71]) by relay.mimecast.com with ESMTP with STARTTLS\n\t(version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id\n\tus-mta-187-zCgmjyytMc2JLyCBhu9sWw-1; Sat, 26 Apr 2025 13:35:08 -0400","by mail-ej1-f71.google.com with SMTP id\n\ta640c23a62f3a-ac6ebab17d8so245156466b.1\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 26 Apr 2025 10:35:08 -0700 (PDT)","from mzamazal-thinkpadp1gen7.tpbc.csb\n\t(ip-77-48-47-2.net.vodafone.cz. [77.48.47.2])\n\tby smtp.gmail.com with ESMTPSA id\n\ta640c23a62f3a-ace6ecf9a64sm313077166b.123.2025.04.26.10.35.05\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSat, 26 Apr 2025 10:35:05 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=redhat.com header.i=@redhat.com\n\theader.b=\"LUEI+DMJ\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n\ts=mimecast20190719; t=1745688910;\n\th=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n\tto:to:cc:cc:mime-version:mime-version:content-type:content-type:\n\tin-reply-to:in-reply-to:references:references;\n\tbh=cFEri+B5ymcwO00Ku0ZJO8PyWn+JdSbZylJiDAaHq54=;\n\tb=LUEI+DMJSBI83dGz0LDEf30M8azsSmk7D1hir98WQAlP+qROiELP+Rg+1awnDZ/V7+5tJ/\n\tAbCBwSWWyMJdqT3spAk6h2kKrsoM9AfEZ3P4cmSbZAOMo1lqG+3apzlD0wD32yUpuZHZIr\n\tiQBtW7QojyAYNetPNumIwC+A0T1rxCY=","X-MC-Unique":"zCgmjyytMc2JLyCBhu9sWw-1","X-Mimecast-MFC-AGG-ID":"zCgmjyytMc2JLyCBhu9sWw_1745688908","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20230601; t=1745688907; x=1746293707;\n\th=mime-version:user-agent:message-id:date:references:in-reply-to\n\t:subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date\n\t:message-id:reply-to;\n\tbh=cFEri+B5ymcwO00Ku0ZJO8PyWn+JdSbZylJiDAaHq54=;\n\tb=dkNdSgWSnNr0j9qyuQlYcIZ5ZdE9F28q4Kj9VK9XKZ0ynZ8FlK00sgyPVfWURVWIxA\n\tIgI4JgoQFBdiZ6uXrxuHUxemktuicPqV/PfRScuuw0I6Mvhs1/chqjHxrAKAPfAwqQQc\n\t7OgUMQNqzx12hebc/fzBSV/tPP0ilv7kOo3uXKZ5z4y71+f7ewVwSiaq7ywNMozv96Ot\n\tf14Bwr0Q99IaviKpRcCD7S6lYpxoCGLMOaKIqZhph/cgTM5CB+3FW2wTkKj0Qhf8iNUN\n\tEn2wJ4Hb5MuJMDuq8UTcIZX92ntKrz8QFf0LP8NOa3QZOqeIKhmv6zCOyATWktsax5LS\n\tiAOw==","X-Gm-Message-State":"AOJu0Yx55X9bea1G9rsYST8Yjni6NOOBDuPpUVqnTOMHPlBQai0Y8UdR\n\tMmyFn4kTrUhjIGf8wWrCI9v4/+EJEldCg3DMwab6w5725VGb5zq1I6nAUp4Oub1gR/sdsbyZdZM\n\tA/jdDHzTFF/PVISXvthBSyShLzS8LgxxgBGZ9RGmD1YMRZI9R8wkX/6o9mpIGM9afD8j69ithjI\n\tW0PK5P1TjyJGJ/KnL+bAimoaojWI5fgmipssw8yYu1HHGURc+rjNb+DJE=","X-Gm-Gg":"ASbGncvFupF1A66peFEb4Wmmte+IRA5Phly/RZvqMwfeqPSEALiHqDv5jjPy3dIZhSr\n\tm49d6b5ccUa8gwdm7BL94HFnSN224X4bem8XamdUrUhVMlOsGyNHr2k/QWflDtep0UN9r8ZC2hg\n\tJiVv5CCHUDXPz2lTixC+QbWH99/qm2YpmN3iAykJwH7EyOdk1dNeCHJamvgqgBCNOp4Djgdfcqe\n\tvT+L5raK5tdwqH1/izoyGtXKGrwJnMvRnXicQTsiN0TCt5OUMJcm5Z9YhE+GsWladx5Mb2J/cgW\n\trjcAtfDOC8vRKIlug2TK/d3bSqmm5nW6mpsE03ugmCZ4Oooy9/Zlps6wzaFqVqoA","X-Received":["by 2002:a17:907:8693:b0:aca:c57f:3a1b with SMTP id\n\ta640c23a62f3a-ace713df0f3mr652976566b.54.1745688906950; \n\tSat, 26 Apr 2025 10:35:06 -0700 (PDT)","by 2002:a17:907:8693:b0:aca:c57f:3a1b with SMTP id\n\ta640c23a62f3a-ace713df0f3mr652973666b.54.1745688906410; \n\tSat, 26 Apr 2025 10:35:06 -0700 (PDT)"],"X-Google-Smtp-Source":"AGHT+IFage6rdBujqqZtjFKROo96pW20AaQJnuWFNEvyvojuqk/+Nm4fpG/8FO4Y3C8VcxnekTsY/w==","From":"Milan Zamazal <mzamazal@redhat.com>","To":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","In-Reply-To":"<20250423091208.2935632-1-paul.elder@ideasonboard.com> (Paul\n\tElder's message of \"Wed, 23 Apr 2025 18:12:08 +0900\")","References":"<20250423091208.2935632-1-paul.elder@ideasonboard.com>","Date":"Sat, 26 Apr 2025 19:35:04 +0200","Message-ID":"<85jz76zv07.fsf@mzamazal-thinkpadp1gen7.tpbc.csb>","User-Agent":"Gnus/5.13 (Gnus v5.13)","MIME-Version":"1.0","X-Mimecast-Spam-Score":"0","X-Mimecast-MFC-PROC-ID":"DoKaKj4bje1oNbGI7M7Tv0z1UEh9qRbW8d8rIu-cup8_1745688908","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain","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":34156,"web_url":"https://patchwork.libcamera.org/comment/34156/","msgid":"<20250507193416.GA1142661@ragnatech.se>","date":"2025-05-07T19:34:16","subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Paul,\n\nThanks for your work that is now now commit ee2b011b65c6 (\"apps: cam: \nTry raw role if default viewfinder role fails\").\n\nI'm afraid this seems to breaks qcam for me.\n\n    arm64 ~ # ./ktool/build/src/apps/qcam/qcam -c 'imx219 1-0010'\n    qt.qpa.xcb: XKeyboard extension not present on the X server\n    There is no XRandR 1.2 and later version available. There will be only fake screen(s) to use.\n    [0:31:31.233222393] [794]  INFO IPAManager ipa_manager.cpp:137 libcamera is not installed. Adding '/root/ktool/build/src/ipa' to the IPA search path\n    [0:31:31.237485661] [794]  WARN IPAManager ipa_manager.cpp:148 No IPA found in '/usr/local/lib/libcamera'\n    [0:31:31.238603349] [794]  INFO Camera camera_manager.cpp:326 libcamera v0.5.0\n    /usr/include/c++/14.2.1/bits/stl_vector.h:1130: std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[](size_type) [with _Tp = libcamera::StreamRole; _Alloc = std::allocator<libcamera::StreamRole>; reference = libcamera::StreamRole&; size_type = long unsigned int]: Assertion '__n < this->size()' failed.\n    Aborted (core dumped)\n\nThe gdb tracenack points to MainWindow::startCapture() and if I revert \nthe commit it seems to solve the problem.\n\n    arm64 ~ # ./ktool/build/src/apps/qcam/qcam -c 'imx219 1-0010'\n    qt.qpa.xcb: XKeyboard extension not present on the X server\n    There is no XRandR 1.2 and later version available. There will be only fake screen(s) to use.\n    [0:28:16.505731015] [746]  INFO IPAManager ipa_manager.cpp:137 libcamera is not installed. Adding '/root/ktool/build/src/ipa' to the IPA search path\n    [0:28:16.509698783] [746]  WARN IPAManager ipa_manager.cpp:148 No IPA found in '/usr/local/lib/libcamera'\n    [0:28:16.510769671] [746]  INFO Camera camera_manager.cpp:326 libcamera v0.5.0\n    [0:28:16.689332683] [746]  INFO Camera camera.cpp:1205 configuring streams: (0) 3280x2464-XRGB8888/Rec709/Rec709/None/Full\n    Zero-copy enabled\n\n      .... viewfinder displays live images ....\n\nI have tested without the -c 'camera' option too, I then get the GUI to \nselect a camera. And then the same crash as reported above with -c \n'camera' provided.\n\nIf I however force a viewfinder role as such,\n\n    arm64 ~ # ./ktool/build/src/apps/qcam/qcam -c 'imx219 1-0010' -s role=viewfinder\n\nI get a functional viewfinder again.\n\nOn 2025-04-23 18:12:08 +0900, Paul Elder wrote:\n> cam currently defaults to the viewfinder role when no role is specified.\n> This means that on platforms that only support the raw role (such as a\n> raw sensor with no softISP on a simple pipeline platform),\n> generateConfiguration() would return nullptr and cam would bail out.\n> \n> At least this is what is supposed to happen based on the little\n> documentation that we have written regarding generateConfiguration(),\n> specifically in the application writer's guide, which is probably the\n> most influential piece of documentation:\n> \n>   The ``Camera::generateConfiguration()`` function accepts a list of\n>   desired roles and generates a ``CameraConfiguration`` with the best\n>   stream parameters configuration for each of the requested roles. If the\n>   camera can handle the requested roles, it returns an initialized\n>   ``CameraConfiguration`` and a null pointer if it can't.\n> \n> Currently the simple pipeline handler will return a raw configuration\n> anyway (if it only supports raw) even if a non-raw role was requested.\n> Thus cam receives a raw configuration instead of a nullptr when no role\n> is specified and viewfinder is requested.\n> \n> However, in the near future, support for raw streams with softISP on the\n> simple pipeline handler will be merged. This will notably change the\n> behavior of the simple pipeline handler to return nullptr if a non-raw\n> role was requested on a platform that only supports raw. This is proper\n> behavior according to documentation, but changes cam's behavior as it\n> used to capture fine with no parameters but will no longer be able to.\n> \n> Technically this is an issue with the roles API, as we are mixing\n> roles in the sense of \"configuration hints\" (eg. viewfinder vs recording\n> vs still capture) with roles in the sense of \"platform capabilities\"\n> (raw vs everything else). In the long term the proper solution is to\n> rework the roles API.\n> \n> In the meantime, fix cam so that it will try the raw role if the default\n> viewfinder role returns no configuration. cam is an app that is capable\n> of using the raw stream, so this is appropriate behavior. If roles are\n> specified, then do not retry, as in this situation the user knows what\n> streams they can use and what they want.\n> \n> Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> ---\n>  src/apps/cam/camera_session.cpp    | 29 +++++++++++++++++++++++++----\n>  src/apps/common/stream_options.cpp |  3 +--\n>  src/apps/qcam/main_window.cpp      |  3 +++\n>  3 files changed, 29 insertions(+), 6 deletions(-)\n> \n> diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp\n> index 97c1ae44995e..f63fcb228519 100644\n> --- a/src/apps/cam/camera_session.cpp\n> +++ b/src/apps/cam/camera_session.cpp\n> @@ -62,11 +62,32 @@ CameraSession::CameraSession(CameraManager *cm,\n>  \t\treturn;\n>  \t}\n>  \n> -\tstd::vector<StreamRole> roles = StreamKeyValueParser::roles(options_[OptStream]);\n> +\tstd::vector<StreamRole> roles =\n> +\t\tStreamKeyValueParser::roles(options_[OptStream]);\n> +\tstd::vector<std::vector<StreamRole>> tryRoles;\n> +\tif (!roles.empty()) {\n> +\t\t/*\n> +\t\t * If the roles are explicitly specified then there's no need\n> +\t\t * to try other roles\n> +\t\t */\n> +\t\ttryRoles.push_back(roles);\n> +\t} else {\n> +\t\ttryRoles.push_back({ StreamRole::Viewfinder });\n> +\t\ttryRoles.push_back({ StreamRole::Raw });\n> +\t}\n> +\n> +\tstd::unique_ptr<CameraConfiguration> config;\n> +\tbool valid = false;\n> +\tfor (std::vector<StreamRole> &rolesIt : tryRoles) {\n> +\t\tconfig = camera_->generateConfiguration(rolesIt);\n> +\t\tif (config && config->size() == rolesIt.size()) {\n> +\t\t\troles = rolesIt;\n> +\t\t\tvalid = true;\n> +\t\t\tbreak;\n> +\t\t}\n> +\t}\n>  \n> -\tstd::unique_ptr<CameraConfiguration> config =\n> -\t\tcamera_->generateConfiguration(roles);\n> -\tif (!config || config->size() != roles.size()) {\n> +\tif (!valid) {\n>  \t\tstd::cerr << \"Failed to get default stream configuration\"\n>  \t\t\t  << std::endl;\n>  \t\treturn;\n> diff --git a/src/apps/common/stream_options.cpp b/src/apps/common/stream_options.cpp\n> index 99239e07e302..288f86530351 100644\n> --- a/src/apps/common/stream_options.cpp\n> +++ b/src/apps/common/stream_options.cpp\n> @@ -42,9 +42,8 @@ KeyValueParser::Options StreamKeyValueParser::parse(const char *arguments)\n>  \n>  std::vector<StreamRole> StreamKeyValueParser::roles(const OptionValue &values)\n>  {\n> -\t/* If no configuration values to examine default to viewfinder. */\n>  \tif (values.empty())\n> -\t\treturn { StreamRole::Viewfinder };\n> +\t\treturn {};\n>  \n>  \tconst std::vector<OptionValue> &streamParameters = values.toArray();\n>  \n> diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\n> index d2ccbd2318fa..224a7e5a693a 100644\n> --- a/src/apps/qcam/main_window.cpp\n> +++ b/src/apps/qcam/main_window.cpp\n> @@ -356,6 +356,9 @@ int MainWindow::startCapture()\n>  \n>  \t/* Verify roles are supported. */\n>  \tswitch (roles.size()) {\n> +\tcase 0:\n> +\t\troles[0] = StreamRole::Viewfinder;\n> +\t\tbreak;\n>  \tcase 1:\n>  \t\tif (roles[0] != StreamRole::Viewfinder) {\n>  \t\t\tqWarning() << \"Only viewfinder supported for single stream\";\n> -- \n> 2.47.2\n>","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id E9563C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  7 May 2025 19:34:23 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 1E81B68B40;\n\tWed,  7 May 2025 21:34:23 +0200 (CEST)","from fhigh-a7-smtp.messagingengine.com\n\t(fhigh-a7-smtp.messagingengine.com [103.168.172.158])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 85A6C68B3F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  7 May 2025 21:34:20 +0200 (CEST)","from phl-compute-07.internal (phl-compute-07.phl.internal\n\t[10.202.2.47])\n\tby mailfhigh.phl.internal (Postfix) with ESMTP id 64E731140138;\n\tWed,  7 May 2025 15:34:19 -0400 (EDT)","from phl-mailfrontend-01 ([10.202.2.162])\n\tby phl-compute-07.internal (MEProxy); Wed, 07 May 2025 15:34:19 -0400","by mail.messagingengine.com (Postfix) with ESMTPA; Wed,\n\t7 May 2025 15:34:18 -0400 (EDT)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (2048-bit key;\n\tunprotected) header.d=ragnatech.se header.i=@ragnatech.se\n\theader.b=\"gqpWunMZ\"; dkim=pass (2048-bit key;\n\tunprotected) header.d=messagingengine.com\n\theader.i=@messagingengine.com header.b=\"wEZkV+OW\"; \n\tdkim-atps=neutral","DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/relaxed; d=ragnatech.se; h=\n\tcc:cc:content-transfer-encoding:content-type:content-type:date\n\t:date:from:from:in-reply-to:in-reply-to:message-id:mime-version\n\t:references:reply-to:subject:subject:to:to; s=fm2; t=1746646459;\n\tx=1746732859; bh=GRIs5Rurz/AVPmKaLu6s78tRTzFBRj6jf1ttsvYYfPs=; b=\n\tgqpWunMZk68ooWf5UD9xT6+n9+mWUh+zLpDLuX9K/gMgMR5u1DucM+nNMSdbp7q8\n\tcXzUIjknXEoH0Cs04q+tnZxCgYSUUzAJARcsDcR3Xs/mglphLMilU52LVmJgINwZ\n\tTcy5Jmi+2jBdjbUCvdV+PkEuBlfYUmetG0q1sWxpPxfczwZHFW8kzTsS9ypIlpyQ\n\txY6InzoMbEp6DhQA0VNhcMxeQEaqQoQ/MxLD/Iczte0Q/AJENGSibF4Pd4qeLv7Q\n\ts89Z6ZBwiiTbY8kgw/2rKyQ+mg/se6yyyqyT3viJ8KBY67/2jd9yfpO5ehglTsID\n\tAqTw/RwTHN0StdJp/pesSA==","v=1; a=rsa-sha256; c=relaxed/relaxed; d=\n\tmessagingengine.com; h=cc:cc:content-transfer-encoding\n\t:content-type:content-type:date:date:feedback-id:feedback-id\n\t:from:from:in-reply-to:in-reply-to:message-id:mime-version\n\t:references:reply-to:subject:subject:to:to:x-me-proxy\n\t:x-me-sender:x-me-sender:x-sasl-enc; s=fm3; t=1746646459; x=\n\t1746732859; bh=GRIs5Rurz/AVPmKaLu6s78tRTzFBRj6jf1ttsvYYfPs=; b=w\n\tEZkV+OWUAMiSw+jyON6Zs8CwqkKvjFk95qLTPPXsAsbjZtf3fIYlXWz3r2kp15aJ\n\tEpIxdEzM53GmP6fjLSU9Rrt0iZY6AQdlXpUvxMQgClHrTCPETMU3eKkM3BFl6XLP\n\tCyvlvyawQBkbIRt2T7HOYijhitbTYRDlajAIppWREfkcIwm7qvuiG9kTXZLTazkK\n\t0OZMyGWH7y6c0a4jr9MngfxmC5E+TdaKmZUQC/COO3bz5abYkv5KIQ/BPuVC9ZTD\n\tozYi5/ax2VUJr4LJ4UTQ25LNsQ9qVzvB3vJB8DODVdGN2VKJLSfghDF+Mvmt+uBa\n\tCL/45yr5u/T4Tf92zDgOw=="],"X-ME-Sender":"<xms:urUbaCruhVyjvDaA4lNMVSCIt-RNS4WGGm7HUBBk5_IccG-lrHfosA>\n\t<xme:urUbaApArvtUjHN4xS4kvWoP3INlz_xkaE75sEnqiwQZOWDvAGyOW6NEntG03HwhR\n\tHlRVRTG8m-Kl_ZURZw>","X-ME-Received":"<xmr:urUbaHOYUmOsVnz0v84t-IBXugwq2Dkkw-sEyrPK5KHvCNsEiV7p9sCVLWiTvwqeRQ7iL5eANMucS1EMKXhPjSbG>","X-ME-Proxy-Cause":"gggruggvucftvghtrhhoucdtuddrgeefvddrtddtgddvkeejjeduucetufdoteggodetrf\n\tdotffvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdggtfgfnhhsuhgsshgtrhhisggv\n\tpdfurfetoffkrfgpnffqhgenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpih\n\tgvnhhtshculddquddttddmnecujfgurhepfffhvfevuffkfhggtggugfgjsehtkeertddt\n\ttdejnecuhfhrohhmpefpihhklhgrshcuufpnuggvrhhluhhnugcuoehnihhklhgrshdrsh\n\thouggvrhhluhhnugesrhgrghhnrghtvggthhdrshgvqeenucggtffrrghtthgvrhhnpeev\n\tteegtddvvdfhtdekgefhfeefheetheekkeegfeejudeiudeuleegtdehkeekteenucevlh\n\thushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehnihhklhgrshdr\n\tshhouggvrhhluhhnugesrhgrghhnrghtvggthhdrshgvpdhnsggprhgtphhtthhopedvpd\n\thmohguvgepshhmthhpohhuthdprhgtphhtthhopehprghulhdrvghluggvrhesihguvggr\n\tshhonhgsohgrrhgurdgtohhmpdhrtghpthhtoheplhhisggtrghmvghrrgdquggvvhgvlh\n\teslhhishhtshdrlhhisggtrghmvghrrgdrohhrgh","X-ME-Proxy":"<xmx:urUbaB6nCQhJpKI68oIjunBq-p6HNRqsfVnXk09y1xbzEVl-W8jzcg>\n\t<xmx:urUbaB7gLGingmG_dpYAlKR4QY9sxidpuUAFNZ4gyiRxLAG2vxRG1w>\n\t<xmx:urUbaBj9BM03h9pinWB86GLv1miVsttaz2gx9eOtMk8OvCL2Jghqqg>\n\t<xmx:urUbaL7kQFvjJ7igi9qHfS1AU-IIiO0fLbdnDrUtkAb0t1aqNwC8Kg>\n\t<xmx:u7UbaARMpPBVM__STgcxL-L439bbCSeT99lfYZ02VpmPfi-ZJgdmspxf>","Feedback-ID":"i80c9496c:Fastmail","Date":"Wed, 7 May 2025 21:34:16 +0200","From":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","To":"Paul Elder <paul.elder@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","Message-ID":"<20250507193416.GA1142661@ragnatech.se>","References":"<20250423091208.2935632-1-paul.elder@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20250423091208.2935632-1-paul.elder@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":34158,"web_url":"https://patchwork.libcamera.org/comment/34158/","msgid":"<174665053136.747038.13442491447264141797@ping.linuxembedded.co.uk>","date":"2025-05-07T20:42:11","subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Quoting Niklas Söderlund (2025-05-07 20:34:16)\n> Hi Paul,\n> \n> Thanks for your work that is now now commit ee2b011b65c6 (\"apps: cam: \n> Try raw role if default viewfinder role fails\").\n> \n> I'm afraid this seems to breaks qcam for me.\n\nEeep - I just tested here and found the same too.\n\nThere's an easy fix that I've just tested.\n\nI'll write a commit message and send after dinner ;-)\n\n--\nKieran\n\n\n> \n>     arm64 ~ # ./ktool/build/src/apps/qcam/qcam -c 'imx219 1-0010'\n>     qt.qpa.xcb: XKeyboard extension not present on the X server\n>     There is no XRandR 1.2 and later version available. There will be only fake screen(s) to use.\n>     [0:31:31.233222393] [794]  INFO IPAManager ipa_manager.cpp:137 libcamera is not installed. Adding '/root/ktool/build/src/ipa' to the IPA search path\n>     [0:31:31.237485661] [794]  WARN IPAManager ipa_manager.cpp:148 No IPA found in '/usr/local/lib/libcamera'\n>     [0:31:31.238603349] [794]  INFO Camera camera_manager.cpp:326 libcamera v0.5.0\n>     /usr/include/c++/14.2.1/bits/stl_vector.h:1130: std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::operator[](size_type) [with _Tp = libcamera::StreamRole; _Alloc = std::allocator<libcamera::StreamRole>; reference = libcamera::StreamRole&; size_type = long unsigned int]: Assertion '__n < this->size()' failed.\n>     Aborted (core dumped)\n> \n> The gdb tracenack points to MainWindow::startCapture() and if I revert \n> the commit it seems to solve the problem.\n> \n>     arm64 ~ # ./ktool/build/src/apps/qcam/qcam -c 'imx219 1-0010'\n>     qt.qpa.xcb: XKeyboard extension not present on the X server\n>     There is no XRandR 1.2 and later version available. There will be only fake screen(s) to use.\n>     [0:28:16.505731015] [746]  INFO IPAManager ipa_manager.cpp:137 libcamera is not installed. Adding '/root/ktool/build/src/ipa' to the IPA search path\n>     [0:28:16.509698783] [746]  WARN IPAManager ipa_manager.cpp:148 No IPA found in '/usr/local/lib/libcamera'\n>     [0:28:16.510769671] [746]  INFO Camera camera_manager.cpp:326 libcamera v0.5.0\n>     [0:28:16.689332683] [746]  INFO Camera camera.cpp:1205 configuring streams: (0) 3280x2464-XRGB8888/Rec709/Rec709/None/Full\n>     Zero-copy enabled\n> \n>       .... viewfinder displays live images ....\n> \n> I have tested without the -c 'camera' option too, I then get the GUI to \n> select a camera. And then the same crash as reported above with -c \n> 'camera' provided.\n> \n> If I however force a viewfinder role as such,\n> \n>     arm64 ~ # ./ktool/build/src/apps/qcam/qcam -c 'imx219 1-0010' -s role=viewfinder\n> \n> I get a functional viewfinder again.\n> \n> On 2025-04-23 18:12:08 +0900, Paul Elder wrote:\n> > cam currently defaults to the viewfinder role when no role is specified.\n> > This means that on platforms that only support the raw role (such as a\n> > raw sensor with no softISP on a simple pipeline platform),\n> > generateConfiguration() would return nullptr and cam would bail out.\n> > \n> > At least this is what is supposed to happen based on the little\n> > documentation that we have written regarding generateConfiguration(),\n> > specifically in the application writer's guide, which is probably the\n> > most influential piece of documentation:\n> > \n> >   The ``Camera::generateConfiguration()`` function accepts a list of\n> >   desired roles and generates a ``CameraConfiguration`` with the best\n> >   stream parameters configuration for each of the requested roles. If the\n> >   camera can handle the requested roles, it returns an initialized\n> >   ``CameraConfiguration`` and a null pointer if it can't.\n> > \n> > Currently the simple pipeline handler will return a raw configuration\n> > anyway (if it only supports raw) even if a non-raw role was requested.\n> > Thus cam receives a raw configuration instead of a nullptr when no role\n> > is specified and viewfinder is requested.\n> > \n> > However, in the near future, support for raw streams with softISP on the\n> > simple pipeline handler will be merged. This will notably change the\n> > behavior of the simple pipeline handler to return nullptr if a non-raw\n> > role was requested on a platform that only supports raw. This is proper\n> > behavior according to documentation, but changes cam's behavior as it\n> > used to capture fine with no parameters but will no longer be able to.\n> > \n> > Technically this is an issue with the roles API, as we are mixing\n> > roles in the sense of \"configuration hints\" (eg. viewfinder vs recording\n> > vs still capture) with roles in the sense of \"platform capabilities\"\n> > (raw vs everything else). In the long term the proper solution is to\n> > rework the roles API.\n> > \n> > In the meantime, fix cam so that it will try the raw role if the default\n> > viewfinder role returns no configuration. cam is an app that is capable\n> > of using the raw stream, so this is appropriate behavior. If roles are\n> > specified, then do not retry, as in this situation the user knows what\n> > streams they can use and what they want.\n> > \n> > Signed-off-by: Paul Elder <paul.elder@ideasonboard.com>\n> > ---\n> >  src/apps/cam/camera_session.cpp    | 29 +++++++++++++++++++++++++----\n> >  src/apps/common/stream_options.cpp |  3 +--\n> >  src/apps/qcam/main_window.cpp      |  3 +++\n> >  3 files changed, 29 insertions(+), 6 deletions(-)\n> > \n> > diff --git a/src/apps/cam/camera_session.cpp b/src/apps/cam/camera_session.cpp\n> > index 97c1ae44995e..f63fcb228519 100644\n> > --- a/src/apps/cam/camera_session.cpp\n> > +++ b/src/apps/cam/camera_session.cpp\n> > @@ -62,11 +62,32 @@ CameraSession::CameraSession(CameraManager *cm,\n> >               return;\n> >       }\n> >  \n> > -     std::vector<StreamRole> roles = StreamKeyValueParser::roles(options_[OptStream]);\n> > +     std::vector<StreamRole> roles =\n> > +             StreamKeyValueParser::roles(options_[OptStream]);\n> > +     std::vector<std::vector<StreamRole>> tryRoles;\n> > +     if (!roles.empty()) {\n> > +             /*\n> > +              * If the roles are explicitly specified then there's no need\n> > +              * to try other roles\n> > +              */\n> > +             tryRoles.push_back(roles);\n> > +     } else {\n> > +             tryRoles.push_back({ StreamRole::Viewfinder });\n> > +             tryRoles.push_back({ StreamRole::Raw });\n> > +     }\n> > +\n> > +     std::unique_ptr<CameraConfiguration> config;\n> > +     bool valid = false;\n> > +     for (std::vector<StreamRole> &rolesIt : tryRoles) {\n> > +             config = camera_->generateConfiguration(rolesIt);\n> > +             if (config && config->size() == rolesIt.size()) {\n> > +                     roles = rolesIt;\n> > +                     valid = true;\n> > +                     break;\n> > +             }\n> > +     }\n> >  \n> > -     std::unique_ptr<CameraConfiguration> config =\n> > -             camera_->generateConfiguration(roles);\n> > -     if (!config || config->size() != roles.size()) {\n> > +     if (!valid) {\n> >               std::cerr << \"Failed to get default stream configuration\"\n> >                         << std::endl;\n> >               return;\n> > diff --git a/src/apps/common/stream_options.cpp b/src/apps/common/stream_options.cpp\n> > index 99239e07e302..288f86530351 100644\n> > --- a/src/apps/common/stream_options.cpp\n> > +++ b/src/apps/common/stream_options.cpp\n> > @@ -42,9 +42,8 @@ KeyValueParser::Options StreamKeyValueParser::parse(const char *arguments)\n> >  \n> >  std::vector<StreamRole> StreamKeyValueParser::roles(const OptionValue &values)\n> >  {\n> > -     /* If no configuration values to examine default to viewfinder. */\n> >       if (values.empty())\n> > -             return { StreamRole::Viewfinder };\n> > +             return {};\n> >  \n> >       const std::vector<OptionValue> &streamParameters = values.toArray();\n> >  \n> > diff --git a/src/apps/qcam/main_window.cpp b/src/apps/qcam/main_window.cpp\n> > index d2ccbd2318fa..224a7e5a693a 100644\n> > --- a/src/apps/qcam/main_window.cpp\n> > +++ b/src/apps/qcam/main_window.cpp\n> > @@ -356,6 +356,9 @@ int MainWindow::startCapture()\n> >  \n> >       /* Verify roles are supported. */\n> >       switch (roles.size()) {\n> > +     case 0:\n> > +             roles[0] = StreamRole::Viewfinder;\n> > +             break;\n> >       case 1:\n> >               if (roles[0] != StreamRole::Viewfinder) {\n> >                       qWarning() << \"Only viewfinder supported for single stream\";\n> > -- \n> > 2.47.2\n> > \n> \n> -- \n> Kind Regards,\n> Niklas Söderlund","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 CE5B8C3226\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed,  7 May 2025 20:42:15 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 14A0768B45;\n\tWed,  7 May 2025 22:42:15 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 5BE5168B3F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  7 May 2025 22:42:14 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9664DE92;\n\tWed,  7 May 2025 22:42:02 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"ukg39vnb\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1746650522;\n\tbh=1plUNrFGIG8+cEN9ejYZhZx1F/5eHlLlHHsd1BLueds=;\n\th=In-Reply-To:References:Subject:From:Cc:To:Date:From;\n\tb=ukg39vnbAa7U1TY6Jsgvk6nY9U8lGxPBcwizH5iQn9bHALlHGsXLFbvyR8l+cCEMC\n\tOepQ+vv5g8Q5uIYbeFB9vH6DLlZntNp7PFA0/cLF5BBNaLbmt9KUqIfmMLkqOfEHVL\n\tdvnCpu3JmtyTaJU6T2LPLH65r3WS/N4F2ekFR80o=","Content-Type":"text/plain; charset=\"utf-8\"","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","In-Reply-To":"<20250507193416.GA1142661@ragnatech.se>","References":"<20250423091208.2935632-1-paul.elder@ideasonboard.com>\n\t<20250507193416.GA1142661@ragnatech.se>","Subject":"Re: [PATCH] apps: cam: Try raw role if default viewfinder role fails","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>,\n\tPaul Elder <paul.elder@ideasonboard.com>","Date":"Wed, 07 May 2025 21:42:11 +0100","Message-ID":"<174665053136.747038.13442491447264141797@ping.linuxembedded.co.uk>","User-Agent":"alot/0.10","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>"}}]