Patch Detail
Show a patch.
GET /api/1.1/patches/2464/?format=api
{ "id": 2464, "url": "https://patchwork.libcamera.org/api/1.1/patches/2464/?format=api", "web_url": "https://patchwork.libcamera.org/patch/2464/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20191230120510.938333-15-niklas.soderlund@ragnatech.se>", "date": "2019-12-30T12:04:59", "name": "[libcamera-devel,v2,14/25] test: camera: buffer_import: Update to FrameBuffer restrictions", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "5b825f2ea72d0f5e12941a1709d2f81cc32a95c4", "submitter": { "id": 5, "url": "https://patchwork.libcamera.org/api/1.1/people/5/?format=api", "name": "Niklas Söderlund", "email": "niklas.soderlund@ragnatech.se" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/2464/mbox/", "series": [ { "id": 593, "url": "https://patchwork.libcamera.org/api/1.1/series/593/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=593", "date": "2019-12-30T12:04:45", "name": "libcamera: Rework buffer API", "version": 2, "mbox": "https://patchwork.libcamera.org/series/593/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/2464/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/2464/checks/", "tags": {}, "headers": { "Return-Path": "<niklas.soderlund@ragnatech.se>", "Received": [ "from bin-mail-out-05.binero.net (bin-mail-out-05.binero.net\n\t[195.74.38.228])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E3EB66046C\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 30 Dec 2019 13:06:01 +0100 (CET)", "from bismarck.berto.se (p4fca2fd0.dip0.t-ipconnect.de\n\t[79.202.47.208]) by bin-vsp-out-01.atm.binero.net (Halon) with ESMTPA\n\tid be69b947-2afc-11ea-a00b-005056917a89;\n\tMon, 30 Dec 2019 13:06:00 +0100 (CET)" ], "X-Halon-ID": "be69b947-2afc-11ea-a00b-005056917a89", "Authorized-sender": "niklas@soderlund.pp.se", "From": "=?utf-8?q?Niklas_S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>", "To": "libcamera-devel@lists.libcamera.org", "Date": "Mon, 30 Dec 2019 13:04:59 +0100", "Message-Id": "<20191230120510.938333-15-niklas.soderlund@ragnatech.se>", "X-Mailer": "git-send-email 2.24.1", "In-Reply-To": "<20191230120510.938333-1-niklas.soderlund@ragnatech.se>", "References": "<20191230120510.938333-1-niklas.soderlund@ragnatech.se>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "Subject": "[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": "Mon, 30 Dec 2019 12:06:02 -0000" }, "content": "With the FrameBuffer interface the V4L2 buffer indexes are not visible\noutside the V4L2VideoDevice so it's not possible to to test that the\nexpected indexes are used when using external buffers (allocated\ndirectly from a V4L2 video device) with a Camera. Rewrite the test to\nthis limitation.\n\nThe idea of the test stays the same, test that buffers allocated from a\nV4L2 video device (vivid) can be imported and used on a Camera (vimc).\nAs an added bonus the rewrite makes us of the FrameBuffer interface for\nthe allocation of buffers at the source (vivid) and imports them to the\nCamera which still uses the Buffer interface internally.\n\nSigned-off-by: Niklas Söderlund <niklas.soderlund@ragnatech.se>\n---\n test/camera/buffer_import.cpp | 390 ++++++++++------------------------\n 1 file changed, 110 insertions(+), 280 deletions(-)", "diff": "diff --git a/test/camera/buffer_import.cpp b/test/camera/buffer_import.cpp\nindex 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 \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);\n", "prefixes": [ "libcamera-devel", "v2", "14/25" ] }