[{"id":2182,"web_url":"https://patchwork.libcamera.org/comment/2182/","msgid":"<20190706120003.GO17685@bigcity.dyn.berto.se>","date":"2019-07-06T12:00:03","subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Jacopo,\n\nThanks for your patch.\n\nOn 2019-07-05 00:53:31 +0200, Jacopo Mondi wrote:\n> Add and operation to map external buffers provided by applications in\n> a Request to the Stream's internal buffers used by the pipeline handlers\n> to interact with the video device.\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  include/libcamera/buffer.h |   1 +\n>  include/libcamera/stream.h |   6 ++\n>  src/libcamera/stream.cpp   | 116 +++++++++++++++++++++++++++++++++++++\n>  3 files changed, 123 insertions(+)\n> \n> diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h\n> index 260a62e9e77e..d5d3dc90a096 100644\n> --- a/include/libcamera/buffer.h\n> +++ b/include/libcamera/buffer.h\n> @@ -59,6 +59,7 @@ private:\n>  \tfriend class BufferPool;\n>  \tfriend class PipelineHandler;\n>  \tfriend class Request;\n> +\tfriend class Stream;\n\nI understand this is needed now so no problem. But for each new friend \ngained now is one more friend we have to try and design away later ;-)\n\n>  \tfriend class V4L2VideoDevice;\n>  \n>  \tvoid cancel();\n> diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> index 796f1aff2602..74415062cbdd 100644\n> --- a/include/libcamera/stream.h\n> +++ b/include/libcamera/stream.h\n> @@ -85,6 +85,8 @@ public:\n>  \tconst StreamConfiguration &configuration() const { return configuration_; }\n>  \tMemoryType memoryType() const { return memoryType_; }\n>  \n> +\tBuffer *mapBuffer(Buffer *applicationBuffer);\n> +\n>  protected:\n>  \tfriend class Camera;\n>  \n> @@ -94,6 +96,10 @@ protected:\n>  \tBufferPool bufferPool_;\n>  \tStreamConfiguration configuration_;\n>  \tMemoryType memoryType_;\n> +\n> +private:\n> +\tstd::vector<Buffer *> mappableBuffers_;\n> +\tstd::map<unsigned int, Buffer *> bufferMap_;\n>  };\n>  \n>  } /* namespace libcamera */\n> diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> index 97e0f429c9fb..4585c0db77a4 100644\n> --- a/src/libcamera/stream.cpp\n> +++ b/src/libcamera/stream.cpp\n> @@ -13,6 +13,8 @@\n>  #include <iomanip>\n>  #include <sstream>\n>  \n> +#include <libcamera/request.h>\n> +\n>  #include \"log.h\"\n>  \n>  /**\n> @@ -470,6 +472,26 @@ void Stream::createBuffers(unsigned int count)\n>  \t\treturn;\n>  \n>  \tbufferPool_.createBuffers(count);\n> +\n> +\t/* Streams with internal memory usage do not need buffer mapping. */\n> +\tif (memoryType_ == InternalMemory)\n> +\t\treturn;\n> +\n> +\t/*\n> +\t * Prepare for buffer mapping by queuing all buffers from the internal\n> +\t * pool. Each external buffer presented by application will be mapped\n> +\t * on an internal one.\n> +\t */\n> +\tmappableBuffers_.clear();\n> +\tfor (Buffer &buffer : bufferPool_.buffers()) {\n> +\t\t/*\n> +\t\t * Reserve all planes to support mapping multiplanar buffers.\n> +\t\t * \\todo I would use VIDEO_MAX_PLANES but it's a V4L2 thing.\n> +\t\t */\n> +\t\tbuffer.planes().resize(3);\n> +\n> +\t\tmappableBuffers_.push_back(&buffer);\n> +\t}\n>  }\n>  \n>  /**\n> @@ -480,6 +502,100 @@ void Stream::destroyBuffers()\n>  \tbufferPool_.destroyBuffers();\n>  }\n>  \n> +/**\n> + * \\brief Map an application provided buffer to a stream buffer\n> + * \\param applicationBuffer The application provided buffer\n> + *\n> + * If a Stream has been configured to use application provided buffers a\n> + * mapping between the external buffers and the internal ones, which are\n> + * actually used to interface with the video device, is required.\n> + *\n> + * The most commonly used mechanism to perform zero-copy memory sharing\n> + * on Linux-based system is dmabuf, which allows user-space applications to\n> + * share buffers by exchanging dmabuf generated file descriptors. This\n> + * operations assumes that all application provided buffers have each of their\n> + * used memory planes exported as dmabuf file descriptor, to copy them in\n> + * the buffer to be then queued on the video device by pipeline handlers.\n> + *\n> + * Perform mapping by maintaining a cache in a map associating the dmabuf file\n> + * descriptor of the application provided buffer to one of the stream's internal\n> + * buffers to provide pipeline handlers the buffer to use to interact with video\n> + * devices.\n> + *\n> + * Once the buffer completes, the mapping should be reverted to return to\n> + * the application the buffer it first provided here.\n> + *\n> + * \\return The stream buffer which maps to the application provided buffer\n> + */\n> +Buffer *Stream::mapBuffer(Buffer *applicationBuffer)\n> +{\n> +\tunsigned int key = applicationBuffer->planes()[0].dmabuf();\n> +\n> +\t/*\n> +\t * Buffer hit: the application buffer has already been mapped, return\n> +\t * the assigned stream buffer\n> +\t */\n> +\tauto mapped = bufferMap_.find(key);\n> +\tif (mapped != bufferMap_.end()) {\n> +\t\tBuffer *buffer = mapped->second;\n> +\n> +\t\t/*\n> +\t\t * Keep the mappableBuffers_ vector warm: move the hit buffer to\n> +\t\t * the vector end as on a buffer miss buffers are below evicted\n> +\t\t * from the vector head.\n> +\t\t */\n> +\t\tauto it = std::find(mappableBuffers_.begin(),\n> +\t\t\t\t    mappableBuffers_.end(), buffer);\n> +\n> +\t\tASSERT(it != mappableBuffers_.end());\n> +\t\tstd::rotate(it, it + 1, mappableBuffers_.end());\n\nThis don't seem to be right.\n\nThe it found will indeed be pushed to the back, but the buffer which was \nat the end will be swapped to the location it as at. Is not correct \nbehavior here to delete the it position and insert it at the end?\n\nI assume the idea is to the closer to end() a buffer is, the \"warmer\" it \nis. So this swapping could lead to non optimal performance.\n\n> +\n> +\t\treturn buffer;\n> +\t}\n> +\n> +\t/*\n> +\t * Buffer miss: assign to the application buffer the stream buffer\n> +\t * at mappableBuffers_ begin, then move it to the end.\n> +\t */\n> +\tBuffer *buffer = *(mappableBuffers_.begin());\n> +\tstd::rotate(mappableBuffers_.begin(), mappableBuffers_.begin() + 1,\n> +\t\t    mappableBuffers_.end());\n> +\n> +\n> +\t /* Remove the [key, buffer] entry buffer from the buffer map */\n> +\tauto deadBuf = std::find_if(bufferMap_.begin(), bufferMap_.end(),\n> +\t\t\t\t    [&](std::pair<const unsigned int, Buffer *> &map) {\n> +\t\t\t\t\treturn bufferMap_[map.first] == buffer;\n> +\t\t\t\t    });\n> +\tif (deadBuf != bufferMap_.end())\n> +\t\tbufferMap_.erase(deadBuf);\n> +\n> +\t/*\n> +\t * Assign the buffer by copying the dmabuf file descriptors from the\n> +\t * application provided buffer.\n> +\t */\n> +\tfor (unsigned int i = 0; i < applicationBuffer->planes().size(); ++i) {\n> +\t\tint fd = applicationBuffer->planes()[i].dmabuf();\n> +\n> +\t\t/*\n> +\t\t * The ARC camera stack seems to report more planes that the\n\ns/that/then/\n\n> +\t\t * ones it actually uses.\n\ns/it//\n\n> +\t\t */\n> +\t\tif (fd < 0)\n> +\t\t\tbreak;\n> +\n> +\t\tbuffer->planes()[i].setDmabuf(fd, 0);\n> +\t}\n> +\n> +\t/* Pipeline handlers use request_ at buffer completion time. */\n> +\tbuffer->request_ = applicationBuffer->request();\n> +\n> +\t/* And finally, store the mapping for later re-use and return it. */\n> +\tbufferMap_[key] = buffer;\n> +\n> +\treturn buffer;\n> +}\n> +\n>  /**\n>   * \\var Stream::bufferPool_\n>   * \\brief The pool of buffers associated with the stream\n> -- \n> 2.21.0\n> \n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-lj1-x241.google.com (mail-lj1-x241.google.com\n\t[IPv6:2a00:1450:4864:20::241])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 92F2861568\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat,  6 Jul 2019 14:00:04 +0200 (CEST)","by mail-lj1-x241.google.com with SMTP id k18so11573407ljc.11\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 06 Jul 2019 05:00:04 -0700 (PDT)","from localhost (customer-145-14-112-32.stosn.net. [145.14.112.32])\n\tby smtp.gmail.com with ESMTPSA id\n\tq21sm1823118lfc.96.2019.07.06.05.00.03\n\t(version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256);\n\tSat, 06 Jul 2019 05:00:03 -0700 (PDT)"],"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\t:user-agent; bh=pRV/b3amLy/UxuyDuKOuzZhdlKVJ1/ewVmW5eVS1+B0=;\n\tb=0l/+jISqSVVJmrE9JSb+c59lsl1cLe8uXkiHcwTYqaEBnwqMgrDt48RJcmuKNV/qRN\n\tiP1t99jHLd6V2RsBScBWyZ8AFp+oEOGEY6C/HqkBJM677LXNEjD5DHSqF0mgiIhZwOka\n\tQwrnpgcHpTzxkccT27vwmNvFlYWki0TQjQixx+v92ltXx3Wdt+RPl8HgTH21z9XjSiIC\n\tj6Jtx5ZCmatz9L4NchAGkOH7PLX+JC0hHAbt0rw7CGaoShTGmq/7VkAw68UENrRBzTMz\n\tRBUcj8zkOA5/+LYO79e1+cL+210X1j0ExL4QtF0UISGKXa086oZ9zEzocIo9Gyvs0Nnl\n\tVZ1A==","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:user-agent;\n\tbh=pRV/b3amLy/UxuyDuKOuzZhdlKVJ1/ewVmW5eVS1+B0=;\n\tb=Y+irAM0+EXJ3XDDm6y8MUDYiTmCF2o9/6ksVZu79kmGeRjzKIAlglWmx2eKNq5cKpG\n\t8QwiOZhGEOHAuqsUnPSxerLbAgDwlszb5+8hGRsXUpdl219cyIpDj98UV6J2H3lMYl0c\n\tOXAqPYRkYDMFPUZ4BCdqbMEhMqf/JYIeBfOevDAg7ZDlvavU8juLxtUwh51hWPFQxjVh\n\tMafu5DdmFE/X8uFRCM7DIiRRYS0XgmeoO09mkJwr8tvD5g0yx0XMTCyDCryo4ol6XzLP\n\toYiSwcFGYc8yKNbgkFkyk3JbpCXnWU/QdFrNF6LnLJ15QKGO4OBlFE99vkfoROtRuWt7\n\to2wA==","X-Gm-Message-State":"APjAAAXPnV5rKBZ0gc7w+NxDQAprELX7GvuJ6aPAm5CIfM65aUVH36cB\n\ty2dEQEde2+oYZuNdAA8iZD/Zkg==","X-Google-Smtp-Source":"APXvYqxaR19HNXRVhF5xO9LXiSiM41yCi430lMhAlRNGKWZDrSG3g4kRgps4YCR+8KOm5E/u7OH/1w==","X-Received":"by 2002:a2e:9ec9:: with SMTP id h9mr4669140ljk.90.1562414404081; \n\tSat, 06 Jul 2019 05:00:04 -0700 (PDT)","Date":"Sat, 6 Jul 2019 14:00:03 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190706120003.GO17685@bigcity.dyn.berto.se>","References":"<20190704225334.26170-1-jacopo@jmondi.org>\n\t<20190704225334.26170-7-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190704225334.26170-7-jacopo@jmondi.org>","User-Agent":"Mutt/1.12.1 (2019-06-15)","Subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Sat, 06 Jul 2019 12:00:04 -0000"}},{"id":2192,"web_url":"https://patchwork.libcamera.org/comment/2192/","msgid":"<5ad733e5-9631-78de-bd6d-81acf304be5d@ideasonboard.com>","date":"2019-07-08T11:39:31","subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"content":"Hi Jacopo,\n\nOn 06/07/2019 13:00, Niklas Söderlund wrote:\n> Hi Jacopo,\n> \n> Thanks for your patch.\n> \n> On 2019-07-05 00:53:31 +0200, Jacopo Mondi wrote:\n>> Add and operation to map external buffers provided by applications in\n>> a Request to the Stream's internal buffers used by the pipeline handlers\n>> to interact with the video device.\n>>\n>> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n>> ---\n>>  include/libcamera/buffer.h |   1 +\n>>  include/libcamera/stream.h |   6 ++\n>>  src/libcamera/stream.cpp   | 116 +++++++++++++++++++++++++++++++++++++\n>>  3 files changed, 123 insertions(+)\n>>\n>> diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h\n>> index 260a62e9e77e..d5d3dc90a096 100644\n>> --- a/include/libcamera/buffer.h\n>> +++ b/include/libcamera/buffer.h\n>> @@ -59,6 +59,7 @@ private:\n>>  \tfriend class BufferPool;\n>>  \tfriend class PipelineHandler;\n>>  \tfriend class Request;\n>> +\tfriend class Stream;\n> \n> I understand this is needed now so no problem. But for each new friend \n> gained now is one more friend we have to try and design away later ;-)\n\n\nCan we handle any mapping/LRU requirements in the bufferPool class instead?\n\n\nThe Bufferpool could have a map instead of the stream? which then\nremoves the friend requirements ...\n\n\n> \n>>  \tfriend class V4L2VideoDevice;\n>>  \n>>  \tvoid cancel();\n>> diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n>> index 796f1aff2602..74415062cbdd 100644\n>> --- a/include/libcamera/stream.h\n>> +++ b/include/libcamera/stream.h\n>> @@ -85,6 +85,8 @@ public:\n>>  \tconst StreamConfiguration &configuration() const { return configuration_; }\n>>  \tMemoryType memoryType() const { return memoryType_; }\n>>  \n>> +\tBuffer *mapBuffer(Buffer *applicationBuffer);\n>> +\n>>  protected:\n>>  \tfriend class Camera;\n>>  \n>> @@ -94,6 +96,10 @@ protected:\n>>  \tBufferPool bufferPool_;\n>>  \tStreamConfiguration configuration_;\n>>  \tMemoryType memoryType_;\n>> +\n>> +private:\n>> +\tstd::vector<Buffer *> mappableBuffers_;\n>> +\tstd::map<unsigned int, Buffer *> bufferMap_;\n>>  };\n>>  \n>>  } /* namespace libcamera */\n>> diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n>> index 97e0f429c9fb..4585c0db77a4 100644\n>> --- a/src/libcamera/stream.cpp\n>> +++ b/src/libcamera/stream.cpp\n>> @@ -13,6 +13,8 @@\n>>  #include <iomanip>\n>>  #include <sstream>\n>>  \n>> +#include <libcamera/request.h>\n>> +\n>>  #include \"log.h\"\n>>  \n>>  /**\n>> @@ -470,6 +472,26 @@ void Stream::createBuffers(unsigned int count)\n>>  \t\treturn;\n>>  \n>>  \tbufferPool_.createBuffers(count);\n>> +\n>> +\t/* Streams with internal memory usage do not need buffer mapping. */\n>> +\tif (memoryType_ == InternalMemory)\n>> +\t\treturn;\n>> +\n>> +\t/*\n>> +\t * Prepare for buffer mapping by queuing all buffers from the internal\n>> +\t * pool. Each external buffer presented by application will be mapped\n>> +\t * on an internal one.\n>> +\t */\n>> +\tmappableBuffers_.clear();\n>> +\tfor (Buffer &buffer : bufferPool_.buffers()) {\n>> +\t\t/*\n>> +\t\t * Reserve all planes to support mapping multiplanar buffers.\n>> +\t\t * \\todo I would use VIDEO_MAX_PLANES but it's a V4L2 thing.\n>> +\t\t */\n>> +\t\tbuffer.planes().resize(3);\n>> +\n>> +\t\tmappableBuffers_.push_back(&buffer);\n>> +\t}\n>>  }\n>>  \n>>  /**\n>> @@ -480,6 +502,100 @@ void Stream::destroyBuffers()\n>>  \tbufferPool_.destroyBuffers();\n>>  }\n>>  \n>> +/**\n>> + * \\brief Map an application provided buffer to a stream buffer\n>> + * \\param applicationBuffer The application provided buffer\n>> + *\n>> + * If a Stream has been configured to use application provided buffers a\n>> + * mapping between the external buffers and the internal ones, which are\n>> + * actually used to interface with the video device, is required.\n>> + *\n>> + * The most commonly used mechanism to perform zero-copy memory sharing\n>> + * on Linux-based system is dmabuf, which allows user-space applications to\n>> + * share buffers by exchanging dmabuf generated file descriptors. This\n>> + * operations assumes that all application provided buffers have each of their\n>> + * used memory planes exported as dmabuf file descriptor, to copy them in\n>> + * the buffer to be then queued on the video device by pipeline handlers.\n>> + *\n>> + * Perform mapping by maintaining a cache in a map associating the dmabuf file\n>> + * descriptor of the application provided buffer to one of the stream's internal\n>> + * buffers to provide pipeline handlers the buffer to use to interact with video\n>> + * devices.\n>> + *\n>> + * Once the buffer completes, the mapping should be reverted to return to\n>> + * the application the buffer it first provided here.\n>> + *\n>> + * \\return The stream buffer which maps to the application provided buffer\n>> + */\n>> +Buffer *Stream::mapBuffer(Buffer *applicationBuffer)\n>> +{\n>> +\tunsigned int key = applicationBuffer->planes()[0].dmabuf();\n>> +\n>> +\t/*\n>> +\t * Buffer hit: the application buffer has already been mapped, return\n>> +\t * the assigned stream buffer\n>> +\t */\n>> +\tauto mapped = bufferMap_.find(key);\n>> +\tif (mapped != bufferMap_.end()) {\n>> +\t\tBuffer *buffer = mapped->second;\n>> +\n>> +\t\t/*\n>> +\t\t * Keep the mappableBuffers_ vector warm: move the hit buffer to\n>> +\t\t * the vector end as on a buffer miss buffers are below evicted\n>> +\t\t * from the vector head.\n>> +\t\t */\n>> +\t\tauto it = std::find(mappableBuffers_.begin(),\n>> +\t\t\t\t    mappableBuffers_.end(), buffer);\n>> +\n>> +\t\tASSERT(it != mappableBuffers_.end());\n>> +\t\tstd::rotate(it, it + 1, mappableBuffers_.end());\n> \n> This don't seem to be right.\n> \n> The it found will indeed be pushed to the back, but the buffer which was \n> at the end will be swapped to the location it as at. Is not correct \n> behavior here to delete the it position and insert it at the end?\n> \n> I assume the idea is to the closer to end() a buffer is, the \"warmer\" it \n> is. So this swapping could lead to non optimal performance.\n> \n>> +\n>> +\t\treturn buffer;\n>> +\t}\n>> +\n>> +\t/*\n>> +\t * Buffer miss: assign to the application buffer the stream buffer\n>> +\t * at mappableBuffers_ begin, then move it to the end.\n>> +\t */\n>> +\tBuffer *buffer = *(mappableBuffers_.begin());\n>> +\tstd::rotate(mappableBuffers_.begin(), mappableBuffers_.begin() + 1,\n>> +\t\t    mappableBuffers_.end());\n>> +\n>> +\n>> +\t /* Remove the [key, buffer] entry buffer from the buffer map */\n>> +\tauto deadBuf = std::find_if(bufferMap_.begin(), bufferMap_.end(),\n>> +\t\t\t\t    [&](std::pair<const unsigned int, Buffer *> &map) {\n>> +\t\t\t\t\treturn bufferMap_[map.first] == buffer;\n>> +\t\t\t\t    });\n>> +\tif (deadBuf != bufferMap_.end())\n>> +\t\tbufferMap_.erase(deadBuf);\n>> +\n>> +\t/*\n>> +\t * Assign the buffer by copying the dmabuf file descriptors from the\n>> +\t * application provided buffer.\n>> +\t */\n>> +\tfor (unsigned int i = 0; i < applicationBuffer->planes().size(); ++i) {\n>> +\t\tint fd = applicationBuffer->planes()[i].dmabuf();\n>> +\n>> +\t\t/*\n>> +\t\t * The ARC camera stack seems to report more planes that the\n> \n> s/that/then/\n\ns/s/that/then//s/that/than// :D ok that's unreadable:\n\nHow about : s/that/than/\n\n:D\n\n> \n>> +\t\t * ones it actually uses.\n> \n> s/it//\n\nthe 'it' pronoun is needed, so it should stay.\n\n\n\n>> +\t\t */\n>> +\t\tif (fd < 0)\n>> +\t\t\tbreak;\n>> +\n>> +\t\tbuffer->planes()[i].setDmabuf(fd, 0);\n>> +\t}\n>> +\n>> +\t/* Pipeline handlers use request_ at buffer completion time. */\n>> +\tbuffer->request_ = applicationBuffer->request();\n>> +\n>> +\t/* And finally, store the mapping for later re-use and return it. */\n>> +\tbufferMap_[key] = buffer;\n>> +\n>> +\treturn buffer;\n>> +}\n>> +\n>>  /**\n>>   * \\var Stream::bufferPool_\n>>   * \\brief The pool of buffers associated with the stream\n>> -- \n>> 2.21.0\n>>\n>> _______________________________________________\n>> libcamera-devel mailing list\n>> libcamera-devel@lists.libcamera.org\n>> https://lists.libcamera.org/listinfo/libcamera-devel\n>","headers":{"Return-Path":"<kieran.bingham@ideasonboard.com>","Received":["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 4F65360C1C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon,  8 Jul 2019 13:39:35 +0200 (CEST)","from [192.168.0.20]\n\t(cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 9107456A;\n\tMon,  8 Jul 2019 13:39:34 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1562585974;\n\tbh=Nl7s54FGEtLTEtlVIbYyNWHoSbsPqv0XTF/q4QpuNMc=;\n\th=Reply-To:Subject:To:Cc:References:From:Date:In-Reply-To:From;\n\tb=NkmeVE0caEqP9X6qrk9rdeLHSeKIxsAOHlTPkScgkpB3nvw7pXpOI6ux9ewDljX9C\n\twNEdnAhgs9OvFhcCThJzjvc0Q93T3Gr+k8wt2elJLlwWE5GO5TcHeljhg3/IosHBcr\n\tde7Mjmnebpx9MLRPcpHdlB6BVgOqzdRwexc0skPY=","Reply-To":"kieran.bingham@ideasonboard.com","To":"=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>,\n\tJacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","References":"<20190704225334.26170-1-jacopo@jmondi.org>\n\t<20190704225334.26170-7-jacopo@jmondi.org>\n\t<20190706120003.GO17685@bigcity.dyn.berto.se>","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Openpgp":"preference=signencrypt","Autocrypt":"addr=kieran.bingham@ideasonboard.com; keydata=\n\t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\n\tsbsRB8KNNvVXBOVNwko86rQqF9drZuw=","Organization":"Ideas on Board","Message-ID":"<5ad733e5-9631-78de-bd6d-81acf304be5d@ideasonboard.com>","Date":"Mon, 8 Jul 2019 12:39:31 +0100","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101\n\tThunderbird/60.7.1","MIME-Version":"1.0","In-Reply-To":"<20190706120003.GO17685@bigcity.dyn.berto.se>","Content-Type":"text/plain; charset=utf-8","Content-Language":"en-GB","Content-Transfer-Encoding":"8bit","Subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Mon, 08 Jul 2019 11:39:35 -0000"}},{"id":2194,"web_url":"https://patchwork.libcamera.org/comment/2194/","msgid":"<20190709010352.GF10889@wyvern>","date":"2019-07-09T01:03:52","subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"On 2019-07-08 12:39:31 +0100, Kieran Bingham wrote:\n> > \n> > s/that/then/\n> \n> s/s/that/then//s/that/than// :D ok that's unreadable:\n> \n> How about : s/that/than/\n\nHow about s@s/that/then/@s/that/than/@ would that make it more readable?  \n;-P","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-pl1-x641.google.com (mail-pl1-x641.google.com\n\t[IPv6:2607:f8b0:4864:20::641])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A9ADE60C3A\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Jul 2019 03:04:03 +0200 (CEST)","by mail-pl1-x641.google.com with SMTP id w24so9150679plp.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 08 Jul 2019 18:04:03 -0700 (PDT)","from localhost (softbank126163157105.bbtec.net. [126.163.157.105])\n\tby smtp.gmail.com with ESMTPSA id\n\ta12sm713086pje.3.2019.07.08.18.03.59\n\t(version=TLS1_3 cipher=AEAD-AES256-GCM-SHA384 bits=256/256);\n\tMon, 08 Jul 2019 18:04:00 -0700 (PDT)"],"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\t:user-agent; bh=GYEMNkZx1hBj+z4RjDyPAusXLli2gzN80MeIqiHIQ5U=;\n\tb=Z0nlu7KPbAsiP2p+w9M7+bWpWV2P5hIOWPPSSjnBXIYJgXtqPYlDOHH23P8nOfojpF\n\t0/I39WVhFXUTB0yVj9EgsP9o19JxpWsUSksmpMbGevC5iRG+LiQiUgUENNykZUYfM6QA\n\twBXMliV2TrutEpIaWCaMqJnSGErdKVqgsk+89YSjxv2tO9dLdSH2L8x4PIk+eF00BMhF\n\t7P/RxbZxxS31dZobnh0PW9IR6nFZQWq9e4pNnBnoUNQ/sc/hRP/A4x7UpFBkcv/DIo9L\n\tKHnYj73bM0U8V3c/gpWeUa79p2AeRQpDsVPNc4nayZ+usZxviY8qI8U5XG3/BnLBDUPY\n\t4pAw==","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:user-agent;\n\tbh=GYEMNkZx1hBj+z4RjDyPAusXLli2gzN80MeIqiHIQ5U=;\n\tb=TL3PcKhydXfH8EpV2jAMuxx7UpByutoNZmpydGthzLNy6cBItBPgG8xRDQ9mqmHS7V\n\tk+tS1H74crbVYd4+29r7WaNGJv/HG6TkkB0nSZqz45yAyeNs0QXSJGrIkSWCOsT5RkR2\n\tXqXyAxqM+p6lpkr5yUp/Ybt9hyZPOyoCtqPxMrbhVRbeubjn8hz8uRJIQdwAk/CJzd5I\n\t/jO+9qzN5rrvDMwZauLKv+VuFaXtpjajayjWZ9J7I5d9uABSipTnTzKGKYzoBBBd779Q\n\t52j49N4uNOCs6hnjgx3NWho9u0KSMcE+jDFEfPCvitTDzDQwI7l5fzq8ln2uKL5J4kmh\n\tHfPQ==","X-Gm-Message-State":"APjAAAUBqFlvBLJ25+baqsZlVfV6Ql18tJx/JOLUDUQffLBqImuDW+2K\n\tev8mMfTyoMFxn5xgtqqyniD1x9/aizXjgA==","X-Google-Smtp-Source":"APXvYqwetyZnzzKALTVKlaXdj9DkpCEgWxMePWjwgioZiY1MLB0uAk3jEvDYS1ZPT2jaTS4+6ElFlg==","X-Received":"by 2002:a17:902:2aab:: with SMTP id\n\tj40mr27303775plb.76.1562634242063; \n\tMon, 08 Jul 2019 18:04:02 -0700 (PDT)","Date":"Tue, 9 Jul 2019 10:03:52 +0900","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"Jacopo Mondi <jacopo@jmondi.org>, libcamera-devel@lists.libcamera.org","Message-ID":"<20190709010352.GF10889@wyvern>","References":"<20190704225334.26170-1-jacopo@jmondi.org>\n\t<20190704225334.26170-7-jacopo@jmondi.org>\n\t<20190706120003.GO17685@bigcity.dyn.berto.se>\n\t<5ad733e5-9631-78de-bd6d-81acf304be5d@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<5ad733e5-9631-78de-bd6d-81acf304be5d@ideasonboard.com>","User-Agent":"Mutt/1.12.1 (2019-06-15)","Subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Tue, 09 Jul 2019 01:04:04 -0000"}},{"id":2198,"web_url":"https://patchwork.libcamera.org/comment/2198/","msgid":"<20190709105742.w7ujur6rgvjwvgyf@uno.localdomain>","date":"2019-07-09T10:57:42","subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Niklas,\n\nOn Sat, Jul 06, 2019 at 02:00:03PM +0200, Niklas Söderlund wrote:\n> Hi Jacopo,\n>\n> Thanks for your patch.\n>\n> On 2019-07-05 00:53:31 +0200, Jacopo Mondi wrote:\n> > Add and operation to map external buffers provided by applications in\n> > a Request to the Stream's internal buffers used by the pipeline handlers\n> > to interact with the video device.\n> >\n> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > ---\n> >  include/libcamera/buffer.h |   1 +\n> >  include/libcamera/stream.h |   6 ++\n> >  src/libcamera/stream.cpp   | 116 +++++++++++++++++++++++++++++++++++++\n> >  3 files changed, 123 insertions(+)\n> >\n> > diff --git a/include/libcamera/buffer.h b/include/libcamera/buffer.h\n> > index 260a62e9e77e..d5d3dc90a096 100644\n> > --- a/include/libcamera/buffer.h\n> > +++ b/include/libcamera/buffer.h\n> > @@ -59,6 +59,7 @@ private:\n> >  \tfriend class BufferPool;\n> >  \tfriend class PipelineHandler;\n> >  \tfriend class Request;\n> > +\tfriend class Stream;\n>\n> I understand this is needed now so no problem. But for each new friend\n> gained now is one more friend we have to try and design away later ;-)\n>\n> >  \tfriend class V4L2VideoDevice;\n> >\n> >  \tvoid cancel();\n> > diff --git a/include/libcamera/stream.h b/include/libcamera/stream.h\n> > index 796f1aff2602..74415062cbdd 100644\n> > --- a/include/libcamera/stream.h\n> > +++ b/include/libcamera/stream.h\n> > @@ -85,6 +85,8 @@ public:\n> >  \tconst StreamConfiguration &configuration() const { return configuration_; }\n> >  \tMemoryType memoryType() const { return memoryType_; }\n> >\n> > +\tBuffer *mapBuffer(Buffer *applicationBuffer);\n> > +\n> >  protected:\n> >  \tfriend class Camera;\n> >\n> > @@ -94,6 +96,10 @@ protected:\n> >  \tBufferPool bufferPool_;\n> >  \tStreamConfiguration configuration_;\n> >  \tMemoryType memoryType_;\n> > +\n> > +private:\n> > +\tstd::vector<Buffer *> mappableBuffers_;\n> > +\tstd::map<unsigned int, Buffer *> bufferMap_;\n> >  };\n> >\n> >  } /* namespace libcamera */\n> > diff --git a/src/libcamera/stream.cpp b/src/libcamera/stream.cpp\n> > index 97e0f429c9fb..4585c0db77a4 100644\n> > --- a/src/libcamera/stream.cpp\n> > +++ b/src/libcamera/stream.cpp\n> > @@ -13,6 +13,8 @@\n> >  #include <iomanip>\n> >  #include <sstream>\n> >\n> > +#include <libcamera/request.h>\n> > +\n> >  #include \"log.h\"\n> >\n> >  /**\n> > @@ -470,6 +472,26 @@ void Stream::createBuffers(unsigned int count)\n> >  \t\treturn;\n> >\n> >  \tbufferPool_.createBuffers(count);\n> > +\n> > +\t/* Streams with internal memory usage do not need buffer mapping. */\n> > +\tif (memoryType_ == InternalMemory)\n> > +\t\treturn;\n> > +\n> > +\t/*\n> > +\t * Prepare for buffer mapping by queuing all buffers from the internal\n> > +\t * pool. Each external buffer presented by application will be mapped\n> > +\t * on an internal one.\n> > +\t */\n> > +\tmappableBuffers_.clear();\n> > +\tfor (Buffer &buffer : bufferPool_.buffers()) {\n> > +\t\t/*\n> > +\t\t * Reserve all planes to support mapping multiplanar buffers.\n> > +\t\t * \\todo I would use VIDEO_MAX_PLANES but it's a V4L2 thing.\n> > +\t\t */\n> > +\t\tbuffer.planes().resize(3);\n> > +\n> > +\t\tmappableBuffers_.push_back(&buffer);\n> > +\t}\n> >  }\n> >\n> >  /**\n> > @@ -480,6 +502,100 @@ void Stream::destroyBuffers()\n> >  \tbufferPool_.destroyBuffers();\n> >  }\n> >\n> > +/**\n> > + * \\brief Map an application provided buffer to a stream buffer\n> > + * \\param applicationBuffer The application provided buffer\n> > + *\n> > + * If a Stream has been configured to use application provided buffers a\n> > + * mapping between the external buffers and the internal ones, which are\n> > + * actually used to interface with the video device, is required.\n> > + *\n> > + * The most commonly used mechanism to perform zero-copy memory sharing\n> > + * on Linux-based system is dmabuf, which allows user-space applications to\n> > + * share buffers by exchanging dmabuf generated file descriptors. This\n> > + * operations assumes that all application provided buffers have each of their\n> > + * used memory planes exported as dmabuf file descriptor, to copy them in\n> > + * the buffer to be then queued on the video device by pipeline handlers.\n> > + *\n> > + * Perform mapping by maintaining a cache in a map associating the dmabuf file\n> > + * descriptor of the application provided buffer to one of the stream's internal\n> > + * buffers to provide pipeline handlers the buffer to use to interact with video\n> > + * devices.\n> > + *\n> > + * Once the buffer completes, the mapping should be reverted to return to\n> > + * the application the buffer it first provided here.\n> > + *\n> > + * \\return The stream buffer which maps to the application provided buffer\n> > + */\n> > +Buffer *Stream::mapBuffer(Buffer *applicationBuffer)\n> > +{\n> > +\tunsigned int key = applicationBuffer->planes()[0].dmabuf();\n> > +\n> > +\t/*\n> > +\t * Buffer hit: the application buffer has already been mapped, return\n> > +\t * the assigned stream buffer\n> > +\t */\n> > +\tauto mapped = bufferMap_.find(key);\n> > +\tif (mapped != bufferMap_.end()) {\n> > +\t\tBuffer *buffer = mapped->second;\n> > +\n> > +\t\t/*\n> > +\t\t * Keep the mappableBuffers_ vector warm: move the hit buffer to\n> > +\t\t * the vector end as on a buffer miss buffers are below evicted\n> > +\t\t * from the vector head.\n> > +\t\t */\n> > +\t\tauto it = std::find(mappableBuffers_.begin(),\n> > +\t\t\t\t    mappableBuffers_.end(), buffer);\n> > +\n> > +\t\tASSERT(it != mappableBuffers_.end());\n> > +\t\tstd::rotate(it, it + 1, mappableBuffers_.end());\n>\n> This don't seem to be right.\n>\n> The it found will indeed be pushed to the back, but the buffer which was\n> at the end will be swapped to the location it as at. Is not correct\n> behavior here to delete the it position and insert it at the end?\n\nNote that the iterator returned by end() point to the past-the-end\nposition of the vector\nhttps://en.cppreference.com/w/cpp/container/vector/end\n\nSo swapping an element with it, it's safe.\nTo make sure, you can run this very simple test program too:\nhttps://paste.debian.net/1090903/\n\nWhiche gives you:\n1234\nMoving 2 to vector end\n1342\n\nAs you can see, 2 does not get swapped with 4, but moved after it\ninstead.\n\n>\n> I assume the idea is to the closer to end() a buffer is, the \"warmer\" it\n> is. So this swapping could lead to non optimal performance.\n\nIt's the other way around actually. Removing and re-inserting causes\nthe vector to be relocated, and it should be avoided as much as\npossible.\n>\n> > +\n> > +\t\treturn buffer;\n> > +\t}\n> > +\n> > +\t/*\n> > +\t * Buffer miss: assign to the application buffer the stream buffer\n> > +\t * at mappableBuffers_ begin, then move it to the end.\n> > +\t */\n> > +\tBuffer *buffer = *(mappableBuffers_.begin());\n> > +\tstd::rotate(mappableBuffers_.begin(), mappableBuffers_.begin() + 1,\n> > +\t\t    mappableBuffers_.end());\n> > +\n> > +\n> > +\t /* Remove the [key, buffer] entry buffer from the buffer map */\n> > +\tauto deadBuf = std::find_if(bufferMap_.begin(), bufferMap_.end(),\n> > +\t\t\t\t    [&](std::pair<const unsigned int, Buffer *> &map) {\n> > +\t\t\t\t\treturn bufferMap_[map.first] == buffer;\n> > +\t\t\t\t    });\n> > +\tif (deadBuf != bufferMap_.end())\n> > +\t\tbufferMap_.erase(deadBuf);\n> > +\n> > +\t/*\n> > +\t * Assign the buffer by copying the dmabuf file descriptors from the\n> > +\t * application provided buffer.\n> > +\t */\n> > +\tfor (unsigned int i = 0; i < applicationBuffer->planes().size(); ++i) {\n> > +\t\tint fd = applicationBuffer->planes()[i].dmabuf();\n> > +\n> > +\t\t/*\n> > +\t\t * The ARC camera stack seems to report more planes that the\n>\n> s/that/then/\n>\n> > +\t\t * ones it actually uses.\n>\n> s/it//\n>\n> > +\t\t */\n> > +\t\tif (fd < 0)\n> > +\t\t\tbreak;\n> > +\n> > +\t\tbuffer->planes()[i].setDmabuf(fd, 0);\n> > +\t}\n> > +\n> > +\t/* Pipeline handlers use request_ at buffer completion time. */\n> > +\tbuffer->request_ = applicationBuffer->request();\n> > +\n> > +\t/* And finally, store the mapping for later re-use and return it. */\n> > +\tbufferMap_[key] = buffer;\n> > +\n> > +\treturn buffer;\n> > +}\n> > +\n> >  /**\n> >   * \\var Stream::bufferPool_\n> >   * \\brief The pool of buffers associated with the stream\n> > --\n> > 2.21.0\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":"<jacopo@jmondi.org>","Received":["from relay6-d.mail.gandi.net (relay6-d.mail.gandi.net\n\t[217.70.183.198])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A37C460BC8\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tTue,  9 Jul 2019 12:56:33 +0200 (CEST)","from uno.localdomain (softbank126163157105.bbtec.net\n\t[126.163.157.105]) (Authenticated sender: jacopo@jmondi.org)\n\tby relay6-d.mail.gandi.net (Postfix) with ESMTPSA id 162D0C0003;\n\tTue,  9 Jul 2019 10:56:31 +0000 (UTC)"],"X-Originating-IP":"126.163.157.105","Date":"Tue, 9 Jul 2019 12:57:42 +0200","From":"Jacopo Mondi <jacopo@jmondi.org>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190709105742.w7ujur6rgvjwvgyf@uno.localdomain>","References":"<20190704225334.26170-1-jacopo@jmondi.org>\n\t<20190704225334.26170-7-jacopo@jmondi.org>\n\t<20190706120003.GO17685@bigcity.dyn.berto.se>","MIME-Version":"1.0","Content-Type":"multipart/signed; micalg=pgp-sha256;\n\tprotocol=\"application/pgp-signature\"; boundary=\"dbpqrdicov4aqupj\"","Content-Disposition":"inline","In-Reply-To":"<20190706120003.GO17685@bigcity.dyn.berto.se>","User-Agent":"NeoMutt/20180716","Subject":"Re: [libcamera-devel] [PATCH 6/9] libcamera: stream: Add operation\n\tto map buffers","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","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>","X-List-Received-Date":"Tue, 09 Jul 2019 10:56:33 -0000"}}]