Visual Servoing Platform version 3.5.0
tutorial-grabber-v4l2-threaded.cpp
1
3#include <iostream>
4
5#include <visp3/core/vpImageConvert.h>
6#include <visp3/core/vpMutex.h>
7#include <visp3/core/vpThread.h>
8#include <visp3/core/vpTime.h>
9#include <visp3/gui/vpDisplayX.h>
10#include <visp3/sensor/vpV4l2Grabber.h>
11
12#if defined(VISP_HAVE_V4L2) && defined(VISP_HAVE_PTHREAD)
13
14// Shared vars
15typedef enum { capture_waiting, capture_started, capture_stopped } t_CaptureState;
16t_CaptureState s_capture_state = capture_waiting;
18vpMutex s_mutex_capture;
20
22vpThread::Return captureFunction(vpThread::Args args)
23{
24 vpV4l2Grabber cap = *(static_cast<vpV4l2Grabber *>(args));
26 bool stop_capture_ = false;
27
28 cap.open(frame_);
29
30 double start_time = vpTime::measureTimeSecond();
31 while ((vpTime::measureTimeSecond() - start_time) < 30 && !stop_capture_) {
32 // Capture in progress
33 cap.acquire(frame_); // get a new frame from camera
34
35 // Update shared data
36 {
37 vpMutex::vpScopedLock lock(s_mutex_capture);
38 if (s_capture_state == capture_stopped)
39 stop_capture_ = true;
40 else
41 s_capture_state = capture_started;
42 s_frame = frame_;
43 }
44 }
45
46 {
47 vpMutex::vpScopedLock lock(s_mutex_capture);
48 s_capture_state = capture_stopped;
49 }
50 std::cout << "End of capture thread" << std::endl;
51 return 0;
52}
54
56vpThread::Return displayFunction(vpThread::Args args)
57{
58 (void)args; // Avoid warning: unused parameter args
60
61 t_CaptureState capture_state_;
62 bool display_initialized_ = false;
63#if defined(VISP_HAVE_X11)
64 vpDisplayX *d_ = NULL;
65#endif
66
67 do {
68 s_mutex_capture.lock();
69 capture_state_ = s_capture_state;
70 s_mutex_capture.unlock();
71
72 // Check if a frame is available
73 if (capture_state_ == capture_started) {
74 // Create a copy of the captured frame
75 {
76 vpMutex::vpScopedLock lock(s_mutex_capture);
77 I_ = s_frame;
78 }
79
80 // Check if we need to initialize the display with the first frame
81 if (!display_initialized_) {
82// Initialize the display
83#if defined(VISP_HAVE_X11)
84 d_ = new vpDisplayX(I_);
85 display_initialized_ = true;
86#endif
87 }
88
89 // Display the image
91
92 // Trigger end of acquisition with a mouse click
93 vpDisplay::displayText(I_, 10, 10, "Click to exit...", vpColor::red);
94 if (vpDisplay::getClick(I_, false)) {
95 vpMutex::vpScopedLock lock(s_mutex_capture);
96 s_capture_state = capture_stopped;
97 }
98
99 // Update the display
101 } else {
102 vpTime::wait(2); // Sleep 2ms
103 }
104 } while (capture_state_ != capture_stopped);
105
106#if defined(VISP_HAVE_X11)
107 delete d_;
108#endif
109
110 std::cout << "End of display thread" << std::endl;
111 return 0;
112}
114
116int main(int argc, const char *argv[])
117{
118 unsigned int opt_device = 0; // Default is opening /dev/video0
119 unsigned int opt_scale = 2; // Default value is 2 in the constructor. Turn
120 // it to 1 to avoid subsampling
121
122 // Command line options
123 for (int i = 0; i < argc; i++) {
124 if (std::string(argv[i]) == "--camera_device")
125 opt_device = (unsigned int)atoi(argv[i + 1]);
126 else if (std::string(argv[i]) == "--scale")
127 opt_scale = (unsigned int)atoi(argv[i + 1]);
128 else if (std::string(argv[i]) == "--help" || std::string(argv[i]) == "--h") {
129 std::cout << "Usage: " << argv[0]
130 << " [--camera_device <camera device (default: 0)>] [--scale <subsampling factor>]"
131 << " [--help] [-h]"
132 << std::endl;
133 return 0;
134 }
135 }
136
137 // Instantiate the grabber
139 std::ostringstream device;
140 device << "/dev/video" << opt_device;
141 g.setDevice(device.str());
142 g.setScale(opt_scale);
143
144 // Start the threads
145 vpThread thread_capture((vpThread::Fn)captureFunction, (vpThread::Args)&g);
146 vpThread thread_display((vpThread::Fn)displayFunction);
147
148 // Wait until thread ends up
149 thread_capture.join();
150 thread_display.join();
151
152 return 0;
153}
155
156#else
157int main()
158{
159#ifndef VISP_HAVE_V4L2
160 std::cout << "You should enable V4L2 to make this example working..." << std::endl;
161#elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
162 std::cout << "You should enable pthread usage and rebuild ViSP..." << std::endl;
163#else
164 std::cout << "Multi-threading seems not supported on this platform" << std::endl;
165#endif
166}
167
168#endif
static const vpColor red
Definition: vpColor.h:217
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:135
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)
Class that allows protection by mutex.
Definition: vpMutex.h:171
void unlock()
Definition: vpMutex.h:111
void lock()
Definition: vpMutex.h:95
void * Return
Definition: vpThread.h:78
void *(* Fn)(Args)
Definition: vpThread.h:79
void * Args
Definition: vpThread.h:77
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)
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeSecond()