record_sensor.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2017 Intel Corporation. All Rights Reserved.
3 
4 #include "record_sensor.h"
5 #include "api.h"
6 #include "stream.h"
7 #include "l500/l500-depth.h"
8 
9 using namespace librealsense;
10 
13  m_sensor(sensor),
14  m_is_recording(false),
15  m_parent_device(device),
16  m_is_sensor_hooked(false),
17  m_register_notification_to_base(true),
18  m_before_start_callback_token(-1)
19 {
20  LOG_DEBUG("Created record_sensor");
21 }
22 
24 {
25  m_sensor.unregister_before_start_callback(m_before_start_callback_token);
28  m_is_recording = false;
29  LOG_DEBUG("Destructed record_sensor");
30 }
31 
33 {
34  //Seperating init from the constructor since callbacks may be called from here,
35  // and the only way to register to them is after creating the record sensor
36 
38  m_before_start_callback_token = m_sensor.register_before_streaming_changes_callback([this](bool streaming)
39  {
40  if (streaming)
41  {
43  }
44  else
45  {
47  }
48  });
49 
50  if (m_sensor.is_streaming())
51  {
52  //In case the sensor is already streaming,
53  // we will not get the above callback (before start) so we hook it now
55  }
56  LOG_DEBUG("Hooked to real sense");
57 }
59 {
60  return m_sensor.get_stream_profiles(tag);
61 }
62 
64 {
65  m_sensor.open(requests);
66 }
67 
69 {
70  m_sensor.close();
71 }
72 
74 {
75  return m_sensor.get_option(id);
76 }
78 {
79  return m_sensor.get_option(id);
80 }
82 {
83  return m_sensor.get_info(info);
84 }
86 {
87  return m_sensor.supports_info(info);
88 }
90 {
91  return m_sensor.supports_option(id);
92 }
93 
95 {
97  {
98  m_sensor.register_notifications_callback(std::move(callback)); //route to base sensor
99  return;
100  }
101 
103  auto from_live_sensor = notifications_callback_ptr(new notification_callback([&](rs2_notification* n)
104  {
105  if (m_is_recording)
106  {
108  }
110  {
111  m_user_notification_callback->on_notification(n);
112  }
113  }), [](rs2_notifications_callback* p) { p->release(); });
114  m_sensor.register_notifications_callback(std::move(from_live_sensor));
115 }
116 
118 {
119  return m_sensor.get_notifications_callback();
120 }
121 
123 {
124  m_sensor.start(callback);
125 }
127 {
128  m_sensor.stop();
129 }
131 {
132  return m_sensor.is_streaming();
133 }
134 
135 template <rs2_extension E, typename P>
137 {
138  using EXT_TYPE = typename ExtensionToType<E>::type;
139  auto ptr = As<EXT_TYPE>(p);
140  if (!ptr)
141  return false;
142 
143 
145  {
146  recordable->enable_recording([this](const EXT_TYPE& ext1) {
147  record_snapshot<EXT_TYPE>(E, ext1);
148  });
149  }
150 
151  *ext = ptr;
152  return true;
153 }
154 
156 {
157  /**************************************************************************************
158  A record sensor wraps the live sensor, and should have the same functionalities.
159  To do that, the record sensor implements the extendable_interface and when the user tries to
160  treat the sensor as some extension, this function is called, and we return a pointer to the
161  live sensor's extension. If that extension is a recordable one, we also enable_recording for it.
162  **************************************************************************************/
163 
164  switch (extension_type)
165  {
166  case RS2_EXTENSION_OPTIONS: // [[fallthrough]]
167  case RS2_EXTENSION_INFO: // [[fallthrough]]
168  *ext = this;
169  return true;
170  case RS2_EXTENSION_DEPTH_SENSOR : return extend_to_aux<RS2_EXTENSION_DEPTH_SENSOR >(&m_sensor, ext);
171  case RS2_EXTENSION_L500_DEPTH_SENSOR: return extend_to_aux<RS2_EXTENSION_L500_DEPTH_SENSOR >(&m_sensor, ext);
172  case RS2_EXTENSION_DEPTH_STEREO_SENSOR: return extend_to_aux<RS2_EXTENSION_DEPTH_STEREO_SENSOR >(&m_sensor, ext);
173  case RS2_EXTENSION_COLOR_SENSOR: return extend_to_aux<RS2_EXTENSION_COLOR_SENSOR >(&m_sensor, ext);
174  case RS2_EXTENSION_MOTION_SENSOR: return extend_to_aux<RS2_EXTENSION_MOTION_SENSOR >(&m_sensor, ext);
175  case RS2_EXTENSION_FISHEYE_SENSOR: return extend_to_aux<RS2_EXTENSION_FISHEYE_SENSOR >(&m_sensor, ext);
176  case RS2_EXTENSION_POSE_SENSOR: return extend_to_aux<RS2_EXTENSION_POSE_SENSOR >(&m_sensor, ext);
177 
178  //Other extensions are not expected to be extensions of a sensor
179  default:
180  LOG_WARNING("Extensions type is unhandled: " << get_string(extension_type));
181  return false;
182  }
183 }
184 
186 {
187  return m_parent_device;
188 }
189 
191 {
192  return m_frame_callback;
193 }
194 
196 {
198 }
199 
201 {
202  return m_sensor.get_active_streams();
203 }
204 
206 {
207  throw librealsense::not_implemented_exception("playback_sensor::register_before_streaming_changes_callback");
208 }
209 
211 {
212  throw librealsense::not_implemented_exception("playback_sensor::unregister_before_start_callback");
213 }
214 
215 template <typename T>
216 void librealsense::record_sensor::record_snapshot(rs2_extension extension_type, const recordable<T>& ext)
217 {
218  std::shared_ptr<T> snapshot;
219  ext.create_snapshot(snapshot);
220  auto ext_snapshot = As<extension_snapshot>(snapshot);
221  if(m_is_recording)
222  {
223  //Send to recording thread
224  on_extension_change(extension_type, ext_snapshot);
225  }
226 }
227 
229 {
232  {
233  std::string msg = to_string() << "Stopping recording for sensor (streaming will continue). (Error: " << error_msg << ")";
235  rs2_notification rs2_noti(&noti);
236  m_user_notification_callback->on_notification(&rs2_noti);
237  }
238 }
239 
241 {
242  m_is_recording = false;
243 }
244 
246 {
247  return m_sensor.get_recommended_processing_blocks();
248 }
249 
251 {
252  if(m_is_recording)
253  {
254  //Send to recording thread
255  on_frame(std::move(frame));
256  }
257 }
258 
260 {
261  std::lock_guard<std::mutex> lock(m_mutex);
262  if (m_is_sensor_hooked)
263  return;
265  wrap_streams();
266  m_is_sensor_hooked = true;
267 }
269 {
270  std::lock_guard<std::mutex> lock(m_mutex);
271  if (!m_is_sensor_hooked)
272  return;
274  m_is_sensor_hooked = false;
276 }
278 {
280  m_user_notification_callback = m_sensor.get_notifications_callback();
282  m_original_callback = m_sensor.get_frames_callback();
284  {
286  m_sensor.set_frames_callback(m_frame_callback);
287  m_is_recording = true;
288  }
289 }
291 {
292  auto record_cb = [this, callback](frame_holder frame)
293  {
294  record_frame(frame.clone());
295 
296  //Raise to user callback
297  frame_interface* ref = nullptr;
298  std::swap(frame.frame, ref);
299  callback->on_frame((rs2_frame*)ref);
300  };
301 
302  return std::make_shared<frame_holder_callback>(record_cb);
303 }
305 {
307  {
308  m_sensor.register_notifications_callback(m_user_notification_callback);
309  }
310 
312  {
313  m_sensor.set_frames_callback(m_original_callback);
314  m_original_callback.reset();
315  }
316 }
318 {
319  for (int i = 0; i < static_cast<int>(RS2_OPTION_COUNT); i++)
320  {
321  rs2_option id = static_cast<rs2_option>(i);
322  if (!m_sensor.supports_option(id))
323  {
324  continue;
325  }
326 
327  if (m_recording_options.find(id) != m_recording_options.end())
328  {
329  continue;
330  }
331 
332  try
333  {
334  auto& opt = m_sensor.get_option(id);
335  opt.enable_recording([this, id](const librealsense::option& option) {
336  options_container options;
337  std::shared_ptr<librealsense::option> option_snapshot;
338  option.create_snapshot(option_snapshot);
339  options.register_option(id, option_snapshot);
340  record_snapshot<options_interface>(RS2_EXTENSION_OPTIONS, options);
341  });
342  m_recording_options.insert(id);
343  }
344  catch (const std::exception& e)
345  {
346  LOG_ERROR("Failed to enable recording for option " << get_string(id) << ", Error: " << e.what());
347  }
348  }
349 }
351 {
352  for (auto id : m_recording_options)
353  {
354  auto& option = m_sensor.get_option(id);
356  }
357 }
359 {
360  auto streams = m_sensor.get_active_streams();
361  for (auto stream : streams)
362  {
363  auto id = stream->get_unique_id();
364  if (m_recorded_streams_ids.count(id) == 0)
365  {
366  std::shared_ptr<stream_profile_interface> snapshot;
367  stream->create_snapshot(snapshot);
368  rs2_extension extension_type;
369  if (Is<librealsense::video_stream_profile_interface>(stream))
370  extension_type = RS2_EXTENSION_VIDEO_PROFILE;
371  else if (Is<librealsense::motion_stream_profile_interface>(stream))
372  extension_type = RS2_EXTENSION_MOTION_PROFILE;
373  else if (Is<librealsense::pose_stream_profile_interface>(stream))
374  extension_type = RS2_EXTENSION_POSE_PROFILE;
375  else
376  throw std::runtime_error("Unsupported stream");
377 
378  on_extension_change(extension_type, std::dynamic_pointer_cast<extension_snapshot>(snapshot));
379 
380  m_recorded_streams_ids.insert(id);
381  }
382  }
383 }
stream_profiles get_active_streams() const override
private const recordable< T > & snapshot
Definition: record_sensor.h:53
static const textual_icon lock
Definition: model-views.h:218
rs2_camera_info
Read-only strings that can be queried from the device. Not all information attributes are available o...
Definition: rs_sensor.h:22
option & get_option(rs2_option id) override
boost_foreach_argument_dependent_lookup_hack tag
Definition: foreach_fwd.hpp:31
const char * get_string(rs2_rs400_visual_preset value)
rs2_option
Defines general configuration controls. These can generally be mapped to camera UVC controls...
Definition: rs_option.h:22
virtual processing_blocks get_recommended_processing_blocks() const override
std::shared_ptr< T > As(std::shared_ptr< P > ptr)
Definition: extension.h:88
const librealsense::notification * _notification
Definition: api.h:25
std::shared_ptr< rs2_frame_callback > frame_callback_ptr
Definition: src/types.h:1071
frame_callback_ptr m_frame_callback
Definition: record_sensor.h:71
GLfloat GLfloat p
Definition: glext.h:12687
virtual void release()=0
#define LOG_WARNING(...)
Definition: src/types.h:241
void start(frame_callback_ptr callback) override
void stop_with_error(const std::string &message)
librealsense::notifications_callback_ptr m_user_notification_callback
Definition: record_sensor.h:69
virtual void create_snapshot(std::shared_ptr< option > &snapshot) const
Definition: option.cpp:30
GLsizei const GLchar *const * string
stream_profiles get_stream_profiles(int tag=profile_tag::PROFILE_TAG_ANY) const override
GLdouble n
Definition: glext.h:1966
e
Definition: rmse.py:177
virtual void enable_recording(std::function< void(const T &)> recording_function)=0
void record_frame(frame_holder holder)
int register_before_streaming_changes_callback(std::function< void(bool)> callback) override
void open(const stream_profiles &requests) override
void register_option(rs2_option id, std::shared_ptr< option > option)
Definition: options.h:86
def info(name, value, persistent=False)
Definition: test.py:301
virtual void create_snapshot(std::shared_ptr< T > &snapshot) const =0
device_interface & get_device() override
frame_callback_ptr m_original_callback
Definition: record_sensor.h:72
notifications_callback_ptr get_notifications_callback() const override
dictionary streams
Definition: t265_stereo.py:140
int get_unique_id() const override
Definition: src/stream.h:25
std::atomic_bool m_is_recording
Definition: record_sensor.h:70
bool supports_option(rs2_option id) const override
std::shared_ptr< rs2_notifications_callback > notifications_callback_ptr
Definition: src/types.h:1073
const std::string & get_info(rs2_camera_info info) const override
bool extend_to_aux(P *p, void **ext)
void unregister_before_start_callback(int token) override
signal< record_sensor, frame_holder > on_frame
Definition: record_sensor.h:46
def callback(frame)
Definition: t265_stereo.py:91
bool is_streaming() const override
frame_callback_ptr wrap_frame_callback(frame_callback_ptr callback)
void register_notifications_callback(notifications_callback_ptr callback) override
#define LOG_ERROR(...)
Definition: src/types.h:242
signal< record_sensor, rs2_extension, std::shared_ptr< extension_snapshot > > on_extension_change
Definition: record_sensor.h:47
record_sensor(device_interface &device, sensor_interface &sensor)
signal< record_sensor, const notification & > on_notification
Definition: record_sensor.h:45
void swap(nlohmann::json &j1, nlohmann::json &j2) noexcept(is_nothrow_move_constructible< nlohmann::json >::value andis_nothrow_move_assignable< nlohmann::json >::value)
exchanges the values of two JSON objects
Definition: json.hpp:12141
std::vector< std::shared_ptr< stream_profile_interface >> stream_profiles
Definition: streaming.h:165
frame_callback_ptr get_frames_callback() const override
rs2_extension
Specifies advanced interfaces (capabilities) objects may implement.
Definition: rs_types.h:166
void set_frames_callback(frame_callback_ptr callback) override
bool extend_to(rs2_extension extension_type, void **ext) override
GLint ref
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
int i
std::set< int > m_recorded_streams_ids
Definition: record_sensor.h:67
#define LOG_DEBUG(...)
Definition: src/types.h:239
bool supports_info(rs2_camera_info info) const override
std::set< rs2_option > m_recording_options
Definition: record_sensor.h:68
device_interface & m_parent_device
Definition: record_sensor.h:74
struct rs2_frame rs2_frame
Definition: rs_types.h:261
std::string to_string(T value)


librealsense2
Author(s): Sergey Dorodnicov , Doron Hirshberg , Mark Horn , Reagan Lopez , Itay Carpis
autogenerated on Mon May 3 2021 02:47:39