[{"id":3070,"web_url":"https://patchwork.libcamera.org/comment/3070/","msgid":"<20191118190821.GE4888@pendragon.ideasonboard.com>","date":"2019-11-18T19:08:21","subject":"Re: [libcamera-devel] [RFC 01/12] test: camera: buffer_import:\n\tRemove test","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nOn Mon, Oct 28, 2019 at 03:25:14AM +0100, Niklas Söderlund wrote:\n> The buffer interface is about to be reworked to hide the specifics of\n> buffer importing and its mapping to V4L2 devices from applications. In\n> preparation of that remove the camera test which examines this.\n> \n> The proper operation of buffer importing on the V4L2 level is still\n> tested in the V4L2 specific buffer sharing test case.\n> \n> Signed-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n\nWhile I'm sad to see 432 lines of test going away, I understand they're\nin the way of the rework, so I'm OK with it. I however assume that the\nnon-RFC version of this series will have a new buffer import test (and\neven more tests if possible :-)). On that basis,\n\nAcked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  test/camera/buffer_import.cpp | 432 ----------------------------------\n>  test/camera/meson.build       |   1 -\n>  2 files changed, 433 deletions(-)\n>  delete mode 100644 test/camera/buffer_import.cpp\n> \n> diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\n> deleted file mode 100644\n> index 9cac19d8ce81fa4d..0000000000000000\n> --- a/test/camera/buffer_import.cpp\n> +++ /dev/null\n> @@ -1,432 +0,0 @@\n> -/* SPDX-License-Identifier: GPL-2.0-or-later */\n> -/*\n> - * Copyright (C) 2019, Google Inc.\n> - *\n> - * libcamera Camera API tests\n> - *\n> - * Test importing buffers exported from the VIVID output device into a Camera\n> - */\n> -\n> -#include <algorithm>\n> -#include <iostream>\n> -#include <numeric>\n> -#include <random>\n> -#include <vector>\n> -\n> -#include \"device_enumerator.h\"\n> -#include \"media_device.h\"\n> -#include \"v4l2_videodevice.h\"\n> -\n> -#include \"camera_test.h\"\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> -\n> -class FrameSink\n> -{\n> -public:\n> -\tFrameSink()\n> -\t\t: video_(nullptr)\n> -\t{\n> -\t}\n> -\n> -\tint init()\n> -\t{\n> -\t\tint ret;\n> -\n> -\t\t/* Locate and open the video device. */\n> -\t\tstd::string videoDeviceName = \"vivid-000-vid-out\";\n> -\n> -\t\tstd::unique_ptr<DeviceEnumerator> enumerator =\n> -\t\t\tDeviceEnumerator::create();\n> -\t\tif (!enumerator) {\n> -\t\t\tstd::cout << \"Failed to create device enumerator\" << std::endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n> -\t\tif (enumerator->enumerate()) {\n> -\t\t\tstd::cout << \"Failed to enumerate media devices\" << std::endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n> -\t\tDeviceMatch dm(\"vivid\");\n> -\t\tdm.add(videoDeviceName);\n> -\n> -\t\tmedia_ = enumerator->search(dm);\n> -\t\tif (!media_) {\n> -\t\t\tstd::cout << \"No vivid output device available\" << std::endl;\n> -\t\t\treturn TestSkip;\n> -\t\t}\n> -\n> -\t\tvideo_ = V4L2VideoDevice::fromEntityName(media_.get(), videoDeviceName);\n> -\t\tif (!video_) {\n> -\t\t\tstd::cout << \"Unable to open \" << videoDeviceName << std::endl;\n> -\t\t\treturn TestFail;\n> -\t\t}\n> -\n> -\t\tif (video_->open())\n> -\t\t\treturn TestFail;\n> -\n> -\t\t/* Configure the 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\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}\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> -\tconst V4L2DeviceFormat &format() const { return format_; }\n> -\n> -\tSignal<uint64_t, int> requestReady;\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].dmabuf();\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> -};\n> -\n> -class BufferImportTest : public CameraTest\n> -{\n> -public:\n> -\tBufferImportTest()\n> -\t\t: CameraTest()\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(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->status() != Buffer::BufferSuccess)\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> -\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> -\n> -\t\tif (remapped)\n> -\t\t\tbufferRemappings_.push_back(framesCaptured_);\n> -\n> -\t\tbufferMappings_[index] = dmabuf;\n> -\t\tframesCaptured_++;\n> -\n> -\t\tsink_.requestComplete(request->cookie(), buffer);\n> -\n> -\t\tif (framesCaptured_ == 60)\n> -\t\t\tsink_.stop();\n> -\t}\n> -\n> -\tint initCamera()\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> -\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\t\treturn TestFail;\n> -\t\t}\n> -\n> -\t\tconst V4L2DeviceFormat &format = sink_.format();\n> -\n> -\t\tStreamConfiguration &cfg = config->at(0);\n> -\t\tcfg.size = format.size;\n> -\t\tcfg.pixelFormat = format.fourcc;\n> -\t\tcfg.bufferCount = CAMERA_BUFFER_COUNT;\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\t\treturn TestFail;\n> -\t\t}\n> -\n> -\t\tstream_ = cfg.stream();\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> -\n> -\t\treturn TestPass;\n> -\t}\n> -\n> -\tint init()\n> -\t{\n> -\t\tint ret = CameraTest::init();\n> -\t\tif (ret)\n> -\t\t\treturn ret;\n> -\n> -\t\tret = sink_.init();\n> -\t\tif (ret != TestPass) {\n> -\t\t\tcleanup();\n> -\t\t\treturn ret;\n> -\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> -\n> -\t\tsink_.requestReady.connect(this, &BufferImportTest::queueRequest);\n> -\t\treturn TestPass;\n> -\t}\n> -\n> -\tint run()\n> -\t{\n> -\t\tint ret;\n> -\n> -\t\tframesCaptured_ = 0;\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\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\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> -\n> -\t\tif (framesCaptured_ < 60) {\n> -\t\t\tstd::cout << \"Too few frames captured\" << 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\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\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> -\n> -\t\tCameraTest::cleanup();\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> -};\n> -\n> -TEST_REGISTER(BufferImportTest);\n> diff --git a/test/camera/meson.build b/test/camera/meson.build\n> index d6fd66b8f89e21b4..35e97ce5de1a72ca 100644\n> --- a/test/camera/meson.build\n> +++ b/test/camera/meson.build\n> @@ -3,7 +3,6 @@\n>  camera_tests = [\n>      [ 'configuration_default',  'configuration_default.cpp' ],\n>      [ 'configuration_set',      'configuration_set.cpp' ],\n> -    [ 'buffer_import',          'buffer_import.cpp' ],\n>      [ 'statemachine',           'statemachine.cpp' ],\n>      [ 'capture',                'capture.cpp' ],\n>  ]","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 6F8DF60F1C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 18 Nov 2019 20:09:18 +0100 (CET)","from pendragon.ideasonboard.com (unknown [38.98.37.142])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 5C1FD311;\n\tMon, 18 Nov 2019 20:08:59 +0100 (CET)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1574104158;\n\tbh=ZAGGI8HKuJmFiW/YjdTP+5xz/GhGp98otndrPIPusJo=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=Bv8NHGGwYgtBpciAu/Em+k9esYmtBPybcbcropij91RRv8eLf0lIBOioi1HKSiVbN\n\txQF3v7lDjXU7FSiiwigvCPXc31yg2xUzi3BdFl1x6qWKwCtjfOOi0uRgwwKALc8A2O\n\tFVQYnrAn1DISC/CvcsIdEOf2YaCjuX++hcVZO+/o=","Date":"Mon, 18 Nov 2019 21:08:21 +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":"<20191118190821.GE4888@pendragon.ideasonboard.com>","References":"<20191028022525.796995-1-niklas.soderlund@ragnatech.se>\n\t<20191028022525.796995-2-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":"<20191028022525.796995-2-niklas.soderlund@ragnatech.se>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [RFC 01/12] test: camera: buffer_import:\n\tRemove test","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":"Mon, 18 Nov 2019 19:09:18 -0000"}}]