Visual Servoing Platform  version 3.6.1 under development (2023-12-02)
vpImageQueue.h
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Image queue for storage helper.
32  */
33 
34 #ifndef vpImageQueue_h
35 #define vpImageQueue_h
36 
37 #include <visp3/core/vpConfig.h>
38 
39 #include <condition_variable>
40 #include <mutex>
41 #include <queue>
42 #include <string>
43 #include <thread>
44 
45 #include <visp3/core/vpDisplay.h>
46 #include <visp3/core/vpIoTools.h>
47 
59 template <class Type> class vpImageQueue
60 {
61 public:
63  { };
64 
72  vpImageQueue(const std::string &seqname, int record_mode)
73  : m_cancelled(false), m_cond(), m_queue_image(), m_queue_data(), m_maxQueueSize(1024 * 8), m_mutex(),
74  m_seqname(seqname), m_recording_mode(record_mode), m_start_recording(false), m_directory_to_create(false),
75  m_recording_trigger(false)
76  {
77  m_directory = vpIoTools::getParent(seqname);
78  if (!m_directory.empty()) {
79  if (!vpIoTools::checkDirectory(m_directory)) {
80  m_directory_to_create = true;
81  }
82  }
83  m_text_record_mode =
84  std::string("Record mode: ") + (m_recording_mode ? std::string("single") : std::string("continuous"));
85  }
86 
90  void cancel()
91  {
92  std::lock_guard<std::mutex> lock(m_mutex);
93  std::cout << "Wait to finish saving images..." << std::endl;
94  m_cancelled = true;
95  m_cond.notify_all();
96  }
97 
101  int getRecordingMode() const { return m_recording_mode; }
102 
106  bool getRecordingTrigger() const { return m_recording_trigger; }
107 
111  std::string getSeqName() const { return m_seqname; }
112 
120  void pop(vpImage<Type> &I, std::string &data)
121  {
122  std::unique_lock<std::mutex> lock(m_mutex);
123 
124  while (m_queue_image.empty()) {
125  if (m_cancelled) {
126  throw vpCancelled_t();
127  }
128 
129  m_cond.wait(lock);
130 
131  if (m_cancelled) {
132  throw vpCancelled_t();
133  }
134  }
135 
136  I = m_queue_image.front();
137 
138  m_queue_image.pop();
139 
140  if (!m_queue_data.empty()) {
141  data = m_queue_data.front();
142  m_queue_data.pop();
143  }
144  }
145 
152  void push(const vpImage<Type> &I, std::string *data)
153  {
154  std::lock_guard<std::mutex> lock(m_mutex);
155 
156  m_queue_image.push(I);
157 
158  if (data != nullptr) {
159  m_queue_data.push(*data);
160  }
161 
162  // Pop extra data in the queue
163  while (m_queue_image.size() > m_maxQueueSize) {
164  m_queue_image.pop();
165  }
166 
167  if (data != nullptr) {
168  while (m_queue_data.size() > m_maxQueueSize) {
169  m_queue_data.pop();
170  }
171  }
172 
173  m_cond.notify_one();
174  }
175 
185  bool record(const vpImage<Type> &I, std::string *data = nullptr, bool trigger_recording = false,
186  bool disable_left_click = false)
187  {
188  if (I.display) {
189  if (!m_seqname.empty()) {
190  if (!disable_left_click) {
191  if (!m_recording_mode) { // continuous
192  if (m_start_recording) {
194  10 * vpDisplay::getDownScalingFactor(I), "Left click: stop recording",
195  vpColor::red);
196  }
197  else {
199  10 * vpDisplay::getDownScalingFactor(I), "Left click: start recording",
200  vpColor::red);
201  }
202  }
203  else {
205  "Left click: record image", vpColor::red);
206  }
207  }
209  "Right click: quit", vpColor::red);
210  }
211  else {
213  "Click to quit", vpColor::red);
214  }
215 
216  if (!m_seqname.empty()) {
218  m_text_record_mode, vpColor::red);
219  }
221  if (vpDisplay::getClick(I, button, false)) {
222  if (!m_seqname.empty()) { // Recording requested
223  if (button == vpMouseButton::button1 && !disable_left_click) { // enable/disable recording
224  m_start_recording = !m_start_recording;
225  }
226  else if (button == vpMouseButton::button3) { // quit
227  return true;
228  }
229  }
230  else { // any button to quit
231  return true;
232  }
233  }
234  }
235  else if (!m_seqname.empty()) {
236  m_start_recording = true;
237  }
238 
239  if (trigger_recording) {
240  m_start_recording = true;
241  }
242 
243  m_recording_trigger = m_start_recording;
244 
245  if (m_start_recording) {
246 
247  if (m_directory_to_create) {
248  std::cout << "Create directory \"" << m_directory << "\"" << std::endl;
249  vpIoTools::makeDirectory(m_directory);
250  m_directory_to_create = false;
251  }
252 
253  push(I, data);
254 
255  if (m_recording_mode == 1) { // single shot mode
256  m_start_recording = false;
257  }
258  }
259  return false;
260  }
261 
266  void setMaxQueueSize(const size_t max_queue_size) { m_maxQueueSize = max_queue_size; }
267 
268 private:
269  bool m_cancelled;
270  std::condition_variable m_cond;
271  std::queue<vpImage<Type> > m_queue_image;
272  std::queue<std::string> m_queue_data;
273  size_t m_maxQueueSize;
274  std::mutex m_mutex;
275  std::string m_seqname;
276  std::string m_directory;
277  int m_recording_mode;
278  bool m_start_recording;
279  std::string m_text_record_mode;
280  bool m_directory_to_create;
281  bool m_recording_trigger;
282 };
283 
284 #endif
static const vpColor red
Definition: vpColor.h:211
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
unsigned int getDownScalingFactor()
Definition: vpDisplay.h:231
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
int getRecordingMode() const
Definition: vpImageQueue.h:101
bool record(const vpImage< Type > &I, std::string *data=nullptr, bool trigger_recording=false, bool disable_left_click=false)
Definition: vpImageQueue.h:185
void pop(vpImage< Type > &I, std::string &data)
Definition: vpImageQueue.h:120
bool getRecordingTrigger() const
Definition: vpImageQueue.h:106
vpImageQueue(const std::string &seqname, int record_mode)
Definition: vpImageQueue.h:72
std::string getSeqName() const
Definition: vpImageQueue.h:111
void cancel()
Definition: vpImageQueue.h:90
void setMaxQueueSize(const size_t max_queue_size)
Definition: vpImageQueue.h:266
void push(const vpImage< Type > &I, std::string *data)
Definition: vpImageQueue.h:152
Definition of the vpImage class member functions.
Definition: vpImage.h:69
vpDisplay * display
Definition: vpImage.h:140
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:449
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:603
static std::string getParent(const std::string &pathname)
Definition: vpIoTools.cpp:1669