sensor.cpp
Go to the documentation of this file.
1 // License: Apache 2.0. See LICENSE file in root directory.
2 // Copyright(c) 2015 Intel Corporation. All Rights Reserved.
3 
4 #include "sensor.h"
5 
6 #include <array>
7 #include <set>
8 #include <unordered_set>
9 #include <iomanip>
10 
11 #include "source.h"
12 #include "device.h"
13 #include "stream.h"
14 #include "metadata.h"
15 #include "proc/synthetic-stream.h"
16 #include "proc/decimation-filter.h"
17 #include "proc/depth-decompress.h"
19 #include "device-calibration.h"
20 
21 namespace librealsense
22 {
26 
30  _is_streaming(false),
31  _is_opened(false),
32  _notifications_processor(std::shared_ptr<notifications_processor>(new notifications_processor())),
33  _on_open(nullptr),
34  _metadata_parsers(std::make_shared<metadata_parser_map>()),
35  _owner(dev),
36  _profiles([this]() {
37  auto profiles = this->init_stream_profiles();
39  return profiles;
40  })
41  {
43 
44  register_metadata(RS2_FRAME_METADATA_TIME_OF_ARRIVAL, std::make_shared<librealsense::md_time_of_arrival_parser>());
45 
47  }
48 
50  {
52  else return _owner->get_info(info);
53  }
54 
56  {
57  return info_container::supports_info(info) || _owner->supports_info(info);
58  }
59 
61  {
62  std::lock_guard<std::mutex> lock(_active_profile_mutex);
63  return _active_profiles;
64  }
65 
67  {
69  {
71  opt.set(1.0f);
72  }
73  _notifications_processor->set_callback(std::move(callback));
74  }
75 
77  {
78  return _notifications_processor->get_callback();
79  }
80 
82  {
83  int token = (on_before_streaming_changes += callback);
84  LOG_DEBUG("Registered token #" << token << " to \"on_before_streaming_changes\"");
85  return token;
86  }
87 
89  {
90  bool successful_unregister = on_before_streaming_changes -= token;
91  if (!successful_unregister)
92  {
93  LOG_WARNING("Failed to unregister token #" << token << " from \"on_before_streaming_changes\"");
94  }
95  }
96 
98  {
99  return _source.get_callback();
100  }
102  {
103  return _source.set_callback(callback);
104  }
105 
107  {
108  return _is_streaming;
109  }
110 
112  {
113  return _is_opened;
114  }
115 
116  std::shared_ptr<notifications_processor> sensor_base::get_notifications_processor() const
117  {
119  }
120 
121  void sensor_base::register_metadata(rs2_frame_metadata_value metadata, std::shared_ptr<md_attribute_parser_base> metadata_parser) const
122  {
123  if (_metadata_parsers.get()->end() != _metadata_parsers.get()->find(metadata))
124  {
125  std::string metadata_type_str(rs2_frame_metadata_to_string(metadata));
126  std::string metadata_found_str = "Metadata attribute parser for " + metadata_type_str + " was previously defined";
127  LOG_DEBUG(metadata_found_str.c_str());
128  }
129  _metadata_parsers.get()->insert(std::pair<rs2_frame_metadata_value, std::shared_ptr<md_attribute_parser_base>>(metadata, metadata_parser));
130  }
131 
132  std::shared_ptr<std::map<uint32_t, rs2_format>>& sensor_base::get_fourcc_to_rs2_format_map()
133  {
134  return _fourcc_to_rs2_format;
135  }
136 
137  std::shared_ptr<std::map<uint32_t, rs2_stream>>& sensor_base::get_fourcc_to_rs2_stream_map()
138  {
139  return _fourcc_to_rs2_stream;
140  }
141 
143  {
145 
146  std::find_if(_fourcc_to_rs2_format->begin(), _fourcc_to_rs2_format->end(), [&fourcc_format, &f](const std::pair<uint32_t, rs2_format>& p) {
147  if (p.first == fourcc_format)
148  {
149  f = p.second;
150  return true;
151  }
152  return false;
153  });
154 
155  return f;
156  }
157 
159  {
161 
162  std::find_if(_fourcc_to_rs2_stream->begin(), _fourcc_to_rs2_stream->end(), [&fourcc_format, &s](const std::pair<uint32_t, rs2_stream>& p) {
163  if (p.first == fourcc_format)
164  {
165  s = p.second;
166  return true;
167  }
168  return false;
169  });
170 
171  return s;
172  }
173 
175  {
176  on_before_streaming_changes(streaming);
177  }
179  {
180  std::lock_guard<std::mutex> lock(_active_profile_mutex);
181  _active_profiles = requests;
182  }
183 
184  void sensor_base::assign_stream(const std::shared_ptr<stream_interface>& stream, std::shared_ptr<stream_profile_interface> target) const
185  {
187  auto uid = stream->get_unique_id();
188  target->set_unique_id(uid);
189  }
190 
192  {
193  _source_owner = owner;
194  }
195 
197  {
198  stream_profiles results;
199  bool const need_debug = tag & profile_tag::PROFILE_TAG_DEBUG;
200  bool const need_any = tag & profile_tag::PROFILE_TAG_ANY;
201  for( auto p : *_profiles )
202  {
203  auto curr_tag = p->get_tag();
204  if( ! need_debug && ( curr_tag & profile_tag::PROFILE_TAG_DEBUG ) )
205  continue;
206 
207  if( curr_tag & tag || need_any )
208  {
209  results.push_back( p );
210  }
211  }
212 
213  return results;
214  }
215 
217  {
219  auto dec = std::make_shared<decimation_filter>();
220  if (!dec->supports_option(RS2_OPTION_STREAM_FILTER))
221  return res;
222  dec->get_option(RS2_OPTION_STREAM_FILTER).set(RS2_STREAM_COLOR);
223  dec->get_option(RS2_OPTION_STREAM_FORMAT_FILTER).set(RS2_FORMAT_ANY);
224  res.push_back(dec);
225  return res;
226  }
227 
229  {
231  auto huffman_decode = std::make_shared<depth_decompression_huffman>();
232  res.push_back(huffman_decode);
233 
234  auto dec = std::make_shared<decimation_filter>();
235  if (dec->supports_option(RS2_OPTION_STREAM_FILTER))
236  {
237  dec->get_option(RS2_OPTION_STREAM_FILTER).set(RS2_STREAM_DEPTH);
238  dec->get_option(RS2_OPTION_STREAM_FORMAT_FILTER).set(RS2_FORMAT_Z16);
239  res.push_back(dec);
240  }
241  return res;
242  }
243 
245  {
246  return *_owner;
247  }
248 
250  frame_timestamp_reader* timestamp_reader,
251  const rs2_time_t& last_timestamp,
252  const unsigned long long& last_frame_number,
253  std::shared_ptr<stream_profile_interface> profile)
254  {
256  auto fr = std::make_shared<frame>();
257  byte* pix = (byte*)fo.pixels;
258  std::vector<byte> pixels(pix, pix + fo.frame_size);
259  fr->data = pixels;
260  fr->set_stream(profile);
261 
262  // generate additional data
263  frame_additional_data additional_data(0,
264  0,
265  system_time,
266  static_cast<uint8_t>(fo.metadata_size),
267  (const uint8_t*)fo.metadata,
268  fo.backend_time,
269  last_timestamp,
270  last_frame_number,
271  false,
272  (uint32_t)fo.frame_size );
273  fr->additional_data = additional_data;
274 
275  // update additional data
276  additional_data.timestamp = timestamp_reader->get_frame_timestamp(fr);
277  additional_data.last_frame_number = last_frame_number;
278  additional_data.frame_number = timestamp_reader->get_frame_counter(fr);
279  fr->additional_data = additional_data;
280 
281  return fr;
282  }
283 
287 
289  {
290  try
291  {
292  if (_is_streaming)
294 
295  if (_is_opened)
297  }
298  catch (...)
299  {
300  LOG_ERROR("An error has occurred while stop_streaming()!");
301  }
302  }
303 
304  void uvc_sensor::open(const stream_profiles& requests)
305  {
306  std::lock_guard<std::mutex> lock(_configure_lock);
307  if (_is_streaming)
308  throw wrong_api_call_sequence_exception("open(...) failed. UVC device is streaming!");
309  else if (_is_opened)
310  throw wrong_api_call_sequence_exception("open(...) failed. UVC device is already opened!");
311 
312  auto on = std::unique_ptr<power>(new power(std::dynamic_pointer_cast<uvc_sensor>(shared_from_this())));
313 
315  _source.set_sensor(_source_owner->shared_from_this());
316 
317  std::vector<platform::stream_profile> commited;
318 
319  for (auto&& req_profile : requests)
320  {
321  auto&& req_profile_base = std::dynamic_pointer_cast<stream_profile_base>(req_profile);
322  try
323  {
324  unsigned long long last_frame_number = 0;
325  rs2_time_t last_timestamp = 0;
326  _device->probe_and_commit(req_profile_base->get_backend_profile(),
327  [this, req_profile_base, req_profile, last_frame_number, last_timestamp](platform::stream_profile p, platform::frame_object f, std::function<void()> continuation) mutable
328  {
329  const auto&& system_time = environment::get_instance().get_time_service()->get_time();
330  const auto&& fr = generate_frame_from_data(f, _timestamp_reader.get(), last_timestamp, last_frame_number, req_profile_base);
331  const auto&& requires_processing = true; // TODO - Ariel add option
332  const auto&& timestamp_domain = _timestamp_reader->get_frame_timestamp_domain(fr);
333  const auto&& bpp = get_image_bpp(req_profile_base->get_format());
334  auto&& frame_counter = fr->additional_data.frame_number;
335  auto&& timestamp = fr->additional_data.timestamp;
336 
337  if (!this->is_streaming())
338  {
339  LOG_WARNING("Frame received with streaming inactive,"
340  << librealsense::get_string(req_profile_base->get_stream_type())
341  << req_profile_base->get_stream_index()
342  << ", Arrived," << std::fixed << f.backend_time << " " << system_time);
343  return;
344  }
345 
346  frame_continuation release_and_enqueue(continuation, f.pixels);
347 
348  LOG_DEBUG("FrameAccepted," << librealsense::get_string(req_profile_base->get_stream_type())
349  << ",Counter," << std::dec << fr->additional_data.frame_number
350  << ",Index," << req_profile_base->get_stream_index()
351  << ",BackEndTS," << std::fixed << f.backend_time
352  << ",SystemTime," << std::fixed << system_time
353  << " ,diff_ts[Sys-BE]," << system_time - f.backend_time
354  << ",TS," << std::fixed << timestamp << ",TS_Domain," << rs2_timestamp_domain_to_string(timestamp_domain)
355  << ",last_frame_number," << last_frame_number << ",last_timestamp," << last_timestamp);
356 
357  last_frame_number = frame_counter;
358  last_timestamp = timestamp;
359 
360  const auto&& vsp = As<video_stream_profile, stream_profile_interface>(req_profile);
361  int width = vsp ? vsp->get_width() : 0;
362  int height = vsp ? vsp->get_height() : 0;
363 
364  frame_holder fh = _source.alloc_frame(stream_to_frame_types(req_profile_base->get_stream_type()), width * height * bpp / 8, fr->additional_data, requires_processing);
365  auto diff = environment::get_instance().get_time_service()->get_time() - system_time;
366  if (diff >10 )
367  LOG_DEBUG("!! Frame allocation took " << diff << " msec");
368 
369  if (fh.frame)
370  {
371  memcpy((void*)fh->get_frame_data(), fr->data.data(), sizeof(byte)*fr->data.size());
372  auto&& video = (video_frame*)fh.frame;
373  video->assign(width, height, width * bpp / 8, bpp);
374  video->set_timestamp_domain(timestamp_domain);
375  fh->set_stream(req_profile_base);
376  }
377  else
378  {
379  LOG_INFO("Dropped frame. alloc_frame(...) returned nullptr");
380  return;
381  }
382 
383  diff = environment::get_instance().get_time_service()->get_time() - system_time;
384  if (diff >10 )
385  LOG_DEBUG("!! Frame memcpy took " << diff << " msec");
386  if (!requires_processing)
387  {
388  fh->attach_continuation(std::move(release_and_enqueue));
389  }
390 
391  if (fh->get_stream().get())
392  {
394  }
395  });
396  }
397  catch (...)
398  {
399  for (auto&& commited_profile : commited)
400  {
401  _device->close(commited_profile);
402  }
403  throw;
404  }
405  commited.push_back(req_profile_base->get_backend_profile());
406  }
407 
408  _internal_config = commited;
409 
410  if (_on_open)
412 
413  _power = move(on);
414  _is_opened = true;
415 
416  try {
417  _device->stream_on([&](const notification& n)
418  {
419  _notifications_processor->raise_notification(n);
420  });
421  }
422  catch (...)
423  {
424  std::stringstream error_msg;
425  error_msg << "\tFormats: \n";
426  for (auto&& profile : _internal_config)
427  {
429  error_msg << "\t " << std::string(rs2_format_to_string(fmt)) << std::endl;
430  try {
431  _device->close(profile);
432  }
433  catch (...) {}
434  }
435  error_msg << std::endl;
436  reset_streaming();
437  _power.reset();
438  _is_opened = false;
439 
440  throw std::runtime_error(error_msg.str());
441  }
442  if (Is<librealsense::global_time_interface>(_owner))
443  {
444  As<librealsense::global_time_interface>(_owner)->enable_time_diff_keeper(true);
445  }
446  set_active_streams(requests);
447  }
448 
450  {
451  std::lock_guard<std::mutex> lock(_configure_lock);
452  if (_is_streaming)
453  throw wrong_api_call_sequence_exception("close() failed. UVC device is streaming!");
454  else if (!_is_opened)
455  throw wrong_api_call_sequence_exception("close() failed. UVC device was not opened!");
456 
457  for (auto&& profile : _internal_config)
458  {
459  try // Handle disconnect event
460  {
461  _device->close(profile);
462  }
463  catch (...) {}
464  }
465  reset_streaming();
466  if (Is<librealsense::global_time_interface>(_owner))
467  {
468  As<librealsense::global_time_interface>(_owner)->enable_time_diff_keeper(false);
469  }
470  _power.reset();
471  _is_opened = false;
472  set_active_streams({});
473  }
474 
476  {
477  _xus.push_back(std::move(xu));
478  }
479 
481  {
482  std::lock_guard<std::mutex> lock(_configure_lock);
483  if (_is_streaming)
484  throw wrong_api_call_sequence_exception("start_streaming(...) failed. UVC device is already streaming!");
485  else if (!_is_opened)
486  throw wrong_api_call_sequence_exception("start_streaming(...) failed. UVC device was not opened!");
487 
488  raise_on_before_streaming_changes(true); //Required to be just before actual start allow recording to work
489  _source.set_callback(callback);
490  _is_streaming = true;
491  _device->start_callbacks();
492  }
493 
495  {
496  std::lock_guard<std::mutex> lock(_configure_lock);
497  if (!_is_streaming)
498  throw wrong_api_call_sequence_exception("stop_streaming() failed. UVC device is not streaming!");
499 
500  _is_streaming = false;
501  _device->stop_callbacks();
503  }
504 
506  {
507  _source.flush();
508  _source.reset();
509  _timestamp_reader->reset();
510  }
511 
513  {
514  std::lock_guard<std::mutex> lock(_power_lock);
515  if (_user_count.fetch_add(1) == 0)
516  {
517  try
518  {
519  _device->set_power_state( platform::D0 );
520  for( auto && xu : _xus )
521  _device->init_xu( xu );
522  }
523  catch( std::exception const & e )
524  {
525  _user_count.fetch_add( -1 );
526  LOG_ERROR( "acquire_power failed: " << e.what() );
527  throw;
528  }
529  catch( ... )
530  {
531  _user_count.fetch_add( -1 );
532  LOG_ERROR( "acquire_power failed" );
533  throw;
534  }
535  }
536  }
537 
539  {
540  std::lock_guard< std::mutex > lock( _power_lock );
541  if( _user_count.fetch_add( -1 ) == 1 )
542  {
543  try
544  {
545  _device->set_power_state( platform::D3 );
546  }
547  catch( std::exception const & e )
548  {
549  // TODO may need to change the user-count?
550  LOG_ERROR( "release_power failed: " << e.what() );
551  }
552  catch( ... )
553  {
554  // TODO may need to change the user-count?
555  LOG_ERROR( "release_power failed" );
556  }
557  }
558  }
559 
561  {
562  std::unordered_set<std::shared_ptr<video_stream_profile>> profiles;
563  power on(std::dynamic_pointer_cast<uvc_sensor>(shared_from_this()));
564 
565  _uvc_profiles = _device->get_profiles();
566 
567  for (auto&& p : _uvc_profiles)
568  {
569  const auto&& rs2_fmt = fourcc_to_rs2_format(p.format);
570  if (rs2_fmt == RS2_FORMAT_ANY)
571  continue;
572 
573  auto&& profile = std::make_shared<video_stream_profile>(p);
574  profile->set_dims(p.width, p.height);
575  profile->set_stream_type(fourcc_to_rs2_stream(p.format));
576  profile->set_stream_index(0);
577  profile->set_format(rs2_fmt);
578  profile->set_framerate(p.fps);
579  profiles.insert(profile);
580  }
581 
582  stream_profiles result{ profiles.begin(), profiles.end() };
583  return result;
584  }
585 
587  {
588  // TODO: explicitly return video_frame for relevant streams and default to an error?
589  switch (stream)
590  {
592  default: return RS2_EXTENSION_VIDEO_FRAME;
593  }
594  }
595 
597  {
598  auto it = _camera_info.find(info);
599  return it != _camera_info.end();
600  }
601 
603  {
604  if (info_container::supports_info(info) && (info_container::get_info(info) != val)) // Append existing infos
605  {
606  _camera_info[info] += "\n" + val;
607  }
608  else
609  {
610  _camera_info[info] = val;
611  }
612  }
613 
615  {
617  {
618  _camera_info[info] = val;
619  }
620  }
622  {
623  auto it = _camera_info.find(info);
624  if (it == _camera_info.end())
625  throw invalid_value_exception("Selected camera info is not supported for this camera!");
626 
627  return it->second;
628  }
629  void info_container::create_snapshot(std::shared_ptr<info_interface>& snapshot) const
630  {
631  snapshot = std::make_shared<info_container>(*this);
632  }
633  void info_container::enable_recording(std::function<void(const info_interface&)> record_action)
634  {
635  //info container is a read only class, nothing to record
636  }
637 
638  void info_container::update(std::shared_ptr<extension_snapshot> ext)
639  {
640  if (auto&& info_api = As<info_interface>(ext))
641  {
642  for (int i = 0; i < RS2_CAMERA_INFO_COUNT; ++i)
643  {
644  rs2_camera_info info = static_cast<rs2_camera_info>(i);
645  if (info_api->supports_info(info))
646  {
647  register_info(info, info_api->get_info(info));
648  }
649  }
650  }
651  }
652 
654  {
655  register_option(id, std::make_shared<uvc_pu_option>(*this, id));
656  }
657 
661 
662  hid_sensor::hid_sensor(std::shared_ptr<platform::hid_device> hid_device, std::unique_ptr<frame_timestamp_reader> hid_iio_timestamp_reader,
663  std::unique_ptr<frame_timestamp_reader> custom_hid_timestamp_reader,
664  const std::map<rs2_stream, std::map<unsigned, unsigned>>& fps_and_sampling_frequency_per_rs2_stream,
665  const std::vector<std::pair<std::string, stream_profile>>& sensor_name_and_hid_profiles,
666  device* dev)
667  : sensor_base("Raw Motion Module", dev, (recommended_proccesing_blocks_interface*)this), _sensor_name_and_hid_profiles(sensor_name_and_hid_profiles),
668  _fps_and_sampling_frequency_per_rs2_stream(fps_and_sampling_frequency_per_rs2_stream),
669  _hid_device(hid_device),
670  _is_configured_stream(RS2_STREAM_COUNT),
671  _hid_iio_timestamp_reader(move(hid_iio_timestamp_reader)),
672  _custom_hid_timestamp_reader(move(custom_hid_timestamp_reader))
673  {
675 
676  std::map<std::string, uint32_t> frequency_per_sensor;
677  for (auto&& elem : sensor_name_and_hid_profiles)
678  frequency_per_sensor.insert(make_pair(elem.first, elem.second.fps));
679 
680  std::vector<platform::hid_profile> profiles_vector;
681  for (auto&& elem : frequency_per_sensor)
682  profiles_vector.push_back(platform::hid_profile{ elem.first, elem.second });
683 
684  _hid_device->register_profiles(profiles_vector);
685  for (auto&& elem : _hid_device->get_sensors())
686  _hid_sensors.push_back(elem);
687  }
688 
690  {
691  try
692  {
693  if (_is_streaming)
694  stop();
695 
696  if (_is_opened)
697  close();
698  }
699  catch (...)
700  {
701  LOG_ERROR("An error has occurred while stop_streaming()!");
702  }
703  }
704 
706  {
708  for (auto&& elem : _sensor_name_and_hid_profiles)
709  {
710  if (!elem.first.compare(sensor_name))
711  {
712  auto&& p = elem.second;
713  platform::stream_profile sp{ 1, 1, p.fps, stream_to_fourcc(p.stream) };
714  auto profile = std::make_shared<motion_stream_profile>(sp);
715  profile->set_stream_index(p.index);
716  profile->set_stream_type(p.stream);
717  profile->set_format(p.format);
718  profile->set_framerate(p.fps);
719  profiles.push_back(profile);
720  }
721  }
722 
723  return profiles;
724  }
725 
726  void hid_sensor::open(const stream_profiles& requests)
727  {
728  std::lock_guard<std::mutex> lock(_configure_lock);
729  if (_is_streaming)
730  throw wrong_api_call_sequence_exception("open(...) failed. Hid device is streaming!");
731  else if (_is_opened)
732  throw wrong_api_call_sequence_exception("Hid device is already opened!");
733 
734  std::vector<platform::hid_profile> configured_hid_profiles;
735  for (auto&& request : requests)
736  {
737  auto&& sensor_name = rs2_stream_to_sensor_name(request->get_stream_type());
738  _configured_profiles.insert(std::make_pair(sensor_name, request));
739  _is_configured_stream[request->get_stream_type()] = true;
740  configured_hid_profiles.push_back(platform::hid_profile{ sensor_name,
741  fps_to_sampling_frequency(request->get_stream_type(), request->get_framerate()) });
742  }
743  _hid_device->open(configured_hid_profiles);
744  if (Is<librealsense::global_time_interface>(_owner))
745  {
746  As<librealsense::global_time_interface>(_owner)->enable_time_diff_keeper(true);
747  }
748  _is_opened = true;
749  set_active_streams(requests);
750  }
751 
753  {
754  std::lock_guard<std::mutex> lock(_configure_lock);
755  if (_is_streaming)
756  throw wrong_api_call_sequence_exception("close() failed. Hid device is streaming!");
757  else if (!_is_opened)
758  throw wrong_api_call_sequence_exception("close() failed. Hid device was not opened!");
759 
760  _hid_device->close();
761  _configured_profiles.clear();
762  _is_configured_stream.clear();
764  _is_opened = false;
765  if (Is<librealsense::global_time_interface>(_owner))
766  {
767  As<librealsense::global_time_interface>(_owner)->enable_time_diff_keeper(false);
768  }
769  set_active_streams({});
770  }
771 
772  // TODO:
774  {
775  if (custom_gpio < 4)
776  {
777  return static_cast<rs2_stream>(RS2_STREAM_GPIO);
778  }
779 #ifndef __APPLE__
780  // TODO to be refactored/tested
781  LOG_ERROR("custom_gpio " << std::to_string(custom_gpio) << " is incorrect!");
782 #endif
783  return RS2_STREAM_ANY;
784  }
785 
787  {
788  std::lock_guard<std::mutex> lock(_configure_lock);
789  if (_is_streaming)
790  throw wrong_api_call_sequence_exception("start_streaming(...) failed. Hid device is already streaming!");
791  else if (!_is_opened)
792  throw wrong_api_call_sequence_exception("start_streaming(...) failed. Hid device was not opened!");
793 
794  _source.set_callback(callback);
796  _source.set_sensor(_source_owner->shared_from_this());
797 
798  unsigned long long last_frame_number = 0;
799  rs2_time_t last_timestamp = 0;
800  raise_on_before_streaming_changes(true); //Required to be just before actual start allow recording to work
801 
802  _hid_device->start_capture([this, last_frame_number, last_timestamp](const platform::sensor_data& sensor_data) mutable
803  {
804  const auto&& system_time = environment::get_instance().get_time_service()->get_time();
805  auto timestamp_reader = _hid_iio_timestamp_reader.get();
806  static const std::string custom_sensor_name = "custom";
807  auto&& sensor_name = sensor_data.sensor.name;
808  auto&& request = _configured_profiles[sensor_name];
809  bool is_custom_sensor = false;
810  static const uint32_t custom_source_id_offset = 16;
811  uint8_t custom_gpio = 0;
812  auto custom_stream_type = RS2_STREAM_ANY;
813  if (sensor_name == custom_sensor_name)
814  {
815  custom_gpio = *(reinterpret_cast<uint8_t*>((uint8_t*)(sensor_data.fo.pixels) + custom_source_id_offset));
816  custom_stream_type = custom_gpio_to_stream_type(custom_gpio);
817 
818  if (!_is_configured_stream[custom_stream_type])
819  {
820  LOG_DEBUG("Unrequested " << rs2_stream_to_string(custom_stream_type) << " frame was dropped.");
821  return;
822  }
823 
824  is_custom_sensor = true;
825  timestamp_reader = _custom_hid_timestamp_reader.get();
826  }
827 
828  if (!this->is_streaming())
829  {
830  auto stream_type = request->get_stream_type();
831  LOG_INFO("HID Frame received when Streaming is not active,"
832  << get_string(stream_type)
833  << ",Arrived," << std::fixed << system_time);
834  return;
835  }
836 
837  const auto&& fr = generate_frame_from_data(sensor_data.fo, timestamp_reader, last_timestamp, last_frame_number, request);
838  auto&& frame_counter = fr->additional_data.frame_number;
839  const auto&& timestamp_domain = timestamp_reader->get_frame_timestamp_domain(fr);
840  auto&& timestamp = fr->additional_data.timestamp;
841  const auto&& bpp = get_image_bpp(request->get_format());
842  auto&& data_size = sensor_data.fo.frame_size;
843 
844  LOG_DEBUG("FrameAccepted," << get_string(request->get_stream_type())
845  << ",Counter," << std::dec << frame_counter << ",Index,0"
846  << ",BackEndTS," << std::fixed << sensor_data.fo.backend_time
847  << ",SystemTime," << std::fixed << system_time
848  << " ,diff_ts[Sys-BE]," << system_time - sensor_data.fo.backend_time
849  << ",TS," << std::fixed << timestamp << ",TS_Domain," << rs2_timestamp_domain_to_string(timestamp_domain)
850  << ",last_frame_number," << last_frame_number << ",last_timestamp," << last_timestamp);
851 
852  last_frame_number = frame_counter;
853  last_timestamp = timestamp;
854  frame_holder frame = _source.alloc_frame(RS2_EXTENSION_MOTION_FRAME, data_size, fr->additional_data, true);
855  memcpy((void*)frame->get_frame_data(), fr->data.data(), sizeof(byte)*fr->data.size());
856  if (!frame)
857  {
858  LOG_INFO("Dropped frame. alloc_frame(...) returned nullptr");
859  return;
860  }
861  frame->set_stream(request);
862  frame->set_timestamp_domain(timestamp_domain);
864  });
865  _is_streaming = true;
866  }
867 
869  {
870  std::lock_guard<std::mutex> lock(_configure_lock);
871  if (!_is_streaming)
872  throw wrong_api_call_sequence_exception("stop_streaming() failed. Hid device is not streaming!");
873 
874 
875  _hid_device->stop_capture();
876  _is_streaming = false;
877  _source.flush();
878  _source.reset();
879  _hid_iio_timestamp_reader->reset();
882  }
883 
884  std::vector<uint8_t> hid_sensor::get_custom_report_data(const std::string& custom_sensor_name,
885  const std::string& report_name, platform::custom_sensor_report_field report_field) const
886  {
887  return _hid_device->get_custom_report_data(custom_sensor_name, report_name, report_field);
888  }
889 
891  {
892  stream_profiles stream_requests;
893  for (auto&& it = _hid_sensors.rbegin(); it != _hid_sensors.rend(); ++it)
894  {
895  auto profiles = get_sensor_profiles(it->name);
896  stream_requests.insert(stream_requests.end(), profiles.begin(), profiles.end());
897  }
898 
899  return stream_requests;
900  }
901 
903  {
904  for (auto&& elem : _sensor_name_and_hid_profiles)
905  {
906  if (stream == elem.second.stream)
907  return elem.first;
908  }
909  throw invalid_value_exception("rs2_stream not found!");
910  }
911 
913  {
914  uint32_t fourcc;
915  try {
916  fourcc = stream_and_fourcc.at(stream);
917  }
918  catch (std::out_of_range)
919  {
920  throw invalid_value_exception(to_string() << "fourcc of stream " << rs2_stream_to_string(stream) << " not found!");
921  }
922 
923  return fourcc;
924  }
925 
927  {
928  // TODO: Add log prints
931  return fps;
932 
933  auto fps_mapping = it->second.find(fps);
934  if (fps_mapping != it->second.end())
935  return fps_mapping->second;
936  else
937  return fps;
938  }
939 
941  std::shared_ptr<platform::uvc_device> uvc_device,
942  std::unique_ptr<frame_timestamp_reader> timestamp_reader,
943  device* dev)
945  _device(move(uvc_device)),
946  _user_count(0),
947  _timestamp_reader(std::move(timestamp_reader))
948  {
951  }
952 
954  {
955  counter.resize(sensors);
956  reset();
957  }
958 
960  {
961  std::lock_guard<std::recursive_mutex> lock(_mtx);
962  started = false;
963  for (auto i = 0; i < sensors; ++i)
964  {
965  counter[i] = 0;
966  }
967  }
968 
969  rs2_time_t iio_hid_timestamp_reader::get_frame_timestamp(const std::shared_ptr<frame_interface>& frame)
970  {
971  std::lock_guard<std::recursive_mutex> lock(_mtx);
972 
973  auto f = std::dynamic_pointer_cast<librealsense::frame>(frame);
974  if (has_metadata(frame))
975  {
976  // The timestamps conversions path comprise of:
977  // FW TS (32bit) -> USB Phy Layer (no changes) -> Host Driver TS (Extend to 64bit) -> LRS read as 64 bit
978  // The flow introduces discrepancy with UVC stream which timestamps are not extended to 64 bit by host driver both for Win and v4l backends.
979  // In order to allow for hw timestamp-based synchronization of Depth and IMU streams the latter will be trimmed to 32 bit.
980  // To revert to the extended 64 bit TS uncomment the next line instead
981  //auto timestamp = *((uint64_t*)((const uint8_t*)fo.metadata));
982 
983  // The ternary operator is replaced by explicit assignment due to an issue with GCC for RaspberryPi that causes segfauls in optimized build.
984  auto timestamp = *(reinterpret_cast<uint32_t*>(f->additional_data.metadata_blob.data()));
985  if (f->additional_data.metadata_size >= platform::hid_header_size)
986  timestamp = static_cast<uint32_t>(reinterpret_cast<const platform::hid_header*>(f->additional_data.metadata_blob.data())->timestamp);
987 
988  // HID timestamps are aligned to FW Default - usec units
989  return static_cast<rs2_time_t>(timestamp * TIMESTAMP_USEC_TO_MSEC);
990  }
991 
992  if (!started)
993  {
994  LOG_WARNING("HID timestamp not found, switching to Host timestamps.");
995  started = true;
996  }
997 
998  return std::chrono::duration<rs2_time_t, std::milli>(std::chrono::system_clock::now().time_since_epoch()).count();
999  }
1000 
1001  bool iio_hid_timestamp_reader::has_metadata(const std::shared_ptr<frame_interface>& frame) const
1002  {
1003  auto f = std::dynamic_pointer_cast<librealsense::frame>(frame);
1004 
1005  if (f->additional_data.metadata_size > 0)
1006  {
1007  return true;
1008  }
1009  return false;
1010  }
1011 
1012  unsigned long long iio_hid_timestamp_reader::get_frame_counter(const std::shared_ptr<frame_interface>& frame) const
1013  {
1014  std::lock_guard<std::recursive_mutex> lock(_mtx);
1015 
1016  int index = 0;
1017  if (frame->get_stream()->get_stream_type() == RS2_STREAM_GYRO)
1018  index = 1;
1019 
1020  return ++counter[index];
1021  }
1022 
1024  {
1025  if (has_metadata(frame))
1026  {
1028  }
1030  }
1031 
1035 
1037  std::shared_ptr<sensor_base> sensor,
1038  device* device,
1039  const std::map<uint32_t, rs2_format>& fourcc_to_rs2_format_map,
1040  const std::map<uint32_t, rs2_stream>& fourcc_to_rs2_stream_map)
1041  : sensor_base(name, device, (recommended_proccesing_blocks_interface*)this), _raw_sensor(std::move(sensor))
1042  {
1043  // synthetic sensor and its raw sensor will share the formats and streams mapping
1044  auto& raw_fourcc_to_rs2_format_map = _raw_sensor->get_fourcc_to_rs2_format_map();
1045  _fourcc_to_rs2_format = std::make_shared<std::map<uint32_t, rs2_format>>(fourcc_to_rs2_format_map);
1046  raw_fourcc_to_rs2_format_map = _fourcc_to_rs2_format;
1047 
1048  auto& raw_fourcc_to_rs2_stream_map = _raw_sensor->get_fourcc_to_rs2_stream_map();
1049  _fourcc_to_rs2_stream = std::make_shared<std::map<uint32_t, rs2_stream>>(fourcc_to_rs2_stream_map);
1050  raw_fourcc_to_rs2_stream_map = _fourcc_to_rs2_stream;
1051  }
1052 
1054  {
1055  try
1056  {
1057  if (is_streaming())
1058  stop();
1059 
1060  if (is_opened())
1061  close();
1062  }
1063  catch (...)
1064  {
1065  LOG_ERROR("An error has occurred while stop_streaming()!");
1066  }
1067  }
1068 
1069  // Register the option to both raw sensor and synthetic sensor.
1070  void synthetic_sensor::register_option(rs2_option id, std::shared_ptr<option> option)
1071  {
1072  _raw_sensor->register_option(id, option);
1073  sensor_base::register_option(id, option);
1074  }
1075 
1076  // Used in dynamic discovery of supported controls in generic UVC devices
1077  bool synthetic_sensor::try_register_option(rs2_option id, std::shared_ptr<option> option)
1078  {
1079  bool res=false;
1080  try
1081  {
1082  auto range = option->get_range();
1083  bool invalid_opt = (range.max < range.min || range.step < 0 || range.def < range.min || range.def > range.max) ||
1084  (range.max == range.min && range.min == range.def && range.def == range.step);
1085  bool readonly_opt = ((range.max == range.min ) && (0.f != range.min ) && ( 0.f == range.step));
1086 
1087  if (invalid_opt)
1088  {
1089  LOG_WARNING(this->get_info(RS2_CAMERA_INFO_NAME) << ": skipping " << rs2_option_to_string(id)
1090  << " control. descriptor: [min/max/step/default]= ["
1091  << range.min << "/" << range.max << "/" << range.step << "/" << range.def << "]");
1092  return res;
1093  }
1094 
1095  if (readonly_opt)
1096  {
1098  << " control was added as read-only. descriptor: [min/max/step/default]= ["
1099  << range.min << "/" << range.max << "/" << range.step << "/" << range.def << "]");
1100  }
1101 
1102  // Check getter only due to options coupling (e.g. Exposure<->AutoExposure)
1103  auto val = option->query();
1105  {
1106  LOG_WARNING(this->get_info(RS2_CAMERA_INFO_NAME) << ": Invalid reading for " << rs2_option_to_string(id)
1107  << ", val = " << val << " range [min..max] = [" << range.min << "/" << range.max << "]");
1108  }
1109 
1110  register_option(id, option);
1111  res = true;
1112  }
1113  catch (...)
1114  {
1115  LOG_WARNING("Failed to add " << rs2_option_to_string(id)<< " control for " << this->get_info(RS2_CAMERA_INFO_NAME));
1116  }
1117  return res;
1118  }
1119 
1121  {
1122  _raw_sensor->unregister_option(id);
1124  }
1125 
1127  {
1128  const auto&& raw_uvc_sensor = As<uvc_sensor, sensor_base>(_raw_sensor);
1129  register_option(id, std::make_shared<uvc_pu_option>(*raw_uvc_sensor.get(), id));
1130  }
1131 
1133  {
1134  const auto&& raw_uvc_sensor = As<uvc_sensor, sensor_base>(_raw_sensor);
1135  return try_register_option(id, std::make_shared<uvc_pu_option>(*raw_uvc_sensor.get(), id));
1136  }
1137 
1139  {
1140  std::sort(profiles->begin(), profiles->end(), [](const std::shared_ptr<stream_profile_interface>& ap,
1141  const std::shared_ptr<stream_profile_interface>& bp)
1142  {
1143  const auto&& a = to_profile(ap.get());
1144  const auto&& b = to_profile(bp.get());
1145 
1146  // stream == RS2_STREAM_COLOR && format == RS2_FORMAT_RGB8 element works around the fact that Y16 gets priority over RGB8 when both
1147  // are available for pipeline stream resolution
1148  // Note: Sort Stream Index decsending to make sure IR1 is chosen over IR2
1149  const auto&& at = std::make_tuple(a.stream, -a.index, a.width, a.height, a.fps, a.stream == RS2_STREAM_COLOR && a.format == RS2_FORMAT_RGB8, a.format);
1150  const auto&& bt = std::make_tuple(b.stream, -b.index, b.width, b.height, b.fps, b.stream == RS2_STREAM_COLOR && b.format == RS2_FORMAT_RGB8, b.format);
1151 
1152  return at > bt;
1153  });
1154  }
1155 
1156  std::shared_ptr<stream_profile_interface> synthetic_sensor::clone_profile(const std::shared_ptr<stream_profile_interface>& profile)
1157  {
1158  auto cloned = std::make_shared<stream_profile_base>(platform::stream_profile{});
1159 
1160  if (auto vsp = std::dynamic_pointer_cast<video_stream_profile>(profile))
1161  {
1162  cloned = std::make_shared<video_stream_profile>(platform::stream_profile{});
1163  std::dynamic_pointer_cast<video_stream_profile>(cloned)->set_dims(vsp->get_width(), vsp->get_height());
1164  }
1165 
1166  if (auto msp = std::dynamic_pointer_cast<motion_stream_profile>(profile))
1167  {
1168  cloned = std::make_shared<motion_stream_profile>(platform::stream_profile{});
1169  }
1170 
1171  assign_stream(profile, cloned);
1172  cloned->set_unique_id(profile->get_unique_id());
1173  cloned->set_format(profile->get_format());
1174  cloned->set_stream_index(profile->get_stream_index());
1175  cloned->set_stream_type(profile->get_stream_type());
1176  cloned->set_framerate(profile->get_framerate());
1177 
1178  return cloned;
1179  }
1180 
1182  {
1183  // Register the missing processing block's options to the sensor
1184  const auto&& options = pb.get_supported_options();
1185 
1186  for (auto&& opt : options)
1187  {
1188  const auto&& already_registered_predicate = [&opt](const rs2_option& o) {return o == opt; };
1189  if (std::none_of(begin(options), end(options), already_registered_predicate))
1190  {
1191  this->register_option(opt, std::shared_ptr<option>(const_cast<option*>(&pb.get_option(opt))));
1192  _cached_processing_blocks_options.push_back(opt);
1193  }
1194  }
1195  }
1196 
1198  {
1199  const auto&& options = pb.get_supported_options();
1200 
1201  // Unregister the cached options related to the processing blocks.
1202  for (auto&& opt : options)
1203  {
1204  const auto&& cached_option_predicate = [&opt](const rs2_option& o) {return o == opt; };
1205  auto&& cached_opt = std::find_if(begin(_cached_processing_blocks_options), end(_cached_processing_blocks_options), cached_option_predicate);
1206 
1207  if (cached_opt != end(_cached_processing_blocks_options))
1208  {
1209  this->unregister_option(*cached_opt);
1210  _cached_processing_blocks_options.erase(cached_opt);
1211  }
1212  }
1213  }
1214 
1215  bool synthetic_sensor::is_duplicated_profile(const std::shared_ptr<stream_profile_interface>& duplicate, const stream_profiles& profiles)
1216  {
1217  // Check if the given profile (duplicate parameter) is already found in profiles list.
1218  const auto&& is_duplicate_predicate = [&duplicate](const std::shared_ptr<stream_profile_interface>& spi) {
1219  return to_profile(spi.get()) == to_profile(duplicate.get());
1220  };
1221 
1222  return std::any_of(begin(profiles), end(profiles), is_duplicate_predicate);
1223  }
1224 
1226  {
1227  stream_profiles result_profiles;
1228  auto profiles = _raw_sensor->get_stream_profiles( PROFILE_TAG_ANY | PROFILE_TAG_DEBUG );
1229 
1230  for (auto&& pbf : _pb_factories)
1231  {
1232  const auto&& sources = pbf->get_source_info();
1233  const auto&& targets = pbf->get_target_info();
1234 
1235  for (auto&& source : sources)
1236  {
1237  // add profiles that are supported by the device
1238  for (auto& profile : profiles)
1239  {
1240  if (profile->get_format() == source.format &&
1241  (source.stream == profile->get_stream_type() || source.stream == RS2_STREAM_ANY))
1242  {
1243  for (auto target : targets)
1244  {
1245  target.fps = profile->get_framerate();
1246 
1247  auto&& cloned_profile = clone_profile(profile);
1248  cloned_profile->set_format(target.format);
1249  cloned_profile->set_stream_index(target.index);
1250  cloned_profile->set_stream_type(target.stream);
1251 
1252  auto&& cloned_vsp = As<video_stream_profile, stream_profile_interface>(cloned_profile);
1253  if (cloned_vsp)
1254  {
1255  const auto&& res = target.stream_resolution({ cloned_vsp->get_width(), cloned_vsp->get_height() });
1256  target.height = res.height;
1257  target.width = res.width;
1258  cloned_vsp->set_dims(target.width, target.height);
1259  }
1260 
1261  // Add the cloned profile to the supported profiles by this processing block factory,
1262  // for later processing validation in resolving the request.
1263  _pbf_supported_profiles[pbf.get()].push_back(cloned_profile);
1264 
1265  // cache the source to target mapping
1266  _source_to_target_profiles_map[profile].push_back(cloned_profile);
1267  // cache each target profile to its source profiles which were generated from.
1269 
1270  // disregard duplicated from profiles list
1271  if (is_duplicated_profile(cloned_profile, result_profiles))
1272  continue;
1273 
1274  // Only injective cloning in many to one mapping.
1275  // One to many is not affected.
1276  if (sources.size() > 1 && target.format != source.format)
1277  continue;
1278 
1279  result_profiles.push_back(cloned_profile);
1280  }
1281  }
1282  }
1283  }
1284  }
1285 
1286  _owner->tag_profiles(result_profiles);
1287  sort_profiles(&result_profiles);
1288  return result_profiles;
1289  }
1290 
1291  std::pair<std::shared_ptr<processing_block_factory>, stream_profiles> synthetic_sensor::find_requests_best_pb_match(const stream_profiles& requests)
1292  {
1293  // Find and retrieve best fitting processing block to the given requests, and the requests which were the best fit.
1294 
1295  // For video stream, the best fitting processing block is defined as the processing block which its sources
1296  // covers the maximum amount of requests.
1297 
1298  stream_profiles best_match_requests;
1299  std::shared_ptr<processing_block_factory> best_match_processing_block_factory;
1300 
1301  int max_satisfied_req = 0;
1302  int best_source_size = 0;
1303  int satisfied_count = 0;
1304 
1305  for (auto&& pbf : _pb_factories)
1306  {
1307  auto satisfied_req = pbf->find_satisfied_requests(requests, _pbf_supported_profiles[pbf.get()]);
1308  satisfied_count = (int)satisfied_req.size();
1309  if (satisfied_count > max_satisfied_req
1310  || (satisfied_count == max_satisfied_req
1311  && pbf->get_source_info().size() < best_source_size))
1312  {
1313  max_satisfied_req = satisfied_count;
1314  best_source_size = (int)pbf->get_source_info().size();
1315  best_match_processing_block_factory = pbf;
1316  best_match_requests = satisfied_req;
1317  }
1318  }
1319 
1320  return { best_match_processing_block_factory, best_match_requests };
1321  }
1322 
1323  void synthetic_sensor::add_source_profile_missing_data(std::shared_ptr<stream_profile_interface>& target)
1324  {
1325  // Add the missing data to the desired source profile.
1326  // This is needed because we duplicate the source profile into multiple target profiles in the init_stream_profiles() method.
1327 
1328  // Update the source profile's fields with the correlated target profile.
1329  // This profile will be propagated to the generated frame received from the backend sensor.
1330 
1331  auto source_profile_ = _target_to_source_profiles_map[to_profile(target.get())];
1332  auto source_profile = source_profile_[0];
1333  source_profile->set_stream_index(target->get_stream_index());
1334  source_profile->set_unique_id(target->get_unique_id());
1335  source_profile->set_stream_type(target->get_stream_type());
1336  auto&& vsp = As<video_stream_profile, stream_profile_interface>(source_profile);
1337  const auto&& cvsp = As<video_stream_profile, stream_profile_interface>(target);
1338  if (vsp)
1339  {
1340  vsp->set_intrinsics([cvsp]() {
1341 
1342  if (cvsp)
1343  return cvsp->get_intrinsics();
1344  else
1345  return rs2_intrinsics{};
1346  });
1347 
1348  vsp->set_dims(cvsp->get_width(), cvsp->get_height());
1349  }
1350  }
1351 
1353  {
1354  // Add missing data to all of the source profiles.
1355  // init_stream_profiles() cloned the source profiles and converted them into target profiles.
1356  // we must pass the missing data from the target profiles to the source profiles.
1357  for (auto&& entry : _target_to_source_profiles_map)
1358  {
1359  for (auto&& source : entry.second)
1361  }
1362  }
1363 
1365  {
1366  // Convert the requests into profiles which are supported by the sensor.
1367 
1368  std::unordered_set<std::shared_ptr<stream_profile_interface>> resolved_req_set;
1369  stream_profiles resolved_req;
1370  stream_profiles unhandled_reqs(requests);
1371 
1372  // cache the requests
1373  for (auto&& req : requests)
1374  {
1375  _cached_requests[req->get_format()].push_back(req);
1376  }
1377 
1378  // while not finished handling all of the requests do
1379  while (!unhandled_reqs.empty())
1380  {
1381  // find the best fitting processing block - the one which resolves the most requests.
1382  const auto&& best_match = find_requests_best_pb_match(unhandled_reqs);
1383  auto&& best_pbf = best_match.first;
1384  auto&& best_reqs = best_match.second;
1385 
1386  // mark as handled resolved requests
1387  for (auto&& req : best_reqs)
1388  {
1389  const auto&& matching_req_predicate = [&req](const std::shared_ptr<stream_profile_interface>& sp) {
1390  return to_profile(req.get()) == to_profile(sp.get());
1391  };
1392  unhandled_reqs.erase(std::remove_if(begin(unhandled_reqs), end(unhandled_reqs), matching_req_predicate));
1393  }
1394 
1395  // Retrieve source profile from cached map and generate the relevant processing block.
1396  std::unordered_set<std::shared_ptr<stream_profile_interface>> current_resolved_reqs;
1397  auto best_pb = best_pbf->generate();
1399  for (auto&& req : best_reqs)
1400  {
1401  auto&& target = to_profile(req.get());
1402  auto&& mapped_source_profiles = _target_to_source_profiles_map[target];
1403 
1404  for (auto&& source_profile : mapped_source_profiles)
1405  {
1406  if (best_pbf->has_source(source_profile))
1407  {
1408  resolved_req_set.insert(source_profile);
1409  current_resolved_reqs.insert(source_profile);
1410 
1411  _profiles_to_processing_block[source_profile].insert(best_pb);
1412  }
1413  }
1414  }
1415  const stream_profiles&& print_current_resolved_reqs = { current_resolved_reqs.begin(), current_resolved_reqs.end() };
1416  LOG_INFO("Request: " << best_reqs << "\nResolved to: " << print_current_resolved_reqs);
1417  }
1418  resolved_req = { resolved_req_set.begin(), resolved_req_set.end() };
1419  return resolved_req;
1420  }
1421 
1423  {
1424  std::lock_guard<std::mutex> lock(_synthetic_configure_lock);
1425 
1426  for (auto source : requests)
1428 
1429  const auto&& resolved_req = resolve_requests(requests);
1430 
1431  _raw_sensor->set_source_owner(this);
1432  try
1433  {
1434  _raw_sensor->open(resolved_req);
1435  }
1436  catch (const std::runtime_error& e)
1437  {
1438  // Throw a more informative exception
1439  std::stringstream requests_info;
1440  for (auto&& r : requests)
1441  {
1442  auto p = to_profile(r.get());
1443  requests_info << "\tFormat: " + std::string(rs2_format_to_string(p.format)) << ", width: " << p.width << ", height: " << p.height << std::endl;
1444  }
1445  throw recoverable_exception("\nFailed to resolve the request: \n" + requests_info.str() + "\nInto:\n" + e.what(),
1447  }
1448 
1449  set_active_streams(requests);
1450  }
1451 
1453  {
1454  std::lock_guard<std::mutex> lock(_synthetic_configure_lock);
1455  _raw_sensor->close();
1456  for (auto&& entry : _profiles_to_processing_block)
1457  {
1458  for (auto&& pb : entry.second)
1460  }
1461  _profiles_to_processing_block.erase(begin(_profiles_to_processing_block), end(_profiles_to_processing_block));
1462  _cached_requests.erase(_cached_requests.begin(), _cached_requests.end());
1463  set_active_streams({});
1464  _post_process_callback.reset();
1465  }
1466 
1467  template<class T>
1469  {
1470  return {
1472  [](rs2_frame_callback* p) { p->release(); }
1473  };
1474  }
1475 
1476  std::shared_ptr<stream_profile_interface> synthetic_sensor::filter_frame_by_requests(const frame_interface* f)
1477  {
1478  const auto&& cached_req = _cached_requests.find(f->get_stream()->get_format());
1479  if (cached_req == _cached_requests.end())
1480  return nullptr;
1481 
1482  auto&& reqs = cached_req->second;
1483  auto&& req_it = std::find_if(begin(reqs), end(reqs), [&f](const std::shared_ptr<stream_profile_interface>& req) {
1484  return (req->get_stream_index() == f->get_stream()->get_stream_index() &&
1485  req->get_stream_type() == f->get_stream()->get_stream_type());
1486  });
1487 
1488  return req_it != end(reqs) ? *req_it : nullptr;
1489  }
1490 
1492  {
1493  std::lock_guard<std::mutex> lock(_synthetic_configure_lock);
1494 
1495  // Set the post-processing callback as the user callback.
1496  // This callback might be modified by other object.
1497  set_frames_callback(callback);
1498 
1499  // After processing callback
1500  const auto&& output_cb = make_callback([&](frame_holder f) {
1501  std::vector<frame_interface*> processed_frames;
1502  processed_frames.push_back(f.frame);
1503 
1504  auto&& composite = dynamic_cast<composite_frame*>(f.frame);
1505  if (composite)
1506  {
1507  for (size_t i = 0; i < composite->get_embedded_frames_count(); i++)
1508  {
1509  processed_frames.push_back(composite->get_frame(i));
1510  }
1511  }
1512 
1513  // process only frames which aren't composite.
1514  for (auto&& fr : processed_frames)
1515  {
1516  if (!dynamic_cast<composite_frame*>(fr))
1517  {
1518  auto&& cached_profile = filter_frame_by_requests(fr);
1519 
1520  if (cached_profile)
1521  {
1522  fr->set_stream(cached_profile);
1523  }
1524  else
1525  continue;
1526 
1527  fr->acquire();
1528  _post_process_callback->on_frame((rs2_frame*)fr);
1529  }
1530  }
1531  });
1532 
1533  // Set callbacks for all of the relevant processing blocks
1534  for (auto&& pb_entry : _profiles_to_processing_block)
1535  {
1536  auto&& pbs = pb_entry.second;
1537  for (auto&& pb : pbs)
1538  if (pb)
1539  {
1540  pb->set_output_callback(output_cb);
1541  }
1542  }
1543 
1544  // Invoke processing blocks callback
1545  const auto&& process_cb = make_callback([&, this](frame_holder f) {
1546  if (!f)
1547  return;
1548 
1549  auto&& pbs = _profiles_to_processing_block[f->get_stream()];
1550  for (auto&& pb : pbs)
1551  {
1552  f->acquire();
1553  pb->invoke(f.frame);
1554  }
1555  });
1556 
1557  // Call the processing block on the frame
1558  _raw_sensor->start(process_cb);
1559  }
1560 
1562  {
1563  std::lock_guard<std::mutex> lock(_synthetic_configure_lock);
1564  _raw_sensor->stop();
1565  }
1566 
1567  void synthetic_sensor::register_processing_block(const std::vector<stream_profile>& from,
1568  const std::vector<stream_profile>& to,
1569  std::function<std::shared_ptr<processing_block>(void)> generate_func)
1570  {
1571  _pb_factories.push_back(std::make_shared<processing_block_factory>(from, to, generate_func));
1572  }
1573 
1575  {
1576  _pb_factories.push_back(std::make_shared<processing_block_factory>(pbf));
1577  }
1578 
1579  void synthetic_sensor::register_processing_block(const std::vector<processing_block_factory>& pbfs)
1580  {
1581  for (auto&& pbf : pbfs)
1583  }
1584 
1586  {
1587  return _post_process_callback;
1588  }
1589 
1591  {
1592  // This callback is mutable, might be modified.
1593  // For instance, record_sensor modifies this callback in order to hook it to record frames.
1595  }
1596 
1598  {
1600  _raw_sensor->register_notifications_callback(callback);
1601  }
1602 
1604  {
1605  return _raw_sensor->register_before_streaming_changes_callback(callback);
1606  }
1607 
1609  {
1610  _raw_sensor->unregister_before_start_callback(token);
1611  }
1612 
1613  void synthetic_sensor::register_metadata(rs2_frame_metadata_value metadata, std::shared_ptr<md_attribute_parser_base> metadata_parser) const
1614  {
1615  sensor_base::register_metadata(metadata, metadata_parser);
1616  _raw_sensor->register_metadata(metadata, metadata_parser);
1617  }
1618 
1620  {
1621  return _raw_sensor->is_streaming();
1622  }
1623 
1625  {
1626  return _raw_sensor->is_opened();
1627  }
1628 
1629  void motion_sensor::create_snapshot(std::shared_ptr<motion_sensor>& snapshot) const
1630  {
1631  snapshot = std::make_shared<motion_sensor_snapshot>();
1632  }
1633 
1634  void fisheye_sensor::create_snapshot(std::shared_ptr<fisheye_sensor>& snapshot) const
1635  {
1636  snapshot = std::make_shared<fisheye_sensor_snapshot>();
1637  }
1638 }
std::pair< std::shared_ptr< processing_block_factory >, stream_profiles > find_requests_best_pb_match(const stream_profiles &sp)
Definition: sensor.cpp:1291
static const textual_icon lock
Definition: model-views.h:218
virtual void register_option(rs2_option id, std::shared_ptr< option > option)
Definition: sensor.cpp:1070
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
bool is_streaming() const override
Definition: sensor.cpp:106
virtual const byte * get_frame_data() const =0
const char * rs2_format_to_string(rs2_format format)
Definition: rs.cpp:1263
frame_source _source
Definition: sensor.h:110
notifications_callback_ptr get_notifications_callback() const override
Definition: sensor.cpp:76
static const double TIMESTAMP_USEC_TO_MSEC
Definition: src/types.h:92
GLuint GLuint end
GLboolean GLboolean GLboolean b
void stop() override
Definition: sensor.cpp:494
void register_xu(platform::extension_unit xu)
Definition: sensor.cpp:475
rs2_stream stream
boost_foreach_argument_dependent_lookup_hack tag
Definition: foreach_fwd.hpp:31
const char * get_string(rs2_rs400_visual_preset value)
std::atomic< bool > _is_opened
Definition: sensor.h:104
GLuint const GLchar * name
void unregister_processing_block_options(const processing_block &pb)
Definition: sensor.cpp:1197
void invoke_callback(frame_holder frame) const
Definition: source.cpp:113
const char * rs2_timestamp_domain_to_string(rs2_timestamp_domain info)
Definition: rs.cpp:1267
virtual bool is_opened() const
Definition: sensor.cpp:111
void tag_profiles(stream_profiles profiles) const override
Definition: device.cpp:283
const char * rs2_frame_metadata_to_string(rs2_frame_metadata_value metadata)
Definition: rs.cpp:1275
stream_profiles init_stream_profiles() override
Definition: sensor.cpp:560
rs2_option
Defines general configuration controls. These can generally be mapped to camera UVC controls...
Definition: rs_option.h:22
void open(const stream_profiles &requests) override
Definition: sensor.cpp:1422
GLdouble s
uvc_sensor(std::string name, std::shared_ptr< platform::uvc_device > uvc_device, std::unique_ptr< frame_timestamp_reader > timestamp_reader, device *dev)
Definition: sensor.cpp:940
std::shared_ptr< platform::time_service > get_time_service()
virtual std::shared_ptr< notifications_processor > get_notifications_processor() const
Definition: sensor.cpp:116
hid_sensor(std::shared_ptr< platform::hid_device > hid_device, std::unique_ptr< frame_timestamp_reader > hid_iio_timestamp_reader, std::unique_ptr< frame_timestamp_reader > custom_hid_timestamp_reader, const std::map< rs2_stream, std::map< unsigned, unsigned >> &fps_and_sampling_frequency_per_rs2_stream, const std::vector< std::pair< std::string, stream_profile >> &sensor_name_and_hid_profiles, device *dev)
Definition: sensor.cpp:662
void init(std::shared_ptr< metadata_parser_map > metadata_parsers)
Definition: source.cpp:50
std::shared_ptr< rs2_frame_callback > frame_callback_ptr
Definition: src/types.h:1071
GLfloat GLfloat p
Definition: glext.h:12687
frame_callback_ptr get_frames_callback() const override
Definition: sensor.cpp:1585
GLboolean reset
void register_processing_block(const std::vector< stream_profile > &from, const std::vector< stream_profile > &to, std::function< std::shared_ptr< processing_block >(void)> generate_func)
Definition: sensor.cpp:1567
stream_profiles resolve_requests(const stream_profiles &requests)
Definition: sensor.cpp:1364
void set_source_owner(sensor_base *owner)
Definition: sensor.cpp:191
#define LOG_WARNING(...)
Definition: src/types.h:241
const char * rs2_option_to_string(rs2_option option)
Definition: rs.cpp:1265
stream_profiles get_stream_profiles(int tag=profile_tag::PROFILE_TAG_ANY) const override
Definition: sensor.cpp:196
std::mutex _synthetic_configure_lock
Definition: sensor.h:242
processing_blocks get_color_recommended_proccesing_blocks()
Definition: sensor.cpp:216
frame_callback_ptr make_callback(T callback)
Definition: sensor.cpp:1468
std::unordered_map< processing_block_factory *, stream_profiles > _pbf_supported_profiles
Definition: sensor.h:247
rs2_timestamp_domain get_frame_timestamp_domain(const std::shared_ptr< frame_interface > &frame) const override
Definition: sensor.cpp:1023
virtual stream_profiles init_stream_profiles() override
Definition: sensor.cpp:1225
void start(frame_callback_ptr callback) override
Definition: sensor.cpp:480
void create_snapshot(std::shared_ptr< info_interface > &snapshot) const override
Definition: sensor.cpp:629
std::vector< platform::hid_sensor > _hid_sensors
Definition: sensor.h:310
rs2_format fourcc_to_rs2_format(uint32_t format) const
Definition: sensor.cpp:142
void register_metadata(rs2_frame_metadata_value metadata, std::shared_ptr< md_attribute_parser_base > metadata_parser) const override
Definition: sensor.cpp:1613
std::unordered_map< stream_profile, stream_profiles > _target_to_source_profiles_map
Definition: sensor.h:250
bool supports_info(rs2_camera_info info) const override
Definition: sensor.cpp:55
int register_before_streaming_changes_callback(std::function< void(bool)> callback) override
Definition: sensor.cpp:1603
void register_same_extrinsics(const stream_interface &from, const stream_interface &to)
Definition: environment.cpp:23
bool supports_option(rs2_option id) const override
Definition: options.h:51
void register_pu(rs2_option id)
Definition: sensor.cpp:653
virtual void register_metadata(rs2_frame_metadata_value metadata, std::shared_ptr< md_attribute_parser_base > metadata_parser) const
Definition: sensor.cpp:121
virtual bool try_register_option(rs2_option id, std::shared_ptr< option > option)
Definition: sensor.cpp:1077
GLsizei const GLchar *const * string
bool has_metadata(const std::shared_ptr< frame_interface > &frame) const
Definition: sensor.cpp:1001
GLuint entry
Definition: glext.h:10991
void open(const stream_profiles &requests) override
Definition: sensor.cpp:304
void create_snapshot(std::shared_ptr< fisheye_sensor > &snapshot) const override
Definition: sensor.cpp:1634
GLdouble n
Definition: glext.h:1966
unsigned char uint8_t
Definition: stdint.h:78
std::shared_ptr< platform::hid_device > _hid_device
Definition: sensor.h:306
std::map< rs2_camera_info, std::string > _camera_info
Definition: info.h:34
e
Definition: rmse.py:177
option & get_option(rs2_option id) override
Definition: options.h:58
frame_callback_ptr _post_process_callback
Definition: sensor.h:244
void sort(sort_type m_sort_type, const std::string &in, const std::string &out)
std::mutex _active_profile_mutex
Definition: sensor.h:120
std::vector< bool > _is_configured_stream
Definition: sensor.h:309
void close() override
Definition: sensor.cpp:449
std::shared_ptr< sensor_base > _raw_sensor
Definition: sensor.h:245
GLenum GLuint id
void unregister_option(rs2_option id)
Definition: options.h:92
GLuint index
void register_option(rs2_option id, std::shared_ptr< option > option)
Definition: options.h:86
virtual void release()=0
void open(const stream_profiles &requests) override
Definition: sensor.cpp:726
void create_snapshot(std::shared_ptr< motion_sensor > &snapshot) const override
Definition: sensor.cpp:1629
GLboolean GLboolean GLboolean GLboolean a
const std::map< rs2_stream, uint32_t > stream_and_fourcc
Definition: sensor.h:300
std::vector< rs2_option > get_supported_options() const override
Definition: option.cpp:197
GLuint GLfloat * val
std::unique_ptr< frame_timestamp_reader > _hid_iio_timestamp_reader
Definition: sensor.h:311
void close() override
Definition: sensor.cpp:752
std::shared_ptr< frame > generate_frame_from_data(const platform::frame_object &fo, frame_timestamp_reader *timestamp_reader, const rs2_time_t &last_timestamp, const unsigned long long &last_frame_number, std::shared_ptr< stream_profile_interface > profile)
Definition: sensor.cpp:249
def info(name, value, persistent=False)
Definition: test.py:301
void set_active_streams(const stream_profiles &requests)
Definition: sensor.cpp:178
virtual ~uvc_sensor() override
Definition: sensor.cpp:288
not_this_one begin(...)
GLdouble f
std::unordered_map< rs2_format, stream_profiles > _cached_requests
Definition: sensor.h:251
~hid_sensor() override
Definition: sensor.cpp:689
frame_callback_ptr get_callback() const
Definition: source.cpp:108
void register_info(rs2_camera_info info, const std::string &val)
Definition: sensor.cpp:602
virtual stream_profiles init_stream_profiles()=0
std::shared_ptr< option > get_published_size_option()
Definition: source.cpp:39
void register_pu(rs2_option id)
Definition: sensor.cpp:1126
std::shared_ptr< std::map< uint32_t, rs2_format > > & get_fourcc_to_rs2_format_map()
Definition: sensor.cpp:132
std::mutex _configure_lock
Definition: sensor.h:307
processing_blocks get_depth_recommended_proccesing_blocks()
Definition: sensor.cpp:228
void start(frame_callback_ptr callback) override
Definition: sensor.cpp:1491
std::shared_ptr< std::map< uint32_t, rs2_format > > _fourcc_to_rs2_format
Definition: sensor.h:114
GLuint counter
Definition: glext.h:5684
GLdouble GLdouble r
stream_profiles _active_profiles
Definition: sensor.h:119
std::unique_ptr< frame_timestamp_reader > _custom_hid_timestamp_reader
Definition: sensor.h:312
unsigned int uint32_t
Definition: stdint.h:80
void raise_on_before_streaming_changes(bool streaming)
Definition: sensor.cpp:174
static rs2_stream custom_gpio_to_stream_type(uint32_t custom_gpio)
Definition: sensor.cpp:773
std::shared_ptr< rs2_notifications_callback > notifications_callback_ptr
Definition: src/types.h:1073
std::multimap< rs2_frame_metadata_value, std::shared_ptr< md_attribute_parser_base > > metadata_parser_map
Definition: archive.h:16
const std::string & get_info(rs2_camera_info info) const override
Definition: sensor.cpp:49
void set_sensor(const std::shared_ptr< sensor_interface > &s)
Definition: source.cpp:94
std::shared_ptr< notifications_processor > _notifications_processor
Definition: sensor.h:105
GLint GLsizei GLsizei height
std::vector< platform::stream_profile > _uvc_profiles
Definition: sensor.h:112
virtual void set_frames_callback(frame_callback_ptr callback) override
Definition: sensor.cpp:101
void add_source_profile_missing_data(std::shared_ptr< stream_profile_interface > &source_profile)
Definition: sensor.cpp:1323
stream_profiles get_sensor_profiles(std::string sensor_name) const
Definition: sensor.cpp:705
GLenum target
Definition: glext.h:1565
def callback(frame)
Definition: t265_stereo.py:91
unsigned long long frame_number
Definition: archive.h:31
void unregister_before_start_callback(int token) override
Definition: sensor.cpp:1608
const std::vector< std::pair< std::string, stream_profile > > _sensor_name_and_hid_profiles
Definition: sensor.h:304
GLsizei GLenum * sources
rs2_format
A stream&#39;s format identifies how binary data is encoded within a frame.
Definition: rs_sensor.h:59
void update(std::shared_ptr< extension_snapshot > ext) override
Definition: sensor.cpp:638
bool supports_info(rs2_camera_info info) const override
Definition: sensor.cpp:596
std::vector< platform::stream_profile > _internal_config
Definition: sensor.h:101
#define LOG_ERROR(...)
Definition: src/types.h:242
signal< sensor_base, bool > on_before_streaming_changes
Definition: sensor.h:121
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
void update_info(rs2_camera_info info, const std::string &val)
Definition: sensor.cpp:614
const std::string & get_info(rs2_camera_info info) const override
Definition: sensor.cpp:621
std::vector< std::shared_ptr< stream_profile_interface >> stream_profiles
Definition: streaming.h:165
rs2_extension stream_to_frame_types(rs2_stream stream) const
Definition: sensor.cpp:586
rs2_stream
Streams are different types of data provided by RealSense devices.
Definition: rs_sensor.h:42
void register_processing_block_options(const processing_block &pb)
Definition: sensor.cpp:1181
bool is_streaming() const override
Definition: sensor.cpp:1619
frame_interface * alloc_frame(rs2_extension type, size_t size, frame_additional_data additional_data, bool requires_memory) const
Definition: source.cpp:87
static environment & get_instance()
void enable_recording(std::function< void(const info_interface &)> record_action) override
Definition: sensor.cpp:633
extrinsics_graph & get_extrinsics_graph()
std::shared_ptr< std::map< uint32_t, rs2_stream > > & get_fourcc_to_rs2_stream_map()
Definition: sensor.cpp:137
void sort_profiles(stream_profiles *profiles)
Definition: sensor.cpp:1138
synthetic_sensor(std::string name, std::shared_ptr< sensor_base > sensor, device *device, const std::map< uint32_t, rs2_format > &fourcc_to_rs2_format_map=std::map< uint32_t, rs2_format >(), const std::map< uint32_t, rs2_stream > &fourcc_to_rs2_stream_map=std::map< uint32_t, rs2_stream >())
Definition: sensor.cpp:1036
LOG_INFO("Log message using LOG_INFO()")
virtual std::shared_ptr< stream_profile_interface > get_stream() const =0
void unregister_before_start_callback(int token) override
Definition: sensor.cpp:88
device_interface & get_device() override
Definition: sensor.cpp:244
std::shared_ptr< stream_profile_interface > clone_profile(const std::shared_ptr< stream_profile_interface > &profile)
Definition: sensor.cpp:1156
unsigned char byte
Definition: src/types.h:52
std::vector< uint8_t > get_custom_report_data(const std::string &custom_sensor_name, const std::string &report_name, platform::custom_sensor_report_field report_field) const
Definition: sensor.cpp:884
sensor_base(std::string name, device *device, recommended_proccesing_blocks_interface *owner)
Definition: sensor.cpp:27
virtual unsigned long long get_frame_counter(const std::shared_ptr< frame_interface > &frame) const =0
virtual frame_callback_ptr get_frames_callback() const override
Definition: sensor.cpp:97
sensor_base * _source_owner
Definition: sensor.h:109
frame_interface * frame
Definition: streaming.h:126
const char * rs2_stream_to_string(rs2_stream stream)
Definition: rs.cpp:1262
rs2_extension
Specifies advanced interfaces (capabilities) objects may implement.
Definition: rs_types.h:166
rs2_stream fourcc_to_rs2_stream(uint32_t fourcc_format) const
Definition: sensor.cpp:158
::realsense_legacy_msgs::metadata_< std::allocator< void > > metadata
static auto it
stream_profile to_profile(const stream_profile_interface *sp)
Definition: src/stream.h:185
std::shared_ptr< metadata_parser_map > _metadata_parsers
Definition: sensor.h:107
void assign_stream(const std::shared_ptr< stream_interface > &stream, std::shared_ptr< stream_profile_interface > target) const
Definition: sensor.cpp:184
lazy< stream_profiles > _profiles
Definition: sensor.h:118
stream_profiles get_active_streams() const override
Definition: sensor.cpp:60
GLint GLsizei count
unsigned long long get_frame_counter(const std::shared_ptr< frame_interface > &frame) const override
Definition: sensor.cpp:1012
uint32_t fps_to_sampling_frequency(rs2_stream stream, uint32_t fps) const
Definition: sensor.cpp:926
void stop() override
Definition: sensor.cpp:868
bool try_register_pu(rs2_option id)
Definition: sensor.cpp:1132
std::vector< std::shared_ptr< processing_block_factory > > _pb_factories
Definition: sensor.h:246
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
Video stream intrinsics.
Definition: rs_types.h:58
void set_callback(frame_callback_ptr callback)
Definition: source.cpp:102
std::unordered_map< std::shared_ptr< stream_profile_interface >, std::unordered_set< std::shared_ptr< processing_block > > > _profiles_to_processing_block
Definition: sensor.h:248
GLsizei GLsizei GLchar * source
std::shared_ptr< stream_profile_interface > filter_frame_by_requests(const frame_interface *f)
Definition: sensor.cpp:1476
std::unordered_map< std::shared_ptr< stream_profile_interface >, stream_profiles > _source_to_target_profiles_map
Definition: sensor.h:249
rs2_time_t get_frame_timestamp(const std::shared_ptr< frame_interface > &frame) override
Definition: sensor.cpp:969
GLsizei range
std::vector< rs2_option > _cached_processing_blocks_options
Definition: sensor.h:252
int i
int register_before_streaming_changes_callback(std::function< void(bool)> callback) override
Definition: sensor.cpp:81
GLuint res
Definition: glext.h:8856
virtual void set_timestamp_domain(rs2_timestamp_domain timestamp_domain)=0
virtual double get_frame_timestamp(const std::shared_ptr< frame_interface > &frame)=0
uint32_t stream_to_fourcc(rs2_stream stream) const
Definition: sensor.cpp:912
void start(frame_callback_ptr callback) override
Definition: sensor.cpp:786
std::shared_ptr< md_attribute_parser_base > make_additional_data_parser(Attribute St::*attribute)
A utility function to create additional_data parser.
void unregister_option(rs2_option id)
Definition: sensor.cpp:1120
rs2_format format
#define LOG_DEBUG(...)
Definition: src/types.h:239
void register_notifications_callback(notifications_callback_ptr callback) override
Definition: sensor.cpp:66
stream_profiles init_stream_profiles() override
Definition: sensor.cpp:890
void register_notifications_callback(notifications_callback_ptr callback) override
Definition: sensor.cpp:1597
bool is_duplicated_profile(const std::shared_ptr< stream_profile_interface > &duplicate, const stream_profiles &profiles)
Definition: sensor.cpp:1215
std::atomic< bool > _is_streaming
Definition: sensor.h:103
double rs2_time_t
Definition: rs_types.h:300
bool is_opened() const override
Definition: sensor.cpp:1624
constexpr uint8_t hid_header_size
Definition: backend.h:166
virtual void attach_continuation(frame_continuation &&continuation)=0
const std::string & rs2_stream_to_sensor_name(rs2_stream stream) const
Definition: sensor.cpp:902
std::shared_ptr< std::map< uint32_t, rs2_stream > > _fourcc_to_rs2_stream
Definition: sensor.h:115
GLuint64EXT * result
Definition: glext.h:10921
void set_frames_callback(frame_callback_ptr callback) override
Definition: sensor.cpp:1590
std::map< rs2_stream, std::map< uint32_t, uint32_t > > _fps_and_sampling_frequency_per_rs2_stream
Definition: sensor.h:305
int get_image_bpp(rs2_format format)
Definition: image.cpp:21
std::map< std::string, std::shared_ptr< stream_profile_interface > > _configured_profiles
Definition: sensor.h:308
GeneratorWrapper< T > map(Func &&function, GeneratorWrapper< U > &&generator)
Definition: catch.hpp:4271
rs2_frame_metadata_value
Per-Frame-Metadata is the set of read-only properties that might be exposed for each individual frame...
Definition: rs_frame.h:29
struct rs2_frame rs2_frame
Definition: rs_types.h:261
GLint GLsizei width
virtual void set_stream(std::shared_ptr< stream_profile_interface > sp)=0
unsigned long long last_frame_number
Definition: archive.h:40
std::string to_string(T value)
rs2_timestamp_domain
Specifies the clock in relation to which the frame timestamp was measured.
Definition: rs_frame.h:19


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