diff options
Diffstat (limited to 'test/v4l2_videodevice')
-rw-r--r-- | test/v4l2_videodevice/buffer_cache.cpp | 41 | ||||
-rw-r--r-- | test/v4l2_videodevice/buffer_sharing.cpp | 16 | ||||
-rw-r--r-- | test/v4l2_videodevice/capture_async.cpp | 25 | ||||
-rw-r--r-- | test/v4l2_videodevice/controls.cpp | 37 | ||||
-rw-r--r-- | test/v4l2_videodevice/dequeue_watchdog.cpp | 102 | ||||
-rw-r--r-- | test/v4l2_videodevice/double_open.cpp | 2 | ||||
-rw-r--r-- | test/v4l2_videodevice/formats.cpp | 13 | ||||
-rw-r--r-- | test/v4l2_videodevice/meson.build | 29 | ||||
-rw-r--r-- | test/v4l2_videodevice/request_buffers.cpp | 2 | ||||
-rw-r--r-- | test/v4l2_videodevice/stream_on_off.cpp | 2 | ||||
-rw-r--r-- | test/v4l2_videodevice/v4l2_m2mdevice.cpp | 29 | ||||
-rw-r--r-- | test/v4l2_videodevice/v4l2_videodevice_test.cpp | 18 | ||||
-rw-r--r-- | test/v4l2_videodevice/v4l2_videodevice_test.h | 36 |
13 files changed, 261 insertions, 91 deletions
diff --git a/test/v4l2_videodevice/buffer_cache.cpp b/test/v4l2_videodevice/buffer_cache.cpp index d730e755..5a9aa219 100644 --- a/test/v4l2_videodevice/buffer_cache.cpp +++ b/test/v4l2_videodevice/buffer_cache.cpp @@ -9,6 +9,7 @@ #include <random> #include <vector> +#include <libcamera/formats.h> #include <libcamera/stream.h> #include "buffer_source.h" @@ -125,6 +126,35 @@ public: return TestPass; } + int testIsEmpty(const std::vector<std::unique_ptr<FrameBuffer>> &buffers) + { + V4L2BufferCache cache(buffers.size()); + + if (!cache.isEmpty()) + return TestFail; + + for (auto const &buffer : buffers) { + FrameBuffer &b = *buffer.get(); + cache.get(b); + } + + if (cache.isEmpty()) + return TestFail; + + unsigned int i; + for (i = 0; i < buffers.size() - 1; i++) + cache.put(i); + + if (cache.isEmpty()) + return TestFail; + + cache.put(i); + if (!cache.isEmpty()) + return TestFail; + + return TestPass; + } + int init() override { std::random_device rd; @@ -142,7 +172,7 @@ public: const unsigned int numBuffers = 8; StreamConfiguration cfg; - cfg.pixelFormat = PixelFormat(DRM_FORMAT_YUYV); + cfg.pixelFormat = formats::YUYV; cfg.size = Size(600, 800); cfg.bufferCount = numBuffers; @@ -203,6 +233,13 @@ public: if (testHot(&cacheHalf, buffers, numBuffers / 2) != TestPass) return TestFail; + /* + * Test that the isEmpty function reports the correct result at + * various levels of cache fullness. + */ + if (testIsEmpty(buffers) != TestPass) + return TestFail; + return TestPass; } @@ -212,4 +249,4 @@ private: } /* namespace */ -TEST_REGISTER(BufferCacheTest); +TEST_REGISTER(BufferCacheTest) diff --git a/test/v4l2_videodevice/buffer_sharing.cpp b/test/v4l2_videodevice/buffer_sharing.cpp index 14d3055a..fa856ab6 100644 --- a/test/v4l2_videodevice/buffer_sharing.cpp +++ b/test/v4l2_videodevice/buffer_sharing.cpp @@ -12,13 +12,17 @@ #include <iostream> -#include <libcamera/buffer.h> -#include <libcamera/event_dispatcher.h> -#include <libcamera/timer.h> +#include <libcamera/framebuffer.h> + +#include <libcamera/base/event_dispatcher.h> +#include <libcamera/base/thread.h> +#include <libcamera/base/timer.h> -#include "thread.h" #include "v4l2_videodevice_test.h" +using namespace libcamera; +using namespace std::chrono_literals; + class BufferSharingTest : public V4L2VideoDeviceTest { public: @@ -142,7 +146,7 @@ protected: return TestFail; } - timeout.start(10000); + timeout.start(10000ms); while (timeout.isRunning()) { dispatcher->processEvents(); if (framesCaptured_ > 30 && framesOutput_ > 30) @@ -199,4 +203,4 @@ private: unsigned int framesOutput_; }; -TEST_REGISTER(BufferSharingTest); +TEST_REGISTER(BufferSharingTest) diff --git a/test/v4l2_videodevice/capture_async.cpp b/test/v4l2_videodevice/capture_async.cpp index b38aabc6..67366461 100644 --- a/test/v4l2_videodevice/capture_async.cpp +++ b/test/v4l2_videodevice/capture_async.cpp @@ -7,13 +7,17 @@ #include <iostream> -#include <libcamera/buffer.h> -#include <libcamera/event_dispatcher.h> -#include <libcamera/timer.h> +#include <libcamera/framebuffer.h> + +#include <libcamera/base/event_dispatcher.h> +#include <libcamera/base/thread.h> +#include <libcamera/base/timer.h> -#include "thread.h" #include "v4l2_videodevice_test.h" +using namespace libcamera; +using namespace std::chrono_literals; + class CaptureAsyncTest : public V4L2VideoDeviceTest { public: @@ -57,10 +61,12 @@ protected: if (ret) return TestFail; - timeout.start(10000); + const unsigned int nFrames = 30; + + timeout.start(500ms * nFrames); while (timeout.isRunning()) { dispatcher->processEvents(); - if (frames > 30) + if (frames > nFrames) break; } @@ -69,8 +75,9 @@ protected: return TestFail; } - if (frames < 30) { - std::cout << "Failed to capture 30 frames within timeout." << std::endl; + if (frames < nFrames) { + std::cout << "Failed to capture " << nFrames + << " frames within timeout." << std::endl; return TestFail; } @@ -87,4 +94,4 @@ private: unsigned int frames; }; -TEST_REGISTER(CaptureAsyncTest); +TEST_REGISTER(CaptureAsyncTest) diff --git a/test/v4l2_videodevice/controls.cpp b/test/v4l2_videodevice/controls.cpp index da9e0111..b0130295 100644 --- a/test/v4l2_videodevice/controls.cpp +++ b/test/v4l2_videodevice/controls.cpp @@ -2,7 +2,7 @@ /* * Copyright (C) 2019, Google Inc. * - * controls.cpp - V4L2 device controls handling test + * V4L2 device controls handling test */ #include <algorithm> @@ -10,12 +10,13 @@ #include <iostream> #include <limits.h> -#include "v4l2_videodevice.h" +#include "libcamera/internal/v4l2_videodevice.h" #include "v4l2_videodevice_test.h" /* These come from the vivid driver. */ #define VIVID_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000) +#define VIVID_CID_INTEGER64 (VIVID_CID_CUSTOM_BASE + 3) #define VIVID_CID_U8_4D_ARRAY (VIVID_CID_CUSTOM_BASE + 10) /* Helper for VIVID_CID_U8_4D_ARRAY control array size: not from kernel. */ @@ -46,6 +47,7 @@ protected: if (infoMap.find(V4L2_CID_BRIGHTNESS) == infoMap.end() || infoMap.find(V4L2_CID_CONTRAST) == infoMap.end() || infoMap.find(V4L2_CID_SATURATION) == infoMap.end() || + infoMap.find(VIVID_CID_INTEGER64) == infoMap.end() || infoMap.find(VIVID_CID_U8_4D_ARRAY) == infoMap.end()) { cerr << "Missing controls" << endl; return TestFail; @@ -54,21 +56,25 @@ protected: const ControlInfo &brightness = infoMap.find(V4L2_CID_BRIGHTNESS)->second; const ControlInfo &contrast = infoMap.find(V4L2_CID_CONTRAST)->second; const ControlInfo &saturation = infoMap.find(V4L2_CID_SATURATION)->second; + const ControlInfo &int64 = infoMap.find(VIVID_CID_INTEGER64)->second; const ControlInfo &u8 = infoMap.find(VIVID_CID_U8_4D_ARRAY)->second; /* Test getting controls. */ - ControlList ctrls(infoMap); - ctrls.set(V4L2_CID_BRIGHTNESS, -1); - ctrls.set(V4L2_CID_CONTRAST, -1); - ctrls.set(V4L2_CID_SATURATION, -1); - ctrls.set(VIVID_CID_U8_4D_ARRAY, 0); - - int ret = capture_->getControls(&ctrls); - if (ret) { + ControlList ctrls = capture_->getControls({ V4L2_CID_BRIGHTNESS, + V4L2_CID_CONTRAST, + V4L2_CID_SATURATION, + VIVID_CID_INTEGER64, + VIVID_CID_U8_4D_ARRAY }); + if (ctrls.empty()) { cerr << "Failed to get controls" << endl; return TestFail; } + if (ctrls.infoMap() != &infoMap) { + cerr << "Incorrect infoMap for retrieved controls" << endl; + return TestFail; + } + if (ctrls.get(V4L2_CID_BRIGHTNESS).get<int32_t>() == -1 || ctrls.get(V4L2_CID_CONTRAST).get<int32_t>() == -1 || ctrls.get(V4L2_CID_SATURATION).get<int32_t>() == -1) { @@ -76,6 +82,12 @@ protected: return TestFail; } + /* + * The VIVID_CID_INTEGER64 control can take any value, just test + * that its value can be retrieved and has the right type. + */ + ctrls.get(VIVID_CID_INTEGER64).get<int64_t>(); + uint8_t u8Min = u8.min().get<uint8_t>(); uint8_t u8Max = u8.max().get<uint8_t>(); @@ -92,12 +104,13 @@ protected: ctrls.set(V4L2_CID_BRIGHTNESS, brightness.min()); ctrls.set(V4L2_CID_CONTRAST, contrast.max()); ctrls.set(V4L2_CID_SATURATION, saturation.min()); + ctrls.set(VIVID_CID_INTEGER64, int64.min()); std::array<uint8_t, VIVID_CID_U8_ARRAY_SIZE> u8Values; std::fill(u8Values.begin(), u8Values.end(), u8.min().get<uint8_t>()); ctrls.set(VIVID_CID_U8_4D_ARRAY, Span<const uint8_t>(u8Values)); - ret = capture_->setControls(&ctrls); + int ret = capture_->setControls(&ctrls); if (ret) { cerr << "Failed to set controls" << endl; return TestFail; @@ -125,4 +138,4 @@ protected: } }; -TEST_REGISTER(V4L2ControlTest); +TEST_REGISTER(V4L2ControlTest) diff --git a/test/v4l2_videodevice/dequeue_watchdog.cpp b/test/v4l2_videodevice/dequeue_watchdog.cpp new file mode 100644 index 00000000..320d14c8 --- /dev/null +++ b/test/v4l2_videodevice/dequeue_watchdog.cpp @@ -0,0 +1,102 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2022, Ideas on Board Oy. + * + * libcamera V4L2 dequeue watchdog test + */ + +#include <iostream> + +#include <libcamera/base/event_dispatcher.h> +#include <libcamera/base/thread.h> +#include <libcamera/base/timer.h> + +#include <libcamera/framebuffer.h> + +#include "v4l2_videodevice_test.h" + +using namespace libcamera; +using namespace std::chrono_literals; + +class DequeueWatchdogTest : public V4L2VideoDeviceTest +{ +public: + DequeueWatchdogTest() + : V4L2VideoDeviceTest("vimc", "Raw Capture 0"), frames_(0), barks_(0) {} + +protected: + int run() + { + constexpr unsigned int bufferCount = 8; + + EventDispatcher *dispatcher = Thread::current()->eventDispatcher(); + Timer timeout; + + int ret = capture_->allocateBuffers(bufferCount, &buffers_); + if (ret < 0) { + std::cout << "Failed to allocate buffers" << std::endl; + return TestFail; + } + + capture_->dequeueTimeout.connect(this, &DequeueWatchdogTest::barkCounter); + capture_->setDequeueTimeout(5ms); + + capture_->bufferReady.connect(this, &DequeueWatchdogTest::receiveBuffer); + + for (const std::unique_ptr<FrameBuffer> &buffer : buffers_) { + if (capture_->queueBuffer(buffer.get())) { + std::cout << "Failed to queue buffer" << std::endl; + return TestFail; + } + } + + ret = capture_->streamOn(); + if (ret < 0) { + std::cout << "Failed to start streaming" << std::endl; + return TestFail; + } + + timeout.start(5s); + while (timeout.isRunning()) { + dispatcher->processEvents(); + if (frames_ > 5) + break; + } + + std::cout << "Processed " << frames_ << " frames_ and heard " + << barks_ << " barks_" << std::endl; + + if (!barks_) { + std::cout << "Failed to hear any barks_." << std::endl; + return TestFail; + } + + capture_->streamOff(); + + return TestPass; + } + +private: + void receiveBuffer(FrameBuffer *buffer) + { + if (buffer->metadata().status == FrameMetadata::FrameCancelled) + return; + + std::cout << "Buffer received" << std::endl; + frames_++; + + /* Requeue the buffer for further use. */ + capture_->queueBuffer(buffer); + } + + void barkCounter() + { + std::cout << "Watchdog is barking" << std::endl; + barks_++; + } + + unsigned int frames_; + unsigned int barks_; +}; + +TEST_REGISTER(DequeueWatchdogTest) diff --git a/test/v4l2_videodevice/double_open.cpp b/test/v4l2_videodevice/double_open.cpp index 5768d404..7d11f6fe 100644 --- a/test/v4l2_videodevice/double_open.cpp +++ b/test/v4l2_videodevice/double_open.cpp @@ -38,4 +38,4 @@ protected: } /* namespace */ -TEST_REGISTER(DoubleOpen); +TEST_REGISTER(DoubleOpen) diff --git a/test/v4l2_videodevice/formats.cpp b/test/v4l2_videodevice/formats.cpp index a7421421..6c052622 100644 --- a/test/v4l2_videodevice/formats.cpp +++ b/test/v4l2_videodevice/formats.cpp @@ -8,8 +8,9 @@ #include <iostream> #include <limits.h> -#include "utils.h" -#include "v4l2_videodevice.h" +#include <libcamera/base/utils.h> + +#include "libcamera/internal/v4l2_videodevice.h" #include "v4l2_videodevice_test.h" @@ -55,10 +56,10 @@ protected: { V4L2_PIX_FMT_Y16_BE, "Y16 -BE" } }; - for (const auto &format : formats) { - if (V4L2PixelFormat(format.first).toString() != format.second) { + for (const auto &fmt : formats) { + if (V4L2PixelFormat(fmt.first).toString() != fmt.second) { cerr << "Failed to convert V4L2PixelFormat" - << utils::hex(format.first) << "to string" + << utils::hex(fmt.first) << "to string" << endl; return TestFail; } @@ -74,4 +75,4 @@ protected: } }; -TEST_REGISTER(Format); +TEST_REGISTER(Format) diff --git a/test/v4l2_videodevice/meson.build b/test/v4l2_videodevice/meson.build index 685fcf6d..87ea4f96 100644 --- a/test/v4l2_videodevice/meson.build +++ b/test/v4l2_videodevice/meson.build @@ -1,21 +1,24 @@ +# SPDX-License-Identifier: CC0-1.0 + # Tests are listed in order of complexity. # They are not alphabetically sorted. v4l2_videodevice_tests = [ - [ 'double_open', 'double_open.cpp' ], - [ 'controls', 'controls.cpp' ], - [ 'formats', 'formats.cpp' ], - [ 'request_buffers', 'request_buffers.cpp' ], - [ 'buffer_cache', 'buffer_cache.cpp' ], - [ 'stream_on_off', 'stream_on_off.cpp' ], - [ 'capture_async', 'capture_async.cpp' ], - [ 'buffer_sharing', 'buffer_sharing.cpp' ], - [ 'v4l2_m2mdevice', 'v4l2_m2mdevice.cpp' ], + {'name': 'double_open', 'sources': ['double_open.cpp']}, + {'name': 'controls', 'sources': ['controls.cpp']}, + {'name': 'formats', 'sources': ['formats.cpp']}, + {'name': 'dequeue_watchdog', 'sources': ['dequeue_watchdog.cpp']}, + {'name': 'request_buffers', 'sources': ['request_buffers.cpp']}, + {'name': 'buffer_cache', 'sources': ['buffer_cache.cpp']}, + {'name': 'stream_on_off', 'sources': ['stream_on_off.cpp']}, + {'name': 'capture_async', 'sources': ['capture_async.cpp']}, + {'name': 'buffer_sharing', 'sources': ['buffer_sharing.cpp']}, + {'name': 'v4l2_m2mdevice', 'sources': ['v4l2_m2mdevice.cpp']}, ] -foreach t : v4l2_videodevice_tests - exe = executable(t[0], [t[1], 'v4l2_videodevice_test.cpp'], - dependencies : libcamera_dep, +foreach test : v4l2_videodevice_tests + exe = executable(test['name'], [test['sources'], 'v4l2_videodevice_test.cpp'], + dependencies : libcamera_private, link_with : test_libraries, include_directories : test_includes_internal) - test(t[0], exe, suite : 'v4l2_videodevice', is_parallel : false) + test(test['name'], exe, suite : 'v4l2_videodevice', is_parallel : false) endforeach diff --git a/test/v4l2_videodevice/request_buffers.cpp b/test/v4l2_videodevice/request_buffers.cpp index 2f8dfe1c..fb577147 100644 --- a/test/v4l2_videodevice/request_buffers.cpp +++ b/test/v4l2_videodevice/request_buffers.cpp @@ -26,4 +26,4 @@ protected: } }; -TEST_REGISTER(RequestBuffersTest); +TEST_REGISTER(RequestBuffersTest) diff --git a/test/v4l2_videodevice/stream_on_off.cpp b/test/v4l2_videodevice/stream_on_off.cpp index ce48310a..4ed99e93 100644 --- a/test/v4l2_videodevice/stream_on_off.cpp +++ b/test/v4l2_videodevice/stream_on_off.cpp @@ -33,4 +33,4 @@ protected: } }; -TEST_REGISTER(StreamOnStreamOffTest); +TEST_REGISTER(StreamOnStreamOffTest) diff --git a/test/v4l2_videodevice/v4l2_m2mdevice.cpp b/test/v4l2_videodevice/v4l2_m2mdevice.cpp index d20e5dfc..c45f581a 100644 --- a/test/v4l2_videodevice/v4l2_m2mdevice.cpp +++ b/test/v4l2_videodevice/v4l2_m2mdevice.cpp @@ -7,19 +7,21 @@ #include <iostream> -#include <libcamera/buffer.h> -#include <libcamera/event_dispatcher.h> -#include <libcamera/timer.h> +#include <libcamera/framebuffer.h> -#include "device_enumerator.h" -#include "media_device.h" -#include "thread.h" -#include "v4l2_videodevice.h" +#include <libcamera/base/event_dispatcher.h> +#include <libcamera/base/thread.h> +#include <libcamera/base/timer.h> + +#include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/media_device.h" +#include "libcamera/internal/v4l2_videodevice.h" #include "test.h" -using namespace std; using namespace libcamera; +using namespace std; +using namespace std::chrono_literals; class V4L2M2MDeviceTest : public Test { @@ -93,6 +95,11 @@ protected: V4L2VideoDevice *capture = vim2m_->capture(); V4L2VideoDevice *output = vim2m_->output(); + if (capture->controls().empty() || output->controls().empty()) { + cerr << "VIM2M device has no control" << endl; + return TestFail; + } + V4L2DeviceFormat format = {}; if (capture->getFormat(&format)) { cerr << "Failed to get capture format" << endl; @@ -154,7 +161,7 @@ protected: } Timer timeout; - timeout.start(5000); + timeout.start(5000ms); while (timeout.isRunning()) { dispatcher->processEvents(); if (captureFrames_ > 30) @@ -187,7 +194,7 @@ protected: void cleanup() { delete vim2m_; - }; + } private: std::unique_ptr<DeviceEnumerator> enumerator_; @@ -201,4 +208,4 @@ private: unsigned int captureFrames_; }; -TEST_REGISTER(V4L2M2MDeviceTest); +TEST_REGISTER(V4L2M2MDeviceTest) diff --git a/test/v4l2_videodevice/v4l2_videodevice_test.cpp b/test/v4l2_videodevice/v4l2_videodevice_test.cpp index 93b9e72d..9fbd24cc 100644 --- a/test/v4l2_videodevice/v4l2_videodevice_test.cpp +++ b/test/v4l2_videodevice/v4l2_videodevice_test.cpp @@ -9,10 +9,10 @@ #include <linux/media-bus-format.h> -#include "v4l2_videodevice_test.h" +#include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/media_device.h" -#include "device_enumerator.h" -#include "media_device.h" +#include "v4l2_videodevice_test.h" using namespace std; using namespace libcamera; @@ -60,9 +60,12 @@ int V4L2VideoDeviceTest::init() if (capture_->getFormat(&format)) return TestFail; + format.size.width = 640; + format.size.height = 480; + if (driver_ == "vimc") { - sensor_ = new CameraSensor(media_->getEntityByName("Sensor A")); - if (sensor_->init()) + sensor_ = CameraSensorFactoryBase::create(media_->getEntityByName("Sensor A")); + if (!sensor_) return TestFail; debayer_ = new V4L2Subdevice(media_->getEntityByName("Debayer A")); @@ -72,7 +75,7 @@ int V4L2VideoDeviceTest::init() format.fourcc = V4L2PixelFormat(V4L2_PIX_FMT_SBGGR8); V4L2SubdeviceFormat subformat = {}; - subformat.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8; + subformat.code = MEDIA_BUS_FMT_SBGGR8_1X8; subformat.size = format.size; if (sensor_->setFormat(&subformat)) @@ -82,8 +85,6 @@ int V4L2VideoDeviceTest::init() return TestFail; } - format.size.width = 640; - format.size.height = 480; if (capture_->setFormat(&format)) return TestFail; @@ -97,6 +98,5 @@ void V4L2VideoDeviceTest::cleanup() capture_->close(); delete debayer_; - delete sensor_; delete capture_; } diff --git a/test/v4l2_videodevice/v4l2_videodevice_test.h b/test/v4l2_videodevice/v4l2_videodevice_test.h index 9acaceb8..7c9003ec 100644 --- a/test/v4l2_videodevice/v4l2_videodevice_test.h +++ b/test/v4l2_videodevice/v4l2_videodevice_test.h @@ -2,24 +2,22 @@ /* * Copyright (C) 2018, Google Inc. * - * vl42device_test.h - libcamera v4l2device test base class + * libcamera v4l2device test base class */ -#ifndef __LIBCAMERA_V4L2_DEVICE_TEST_H_ -#define __LIBCAMERA_V4L2_DEVICE_TEST_H_ -#include <memory> +#pragma once -#include <libcamera/buffer.h> +#include <memory> -#include "test.h" +#include <libcamera/framebuffer.h> -#include "camera_sensor.h" -#include "device_enumerator.h" -#include "media_device.h" -#include "v4l2_subdevice.h" -#include "v4l2_videodevice.h" +#include "libcamera/internal/camera_sensor.h" +#include "libcamera/internal/device_enumerator.h" +#include "libcamera/internal/media_device.h" +#include "libcamera/internal/v4l2_subdevice.h" +#include "libcamera/internal/v4l2_videodevice.h" -using namespace libcamera; +#include "test.h" class V4L2VideoDeviceTest : public Test { @@ -36,12 +34,10 @@ protected: std::string driver_; std::string entity_; - std::unique_ptr<DeviceEnumerator> enumerator_; - std::shared_ptr<MediaDevice> media_; - CameraSensor *sensor_; - V4L2Subdevice *debayer_; - V4L2VideoDevice *capture_; - std::vector<std::unique_ptr<FrameBuffer>> buffers_; + std::unique_ptr<libcamera::DeviceEnumerator> enumerator_; + std::shared_ptr<libcamera::MediaDevice> media_; + std::unique_ptr<libcamera::CameraSensor> sensor_; + libcamera::V4L2Subdevice *debayer_; + libcamera::V4L2VideoDevice *capture_; + std::vector<std::unique_ptr<libcamera::FrameBuffer>> buffers_; }; - -#endif /* __LIBCAMERA_V4L2_DEVICE_TEST_H_ */ |