[{"id":11430,"web_url":"https://patchwork.libcamera.org/comment/11430/","msgid":"<20200718160400.GB576734@oden.dyn.berto.se>","date":"2020-07-18T16:04:00","subject":"Re: [libcamera-devel] [PATCH v3 10/10] libcamera: pipeline:\n\traspberrypi: Handle any externally allocated FrameBuffer","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Naushir,\n\nThanks for your work.\n\nOn 2020-07-17 09:54:10 +0100, Naushir Patuck wrote:\n> Handle the case where a FrameBuffer that has been externally allocated\n> (i.e. not through the v4l2 video device) is passed into a Request.\n> \n> We must store the buffer pointer in our internal buffer list to identify\n> when used, as well as mmap the buffer in the IPA if needed.\n> \n> Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> ---\n>  .../pipeline/raspberrypi/raspberrypi.cpp      | 94 +++++++++++--------\n>  .../pipeline/raspberrypi/rpi_stream.cpp       |  5 +\n>  .../pipeline/raspberrypi/rpi_stream.h         |  1 +\n>  3 files changed, 63 insertions(+), 37 deletions(-)\n> \n> diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> index e400c10c..99896eee 100644\n> --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> @@ -171,8 +171,8 @@ public:\n>  \tRPi::RPiDevice<Isp, 4> isp_;\n>  \t/* The vector below is just for convenience when iterating over all streams. */\n>  \tstd::vector<RPi::RPiStream *> streams_;\n> -\t/* Buffers passed to the IPA. */\n> -\tstd::vector<IPABuffer> ipaBuffers_;\n> +\t/* Stores the ids of the buffers mapped in the IPA. */\n> +\tstd::vector<unsigned int> ipaBufferIds_;\n>  \n>  \t/* VCSM allocation helper. */\n>  \t::RPi::Vcsm vcsm_;\n> @@ -192,7 +192,6 @@ public:\n>  \tstd::queue<FrameBuffer *> bayerQueue_;\n>  \tstd::queue<FrameBuffer *> embeddedQueue_;\n>  \tstd::deque<Request *> requestQueue_;\n> -\n>  \tunsigned int dropFrameCount_;\n>  \n>  private:\n> @@ -243,6 +242,8 @@ private:\n>  \tint queueAllBuffers(Camera *camera);\n>  \tint prepareBuffers(Camera *camera);\n>  \tvoid freeBuffers(Camera *camera);\n> +\tvoid mapBuffers(Camera *camera, const std::vector<FrameBuffer *> &buffers,\n> +\t\t\tunsigned int startId);\n>  \n>  \tMediaDevice *unicam_;\n>  \tMediaDevice *isp_;\n> @@ -736,20 +737,38 @@ int PipelineHandlerRPi::queueRequestDevice(Camera *camera, Request *request)\n>  \n>  \t/* Push all buffers supplied in the Request to the respective streams. */\n>  \tfor (auto stream : data->streams_) {\n> -\t\tif (stream->isExternal()) {\n> -\t\t\tFrameBuffer *buffer = request->findBuffer(stream);\n> +\t\tif (!stream->isExternal())\n> +\t\t\tcontinue;\n> +\n> +\t\tFrameBuffer *buffer = request->findBuffer(stream);\n> +\t\tif (buffer && stream->getBufferIndex(buffer) == -1) {\n>  \t\t\t/*\n> -\t\t\t * A nullptr in buffer means that we should queue an internally\n> -\t\t\t * allocated buffer.\n> -\t\t\t *\n> -\t\t\t * The below queueBuffer() call will do nothing if there are not\n> -\t\t\t * enough internal buffers allocated, but this will be handled by\n> -\t\t\t * queuing the request for buffers in the RPiStream object.\n> +\t\t\t * This buffer is not recognised, so it must have been allocated\n> +\t\t\t * outside the v4l2 device. Store it in the stream buffer list\n> +\t\t\t * so we can track it.\n>  \t\t\t */\n> -\t\t\tint ret = stream->queueBuffer(buffer);\n> -\t\t\tif (ret)\n> -\t\t\t\treturn ret;\n> +\t\t\tstream->setExternalBuffer(buffer);\n\nThere is noting wrong tracking external buffers in this way but I feel \nit's ill prepared for the scenario where a new external buffer is used \neach time. As the tracking is not undone when foreign buffer buffer \nleaves the pipeline handler, perhaps never to be seen again.\n\n> +\n> +\t\t\t/* Also get the IPA to mmap it if needed. */\n> +\t\t\tif (stream == &data->unicam_[Unicam::Embedded]) {\n> +\t\t\t\tmapBuffers(camera, { buffer },\n> +\t\t\t\t\t   RPiIpaMask::EMBEDDED_DATA | (stream->getBuffers().size() - 1));\n> +\t\t\t} else if (stream == &data->isp_[Isp::Stats]) {\n> +\t\t\t\tmapBuffers(camera, { buffer },\n> +\t\t\t\t\t   RPiIpaMask::STATS | (stream->getBuffers().size() - 1));\n> +\t\t\t}\n\nSame argument here as above but with a hight cost. What if the buffers \nmapped here are never reused and a new buffer is attached to each new \nrequest? Maybe some form of time-to-live would be a middle ground for \nefficiency between always mapping a foreign buffer when it enters the \npipeline and unmap it when it exits?\n\n>  \t\t}\n> +\t\t/*\n> +\t\t * A nullptr in buffer means that we should queue an internally\n> +\t\t * allocated buffer.\n> +\t\t *\n> +\t\t * The below queueBuffer() call will do nothing if there are not\n> +\t\t * enough internal buffers allocated, but this will be handled by\n> +\t\t * queuing the request for buffers in the RPiStream object.\n> +\t\t */\n> +\t\tint ret = stream->queueBuffer(buffer);\n> +\t\tif (ret)\n> +\t\t\treturn ret;\n>  \t}\n>  \n>  \t/* Push the request to the back of the queue. */\n> @@ -888,7 +907,6 @@ int PipelineHandlerRPi::queueAllBuffers(Camera *camera)\n>  int PipelineHandlerRPi::prepareBuffers(Camera *camera)\n>  {\n>  \tRPiCameraData *data = cameraData(camera);\n> -\tunsigned int index;\n>  \tint ret;\n>  \n>  \t/*\n> @@ -908,42 +926,44 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera)\n>  \t\t\treturn ret;\n>  \t}\n>  \n> +\t/*\n> +\t * Pass the stats and embedded data buffers to the IPA. No other\n> +\t * buffers need to be passed.\n> +\t */\n> +\tmapBuffers(camera, data->isp_[Isp::Stats].getBuffers(), RPiIpaMask::STATS);\n> +\tmapBuffers(camera, data->unicam_[Unicam::Embedded].getBuffers(), RPiIpaMask::EMBEDDED_DATA);\n> +\n> +\treturn 0;\n> +}\n> +\n> +void PipelineHandlerRPi::mapBuffers(Camera *camera, const std::vector<FrameBuffer *> &buffers,\n> +\t\t\t\t    unsigned int startId)\n> +{\n> +\tRPiCameraData *data = cameraData(camera);\n> +\tstd::vector<IPABuffer> ipaBuffers;\n> +\tunsigned int id = startId;\n>  \t/*\n>  \t * Link the FrameBuffers with the index of their position in the vector\n> -\t * stored in the RPi stream object.\n> +\t * stored in the RPi stream object - along with an identifer mask.\n>  \t *\n>  \t * This will allow us to identify buffers passed between the pipeline\n>  \t * handler and the IPA.\n>  \t */\n> -\tindex = 0;\n> -\tfor (auto const &b : data->isp_[Isp::Stats].getBuffers()) {\n> -\t\tdata->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | index,\n> -\t\t\t\t\t      .planes = b->planes() });\n> -\t\tindex++;\n> -\t}\n> -\n> -\tindex = 0;\n> -\tfor (auto const &b : data->unicam_[Unicam::Embedded].getBuffers()) {\n> -\t\tdata->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | index,\n> -\t\t\t\t\t      .planes = b->planes() });\n> -\t\tindex++;\n> +\tfor (auto const &b : buffers) {\n> +\t\tipaBuffers.push_back({ .id = id, .planes = b->planes() });\n> +\t\tdata->ipaBufferIds_.push_back(id);\n> +\t\tid++;\n>  \t}\n>  \n> -\tdata->ipa_->mapBuffers(data->ipaBuffers_);\n> -\n> -\treturn 0;\n> +\tdata->ipa_->mapBuffers(ipaBuffers);\n>  }\n>  \n>  void PipelineHandlerRPi::freeBuffers(Camera *camera)\n>  {\n>  \tRPiCameraData *data = cameraData(camera);\n>  \n> -\tstd::vector<unsigned int> ids;\n> -\tfor (IPABuffer &ipabuf : data->ipaBuffers_)\n> -\t\tids.push_back(ipabuf.id);\n> -\n> -\tdata->ipa_->unmapBuffers(ids);\n> -\tdata->ipaBuffers_.clear();\n> +\tdata->ipa_->unmapBuffers(data->ipaBufferIds_);\n> +\tdata->ipaBufferIds_.clear();\n>  \n>  \tfor (auto const stream : data->streams_)\n>  \t\tstream->releaseBuffers();\n> diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp\n> index 61226e94..e4158e3a 100644\n> --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp\n> +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp\n> @@ -48,6 +48,11 @@ void RPiStream::setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *bu\n>  \t\t       [](std::unique_ptr<FrameBuffer> &b) { return b.get(); });\n>  }\n>  \n> +void RPiStream::setExternalBuffer(FrameBuffer *buffer)\n> +{\n> +\tbufferList_.push_back(buffer);\n> +}\n> +\n>  const std::vector<FrameBuffer *> &RPiStream::getBuffers() const\n>  {\n>  \treturn bufferList_;\n> diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> index a6fd5c8e..e2534a32 100644\n> --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> @@ -41,6 +41,7 @@ public:\n>  \tvoid reset();\n>  \tstd::string name() const;\n>  \tvoid setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n> +\tvoid setExternalBuffer(FrameBuffer *buffer);\n>  \tconst std::vector<FrameBuffer *> &getBuffers() const;\n>  \tvoid releaseBuffers();\n>  \tint prepareBuffers(unsigned int count);\n> -- \n> 2.25.1\n> \n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","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 35206C0109\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSat, 18 Jul 2020 16:04:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id AB1A4605B2;\n\tSat, 18 Jul 2020 18:04:03 +0200 (CEST)","from mail-lf1-x133.google.com (mail-lf1-x133.google.com\n\t[IPv6:2a00:1450:4864:20::133])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id AA01860493\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 18 Jul 2020 18:04:02 +0200 (CEST)","by mail-lf1-x133.google.com with SMTP id b30so5353563lfj.12\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 18 Jul 2020 09:04:02 -0700 (PDT)","from localhost (h-209-203.A463.priv.bahnhof.se. [155.4.209.203])\n\tby smtp.gmail.com with ESMTPSA id\n\tm25sm2264384ljj.128.2020.07.18.09.04.00\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSat, 18 Jul 2020 09:04:01 -0700 (PDT)"],"Authentication-Results":"lancelot.ideasonboard.com;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=ragnatech-se.20150623.gappssmtp.com\n\theader.i=@ragnatech-se.20150623.gappssmtp.com\n\theader.b=\"gXDbeMew\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to;\n\tbh=3tJVtMpS4SzdIRaBVVy514vYd5Jw/84sL0knZGjGz70=;\n\tb=gXDbeMewz7qr9p9c9v4cmgyNXz4fBt1Be1FjKHr7/44EjLOtLZ0TjmAAV66jWDiBLr\n\t5oKJodttpiVk8IXNdYE8Pyq1MTiq2ehp4s8JsCaZ65d07MXTZiWAjN40+2CT8J9/vfS2\n\tNH+lmOtXphlFaQlLpQZj5zAwavymmopkgpg7ENQPrGrv/TwKCAGo7a8g58jHyjF3l719\n\tEiYIux4AVY/wNv66QW7X3EEcug5xrY3zpoKMJb1GsqqWyr4/3j8UseJHIS53AC6ax1k6\n\tQtKEzs/sYOIjf4adyAcx3vrtPp7N7yOJ6auXcjN4FXzf/eF/BkyoYFQ7tJjfBUuIP9wo\n\tD9EQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to;\n\tbh=3tJVtMpS4SzdIRaBVVy514vYd5Jw/84sL0knZGjGz70=;\n\tb=W/EqKFidfkpYAJzL0mOM7rJ/TmmR1XwvDKnmIR3RMfkEH7aL/owHg68AFvHKFZM2bq\n\tDfQgaStrd9UY8k+l0WIadVEFrh/9OsNl6WVSUwvdOgxYnFCeozmuGIEBlHOJLvblT14Q\n\txiJS/Lf86YTdr1I9VudWvNBujG+G2EhsAWlAWIgz6/Ib/IV6Tqhj5AYZY449E7iosSpp\n\tAdMuXroX9DT/XlS457GfUS089EIXQPk22XfvVmGtCPaY0buDSTv99AKvdgQ0/22vqf+q\n\twqYSN6o/tE6e8NW4Ca+wT6kl07Q+JJrviHMHn6m0PQ0Vr5VFMjZj5S9xmpaxKUjmPDKr\n\tyJjw==","X-Gm-Message-State":"AOAM533VqtBEt0n+lRk3tP9Lv6VN115siQGaHz3eZn7mwAIGoMZbvdNR\n\tXS4bVViY8EGZYViTAJuZsF/Mxtgbccw=","X-Google-Smtp-Source":"ABdhPJysVwcDg/2Xuvsnx02NZYpCdiIKdbliKYOwRFw8JFYtZhHd654jhCEjzkNQ/QVO5nubfq6LeQ==","X-Received":"by 2002:ac2:569c:: with SMTP id 28mr6885315lfr.195.1595088241900;\n\tSat, 18 Jul 2020 09:04:01 -0700 (PDT)","Date":"Sat, 18 Jul 2020 18:04:00 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Naushir Patuck <naush@raspberrypi.com>","Message-ID":"<20200718160400.GB576734@oden.dyn.berto.se>","References":"<20200717085410.732308-1-naush@raspberrypi.com>\n\t<20200717085410.732308-11-naush@raspberrypi.com>","MIME-Version":"1.0","Content-Disposition":"inline","In-Reply-To":"<20200717085410.732308-11-naush@raspberrypi.com>","Subject":"Re: [libcamera-devel] [PATCH v3 10/10] libcamera: pipeline:\n\traspberrypi: Handle any externally allocated FrameBuffer","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=\"iso-8859-1\"","Content-Transfer-Encoding":"quoted-printable","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":11435,"web_url":"https://patchwork.libcamera.org/comment/11435/","msgid":"<CAEmqJPp7xw=-8mLOPduqpCazcgrJQMs7_Asm2P0Usa7NojcJgw@mail.gmail.com>","date":"2020-07-20T08:06:21","subject":"Re: [libcamera-devel] [PATCH v3 10/10] libcamera: pipeline:\n\traspberrypi: Handle any externally allocated FrameBuffer","submitter":{"id":34,"url":"https://patchwork.libcamera.org/api/people/34/","name":"Naushir Patuck","email":"naush@raspberrypi.com"},"content":"Hi Niklas,\n\nThank you for the review comments, for this and all the patches in the series.\n\nOn Sat, 18 Jul 2020 at 17:04, Niklas Söderlund\n<niklas.soderlund@ragnatech.se> wrote:\n>\n> Hi Naushir,\n>\n> Thanks for your work.\n>\n> On 2020-07-17 09:54:10 +0100, Naushir Patuck wrote:\n> > Handle the case where a FrameBuffer that has been externally allocated\n> > (i.e. not through the v4l2 video device) is passed into a Request.\n> >\n> > We must store the buffer pointer in our internal buffer list to identify\n> > when used, as well as mmap the buffer in the IPA if needed.\n> >\n> > Signed-off-by: Naushir Patuck <naush@raspberrypi.com>\n> > ---\n> >  .../pipeline/raspberrypi/raspberrypi.cpp      | 94 +++++++++++--------\n> >  .../pipeline/raspberrypi/rpi_stream.cpp       |  5 +\n> >  .../pipeline/raspberrypi/rpi_stream.h         |  1 +\n> >  3 files changed, 63 insertions(+), 37 deletions(-)\n> >\n> > diff --git a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > index e400c10c..99896eee 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/raspberrypi.cpp\n> > @@ -171,8 +171,8 @@ public:\n> >       RPi::RPiDevice<Isp, 4> isp_;\n> >       /* The vector below is just for convenience when iterating over all streams. */\n> >       std::vector<RPi::RPiStream *> streams_;\n> > -     /* Buffers passed to the IPA. */\n> > -     std::vector<IPABuffer> ipaBuffers_;\n> > +     /* Stores the ids of the buffers mapped in the IPA. */\n> > +     std::vector<unsigned int> ipaBufferIds_;\n> >\n> >       /* VCSM allocation helper. */\n> >       ::RPi::Vcsm vcsm_;\n> > @@ -192,7 +192,6 @@ public:\n> >       std::queue<FrameBuffer *> bayerQueue_;\n> >       std::queue<FrameBuffer *> embeddedQueue_;\n> >       std::deque<Request *> requestQueue_;\n> > -\n> >       unsigned int dropFrameCount_;\n> >\n> >  private:\n> > @@ -243,6 +242,8 @@ private:\n> >       int queueAllBuffers(Camera *camera);\n> >       int prepareBuffers(Camera *camera);\n> >       void freeBuffers(Camera *camera);\n> > +     void mapBuffers(Camera *camera, const std::vector<FrameBuffer *> &buffers,\n> > +                     unsigned int startId);\n> >\n> >       MediaDevice *unicam_;\n> >       MediaDevice *isp_;\n> > @@ -736,20 +737,38 @@ int PipelineHandlerRPi::queueRequestDevice(Camera *camera, Request *request)\n> >\n> >       /* Push all buffers supplied in the Request to the respective streams. */\n> >       for (auto stream : data->streams_) {\n> > -             if (stream->isExternal()) {\n> > -                     FrameBuffer *buffer = request->findBuffer(stream);\n> > +             if (!stream->isExternal())\n> > +                     continue;\n> > +\n> > +             FrameBuffer *buffer = request->findBuffer(stream);\n> > +             if (buffer && stream->getBufferIndex(buffer) == -1) {\n> >                       /*\n> > -                      * A nullptr in buffer means that we should queue an internally\n> > -                      * allocated buffer.\n> > -                      *\n> > -                      * The below queueBuffer() call will do nothing if there are not\n> > -                      * enough internal buffers allocated, but this will be handled by\n> > -                      * queuing the request for buffers in the RPiStream object.\n> > +                      * This buffer is not recognised, so it must have been allocated\n> > +                      * outside the v4l2 device. Store it in the stream buffer list\n> > +                      * so we can track it.\n> >                        */\n> > -                     int ret = stream->queueBuffer(buffer);\n> > -                     if (ret)\n> > -                             return ret;\n> > +                     stream->setExternalBuffer(buffer);\n>\n> There is noting wrong tracking external buffers in this way but I feel\n> it's ill prepared for the scenario where a new external buffer is used\n> each time. As the tracking is not undone when foreign buffer buffer\n> leaves the pipeline handler, perhaps never to be seen again.\n\nThat is a very good point.  I only assumed that the external buffers\nwould be continually recycled, but that is not necessarily the case.\nI'm going to have to think about this one a bit more - it is quite an\nawkward case to deal with in many ways.  I think what I might do is\nremove this patch from the set, resubmit with your suggestions for the\nother patches, and work on this one separately.  Given that no apps\ncurrently do this, I think it should be ok to ignore this for now :-)\n\nRegards,\nNaush\n\n\n\n>\n> > +\n> > +                     /* Also get the IPA to mmap it if needed. */\n> > +                     if (stream == &data->unicam_[Unicam::Embedded]) {\n> > +                             mapBuffers(camera, { buffer },\n> > +                                        RPiIpaMask::EMBEDDED_DATA | (stream->getBuffers().size() - 1));\n> > +                     } else if (stream == &data->isp_[Isp::Stats]) {\n> > +                             mapBuffers(camera, { buffer },\n> > +                                        RPiIpaMask::STATS | (stream->getBuffers().size() - 1));\n> > +                     }\n>\n> Same argument here as above but with a hight cost. What if the buffers\n> mapped here are never reused and a new buffer is attached to each new\n> request? Maybe some form of time-to-live would be a middle ground for\n> efficiency between always mapping a foreign buffer when it enters the\n> pipeline and unmap it when it exits?\n>\n> >               }\n> > +             /*\n> > +              * A nullptr in buffer means that we should queue an internally\n> > +              * allocated buffer.\n> > +              *\n> > +              * The below queueBuffer() call will do nothing if there are not\n> > +              * enough internal buffers allocated, but this will be handled by\n> > +              * queuing the request for buffers in the RPiStream object.\n> > +              */\n> > +             int ret = stream->queueBuffer(buffer);\n> > +             if (ret)\n> > +                     return ret;\n> >       }\n> >\n> >       /* Push the request to the back of the queue. */\n> > @@ -888,7 +907,6 @@ int PipelineHandlerRPi::queueAllBuffers(Camera *camera)\n> >  int PipelineHandlerRPi::prepareBuffers(Camera *camera)\n> >  {\n> >       RPiCameraData *data = cameraData(camera);\n> > -     unsigned int index;\n> >       int ret;\n> >\n> >       /*\n> > @@ -908,42 +926,44 @@ int PipelineHandlerRPi::prepareBuffers(Camera *camera)\n> >                       return ret;\n> >       }\n> >\n> > +     /*\n> > +      * Pass the stats and embedded data buffers to the IPA. No other\n> > +      * buffers need to be passed.\n> > +      */\n> > +     mapBuffers(camera, data->isp_[Isp::Stats].getBuffers(), RPiIpaMask::STATS);\n> > +     mapBuffers(camera, data->unicam_[Unicam::Embedded].getBuffers(), RPiIpaMask::EMBEDDED_DATA);\n> > +\n> > +     return 0;\n> > +}\n> > +\n> > +void PipelineHandlerRPi::mapBuffers(Camera *camera, const std::vector<FrameBuffer *> &buffers,\n> > +                                 unsigned int startId)\n> > +{\n> > +     RPiCameraData *data = cameraData(camera);\n> > +     std::vector<IPABuffer> ipaBuffers;\n> > +     unsigned int id = startId;\n> >       /*\n> >        * Link the FrameBuffers with the index of their position in the vector\n> > -      * stored in the RPi stream object.\n> > +      * stored in the RPi stream object - along with an identifer mask.\n> >        *\n> >        * This will allow us to identify buffers passed between the pipeline\n> >        * handler and the IPA.\n> >        */\n> > -     index = 0;\n> > -     for (auto const &b : data->isp_[Isp::Stats].getBuffers()) {\n> > -             data->ipaBuffers_.push_back({ .id = RPiIpaMask::STATS | index,\n> > -                                           .planes = b->planes() });\n> > -             index++;\n> > -     }\n> > -\n> > -     index = 0;\n> > -     for (auto const &b : data->unicam_[Unicam::Embedded].getBuffers()) {\n> > -             data->ipaBuffers_.push_back({ .id = RPiIpaMask::EMBEDDED_DATA | index,\n> > -                                           .planes = b->planes() });\n> > -             index++;\n> > +     for (auto const &b : buffers) {\n> > +             ipaBuffers.push_back({ .id = id, .planes = b->planes() });\n> > +             data->ipaBufferIds_.push_back(id);\n> > +             id++;\n> >       }\n> >\n> > -     data->ipa_->mapBuffers(data->ipaBuffers_);\n> > -\n> > -     return 0;\n> > +     data->ipa_->mapBuffers(ipaBuffers);\n> >  }\n> >\n> >  void PipelineHandlerRPi::freeBuffers(Camera *camera)\n> >  {\n> >       RPiCameraData *data = cameraData(camera);\n> >\n> > -     std::vector<unsigned int> ids;\n> > -     for (IPABuffer &ipabuf : data->ipaBuffers_)\n> > -             ids.push_back(ipabuf.id);\n> > -\n> > -     data->ipa_->unmapBuffers(ids);\n> > -     data->ipaBuffers_.clear();\n> > +     data->ipa_->unmapBuffers(data->ipaBufferIds_);\n> > +     data->ipaBufferIds_.clear();\n> >\n> >       for (auto const stream : data->streams_)\n> >               stream->releaseBuffers();\n> > diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp\n> > index 61226e94..e4158e3a 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp\n> > +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.cpp\n> > @@ -48,6 +48,11 @@ void RPiStream::setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *bu\n> >                      [](std::unique_ptr<FrameBuffer> &b) { return b.get(); });\n> >  }\n> >\n> > +void RPiStream::setExternalBuffer(FrameBuffer *buffer)\n> > +{\n> > +     bufferList_.push_back(buffer);\n> > +}\n> > +\n> >  const std::vector<FrameBuffer *> &RPiStream::getBuffers() const\n> >  {\n> >       return bufferList_;\n> > diff --git a/src/libcamera/pipeline/raspberrypi/rpi_stream.h b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> > index a6fd5c8e..e2534a32 100644\n> > --- a/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> > +++ b/src/libcamera/pipeline/raspberrypi/rpi_stream.h\n> > @@ -41,6 +41,7 @@ public:\n> >       void reset();\n> >       std::string name() const;\n> >       void setExportedBuffers(std::vector<std::unique_ptr<FrameBuffer>> *buffers);\n> > +     void setExternalBuffer(FrameBuffer *buffer);\n> >       const std::vector<FrameBuffer *> &getBuffers() const;\n> >       void releaseBuffers();\n> >       int prepareBuffers(unsigned int count);\n> > --\n> > 2.25.1\n> >\n> > _______________________________________________\n> > libcamera-devel mailing list\n> > libcamera-devel@lists.libcamera.org\n> > https://lists.libcamera.org/listinfo/libcamera-devel\n>\n> --\n> 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 CFC0BC0109\n\tfor <parsemail@patchwork.libcamera.org>;\n\tMon, 20 Jul 2020 08:06:40 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4BFC1605A8;\n\tMon, 20 Jul 2020 10:06:40 +0200 (CEST)","from mail-lf1-x143.google.com (mail-lf1-x143.google.com\n\t[IPv6:2a00:1450:4864:20::143])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 766FD6039E\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 20 Jul 2020 10:06:38 +0200 (CEST)","by mail-lf1-x143.google.com with SMTP id o4so9215717lfi.7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 20 Jul 2020 01:06:38 -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=\"ESFXlagx\"; 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:content-transfer-encoding;\n\tbh=vzQiRkSOvynTzkM0t0b04+/QH43M5mk+XdEjGUTLV3s=;\n\tb=ESFXlagx7JKTFC00V4nWgfNULGbB5U+T6qIYCDtWhC8tcJAa/Nrpoi96fjMBOD9NXx\n\tgxR7qv1EbsA7TG1n5e876Wl+o4brmO7VCrzQtHkxJ7QUpT4zOwtnWyIrm3y9rfTIlP8D\n\tCBU/Q2EnLJg+CU6W6hScc8O+ccbF83yk/LKZc/pfFQxT2rWNRZO1ZsrwBKiorhvpxJo7\n\t+sy1uRdixFQyuvCXIjvppa94M+icAwr5P3VPI4ETmAvFnoX6nWVy89QFm05jNToDh9Cp\n\t3uC8mtgh5GxnihLoMmVc0aUIP8EDQRF7exojroSkd6W04Tv5oR+I5kjYnHs1wnO6sNHq\n\tY1Qg==","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:content-transfer-encoding;\n\tbh=vzQiRkSOvynTzkM0t0b04+/QH43M5mk+XdEjGUTLV3s=;\n\tb=HuG4X4ittqzF7PI/79aGVrNlp3tx87T/eE1k+CT0FuxPgCWYJd53NXoLpIo1HreC0F\n\tSUJFaiJJH0451DcnpgYupqBioB9GQlFpDAIkIfY7+HerdpFO/QgGDPx7//UfwriT9M68\n\tFKtFBHgcdE7EQqgHObMrWHiHqLKugdX8YfxI1WHXykA6s9uI43mOQ2bOcP4Tm9XLqytj\n\tESvW/CbJzNcMJCxSkspU+qODm6xIwDfijcV77ptetfyUYoQMVieh+4CI3iyIlfgn5WQg\n\t+bS4lTxnTJPkn55X1iml4ToFW2boe9J8zr0Bj3MIa8zXxVw3VdyaIp4YM3fI+6hxrle5\n\t5ukA==","X-Gm-Message-State":"AOAM531rrR/74ZgbgqnYqk8lpOV6oUEHp/d/GQJyjTWTV041FEXG0WMt\n\tRZuwLko/OQZUr0Yd7T3NKk0TgGvFaAJQPykOqT2MUQ==","X-Google-Smtp-Source":"ABdhPJzNAUpOvEKryfXNRb89g6UXKoXWMPNDE5k9D1wZASkA80CmP9BhVvIQWtUKQqD5qWEdvtZCVsfkFQTe35qKpeE=","X-Received":"by 2002:a19:ae19:: with SMTP id\n\tf25mr10580350lfc.63.1595232397380; \n\tMon, 20 Jul 2020 01:06:37 -0700 (PDT)","MIME-Version":"1.0","References":"<20200717085410.732308-1-naush@raspberrypi.com>\n\t<20200717085410.732308-11-naush@raspberrypi.com>\n\t<20200718160400.GB576734@oden.dyn.berto.se>","In-Reply-To":"<20200718160400.GB576734@oden.dyn.berto.se>","From":"Naushir Patuck <naush@raspberrypi.com>","Date":"Mon, 20 Jul 2020 09:06:21 +0100","Message-ID":"<CAEmqJPp7xw=-8mLOPduqpCazcgrJQMs7_Asm2P0Usa7NojcJgw@mail.gmail.com>","To":"=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Subject":"Re: [libcamera-devel] [PATCH v3 10/10] libcamera: pipeline:\n\traspberrypi: Handle any externally allocated FrameBuffer","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=\"utf-8\"","Content-Transfer-Encoding":"base64","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]