[{"id":3379,"web_url":"https://patchwork.libcamera.org/comment/3379/","msgid":"<20200108011741.GU4871@pendragon.ideasonboard.com>","date":"2020-01-08T01:17:41","subject":"Re: [libcamera-devel] [PATCH v2 14/25] test: camera: buffer_import:\n\tUpdate to FrameBuffer restrictions","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nThank you for the patch.\n\nOn Mon, Dec 30, 2019 at 01:04:59PM +0100, Niklas Söderlund wrote:\n> With the FrameBuffer interface the V4L2 buffer indexes are not visible\n> outside the V4L2VideoDevice so it's not possible to to test that the\n> expected indexes are used when using external buffers (allocated\n> directly from a V4L2 video device) with a Camera. Rewrite the test to\n> this limitation.\n> \n> The idea of the test stays the same, test that buffers allocated from a\n> V4L2 video device (vivid) can be imported and used on a Camera (vimc).\n> As an added bonus the rewrite makes us of the FrameBuffer interface for\n\ns/us/use/\n\n> the allocation of buffers at the source (vivid) and imports them to the\n> Camera which still uses the Buffer interface internally.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  test/camera/buffer_import.cpp | 390 ++++++++++------------------------\n>  1 file changed, 110 insertions(+), 280 deletions(-)\n> \n> diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> index 3ba6ce9690f29329..6559a89ce914a183 100644\n> --- a/test/camera/buffer_import.cpp\n> +++ b/test/camera/buffer_import.cpp\n> @@ -22,19 +22,32 @@\n>  \n>  using namespace libcamera;\n>  \n> -/* Keep SINK_BUFFER_COUNT > CAMERA_BUFFER_COUNT + 1 */\n> -static constexpr unsigned int SINK_BUFFER_COUNT = 8;\n> -static constexpr unsigned int CAMERA_BUFFER_COUNT = 4;\n> +namespace {\n>  \n> -class FrameSink\n> +/* A provider of external buffers, suitable for import by a Camera. */\n> +class BufferSource\n>  {\n>  public:\n> -\tFrameSink()\n> +\tBufferSource()\n>  \t\t: video_(nullptr)\n>  \t{\n>  \t}\n>  \n> -\tint init()\n> +\t~BufferSource()\n> +\t{\n> +\t\tif (video_) {\n> +\t\t\tvideo_->releaseBuffers();\n> +\t\t\tvideo_->close();\n> +\t\t}\n> +\n> +\t\tdelete video_;\n> +\t\tvideo_ = nullptr;\n> +\n> +\t\tif (media_)\n> +\t\t\tmedia_->release();\n> +\t}\n> +\n> +\tint allocate(const StreamConfiguration &config)\n>  \t{\n>  \t\tint ret;\n>  \n> @@ -72,187 +85,27 @@ public:\n>  \t\t\treturn TestFail;\n>  \n>  \t\t/* Configure the format. */\n> -\t\tret = video_->getFormat(&format_);\n> +\t\tV4L2DeviceFormat format;\n> +\t\tret = video_->getFormat(&format);\n>  \t\tif (ret) {\n>  \t\t\tstd::cout << \"Failed to get format on output device\" << std::endl;\n>  \t\t\treturn ret;\n>  \t\t}\n>  \n> -\t\tformat_.size.width = 1920;\n> -\t\tformat_.size.height = 1080;\n> -\t\tformat_.fourcc = V4L2_PIX_FMT_RGB24;\n> -\t\tformat_.planesCount = 1;\n> -\t\tformat_.planes[0].size = 1920 * 1080 * 3;\n> -\t\tformat_.planes[0].bpl = 1920 * 3;\n> -\n> -\t\tif (video_->setFormat(&format_)) {\n> -\t\t\tcleanup();\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n> -\t\t/* Export the buffers to a pool. */\n> -\t\tpool_.createBuffers(SINK_BUFFER_COUNT);\n> -\t\tret = video_->exportBuffers(&pool_);\n> -\t\tif (ret) {\n> -\t\t\tstd::cout << \"Failed to export buffers\" << std::endl;\n> -\t\t\tcleanup();\n> +\t\tformat.size = config.size;\n> +\t\tformat.fourcc = V4L2VideoDevice::toV4L2Fourcc(config.pixelFormat, false);\n> +\t\tif (video_->setFormat(&format))\n>  \t\t\treturn TestFail;\n> -\t\t}\n> -\n> -\t\t/* Only use the first CAMERA_BUFFER_COUNT buffers to start with. */\n> -\t\tavailableBuffers_.resize(CAMERA_BUFFER_COUNT);\n> -\t\tstd::iota(availableBuffers_.begin(), availableBuffers_.end(), 0);\n> -\n> -\t\t/* Connect the buffer ready signal. */\n> -\t\tvideo_->bufferReady.connect(this, &FrameSink::bufferComplete);\n> -\n> -\t\treturn TestPass;\n> -\t}\n> -\n> -\tvoid cleanup()\n> -\t{\n> -\t\tif (video_) {\n> -\t\t\tvideo_->streamOff();\n> -\t\t\tvideo_->releaseBuffers();\n> -\t\t\tvideo_->close();\n> -\n> -\t\t\tdelete video_;\n> -\t\t\tvideo_ = nullptr;\n> -\t\t}\n>  \n> -\t\tif (media_)\n> -\t\t\tmedia_->release();\n> +\t\treturn video_->exportBuffers(config.bufferCount, &buffers_);\n>  \t}\n>  \n> -\tint start()\n> -\t{\n> -\t\trequestsCount_ = 0;\n> -\t\tdone_ = false;\n> -\n> -\t\tint ret = video_->streamOn();\n> -\t\tif (ret < 0)\n> -\t\t\treturn ret;\n> -\n> -\t\t/* Queue all the initial requests. */\n> -\t\tfor (unsigned int index = 0; index < CAMERA_BUFFER_COUNT; ++index)\n> -\t\t\tqueueRequest(index);\n> -\n> -\t\treturn 0;\n> -\t}\n> -\n> -\tint stop()\n> -\t{\n> -\t\treturn video_->streamOff();\n> -\t}\n> -\n> -\tvoid requestComplete(uint64_t cookie, const Buffer *metadata)\n> -\t{\n> -\t\tunsigned int index = cookie;\n> -\n> -\t\tBuffer *buffer = new Buffer(index, metadata);\n> -\t\tint ret = video_->queueBuffer(buffer);\n> -\t\tif (ret < 0)\n> -\t\t\tstd::cout << \"Failed to queue buffer to sink\" << std::endl;\n> -\t}\n> -\n> -\tbool done() const { return done_; }\n> -\n> -\tPixelFormat format() const\n> -\t{\n> -\t\treturn video_->toPixelFormat(format_.fourcc);\n> -\t}\n> -\n> -\tconst Size &size() const\n> -\t{\n> -\t\treturn format_.size;\n> -\t}\n> -\n> -\tSignal<uint64_t, int> requestReady;\n> +\tconst std::vector<std::unique_ptr<FrameBuffer>> &buffers() { return buffers_; };\n\ns/;$//\n\nand I'd wrap this as\n\n\t{\n\t\treturn buffers_;\n\t}\n\nto keep the line shorter.\n\n>  \n>  private:\n> -\tvoid queueRequest(unsigned int index)\n> -\t{\n> -\t\tauto it = std::find(availableBuffers_.begin(),\n> -\t\t\t\t    availableBuffers_.end(), index);\n> -\t\tavailableBuffers_.erase(it);\n> -\n> -\t\tuint64_t cookie = index;\n> -\t\tBufferMemory &mem = pool_.buffers()[index];\n> -\t\tint dmabuf = mem.planes()[0].fd.fd();\n> -\n> -\t\trequestReady.emit(cookie, dmabuf);\n> -\n> -\t\trequestsCount_++;\n> -\t}\n> -\n> -\tvoid bufferComplete(Buffer *buffer)\n> -\t{\n> -\t\tavailableBuffers_.push_back(buffer->index());\n> -\n> -\t\t/*\n> -\t\t * Pick the buffer for the next request among the available\n> -\t\t * buffers.\n> -\t\t *\n> -\t\t * For the first 20 frames, select the buffer that has just\n> -\t\t * completed to keep the mapping of dmabuf fds to buffers\n> -\t\t * unchanged in the camera.\n> -\t\t *\n> -\t\t * For the next 20 frames, cycle randomly over the available\n> -\t\t * buffers. The mapping should still be kept unchanged, as the\n> -\t\t * camera should map using the cached fds.\n> -\t\t *\n> -\t\t * For the last 20 frames, cycles through all buffers, which\n> -\t\t * should trash the mappings.\n> -\t\t */\n> -\t\tunsigned int index = buffer->index();\n> -\t\tdelete buffer;\n> -\n> -\t\tstd::cout << \"Completed buffer, request=\" << requestsCount_\n> -\t\t\t  << \", available buffers=\" << availableBuffers_.size()\n> -\t\t\t  << std::endl;\n> -\n> -\t\tif (requestsCount_ >= 60) {\n> -\t\t\tif (availableBuffers_.size() == SINK_BUFFER_COUNT)\n> -\t\t\t\tdone_ = true;\n> -\t\t\treturn;\n> -\t\t}\n> -\n> -\t\tif (requestsCount_ == 40) {\n> -\t\t\t/* Add the remaining of the buffers. */\n> -\t\t\tfor (unsigned int i = CAMERA_BUFFER_COUNT;\n> -\t\t\t     i < SINK_BUFFER_COUNT; ++i)\n> -\t\t\t\tavailableBuffers_.push_back(i);\n> -\t\t}\n> -\n> -\t\tif (requestsCount_ >= 20) {\n> -\t\t\t/*\n> -\t\t\t * Wait until we have enough buffers to make this\n> -\t\t\t * meaningful. Preferably half of the camera buffers,\n> -\t\t\t * but no less than 2 in any case.\n> -\t\t\t */\n> -\t\t\tconst unsigned int min_pool_size =\n> -\t\t\t\tstd::min(CAMERA_BUFFER_COUNT / 2, 2U);\n> -\t\t\tif (availableBuffers_.size() < min_pool_size)\n> -\t\t\t\treturn;\n> -\n> -\t\t\t/* Pick a buffer at random. */\n> -\t\t\tunsigned int pos = random_() % availableBuffers_.size();\n> -\t\t\tindex = availableBuffers_[pos];\n> -\t\t}\n> -\n> -\t\tqueueRequest(index);\n> -\t}\n> -\n>  \tstd::shared_ptr<MediaDevice> media_;\n>  \tV4L2VideoDevice *video_;\n> -\tBufferPool pool_;\n> -\tV4L2DeviceFormat format_;\n> -\n> -\tunsigned int requestsCount_;\n> -\tstd::vector<int> availableBuffers_;\n> -\tstd::random_device random_;\n> -\n> -\tbool done_;\n> +\tstd::vector<std::unique_ptr<FrameBuffer>> buffers_;\n>  };\n>  \n>  class BufferImportTest : public CameraTest, public Test\n> @@ -263,175 +116,152 @@ public:\n>  \t{\n>  \t}\n>  \n> -\tvoid queueRequest(uint64_t cookie, int dmabuf)\n> -\t{\n> -\t\tRequest *request = camera_->createRequest(cookie);\n> -\n> -\t\tstd::unique_ptr<Buffer> buffer = stream_->createBuffer({ dmabuf, -1, -1 });\n> -\t\trequest->addBuffer(stream_, move(buffer));\n> -\t\tcamera_->queueRequest(request);\n> -\t}\n> -\n>  protected:\n>  \tvoid bufferComplete(Request *request, Buffer *buffer)\n>  \t{\n>  \t\tif (buffer->metadata().status != FrameMetadata::FrameSuccess)\n>  \t\t\treturn;\n>  \n> -\t\tunsigned int index = buffer->index();\n> -\t\tint dmabuf = buffer->dmabufs()[0];\n> -\n> -\t\t/* Record dmabuf to index remappings. */\n> -\t\tbool remapped = false;\n> -\t\tif (bufferMappings_.find(index) != bufferMappings_.end()) {\n> -\t\t\tif (bufferMappings_[index] != dmabuf)\n> -\t\t\t\tremapped = true;\n> -\t\t}\n> +\t\tcompleteBuffersCount_++;\n> +\t}\n>  \n> -\t\tstd::cout << \"Completed request \" << framesCaptured_\n> -\t\t\t  << \": dmabuf fd \" << dmabuf\n> -\t\t\t  << \" -> index \" << index\n> -\t\t\t  << \" (\" << (remapped ? 'R' : '-') << \")\"\n> -\t\t\t  << std::endl;\n> +\tvoid requestComplete(Request *request)\n> +\t{\n> +\t\tif (request->status() != Request::RequestComplete)\n> +\t\t\treturn;\n>  \n> -\t\tif (remapped)\n> -\t\t\tbufferRemappings_.push_back(framesCaptured_);\n> +\t\tconst std::map<Stream *, Buffer *> &buffers = request->buffers();\n>  \n> -\t\tbufferMappings_[index] = dmabuf;\n> -\t\tframesCaptured_++;\n> +\t\tcompleteRequestsCount_++;\n>  \n> -\t\tsink_.requestComplete(request->cookie(), buffer);\n> +\t\t/* Create a new request. */\n> +\t\tStream *stream = buffers.begin()->first;\n> +\t\tint dmabuf = buffers.begin()->second->dmabufs()[0];\n> +\t\tstd::unique_ptr<Buffer> buffer = stream->createBuffer({ dmabuf, -1, -1 });\n>  \n> -\t\tif (framesCaptured_ == 60)\n> -\t\t\tsink_.stop();\n> +\t\trequest = camera_->createRequest();\n> +\t\trequest->addBuffer(stream, std::move(buffer));\n> +\t\tcamera_->queueRequest(request);\n>  \t}\n>  \n> -\tint initCamera()\n> +\tint init() override\n>  \t{\n> -\t\tif (camera_->acquire()) {\n> -\t\t\tstd::cout << \"Failed to acquire the camera\" << std::endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> +\t\tif (status_ != TestPass)\n> +\t\t\treturn status_;\n>  \n> -\t\t/*\n> -\t\t * Configure the Stream to work with externally allocated\n> -\t\t * buffers by setting the memoryType to ExternalMemory.\n> -\t\t */\n> -\t\tstd::unique_ptr<CameraConfiguration> config;\n> -\t\tconfig = camera_->generateConfiguration({ StreamRole::VideoRecording });\n> -\t\tif (!config || config->size() != 1) {\n> -\t\t\tstd::cout << \"Failed to generate configuration\" << std::endl;\n> +\t\tconfig_ = camera_->generateConfiguration({ StreamRole::VideoRecording });\n> +\t\tif (!config_ || config_->size() != 1) {\n> +\t\t\tstd::cout << \"Failed to generate default configuration\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tStreamConfiguration &cfg = config->at(0);\n> -\t\tcfg.size = sink_.size();\n> -\t\tcfg.pixelFormat = sink_.format();\n> -\t\tcfg.bufferCount = CAMERA_BUFFER_COUNT;\n> +\t\tStreamConfiguration &cfg = config_->at(0);\n>  \t\tcfg.memoryType = ExternalMemory;\n>  \n> -\t\tif (camera_->configure(config.get())) {\n> -\t\t\tstd::cout << \"Failed to set configuration\" << std::endl;\n> +\t\treturn TestPass;\n> +\t}\n> +\n> +\tint run() override\n> +\t{\n> +\t\tStreamConfiguration &cfg = config_->at(0);\n> +\n> +\t\tif (camera_->acquire()) {\n> +\t\t\tstd::cout << \"Failed to acquire the camera\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tstream_ = cfg.stream();\n> +\t\tif (camera_->configure(config_.get())) {\n> +\t\t\tstd::cout << \"Failed to set default configuration\" << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n>  \n> -\t\t/* Allocate buffers. */\n>  \t\tif (camera_->allocateBuffers()) {\n>  \t\t\tstd::cout << \"Failed to allocate buffers\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\t/* Connect the buffer completed signal. */\n> -\t\tcamera_->bufferCompleted.connect(this, &BufferImportTest::bufferComplete);\n> +\t\tStream *stream = cfg.stream();\n>  \n> -\t\treturn TestPass;\n> -\t}\n> +\t\tBufferSource source;\n> +\t\tint ret = source.allocate(cfg);\n> +\t\tif (ret < 0)\n> +\t\t\treturn TestFail;\n>  \n> -\tint init()\n> -\t{\n> -\t\tif (status_ != TestPass)\n> -\t\t\treturn status_;\n> +\t\tstd::vector<Request *> requests;\n> +\t\tfor (const std::unique_ptr<FrameBuffer> &framebuffer : source.buffers()) {\n> +\t\t\tint dmabuf = framebuffer->planes()[0].fd.fd();\n>  \n> -\t\tint ret = sink_.init();\n> -\t\tif (ret != TestPass) {\n> -\t\t\tcleanup();\n> -\t\t\treturn ret;\n> -\t\t}\n> +\t\t\tRequest *request = camera_->createRequest();\n> +\t\t\tif (!request) {\n> +\t\t\t\tstd::cout << \"Failed to create request\" << std::endl;\n> +\t\t\t\treturn TestFail;\n> +\t\t\t}\n>  \n> -\t\tret = initCamera();\n> -\t\tif (ret != TestPass) {\n> -\t\t\tcleanup();\n> -\t\t\treturn ret;\n> -\t\t}\n> +\t\t\tstd::unique_ptr<Buffer> buffer = stream->createBuffer({ dmabuf, -1, -1 });\n> +\t\t\tif (request->addBuffer(stream, std::move(buffer))) {\n> +\t\t\t\tstd::cout << \"Failed to associating buffer with request\" << std::endl;\n> +\t\t\t\treturn TestFail;\n> +\t\t\t}\n>  \n> -\t\tsink_.requestReady.connect(this, &BufferImportTest::queueRequest);\n> -\t\treturn TestPass;\n> -\t}\n> +\t\t\trequests.push_back(request);\n> +\t\t}\n>  \n> -\tint run()\n> -\t{\n> -\t\tint ret;\n> +\t\tcompleteRequestsCount_ = 0;\n> +\t\tcompleteBuffersCount_ = 0;\n>  \n> -\t\tframesCaptured_ = 0;\n> +\t\tcamera_->bufferCompleted.connect(this, &BufferImportTest::bufferComplete);\n> +\t\tcamera_->requestCompleted.connect(this, &BufferImportTest::requestComplete);\n>  \n>  \t\tif (camera_->start()) {\n>  \t\t\tstd::cout << \"Failed to start camera\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tret = sink_.start();\n> -\t\tif (ret < 0) {\n> -\t\t\tstd::cout << \"Failed to start sink\" << std::endl;\n> -\t\t\treturn TestFail;\n> +\t\tfor (Request *request : requests) {\n> +\t\t\tif (camera_->queueRequest(request)) {\n> +\t\t\t\tstd::cout << \"Failed to queue request\" << std::endl;\n> +\t\t\t\treturn TestFail;\n> +\t\t\t}\n>  \t\t}\n>  \n>  \t\tEventDispatcher *dispatcher = cm_->eventDispatcher();\n>  \n>  \t\tTimer timer;\n> -\t\ttimer.start(5000);\n> -\t\twhile (timer.isRunning() && !sink_.done())\n> +\t\ttimer.start(1000);\n> +\t\twhile (timer.isRunning())\n>  \t\t\tdispatcher->processEvents();\n>  \n> -\t\tstd::cout << framesCaptured_ << \" frames captured, \"\n> -\t\t\t  << bufferRemappings_.size() << \" buffers remapped\"\n> -\t\t\t  << std::endl;\n> +\t\tif (completeRequestsCount_ <= cfg.bufferCount * 2) {\n> +\t\t\tstd::cout << \"Failed to capture enough frames (got \"\n> +\t\t\t\t  << completeRequestsCount_ << \" expected at least \"\n> +\t\t\t\t  << cfg.bufferCount * 2 << \")\" << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n>  \n> -\t\tif (framesCaptured_ < 60) {\n> -\t\t\tstd::cout << \"Too few frames captured\" << std::endl;\n> +\t\tif (completeRequestsCount_ != completeBuffersCount_) {\n> +\t\t\tstd::cout << \"Number of completed buffers and requests differ\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (bufferRemappings_.empty()) {\n> -\t\t\tstd::cout << \"No buffer remappings\" << std::endl;\n> +\t\tif (camera_->stop()) {\n> +\t\t\tstd::cout << \"Failed to stop camera\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (bufferRemappings_[0] < 40) {\n> -\t\t\tstd::cout << \"Early buffer remapping\" << std::endl;\n> +\t\tif (camera_->freeBuffers()) {\n> +\t\t\tstd::cout << \"Failed to free buffers\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n>  \t\treturn TestPass;\n>  \t}\n>  \n> -\tvoid cleanup()\n> -\t{\n> -\t\tsink_.cleanup();\n> -\n> -\t\tcamera_->stop();\n> -\t\tcamera_->freeBuffers();\n> -\t}\n> -\n>  private:\n> -\tStream *stream_;\n> -\n> -\tstd::map<unsigned int, int> bufferMappings_;\n> -\tstd::vector<unsigned int> bufferRemappings_;\n> -\tunsigned int framesCaptured_;\n> -\n> -\tFrameSink sink_;\n> +\tunsigned int completeBuffersCount_;\n> +\tunsigned int completeRequestsCount_;\n> +\tstd::unique_ptr<CameraConfiguration> config_;\n>  };\n>  \n> +} /* namespace */\n> +\n>  TEST_REGISTER(BufferImportTest);","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8A6FE60612\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed,  8 Jan 2020 02:17:54 +0100 (CET)","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 8E8BC52F;\n\tWed,  8 Jan 2020 02:17:53 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1578446274;\n\tbh=SYlQU2YScfP5sh9CAAVNpPPKbbqRDWg98oi8TUr1njU=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=Ohot2UrpWTgL3wI9pr54hEd170LPqjC40i9L105xRcCusJzVF2qotvd070NJTVIoQ\n\tp+PxKnomKCUNF78Mae10TO7pcqow/YBmD13CKspqOQjEVWvGGDBo4izMC6pWkPNzC5\n\tOezJW6s79Byrjjpfc+3ZhelBfbu/rcHShJKDSAEw=","Date":"Wed, 8 Jan 2020 03:17:41 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20200108011741.GU4871@pendragon.ideasonboard.com>","References":"<20191230120510.938333-1-niklas.soderlund@ragnatech.se>\n\t<20191230120510.938333-15-niklas.soderlund@ragnatech.se>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20191230120510.938333-15-niklas.soderlund@ragnatech.se>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH v2 14/25] test: camera: buffer_import:\n\tUpdate to FrameBuffer restrictions","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>","X-List-Received-Date":"Wed, 08 Jan 2020 01:17:54 -0000"}}]