Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
tutorial-grabber-v4l2-threaded.cpp
1
3#include <iostream>
4#include <visp3/core/vpConfig.h>
5#include <visp3/core/vpImageConvert.h>
6#include <visp3/core/vpTime.h>
7#include <visp3/gui/vpDisplayFactory.h>
8#include <visp3/sensor/vpV4l2Grabber.h>
9
10#if defined(VISP_HAVE_V4L2) && defined(VISP_HAVE_THREADS) && defined(VISP_HAVE_DISPLAY)
11
12#include <thread>
13#include <mutex>
14
15#ifdef ENABLE_VISP_NAMESPACE
16using namespace VISP_NAMESPACE_NAME;
17#endif
18
19// Shared vars
20typedef enum { capture_waiting, capture_started, capture_stopped } t_CaptureState;
22
24void captureFunction(vpV4l2Grabber &cap, std::mutex &mutex_capture, vpImage<unsigned char> &frame, t_CaptureState &capture_state)
25{
27 bool stop_capture_ = false;
28
29 cap.open(frame_);
30
32 while ((vpTime::measureTimeSecond() - start_time) < 30 && !stop_capture_) {
33 // Capture in progress
34 cap.acquire(frame_); // get a new frame from camera
35
36 // Update shared data
37 {
38 std::lock_guard<std::mutex> lock(mutex_capture);
39 if (capture_state == capture_stopped)
40 stop_capture_ = true;
41 else
42 capture_state = capture_started;
43 frame = frame_;
44 }
45 }
46
47 {
48 std::lock_guard<std::mutex> lock(mutex_capture);
49 capture_state = capture_stopped;
50 }
51 std::cout << "End of capture thread" << std::endl;
52}
54
56void displayFunction(std::mutex &mutex_capture, vpImage<unsigned char> &frame, t_CaptureState &capture_state)
57{
59
60 t_CaptureState capture_state_;
61 bool display_initialized_ = false;
63
64 do {
65 mutex_capture.lock();
66 capture_state_ = capture_state;
67 mutex_capture.unlock();
68
69 // Check if a frame is available
70 if (capture_state_ == capture_started) {
71 // Create a copy of the captured frame
72 {
73 std::lock_guard<std::mutex> lock(mutex_capture);
74 I_ = frame;
75 }
76
77 // Check if we need to initialize the display with the first frame
78 if (!display_initialized_) {
79 // Initialize the display
80 d_->init(I_);
81 display_initialized_ = true;
82 }
83
84 // Display the image
86
87 // Trigger end of acquisition with a mouse click
88 vpDisplay::displayText(I_, 10, 10, "Click to exit...", vpColor::red);
89 if (vpDisplay::getClick(I_, false)) {
90 std::lock_guard<std::mutex> lock(mutex_capture);
91 capture_state = capture_stopped;
92 }
93
94 // Update the display
96 }
97 else {
98 vpTime::wait(2); // Sleep 2ms
99 }
100 } while (capture_state_ != capture_stopped);
101
102 delete d_;
103
104 std::cout << "End of display thread" << std::endl;
105}
107
109int main(int argc, const char *argv[])
110{
111 unsigned int opt_device = 0; // Default is opening /dev/video0
112 unsigned int opt_scale = 2; // Default value is 2 in the constructor. Turn
113 // it to 1 to avoid subsampling
114
115 // Command line options
116 for (int i = 1; i < argc; i++) {
117 if (std::string(argv[i]) == "--camera-device" && i + 1 < argc) {
118 opt_device = static_cast<unsigned int>(atoi(argv[++i]));
119 }
120 else if (std::string(argv[i]) == "--scale" && i + 1 < argc) {
121 opt_scale = static_cast<unsigned int>(atoi(argv[++i]));
122 }
123 else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "--h") {
124 std::cout << "Usage: " << argv[0]
125 << " [--camera-device <camera device (default: 0)>]"
126 << " [--scale <subsampling factor>]"
127 << " [--help] [-h]" << std::endl;
128 return EXIT_SUCCESS;
129 }
130 }
131
132 // Instantiate the grabber
134 std::ostringstream device;
135 device << "/dev/video" << opt_device;
136 g.setDevice(device.str());
137 g.setScale(opt_scale);
138
140 std::mutex mutex_capture;
141 t_CaptureState capture_state = capture_waiting;
142
143 // Start the threads
144 std::thread thread_capture(&captureFunction, std::ref(g), std::ref(mutex_capture), std::ref(frame), std::ref(capture_state));
145 std::thread thread_display(&displayFunction, std::ref(mutex_capture), std::ref(frame), std::ref(capture_state));
146
147 // Wait until thread ends up
148 thread_capture.join();
149 thread_display.join();
150
151 return EXIT_SUCCESS;
152}
154
155#else
156int main()
157{
158#ifndef VISP_HAVE_V4L2
159 std::cout << "You should enable V4L2 to make this example working..." << std::endl;
160#elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
161 std::cout << "You should enable pthread usage and rebuild ViSP..." << std::endl;
162#elif !defined(VISP_HAVE_DISPLAY)
163 std::cout << "You should have at least one GUI library installed to use this example." << std::endl;
164#else
165 std::cout << "Multi-threading seems not supported on this platform" << std::endl;
166#endif
167}
168
169#endif
static const vpColor red
Definition vpColor.h:198
Class that defines generic functionalities for display.
Definition vpDisplay.h:171
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Definition of the vpImage class member functions.
Definition vpImage.h:131
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
void open(vpImage< unsigned char > &I)
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setDevice(const std::string &devname)
void acquire(vpImage< unsigned char > &I)
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeSecond()