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