[{"id":11720,"web_url":"https://patchwork.libcamera.org/comment/11720/","msgid":"<20200729151840.GH6183@pendragon.ideasonboard.com>","date":"2020-07-29T15:18:40","subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: raspberrypi: Apply\n\ttransform and pass through to IPA","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi David,\n\nThank you for the patch.\n\nOn Wed, Jul 29, 2020 at 10:31:51AM +0100, David Plowman wrote:\n> The user-supplied transform is applied to the camera, taking account\n> of any pre-existing rotation. It is then also plumbed through to the\n> IPA so that it will (in a further commit) be able to make use of\n> it.\n> ---\n>  include/libcamera/ipa/raspberrypi.h           |  1 +\n>  src/ipa/raspberrypi/raspberrypi.cpp           | 13 ++++++++-\n>  .../pipeline/raspberrypi/raspberrypi.cpp      | 27 +++++++++++++++++--\n>  3 files changed, 38 insertions(+), 3 deletions(-)\n> \n> diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h\n> index ca62990..3905a4a 100644\n> --- a/include/libcamera/ipa/raspberrypi.h\n> +++ b/include/libcamera/ipa/raspberrypi.h\n> @@ -14,6 +14,7 @@ enum RPiConfigParameters {\n>  \tRPI_IPA_CONFIG_LS_TABLE = (1 << 0),\n>  \tRPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),\n>  \tRPI_IPA_CONFIG_SENSOR = (1 << 2),\n> +\tRPI_IPA_CONFIG_TRANSFORM = (1 << 3),\n\nI would drop this flag and always pass the transform value. You could\nalso store it first to avoid the next_element variable below.\n\n>  };\n>  \n>  enum RPiOperations {\n> diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> index 3747208..2809521 100644\n> --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> @@ -21,6 +21,7 @@\n>  #include <libcamera/ipa/raspberrypi.h>\n>  #include <libcamera/request.h>\n>  #include <libcamera/span.h>\n> +#include <libcamera/transform.h>\n>  \n>  #include <libipa/ipa_interface_wrapper.h>\n>  \n> @@ -144,6 +145,9 @@ private:\n>  \t/* LS table allocation passed in from the pipeline handler. */\n>  \tFileDescriptor lsTableHandle_;\n>  \tvoid *lsTable_;\n> +\n> +\t/* This is the transform requested by the user/application driving libcamera. */\n> +\tTransform userTransform_;\n>  };\n>  \n>  int IPARPi::init(const IPASettings &settings)\n> @@ -282,6 +286,7 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>  \tlastMode_ = mode_;\n>  \n>  \t/* Store the lens shading table pointer and handle if available. */\n> +\tunsigned int next_element = 0;\n>  \tif (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {\n>  \t\t/* Remove any previous table, if there was one. */\n>  \t\tif (lsTable_) {\n> @@ -290,7 +295,7 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>  \t\t}\n>  \n>  \t\t/* Map the LS table buffer into user space. */\n> -\t\tlsTableHandle_ = FileDescriptor(ipaConfig.data[0]);\n> +\t\tlsTableHandle_ = FileDescriptor(ipaConfig.data[next_element++]);\n>  \t\tif (lsTableHandle_.isValid()) {\n>  \t\t\tlsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,\n>  \t\t\t\t\tMAP_SHARED, lsTableHandle_.fd(), 0);\n> @@ -301,6 +306,12 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n>  \t\t\t}\n>  \t\t}\n>  \t}\n> +\n> +\t/* Fish out any transform set by the user/application. */\n> +\tif (ipaConfig.operation & RPI_IPA_CONFIG_TRANSFORM) {\n> +\t\tuint32_t transformType = ipaConfig.data[next_element++];\n> +\t\tuserTransform_ = reinterpret_cast<Transform &>(transformType);\n\nI think it would be best to just make the constructor that takes a\nTransform::Type public.\n\n> +\t}\n>  }\n>  \n>  void IPARPi::mapBuffers(const std::vector<IPABuffer> &buffers)\n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index 82a0a4d..5fb427a 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -324,6 +324,9 @@ public:\n>  \tuint32_t expectedSequence_;\n>  \tbool sensorMetadata_;\n>  \n> +\t/* This is the transform requested by the user/application driving libcamera. */\n\nCould you wrap this line at 80 columns ?\n\n> +\tTransform userTransform_;\n> +\n>  \t/*\n>  \t * All the functions in this class are called from a single calling\n>  \t * thread. So, we do not need to have any mutex to protect access to any\n> @@ -400,6 +403,9 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n>  \tif (config_.empty())\n>  \t\treturn Invalid;\n>  \n> +\tif (userTransform.contains(Transform::transpose()))\n> +\t\treturn Invalid;\n\nShouldn't you adjust it instead ?\n\n> +\n>  \tunsigned int rawCount = 0, outCount = 0, count = 0, maxIndex = 0;\n>  \tstd::pair<int, Size> outSize[2];\n>  \tSize maxSize;\n> @@ -609,6 +615,9 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n>  \tunsigned int maxIndex = 0;\n>  \tbool rawStream = false;\n>  \n> +\t/* Record the transform requested by the application. */\n> +\tdata->userTransform_ = config->userTransform;\n> +\n>  \t/*\n>  \t * Look for the RAW stream (if given) size as well as the largest\n>  \t * ISP output size.\n> @@ -1140,6 +1149,11 @@ int RPiCameraData::configureIPA()\n>  \t\tipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };\n>  \t}\n>  \n> +\t/* We must pass the user transform to the IPA too. */\n> +\tuint32_t transformType = reinterpret_cast<uint32_t &>(userTransform_);\n> +\tipaConfig.operation |= RPI_IPA_CONFIG_TRANSFORM;\n> +\tipaConfig.data.push_back(transformType);\n> +\n>  \tCameraSensorInfo sensorInfo = {};\n>  \tint ret = sensor_->sensorInfo(&sensorInfo);\n>  \tif (ret) {\n> @@ -1168,8 +1182,17 @@ int RPiCameraData::configureIPA()\n>  \t\t/* Configure the H/V flip controls based on the sensor rotation. */\n>  \t\tControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n>  \t\tint32_t rotation = sensor_->properties().get(properties::Rotation);\n> -\t\tctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> -\t\tctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> +\n> +\t\t/* The camera needs to compose the user transform with the rotation. */\n> +\t\tTransform rotationTransform;\n> +\t\tif (Transform::rotation(rotation, rotationTransform) == false)\n> +\t\t\treturn -EINVAL;\n> +\t\tTransform transform = userTransform_ * rotationTransform;\n> +\n> +\t\tctrls.set(V4L2_CID_HFLIP,\n> +\t\t\t  static_cast<int32_t>(transform.contains(Transform::hflip())));\n> +\t\tctrls.set(V4L2_CID_VFLIP,\n> +\t\t\t  static_cast<int32_t>(transform.contains(Transform::vflip())));\n>  \t\tunicam_[Unicam::Image].dev()->setControls(&ctrls);\n>  \t}\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 1C0BCBD878\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 Jul 2020 15:18:55 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 8EB72613C6;\n\tWed, 29 Jul 2020 17:18:54 +0200 (CEST)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id ECF646039D\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 Jul 2020 17:18:52 +0200 (CEST)","from pendragon.ideasonboard.com (81-175-216-236.bb.dnainternet.fi\n\t[81.175.216.236])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 2880131F;\n\tWed, 29 Jul 2020 17:18:49 +0200 (CEST)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"kRiiaRQR\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1596035929;\n\tbh=1FdAgngGIqKEiI+6NadMHJnY66WiUjoUpot6PLhcLDI=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=kRiiaRQRPQx2OSxVW18Ht0dLmXYzrhzbt/o10VVkbog8vE7EzXU1x1TJJQMX/TMSa\n\t1LrSpYWDuUYBz0GbS0Z6Iy/ZtF3w6h8Bum68hiiDfhMgxNTtbO4frWAQORa03uoWGB\n\t6O3YLwIgS+NlRcmNGzfowR91EYV3qKFlsdvgr7v0=","Date":"Wed, 29 Jul 2020 18:18:40 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"David Plowman <david.plowman@raspberrypi.com>","Message-ID":"<20200729151840.GH6183@pendragon.ideasonboard.com>","References":"<20200729093154.12296-1-david.plowman@raspberrypi.com>\n\t<20200729093154.12296-3-david.plowman@raspberrypi.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200729093154.12296-3-david.plowman@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: raspberrypi: Apply\n\ttransform and pass through to IPA","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>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":11729,"web_url":"https://patchwork.libcamera.org/comment/11729/","msgid":"<CAHW6GY+-E4fC7sq_fs_VDTJ7pZ4T4CaYzo_-w1fAzka0S4gEfA@mail.gmail.com>","date":"2020-07-29T16:42:23","subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: raspberrypi: Apply\n\ttransform and pass through to IPA","submitter":{"id":42,"url":"https://patchwork.libcamera.org/api/people/42/","name":"David Plowman","email":"david.plowman@raspberrypi.com"},"content":"Hi Laurent\n\nThanks for the comments.\n\nOn Wed, 29 Jul 2020 at 16:19, Laurent Pinchart\n<laurent.pinchart@ideasonboard.com> wrote:\n>\n> Hi David,\n>\n> Thank you for the patch.\n>\n> On Wed, Jul 29, 2020 at 10:31:51AM +0100, David Plowman wrote:\n> > The user-supplied transform is applied to the camera, taking account\n> > of any pre-existing rotation. It is then also plumbed through to the\n> > IPA so that it will (in a further commit) be able to make use of\n> > it.\n> > ---\n> >  include/libcamera/ipa/raspberrypi.h           |  1 +\n> >  src/ipa/raspberrypi/raspberrypi.cpp           | 13 ++++++++-\n> >  .../pipeline/raspberrypi/raspberrypi.cpp      | 27 +++++++++++++++++--\n> >  3 files changed, 38 insertions(+), 3 deletions(-)\n> >\n> > diff --git a/include/libcamera/ipa/raspberrypi.h b/include/libcamera/ipa/raspberrypi.h\n> > index ca62990..3905a4a 100644\n> > --- a/include/libcamera/ipa/raspberrypi.h\n> > +++ b/include/libcamera/ipa/raspberrypi.h\n> > @@ -14,6 +14,7 @@ enum RPiConfigParameters {\n> >       RPI_IPA_CONFIG_LS_TABLE = (1 << 0),\n> >       RPI_IPA_CONFIG_STAGGERED_WRITE = (1 << 1),\n> >       RPI_IPA_CONFIG_SENSOR = (1 << 2),\n> > +     RPI_IPA_CONFIG_TRANSFORM = (1 << 3),\n>\n> I would drop this flag and always pass the transform value. You could\n> also store it first to avoid the next_element variable below.\n>\n> >  };\n> >\n> >  enum RPiOperations {\n> > diff --git a/src/ipa/raspberrypi/raspberrypi.cpp b/src/ipa/raspberrypi/raspberrypi.cpp\n> > index 3747208..2809521 100644\n> > --- a/src/ipa/raspberrypi/raspberrypi.cpp\n> > +++ b/src/ipa/raspberrypi/raspberrypi.cpp\n> > @@ -21,6 +21,7 @@\n> >  #include <libcamera/ipa/raspberrypi.h>\n> >  #include <libcamera/request.h>\n> >  #include <libcamera/span.h>\n> > +#include <libcamera/transform.h>\n> >\n> >  #include <libipa/ipa_interface_wrapper.h>\n> >\n> > @@ -144,6 +145,9 @@ private:\n> >       /* LS table allocation passed in from the pipeline handler. */\n> >       FileDescriptor lsTableHandle_;\n> >       void *lsTable_;\n> > +\n> > +     /* This is the transform requested by the user/application driving libcamera. */\n> > +     Transform userTransform_;\n> >  };\n> >\n> >  int IPARPi::init(const IPASettings &settings)\n> > @@ -282,6 +286,7 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n> >       lastMode_ = mode_;\n> >\n> >       /* Store the lens shading table pointer and handle if available. */\n> > +     unsigned int next_element = 0;\n> >       if (ipaConfig.operation & RPI_IPA_CONFIG_LS_TABLE) {\n> >               /* Remove any previous table, if there was one. */\n> >               if (lsTable_) {\n> > @@ -290,7 +295,7 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n> >               }\n> >\n> >               /* Map the LS table buffer into user space. */\n> > -             lsTableHandle_ = FileDescriptor(ipaConfig.data[0]);\n> > +             lsTableHandle_ = FileDescriptor(ipaConfig.data[next_element++]);\n> >               if (lsTableHandle_.isValid()) {\n> >                       lsTable_ = mmap(nullptr, MAX_LS_GRID_SIZE, PROT_READ | PROT_WRITE,\n> >                                       MAP_SHARED, lsTableHandle_.fd(), 0);\n> > @@ -301,6 +306,12 @@ void IPARPi::configure(const CameraSensorInfo &sensorInfo,\n> >                       }\n> >               }\n> >       }\n> > +\n> > +     /* Fish out any transform set by the user/application. */\n> > +     if (ipaConfig.operation & RPI_IPA_CONFIG_TRANSFORM) {\n> > +             uint32_t transformType = ipaConfig.data[next_element++];\n> > +             userTransform_ = reinterpret_cast<Transform &>(transformType);\n>\n> I think it would be best to just make the constructor that takes a\n> Transform::Type public.\n\nIndeed, except that I didn't like the public Type field...  oh dear...!\n\n>\n> > +     }\n> >  }\n> >\n> >  void IPARPi::mapBuffers(const std::vector<IPABuffer> &buffers)\n> > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > index 82a0a4d..5fb427a 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > @@ -324,6 +324,9 @@ public:\n> >       uint32_t expectedSequence_;\n> >       bool sensorMetadata_;\n> >\n> > +     /* This is the transform requested by the user/application driving libcamera. */\n>\n> Could you wrap this line at 80 columns ?\n>\n> > +     Transform userTransform_;\n> > +\n> >       /*\n> >        * All the functions in this class are called from a single calling\n> >        * thread. So, we do not need to have any mutex to protect access to any\n> > @@ -400,6 +403,9 @@ CameraConfiguration::Status RPiCameraConfiguration::validate()\n> >       if (config_.empty())\n> >               return Invalid;\n> >\n> > +     if (userTransform.contains(Transform::transpose()))\n> > +             return Invalid;\n>\n> Shouldn't you adjust it instead ?\n\nAs I said earlier, it wasn't clear to me that \"adjusting\" felt right.\nBut maybe it makes sense, I wonder what we adjust it to - perhaps we\njust set it to \"identity\" if we can't do it, and then it becomes the\napplication's problem to do it in another way?\n\nThanks!\nDavid\n\n>\n> > +\n> >       unsigned int rawCount = 0, outCount = 0, count = 0, maxIndex = 0;\n> >       std::pair<int, Size> outSize[2];\n> >       Size maxSize;\n> > @@ -609,6 +615,9 @@ int PipelineHandlerRPi::configure(Camera *camera, CameraConfiguration *config)\n> >       unsigned int maxIndex = 0;\n> >       bool rawStream = false;\n> >\n> > +     /* Record the transform requested by the application. */\n> > +     data->userTransform_ = config->userTransform;\n> > +\n> >       /*\n> >        * Look for the RAW stream (if given) size as well as the largest\n> >        * ISP output size.\n> > @@ -1140,6 +1149,11 @@ int RPiCameraData::configureIPA()\n> >               ipaConfig.data = { static_cast<unsigned int>(lsTable_.fd()) };\n> >       }\n> >\n> > +     /* We must pass the user transform to the IPA too. */\n> > +     uint32_t transformType = reinterpret_cast<uint32_t &>(userTransform_);\n> > +     ipaConfig.operation |= RPI_IPA_CONFIG_TRANSFORM;\n> > +     ipaConfig.data.push_back(transformType);\n> > +\n> >       CameraSensorInfo sensorInfo = {};\n> >       int ret = sensor_->sensorInfo(&sensorInfo);\n> >       if (ret) {\n> > @@ -1168,8 +1182,17 @@ int RPiCameraData::configureIPA()\n> >               /* Configure the H/V flip controls based on the sensor rotation. */\n> >               ControlList ctrls(unicam_[Unicam::Image].dev()->controls());\n> >               int32_t rotation = sensor_->properties().get(properties::Rotation);\n> > -             ctrls.set(V4L2_CID_HFLIP, static_cast<int32_t>(!!rotation));\n> > -             ctrls.set(V4L2_CID_VFLIP, static_cast<int32_t>(!!rotation));\n> > +\n> > +             /* The camera needs to compose the user transform with the rotation. */\n> > +             Transform rotationTransform;\n> > +             if (Transform::rotation(rotation, rotationTransform) == false)\n> > +                     return -EINVAL;\n> > +             Transform transform = userTransform_ * rotationTransform;\n> > +\n> > +             ctrls.set(V4L2_CID_HFLIP,\n> > +                       static_cast<int32_t>(transform.contains(Transform::hflip())));\n> > +             ctrls.set(V4L2_CID_VFLIP,\n> > +                       static_cast<int32_t>(transform.contains(Transform::vflip())));\n> >               unicam_[Unicam::Image].dev()->setControls(&ctrls);\n> >       }\n> >\n>\n> --\n> Regards,\n>\n> Laurent Pinchart","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 BA9D2BD86F\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 29 Jul 2020 16:42:36 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 2392E617AF;\n\tWed, 29 Jul 2020 18:42:36 +0200 (CEST)","from mail-oi1-x244.google.com (mail-oi1-x244.google.com\n\t[IPv6:2607:f8b0:4864:20::244])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 9078660540\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 Jul 2020 18:42:35 +0200 (CEST)","by mail-oi1-x244.google.com with SMTP id o21so557937oie.12\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 29 Jul 2020 09:42:35 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=raspberrypi.com header.i=@raspberrypi.com\n\theader.b=\"tOvGlJzx\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=raspberrypi.com; s=google;\n\th=mime-version:references:in-reply-to:from:date:message-id:subject:to\n\t:cc; bh=1x3fFeJE3y2RwyZXnBU+h30U3jtF8DaHaGzfb7EjD2M=;\n\tb=tOvGlJzx6BFA/WsvxDJbsRwQ3zDuOO97eioXpmW7mCp0xbPEiff4o6YNMYZcWyItWo\n\t1Xxx7q1eMC5f86lQrWPNe0EvK6nrDKUUuo0jkseMgHREeX1k0dtWQpQrtTRtOOTlAirS\n\tMyIdl4l+BPdMa9IefMTa8Y9t04TW2D/6GHSgpbU6wO7gk8awVJG+Kdcq01AXnMzm2N5X\n\t/EOcDdD/nB9AS+2AkqmCPx4pz+LeboSv4CqxeBbzPbt/yYl6Y2IKi7tai0GcWHvFq0eR\n\tUan1thRQoJVd35uLZx6zPTwhbJkApqaHTIbaAGj4UOVeEOZtyW6FG88QgB/u1Z6DX8Z/\n\tcAwQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:mime-version:references:in-reply-to:from:date\n\t:message-id:subject:to:cc;\n\tbh=1x3fFeJE3y2RwyZXnBU+h30U3jtF8DaHaGzfb7EjD2M=;\n\tb=TEmZok59owRD9OJxn/1QSU3eETQ8roUvA7xMtpa+VZZW1x0ggAAKsXMQghMReh+D+g\n\tMimtEKvsrDY60wmtDshsl17zX9WdnirBOf6n9bzouIOKjEuxNGFDP3tlqEfY0HCHiqIU\n\tTbSY+psNr+1vIRStMx32uLolrm55GGbJIliMdo1LVgqoiCdD/QBpV8hmuXSxgK6rB3fC\n\tJnVYxTIlBWa+rQu1ReJHVTNSxxg/sU6Lm0c3F7KCcnn45+LpgMRrxPAA5579mM+HvHyg\n\thd9/hHy78BDkKyd6tiU4eSKsJ1Zkp6DY3wl5fsFfQfVWin45MC7UFmEzS2o3zrzGfkgt\n\tC6Pw==","X-Gm-Message-State":"AOAM5306b9UsyA4f2zO71Bt1EMFWNpbBL9hmP1alshEpVrmZtOdOnr6Q\n\tF/PyPt48GA3tkdLvplOFQCrrGWAdmmqxWKZ815DzMNg49lc=","X-Google-Smtp-Source":"ABdhPJwd3FbF4157Bq+8PdIfLW+KAAtFFcBwDZpPsOajjN2RYZLByW9DcL1q0eQmI0z9+h+lKVTl+wxXJkhoLuz/bGw=","X-Received":"by 2002:aca:bfc6:: with SMTP id\n\tp189mr8087897oif.55.1596040954240; \n\tWed, 29 Jul 2020 09:42:34 -0700 (PDT)","MIME-Version":"1.0","References":"<20200729093154.12296-1-david.plowman@raspberrypi.com>\n\t<20200729093154.12296-3-david.plowman@raspberrypi.com>\n\t<20200729151840.GH6183@pendragon.ideasonboard.com>","In-Reply-To":"<20200729151840.GH6183@pendragon.ideasonboard.com>","From":"David Plowman <david.plowman@raspberrypi.com>","Date":"Wed, 29 Jul 2020 17:42:23 +0100","Message-ID":"<CAHW6GY+-E4fC7sq_fs_VDTJ7pZ4T4CaYzo_-w1fAzka0S4gEfA@mail.gmail.com>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH 2/5] libcamera: raspberrypi: Apply\n\ttransform and pass through to IPA","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>","Cc":"libcamera-devel@lists.libcamera.org","Content-Type":"text/plain; charset=\"us-ascii\"","Content-Transfer-Encoding":"7bit","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]