mf-uvc.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 #if (_MSC_FULL_VER < 180031101)
5 #error At least Visual Studio 2013 Update 4 is required to compile this backend
6 #endif
7 
8 #include <ntverp.h>
9 #if VER_PRODUCTBUILD <= 9600 // (WinSDK 8.1)
10 #ifdef ENFORCE_METADATA
11 #error( "Librealsense Error!: Featuring UVC Metadata requires WinSDK 10.0.10586.0. \
12  Install the required toolset to proceed. Alternatively, uncheck ENFORCE_METADATA option in CMake GUI tool")
13 #else
14 #pragma message ( "\nLibrealsense notification: Featuring UVC Metadata requires WinSDK 10.0.10586.0 toolset. \
15 The library will be compiled without the metadata support!\n")
16 #endif // ENFORCE_METADATA
17 #else
18 #define METADATA_SUPPORT
19 #endif // (WinSDK 8.1)
20 
21 #ifndef NOMINMAX
22 #define NOMINMAX
23 #endif
24 
25 #define DEVICE_ID_MAX_SIZE 256
26 
27 #include "mf-uvc.h"
28 #include "../types.h"
29 #include "uvc/uvc-types.h"
30 
31 #include "Shlwapi.h"
32 #include <Windows.h>
33 #include <limits>
34 #include "mfapi.h"
35 #include <vidcap.h>
36 #include <ksmedia.h> // Metadata Extension
37 #include <Mferror.h>
38 
39 #pragma comment(lib, "Shlwapi.lib")
40 #pragma comment(lib, "mf.lib")
41 #pragma comment(lib, "mfplat.lib")
42 #pragma comment(lib, "mfreadwrite.lib")
43 #pragma comment(lib, "mfuuid.lib")
44 
45 #define type_guid MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
46 #define did_guid MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK
47 
48 #define DEVICE_NOT_READY_ERROR _HRESULT_TYPEDEF_(0x80070015L)
49 #define MF_E_SHUTDOWN_ERROR _HRESULT_TYPEDEF_(0xC00D3E85)
50 
51 #define MAX_PINS 5
52 
53 namespace librealsense
54 {
55  namespace platform
56  {
57 
58 #ifdef METADATA_SUPPORT
59 
60 #pragma pack(push, 1)
61  struct ms_proprietary_md_blob
62  {
63  // These fields are identical in layout and content with the standard UVC header
65  uint8_t source_clock[6];
66  // MS internal
67  uint8_t reserved[6];
68  };
69 
70  struct ms_metadata_header
71  {
72  KSCAMERA_METADATA_ITEMHEADER ms_header;
73  ms_proprietary_md_blob ms_blobs[2]; // The blobs content is identical
74  };
75 #pragma pack(pop)
76 
77  constexpr uint8_t ms_header_size = sizeof(ms_metadata_header);
78 
79  bool try_read_metadata(IMFSample *pSample, uint8_t& metadata_size, byte** bytes)
80  {
81  CComPtr<IUnknown> spUnknown;
82  CComPtr<IMFAttributes> spSample;
83  HRESULT hr = S_OK;
84 
85  CHECK_HR(hr = pSample->QueryInterface(IID_PPV_ARGS(&spSample)));
86  LOG_HR(hr = spSample->GetUnknown(MFSampleExtension_CaptureMetadata, IID_PPV_ARGS(&spUnknown)));
87 
88  if (SUCCEEDED(hr))
89  {
90  CComPtr<IMFAttributes> spMetadata;
91  CComPtr<IMFMediaBuffer> spBuffer;
92  PKSCAMERA_METADATA_ITEMHEADER pMetadata = nullptr;
93  DWORD dwMaxLength = 0;
94  DWORD dwCurrentLength = 0;
95 
96  CHECK_HR(hr = spUnknown->QueryInterface(IID_PPV_ARGS(&spMetadata)));
97  CHECK_HR(hr = spMetadata->GetUnknown(MF_CAPTURE_METADATA_FRAME_RAWSTREAM, IID_PPV_ARGS(&spBuffer)));
98  CHECK_HR(hr = spBuffer->Lock((BYTE**)&pMetadata, &dwMaxLength, &dwCurrentLength));
99 
100  if (nullptr == pMetadata) // Bail, no data.
101  return false;
102 
103  if (pMetadata->MetadataId != MetadataId_UsbVideoHeader) // Wrong metadata type, bail.
104  return false;
105 
106  // Microsoft converts the standard UVC (12-byte) header into MS proprietary 40-bytes struct
107  // Therefore we revert it to the original structure for uniform handling
108  static const uint8_t md_lenth_max = 0xff;
109  auto md_raw = reinterpret_cast<byte*>(pMetadata);
110  ms_metadata_header *ms_hdr = reinterpret_cast<ms_metadata_header*>(md_raw);
111  uvc_header *uvc_hdr = reinterpret_cast<uvc_header*>(md_raw + ms_header_size - uvc_header_size);
112  try
113  { // restore the original timestamp and source clock fields
114  memcpy(&(uvc_hdr->timestamp), &ms_hdr->ms_blobs[0], 10);
115  }
116  catch (...)
117  {
118  return false;
119  }
120 
121  // Metadata for Bulk endpoints is limited to 255 bytes by design
122  auto payload_length = ms_hdr->ms_header.Size - ms_header_size;
123  if ((int)payload_length > (md_lenth_max - uvc_header_size))
124  {
125  LOG_WARNING("Invalid metadata payload, length"
126  << payload_length << ", expected [0-" << int(md_lenth_max - uvc_header_size) << "]");
127  return false;
128  }
129  uvc_hdr->length = static_cast<uint8_t>(payload_length);
130  uvc_hdr->info = 0x0; // TODO - currently not available
131  metadata_size = static_cast<uint8_t>(uvc_hdr->length + uvc_header_size);
132 
133  *bytes = (byte*)uvc_hdr;
134 
135  return true;
136  }
137  else
138  return false;
139  }
140 #endif // METADATA_SUPPORT
141 
142  STDMETHODIMP source_reader_callback::QueryInterface(REFIID iid, void** ppv)
143  {
144 #pragma warning( push )
145 #pragma warning(disable : 4838)
146  static const QITAB qit[] =
147  {
148  QITABENT(source_reader_callback, IMFSourceReaderCallback),
149  { nullptr },
150  };
151  return QISearch(this, qit, iid, ppv);
152 #pragma warning( pop )
153  };
154 
155  STDMETHODIMP_(ULONG) source_reader_callback::AddRef() { return InterlockedIncrement(&_refCount); }
156 
157  STDMETHODIMP_(ULONG) source_reader_callback::Release() {
158  ULONG count = InterlockedDecrement(&_refCount);
159  if (count <= 0)
160  {
161  delete this;
162  }
163  return count;
164  }
165 
166 
167  STDMETHODIMP source_reader_callback::OnReadSample(HRESULT hrStatus,
168  DWORD dwStreamIndex,
169  DWORD dwStreamFlags,
170  LONGLONG llTimestamp,
171  IMFSample *sample)
172  {
173  auto owner = _owner.lock();
174  if (owner && owner->_reader)
175  {
176  if (FAILED(hrStatus))
177  {
178  owner->_readsample_result = hrStatus;
179  if (dwStreamFlags == MF_SOURCE_READERF_ERROR)
180  {
181  owner->close_all();
182  return S_OK;
183  }
184  }
185  owner->_has_started.set();
186 
187  LOG_HR(owner->_reader->ReadSample(dwStreamIndex, 0, nullptr, nullptr, nullptr, nullptr));
188 
189  if (!owner->_is_started)
190  return S_OK;
191 
192  if (sample)
193  {
194  CComPtr<IMFMediaBuffer> buffer = nullptr;
195  if (SUCCEEDED(sample->GetBufferByIndex(0, &buffer)))
196  {
197  byte* byte_buffer=nullptr;
198  DWORD max_length{}, current_length{};
199  if (SUCCEEDED(buffer->Lock(&byte_buffer, &max_length, &current_length)))
200  {
201  byte* metadata = nullptr;
202  uint8_t metadata_size = 0;
203 #ifdef METADATA_SUPPORT
204  try_read_metadata(sample, metadata_size, &metadata);
205 #endif
206  try
207  {
208  auto& stream = owner->_streams[dwStreamIndex];
209  std::lock_guard<std::mutex> lock(owner->_streams_mutex);
210  auto profile = stream.profile;
211  frame_object f{ current_length, metadata_size, byte_buffer, metadata, monotonic_to_realtime(llTimestamp/10000.f) };
212 
213  auto continuation = [buffer, this]()
214  {
215  buffer->Unlock();
216  };
217 
218  stream.callback(profile, f, continuation);
219  }
220  catch (...)
221  {
222  // TODO: log
223  }
224  }
225  }
226  }
227  }
228 
229  return S_OK;
230  };
231  STDMETHODIMP source_reader_callback::OnEvent(DWORD /*sidx*/, IMFMediaEvent* /*event*/) { return S_OK; }
233  {
234  auto owner = _owner.lock();
235  if (owner)
236  {
237  owner->_is_flushed.set();
238  }
239  return S_OK;
240  }
241 
243  {
244  auto result = false;
245  foreach_uvc_device([&result, &info](const uvc_device_info& i, IMFActivate*)
246  {
247  if (i == info) result = true;
248  });
249  return result;
250  }
251 
252  IKsControl* wmf_uvc_device::get_ks_control(const extension_unit & xu) const
253  {
254  auto it = _ks_controls.find(xu.node);
255  if (it != std::end(_ks_controls)) return it->second;
256  throw std::runtime_error("Extension control must be initialized before use!");
257  }
258 
260  {
261  if (!_source)
262  throw std::runtime_error("Could not initialize extensions controls!");
263 
264  // Attempt to retrieve IKsControl
265  CComPtr<IKsTopologyInfo> ks_topology_info = nullptr;
266  CHECK_HR(_source->QueryInterface(__uuidof(IKsTopologyInfo),
267  reinterpret_cast<void **>(&ks_topology_info)));
268 
269  DWORD nNodes=0;
270  check("get_NumNodes", ks_topology_info->get_NumNodes(&nNodes));
271 
272  CComPtr<IUnknown> unknown = nullptr;
273  CHECK_HR(ks_topology_info->CreateNodeInstance(xu.node, IID_IUnknown,
274  reinterpret_cast<LPVOID *>(&unknown)));
275 
276  CComPtr<IKsControl> ks_control = nullptr;
277  CHECK_HR(unknown->QueryInterface(__uuidof(IKsControl),
278  reinterpret_cast<void **>(&ks_control)));
279  _ks_controls[xu.node] = ks_control;
280  }
281 
282  bool wmf_uvc_device::set_xu(const extension_unit& xu, uint8_t ctrl, const uint8_t* data, int len)
283  {
284  auto ks_control = get_ks_control(xu);
285 
286  KSP_NODE node;
287  memset(&node, 0, sizeof(KSP_NODE));
288  node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
289  node.Property.Id = ctrl;
290  node.Property.Flags = KSPROPERTY_TYPE_SET | KSPROPERTY_TYPE_TOPOLOGY;
291  node.NodeId = xu.node;
292 
293  ULONG bytes_received = 0;
294  auto hr = ks_control->KsProperty(reinterpret_cast<PKSPROPERTY>(&node),
295  sizeof(KSP_NODE), (void*)data, len, &bytes_received);
296 
297  if (hr == DEVICE_NOT_READY_ERROR)
298  return false;
299 
300  CHECK_HR(hr);
301  return true;
302  }
303 
304  bool wmf_uvc_device::get_xu(const extension_unit& xu, uint8_t ctrl, uint8_t* data, int len) const
305  {
306  auto ks_control = get_ks_control(xu);
307 
308  KSP_NODE node;
309  memset(&node, 0, sizeof(KSP_NODE));
310  node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
311  node.Property.Id = ctrl;
312  node.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
313  node.NodeId = xu.node;
314 
315  ULONG bytes_received = 0;
316  auto hr = ks_control->KsProperty(reinterpret_cast<PKSPROPERTY>(&node),
317  sizeof(node), data, len, &bytes_received);
318 
319  if (hr == DEVICE_NOT_READY_ERROR)
320  return false;
321  CHECK_HR( hr );
322 
323  if (bytes_received != len)
324  throw std::runtime_error(to_string() << "Get XU n:" << (int)ctrl << " received " << bytes_received << "/" << len << " bytes");
325 
326  return true;
327  }
328 
330  {
331  BYTE* next_struct = buffer;
332 
333  PKSPROPERTY_DESCRIPTION pDesc = reinterpret_cast<PKSPROPERTY_DESCRIPTION>(next_struct);
334  next_struct += sizeof(KSPROPERTY_DESCRIPTION);
335 
336  if (pDesc->MembersListCount < 1)
337  throw std::exception("no data ksprop");
338 
339  PKSPROPERTY_MEMBERSHEADER pHeader = reinterpret_cast<PKSPROPERTY_MEMBERSHEADER>(next_struct);
340  next_struct += sizeof(KSPROPERTY_MEMBERSHEADER);
341 
342  if (pHeader->MembersCount < 1)
343  throw std::exception("no data ksprop");
344 
345  // The data fields are up to four bytes
346  auto field_width = std::min(sizeof(uint32_t), (size_t)length);
347  auto option_range_size = std::max(sizeof(uint32_t), (size_t)length);
348  switch (pHeader->MembersFlags)
349  {
350  /* member flag is not set correctly in current IvCam Implementation */
351  case KSPROPERTY_MEMBER_RANGES:
352  case KSPROPERTY_MEMBER_STEPPEDRANGES:
353  {
354  if (pDesc->DescriptionSize < sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + 3 * sizeof(UCHAR))
355  {
356  throw std::exception("no data ksprop");
357  }
358 
359  auto pStruct = next_struct;
360  cfg.step.resize(option_range_size);
361  librealsense::copy(cfg.step.data(), pStruct, field_width);
362  pStruct += length;
363  cfg.min.resize(option_range_size);
364  librealsense::copy(cfg.min.data(), pStruct, field_width);
365  pStruct += length;
366  cfg.max.resize(option_range_size);
367  librealsense::copy(cfg.max.data(), pStruct, field_width);
368  return;
369  }
370  case KSPROPERTY_MEMBER_VALUES:
371  {
372  /*
373  * we don't yet support reading a list of values, only min-max.
374  * so we only support reading default value from a list
375  */
376 
377  if (pHeader->Flags == KSPROPERTY_MEMBER_FLAG_DEFAULT && pHeader->MembersCount == 1)
378  {
379  if (pDesc->DescriptionSize < sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(UCHAR))
380  {
381  throw std::exception("no data ksprop");
382  }
383 
384  cfg.def.resize(option_range_size);
385  librealsense::copy(cfg.def.data(), next_struct, field_width);
386  }
387  return;
388  }
389  default:
390  throw std::exception("unsupported");
391  }
392  }
393 
395  {
396  auto ks_control = get_ks_control(xu);
397 
398  /* get step, min and max values*/
399  KSP_NODE node;
400  memset(&node, 0, sizeof(KSP_NODE));
401  node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
402  node.Property.Id = ctrl;
403  node.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY;
404  node.NodeId = xu.node;
405 
406  KSPROPERTY_DESCRIPTION description;
407  unsigned long bytes_received = 0;
408  CHECK_HR(ks_control->KsProperty(
409  reinterpret_cast<PKSPROPERTY>(&node),
410  sizeof(node),
411  &description,
412  sizeof(KSPROPERTY_DESCRIPTION),
413  &bytes_received));
414 
415  auto size = description.DescriptionSize;
416  std::vector<BYTE> buffer(static_cast<long>(size));
417 
418  CHECK_HR(ks_control->KsProperty(
419  reinterpret_cast<PKSPROPERTY>(&node),
420  sizeof(node),
421  buffer.data(),
422  size,
423  &bytes_received));
424 
425  if (bytes_received != size) { throw std::runtime_error("wrong data"); }
426 
428  ReadFromBuffer(result, buffer.data(), len);
429 
430  /* get def value*/
431  memset(&node, 0, sizeof(KSP_NODE));
432  node.Property.Set = reinterpret_cast<const GUID &>(xu.id);
433  node.Property.Id = ctrl;
434  node.Property.Flags = KSPROPERTY_TYPE_DEFAULTVALUES | KSPROPERTY_TYPE_TOPOLOGY;
435  node.NodeId = xu.node;
436 
437  bytes_received = 0;
438  CHECK_HR(ks_control->KsProperty(
439  reinterpret_cast<PKSPROPERTY>(&node),
440  sizeof(node),
441  &description,
442  sizeof(KSPROPERTY_DESCRIPTION),
443  &bytes_received));
444 
445  size = description.DescriptionSize;
446  buffer.clear();
447  buffer.resize(size);
448 
449  CHECK_HR(ks_control->KsProperty(
450  reinterpret_cast<PKSPROPERTY>(&node),
451  sizeof(node),
452  buffer.data(),
453  size,
454  &bytes_received));
455 
456  if (bytes_received != size) { throw std::runtime_error("wrong data"); }
457 
458  ReadFromBuffer(result, buffer.data(), len);
459 
460  return result;
461  }
462 
463  struct pu_control { rs2_option option; long property; bool enable_auto; };
464  static const pu_control pu_controls[] = {
465  { RS2_OPTION_BRIGHTNESS, KSPROPERTY_VIDEOPROCAMP_BRIGHTNESS },
466  { RS2_OPTION_CONTRAST, KSPROPERTY_VIDEOPROCAMP_CONTRAST },
467  { RS2_OPTION_HUE, KSPROPERTY_VIDEOPROCAMP_HUE },
468  { RS2_OPTION_SATURATION, KSPROPERTY_VIDEOPROCAMP_SATURATION },
469  { RS2_OPTION_SHARPNESS, KSPROPERTY_VIDEOPROCAMP_SHARPNESS },
470  { RS2_OPTION_GAMMA, KSPROPERTY_VIDEOPROCAMP_GAMMA },
471  { RS2_OPTION_WHITE_BALANCE, KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE },
472  { RS2_OPTION_ENABLE_AUTO_WHITE_BALANCE, KSPROPERTY_VIDEOPROCAMP_WHITEBALANCE, true },
473  { RS2_OPTION_BACKLIGHT_COMPENSATION, KSPROPERTY_VIDEOPROCAMP_BACKLIGHT_COMPENSATION },
474  { RS2_OPTION_GAIN, KSPROPERTY_VIDEOPROCAMP_GAIN },
475  { RS2_OPTION_POWER_LINE_FREQUENCY, KSPROPERTY_VIDEOPROCAMP_POWERLINE_FREQUENCY }
476  };
477 
478  // Camera Terminal controls will be handled with PU option transport and handling mechanism
479  static const pu_control ct_controls[] = {
480  { RS2_OPTION_AUTO_EXPOSURE_PRIORITY, KSPROPERTY_CAMERACONTROL_AUTO_EXPOSURE_PRIORITY },
481  };
482 
483  long to_100micros(long v)
484  {
485  double res = pow(2.0, v);
486  return static_cast<long>(res * 10000);
487  }
488 
489  long from_100micros(long val)
490  {
491  double d = val * 0.0001;
492  double l = (d != 0) ? std::log2(d) : 1;
493  long v = static_cast<long>(std::roundl(l));
494  // Exposure values use logarithmic scale and can reach -13 with D400
495  assert(v <= 0 && v >= -15);
496  return v;
497  }
498 
500  {
501  long val = 0, flags = 0;
502  if ((opt == RS2_OPTION_EXPOSURE) || (opt == RS2_OPTION_ENABLE_AUTO_EXPOSURE))
503  {
504  auto hr = get_camera_control()->Get(CameraControl_Exposure, &val, &flags);
505  if (hr == DEVICE_NOT_READY_ERROR)
506  return false;
507 
508  value = (opt == RS2_OPTION_EXPOSURE) ? to_100micros(val) : (flags == CameraControl_Flags_Auto);
509  CHECK_HR(hr);
510  return true;
511  }
512 
513  for (auto & pu : pu_controls)
514  {
515  if (opt == pu.option)
516  {
517  auto hr = get_video_proc()->Get(pu.property, &val, &flags);
518  if (hr == DEVICE_NOT_READY_ERROR)
519  return false;
520 
521  value = (pu.enable_auto) ? (flags == VideoProcAmp_Flags_Auto) : val;
522 
523  CHECK_HR(hr);
524  return true;
525  }
526  }
527 
528  for (auto & ct : ct_controls)
529  {
530  if (opt == ct.option)
531  {
532  auto hr = get_camera_control()->Get(ct.property, &val, &flags);
533  if (hr == DEVICE_NOT_READY_ERROR)
534  return false;
535 
536  value = val;
537 
538  CHECK_HR(hr);
539  return true;
540  }
541  }
542 
543  throw std::runtime_error(to_string() << "Unsupported control - " << opt);
544  }
545 
547  {
548  if (opt == RS2_OPTION_EXPOSURE)
549  {
550  auto hr = get_camera_control()->Set(CameraControl_Exposure, from_100micros(value), CameraControl_Flags_Manual);
551  if (hr == DEVICE_NOT_READY_ERROR)
552  return false;
553 
554  CHECK_HR(hr);
555  return true;
556  }
558  {
559  if (value)
560  {
561  auto hr = get_camera_control()->Set(CameraControl_Exposure, 0, CameraControl_Flags_Auto);
562  if (hr == DEVICE_NOT_READY_ERROR)
563  return false;
564 
565  CHECK_HR(hr);
566  }
567  else
568  {
569  long min, max, step, def, caps;
570  auto hr = get_camera_control()->GetRange(CameraControl_Exposure, &min, &max, &step, &def, &caps);
571  if (hr == DEVICE_NOT_READY_ERROR)
572  return false;
573 
574  CHECK_HR(hr);
575 
576  hr = get_camera_control()->Set(CameraControl_Exposure, def, CameraControl_Flags_Manual);
577  if (hr == DEVICE_NOT_READY_ERROR)
578  return false;
579 
580  CHECK_HR(hr);
581  }
582  return true;
583  }
584 
585 
586  for (auto & pu : pu_controls)
587  {
588  if (opt == pu.option)
589  {
590  if (pu.enable_auto)
591  {
592  if (value)
593  {
594  auto hr = get_video_proc()->Set(pu.property, 0, VideoProcAmp_Flags_Auto);
595  if (hr == DEVICE_NOT_READY_ERROR)
596  return false;
597 
598  CHECK_HR(hr);
599  }
600  else
601  {
602  long min, max, step, def, caps;
603  auto hr = get_video_proc()->GetRange(pu.property, &min, &max, &step, &def, &caps);
604  if (hr == DEVICE_NOT_READY_ERROR)
605  return false;
606 
607  CHECK_HR(hr);
608 
609  hr = get_video_proc()->Set(pu.property, def, VideoProcAmp_Flags_Manual);
610  if (hr == DEVICE_NOT_READY_ERROR)
611  return false;
612 
613  CHECK_HR(hr);
614  }
615  }
616  else
617  {
618  auto hr = get_video_proc()->Set(pu.property, value, VideoProcAmp_Flags_Manual);
619  if (hr == DEVICE_NOT_READY_ERROR)
620  return false;
621 
622  CHECK_HR(hr);
623  }
624  return true;
625  }
626  }
627  for (auto & ct : ct_controls)
628  {
629  if (opt == ct.option)
630  {
631  if (ct.enable_auto)
632  {
633  if (value)
634  {
635  auto hr = get_camera_control()->Set(ct.property, 0, CameraControl_Flags_Auto);
636  if (hr == DEVICE_NOT_READY_ERROR)
637  return false;
638 
639  CHECK_HR(hr);
640  }
641  else
642  {
643  long min, max, step, def, caps;
644  auto hr = get_camera_control()->GetRange(ct.property, &min, &max, &step, &def, &caps);
645  if (hr == DEVICE_NOT_READY_ERROR)
646  return false;
647 
648  CHECK_HR(hr);
649 
650  hr = get_camera_control()->Set(ct.property, def, CameraControl_Flags_Manual);
651  if (hr == DEVICE_NOT_READY_ERROR)
652  return false;
653 
654  CHECK_HR(hr);
655  }
656  }
657  else
658  {
659  auto hr = get_camera_control()->Set(ct.property, value, CameraControl_Flags_Manual);
660  if (hr == DEVICE_NOT_READY_ERROR)
661  return false;
662 
663  CHECK_HR(hr);
664  }
665  return true;
666  }
667  }
668  throw std::runtime_error(to_string() << "Unsupported control - " << opt);
669  }
670 
672  {
673  if (opt == RS2_OPTION_ENABLE_AUTO_EXPOSURE ||
675  {
676  static const int32_t min = 0, max = 1, step = 1, def = 1;
677  control_range result(min, max, step, def);
678  return result;
679  }
680 
681  long minVal = 0, maxVal = 0, steppingDelta = 0, defVal = 0, capsFlag = 0;
682  if (opt == RS2_OPTION_EXPOSURE)
683  {
684  CHECK_HR(get_camera_control()->GetRange(CameraControl_Exposure, &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
685  long min = to_100micros(minVal), max = to_100micros(maxVal), def = to_100micros(defVal);
686  control_range result(min, max, min, def);
687  return result;
688  }
689  for (auto & pu : pu_controls)
690  {
691  if (opt == pu.option)
692  {
693  CHECK_HR(get_video_proc()->GetRange(pu.property, &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
694  control_range result(minVal, maxVal, steppingDelta, defVal);
695  return result;
696  }
697  }
698  for (auto & ct : ct_controls)
699  {
700  if (opt == ct.option)
701  {
702  CHECK_HR(get_camera_control()->GetRange(ct.property, &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
703  control_range result(minVal, maxVal, steppingDelta, defVal);
704  return result;
705  }
706  }
707  throw std::runtime_error("unsupported control");
708  }
709 
711  {
712  for (auto attributes_params_set : attributes_params)
713  {
714  CComPtr<IMFAttributes> pAttributes = nullptr;
715  CHECK_HR(MFCreateAttributes(&pAttributes, 1));
716  for (auto attribute_params : attributes_params_set)
717  {
718  CHECK_HR(pAttributes->SetGUID(attribute_params.first, attribute_params.second));
719  }
720 
721  IMFActivate ** ppDevices;
722  UINT32 numDevices;
723  CHECK_HR(MFEnumDeviceSources(pAttributes, &ppDevices, &numDevices));
724 
725  for (UINT32 i = 0; i < numDevices; ++i)
726  {
727  CComPtr<IMFActivate> pDevice;
728  *&pDevice = ppDevices[i];
729 
730  WCHAR * wchar_name = nullptr; UINT32 length;
731  CHECK_HR(pDevice->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &wchar_name, &length));
732  auto name = win_to_utf(wchar_name);
733  CoTaskMemFree(wchar_name);
734 
735  uint16_t vid, pid, mi; std::string unique_id, guid;
736  if (!parse_usb_path_multiple_interface(vid, pid, mi, unique_id, name, guid)) continue;
737 
739  info.vid = vid;
740  info.pid = pid;
741  info.unique_id = unique_id;
742  info.mi = mi;
743  info.device_path = name;
744  try
745  {
746  action(info, ppDevices[i]);
747  }
748  catch (...)
749  {
750  // TODO
751  }
752  }
753  safe_release(pAttributes);
754  CoTaskMemFree(ppDevices);
755  }
756  }
757 
759  {
760  if (state == _power_state)
761  return;
762 
763  switch (state)
764  {
765  case D0: set_d0(); break;
766  case D3: set_d3(); break;
767  default:
768  throw std::runtime_error("illegal power state request");
769  }
770  }
771 
773  std::shared_ptr<const wmf_backend> backend)
774  : _streamIndex(MAX_PINS), _info(info), _is_flushed(), _has_started(), _backend(std::move(backend)),
775  _systemwide_lock(info.unique_id.c_str(), WAIT_FOR_MUTEX_TIME_OUT),
776  _location(""), _device_usb_spec(usb3_type)
777  {
778  if (!is_connected(info))
779  {
780  throw std::runtime_error("Camera not connected!");
781  }
782  try
783  {
785  {
786  LOG_WARNING("Could not retrieve USB descriptor for device " << std::hex << info.vid << ":"
787  << info.pid << " , id:" << info.unique_id << std::dec);
788  }
789  }
790  catch (...)
791  {
792  LOG_WARNING("Accessing USB info failed for " << std::hex << info.vid << ":"
793  << info.pid << " , id:" << info.unique_id << std::dec);
794  }
795  foreach_uvc_device([this](const uvc_device_info& i, IMFActivate* device)
796  {
797  if (i == _info && device)
798  {
800  CHECK_HR(device->GetString(did_guid, const_cast<LPWSTR>(_device_id.c_str()), UINT32(_device_id.size()), nullptr));
801  }
802  });
803  }
804 
806  {
807  try {
808  if (_streaming)
809  {
810  flush(MF_SOURCE_READER_ALL_STREAMS);
811  }
812 
814 
817  for (auto&& c : _ks_controls)
818  safe_release(c.second);
819  _ks_controls.clear();
820  }
821  catch (...)
822  {
823  LOG_WARNING("Exception thrown while flushing MF source");
824  }
825  }
826 
827  CComPtr<IMFAttributes> wmf_uvc_device::create_device_attrs()
828  {
829  CComPtr<IMFAttributes> device_attrs = nullptr;
830 
831  CHECK_HR(MFCreateAttributes(&device_attrs, 2));
832  CHECK_HR(device_attrs->SetGUID(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE, type_guid));
833  CHECK_HR(device_attrs->SetString(did_guid, _device_id.c_str()));
834  return device_attrs;
835  }
836 
837  CComPtr<IMFAttributes> wmf_uvc_device::create_reader_attrs()
838  {
839  CComPtr<IMFAttributes> reader_attrs = nullptr;
840 
841  CHECK_HR(MFCreateAttributes(&reader_attrs, 3));
842  CHECK_HR(reader_attrs->SetUINT32(MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN, FALSE));
843  CHECK_HR(reader_attrs->SetUINT32(MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, TRUE));
844  CHECK_HR(reader_attrs->SetUnknown(MF_SOURCE_READER_ASYNC_CALLBACK,
845  static_cast<IUnknown*>(new source_reader_callback(shared_from_this()))));
846  return reader_attrs;
847  }
848 
850  {
851  if (!_device_attrs)
853 
854  if (!_reader_attrs)
856  _streams.resize(_streamIndex);
857 
858  //enable source
859  CHECK_HR(MFCreateDeviceSource(_device_attrs, &_source));
860  LOG_HR(_source->QueryInterface(__uuidof(IAMCameraControl), reinterpret_cast<void **>(&_camera_control)));
861  LOG_HR(_source->QueryInterface(__uuidof(IAMVideoProcAmp), reinterpret_cast<void **>(&_video_proc)));
862 
863  //enable reader
864  CHECK_HR(MFCreateSourceReaderFromMediaSource(_source, _reader_attrs, &_reader));
865  CHECK_HR(_reader->SetStreamSelection(static_cast<DWORD>(MF_SOURCE_READER_ALL_STREAMS), TRUE));
866  _power_state = D0;
867  }
868 
870  {
874  _source->Shutdown(); //Failure to call Shutdown can result in memory leak
876  for (auto& elem : _streams)
877  elem.callback = nullptr;
878  _power_state = D3;
879  }
880 
881  void wmf_uvc_device::foreach_profile(std::function<void(const mf_profile& profile, CComPtr<IMFMediaType> media_type, bool& quit)> action) const
882  {
883  bool quit = false;
884  CComPtr<IMFMediaType> pMediaType = nullptr;
885  for (unsigned int sIndex = 0; sIndex < _streams.size(); ++sIndex)
886  {
887  for (auto k = 0;; k++)
888  {
889  auto hr = _reader->GetNativeMediaType(sIndex, k, &pMediaType.p);
890  if (FAILED(hr) || pMediaType == nullptr)
891  {
892  safe_release(pMediaType);
893  if (hr != MF_E_NO_MORE_TYPES) // An object ran out of media types to suggest therefore the requested chain of streaming objects cannot be completed
894  check("_reader->GetNativeMediaType(sIndex, k, &pMediaType.p)", hr, false);
895 
896  break;
897  }
898 
899  GUID subtype;
900  CHECK_HR(pMediaType->GetGUID(MF_MT_SUBTYPE, &subtype));
901 
902  unsigned width = 0;
903  unsigned height = 0;
904 
905  CHECK_HR(MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &width, &height));
906 
907  frame_rate frameRateMin;
908  frame_rate frameRateMax;
909 
910  CHECK_HR(MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE_RANGE_MIN, &frameRateMin.numerator, &frameRateMin.denominator));
911  CHECK_HR(MFGetAttributeRatio(pMediaType, MF_MT_FRAME_RATE_RANGE_MAX, &frameRateMax.numerator, &frameRateMax.denominator));
912 
913  if (static_cast<float>(frameRateMax.numerator) / frameRateMax.denominator <
914  static_cast<float>(frameRateMin.numerator) / frameRateMin.denominator)
915  {
916  std::swap(frameRateMax, frameRateMin);
917  }
918  int currFps = frameRateMax.numerator / frameRateMax.denominator;
919 
920  uint32_t device_fourcc = reinterpret_cast<const big_endian<uint32_t> &>(subtype.Data1);
921  if (fourcc_map.count(device_fourcc))
922  device_fourcc = fourcc_map.at(device_fourcc);
923 
924  stream_profile sp;
925  sp.width = width;
926  sp.height = height;
927  sp.fps = currFps;
928  sp.format = device_fourcc;
929 
930  mf_profile mfp;
931  mfp.index = sIndex;
932  mfp.min_rate = frameRateMin;
933  mfp.max_rate = frameRateMax;
934  mfp.profile = sp;
935 
936  action(mfp, pMediaType, quit);
937 
938  safe_release(pMediaType);
939 
940  if (quit)
941  return;
942  }
943  }
944  }
945 
946  std::vector<stream_profile> wmf_uvc_device::get_profiles() const
947  {
949 
950  if (get_power_state() != D0)
951  throw std::runtime_error("Device must be powered to query supported profiles!");
952 
953  std::vector<stream_profile> results;
954  foreach_profile([&results](const mf_profile& mfp, CComPtr<IMFMediaType> media_type, bool& quit)
955  {
956  results.push_back(mfp.profile);
957  });
958 
959  return results;
960  }
961 
963  {
964  bool profile_found = false;
965  foreach_profile([this, profile, callback, &profile_found](const mf_profile& mfp, CComPtr<IMFMediaType> media_type, bool& quit)
966  {
967  if (mfp.profile.format != profile.format &&
968  (fourcc_map.count(mfp.profile.format) == 0 ||
969  profile.format != fourcc_map.at(mfp.profile.format)))
970  return;
971 
972  if ((mfp.profile.width == profile.width) && (mfp.profile.height == profile.height))
973  {
974  if (mfp.max_rate.denominator && mfp.min_rate.denominator)
975  {
976  if (mfp.profile.fps == int(profile.fps))
977  {
978  auto hr = _reader->SetCurrentMediaType(mfp.index, nullptr, media_type);
979  if (SUCCEEDED(hr) && media_type)
980  {
981  for (unsigned int i = 0; i < _streams.size(); ++i)
982  {
983  if (mfp.index == i || (_streams[i].callback))
984  continue;
985 
986  _reader->SetStreamSelection(i, FALSE);
987  }
988 
989  CHECK_HR(_reader->SetStreamSelection(mfp.index, TRUE));
990 
991  {
992  std::lock_guard<std::mutex> lock(_streams_mutex);
993  if (_streams[mfp.index].callback)
994  throw std::runtime_error("Camera already streaming via this stream index!");
995 
996  _streams[mfp.index].profile = profile;
997  _streams[mfp.index].callback = callback;
998  }
999 
1000  _readsample_result = S_OK;
1001  CHECK_HR(_reader->ReadSample(mfp.index, 0, nullptr, nullptr, nullptr, nullptr));
1002 
1003  const auto timeout_ms = RS2_DEFAULT_TIMEOUT;
1004  if (_has_started.wait(timeout_ms))
1005  {
1006  check("_reader->ReadSample(...)", _readsample_result);
1007  }
1008  else
1009  {
1010  LOG_WARNING("First frame took more then " << timeout_ms << "ms to arrive!");
1011  }
1012  profile_found = true;
1013  quit = true;
1014  return;
1015  }
1016  else
1017  {
1018  throw std::runtime_error("Could not set Media Type. Device may be locked");
1019  }
1020  }
1021  }
1022  }
1023  });
1024  if (!profile_found)
1025  throw std::runtime_error("Stream profile not found!");
1026  }
1027 
1029  {
1030  if (_streaming)
1031  throw std::runtime_error("Device is already streaming!");
1032 
1033  _profiles.push_back(profile);
1034  _frame_callbacks.push_back(callback);
1035  }
1036 
1037  IAMVideoProcAmp* wmf_uvc_device::get_video_proc() const
1038  {
1039  if (get_power_state() != D0)
1040  throw std::runtime_error("Device must be powered to query video_proc!");
1041  if (!_video_proc.p)
1042  throw std::runtime_error("The device does not support adjusting the qualities of an incoming video signal, such as brightness, contrast, hue, saturation, gamma, and sharpness.");
1043  return _video_proc.p;
1044  }
1045 
1046  IAMCameraControl* wmf_uvc_device::get_camera_control() const
1047  {
1048  if (get_power_state() != D0)
1049  throw std::runtime_error("Device must be powered to query camera_control!");
1050  if (!_camera_control.p)
1051  throw std::runtime_error("The device does not support camera settings such as zoom, pan, aperture adjustment, or shutter speed.");
1052  return _camera_control.p;
1053  }
1054 
1055  void wmf_uvc_device::stream_on(std::function<void(const notification& n)> error_handler)
1056  {
1057  if (_profiles.empty())
1058  throw std::runtime_error("Stream not configured");
1059 
1060  if (_streaming)
1061  throw std::runtime_error("Device is already streaming!");
1062 
1063  check_connection();
1064 
1065  try
1066  {
1067  for (uint32_t i = 0; i < _profiles.size(); ++i)
1068  {
1070  }
1071 
1072  _streaming = true;
1073  }
1074  catch (...)
1075  {
1076  close_all();
1077 
1078  throw;
1079  }
1080  }
1081 
1083  {
1084  _is_started = true;
1085  }
1086 
1088  {
1089  _is_started = false;
1090  }
1091 
1092  void wmf_uvc_device::stop_stream_cleanup(const stream_profile& profile, std::vector<profile_and_callback>::iterator& elem)
1093  {
1094  if (elem != _streams.end())
1095  {
1096  elem->callback = nullptr;
1097  elem->profile.format = 0;
1098  elem->profile.fps = 0;
1099  elem->profile.width = 0;
1100  elem->profile.height = 0;
1101  }
1102 
1103  auto pos = std::find(_profiles.begin(), _profiles.end(), profile) - _profiles.begin();
1104  if (pos != _profiles.size())
1105  {
1106  _profiles.erase(_profiles.begin() + pos);
1107  _frame_callbacks.erase(_frame_callbacks.begin() + pos);
1108  }
1109 
1110  if (_profiles.empty())
1111  _streaming = false;
1112 
1113  _has_started.reset();
1114  }
1115 
1117  {
1118  _is_started = false;
1119 
1120  check_connection();
1121 
1122  auto& elem = std::find_if(_streams.begin(), _streams.end(),
1123  [&](const profile_and_callback& pac) {
1124  return (pac.profile == profile && (pac.callback));
1125  });
1126 
1127  if (elem == _streams.end() && _frame_callbacks.empty())
1128  throw std::runtime_error("Camera is not streaming!");
1129 
1130  if (elem != _streams.end())
1131  {
1132  try {
1133  flush(int(elem - _streams.begin()));
1134  }
1135  catch (...)
1136  {
1137  stop_stream_cleanup(profile, elem); // TODO: move to RAII
1138  throw;
1139  }
1140  }
1141  stop_stream_cleanup(profile, elem);
1142  }
1143 
1144  // ReSharper disable once CppMemberFunctionMayBeConst
1145  void wmf_uvc_device::flush(int sIndex)
1146  {
1147  if (is_connected(_info))
1148  {
1149  if (_reader != nullptr)
1150  {
1151  auto sts = _reader->Flush(sIndex);
1152  if (sts != S_OK)
1153  {
1154  if (sts == MF_E_HW_MFT_FAILED_START_STREAMING)
1155  throw std::runtime_error("Camera already streaming");
1156 
1157  throw std::runtime_error(to_string() << "Flush failed" << sts);
1158  }
1159 
1160  _is_flushed.wait(INFINITE);
1161  }
1162  }
1163  }
1164 
1166  {
1167  if (!is_connected(_info))
1168  throw std::runtime_error("Camera is no longer connected!");
1169  }
1170 
1172  {
1173  for (auto& elem : _streams)
1174  if (elem.callback)
1175  {
1176  try
1177  {
1178  close(elem.profile);
1179  }
1180  catch (...) {}
1181  }
1182 
1183  _profiles.clear();
1184  _frame_callbacks.clear();
1185  }
1186  }
1187 }
wmf_uvc_device(const uvc_device_info &info, std::shared_ptr< const wmf_backend > backend)
Definition: mf-uvc.cpp:772
static const textual_icon lock
Definition: model-views.h:218
CComPtr< IAMVideoProcAmp > _video_proc
Definition: mf-uvc.h:135
std::vector< stream_profile > get_profiles() const override
Definition: mf-uvc.cpp:946
GLuint GLuint end
std::unordered_map< int, CComPtr< IKsControl > > _ks_controls
Definition: mf-uvc.h:136
void ReadFromBuffer(control_range &cfg, BYTE *buffer, int length)
Definition: mf-uvc.cpp:329
CComPtr< IMFAttributes > _reader_attrs
Definition: mf-uvc.h:132
GLuint const GLchar * name
std::vector< uint8_t > max
Definition: backend.h:88
#define DEVICE_ID_MAX_SIZE
Definition: mf-uvc.cpp:25
rs2_option
Defines general configuration controls. These can generally be mapped to camera UVC controls...
Definition: rs_option.h:22
bool set_xu(const extension_unit &xu, uint8_t ctrl, const uint8_t *data, int len) override
Definition: mf-uvc.cpp:282
control_range get_xu_range(const extension_unit &xu, uint8_t ctrl, int len) const override
Definition: mf-uvc.cpp:394
manual_reset_event _has_started
Definition: mf-uvc.h:139
constexpr uint8_t uvc_header_size
Definition: backend.h:165
#define LOG_WARNING(...)
Definition: src/types.h:241
GLfloat value
void stop_stream_cleanup(const stream_profile &profile, std::vector< profile_and_callback >::iterator &elem)
Definition: mf-uvc.cpp:1092
power_state get_power_state() const override
Definition: mf-uvc.h:84
#define WAIT_FOR_MUTEX_TIME_OUT
Definition: win-helpers.h:16
std::string win_to_utf(const WCHAR *s)
Definition: win-helpers.cpp:94
unsigned short uint16_t
Definition: stdint.h:79
#define CHECK_HR(x)
Definition: win-helpers.h:23
GLsizei const GLchar *const * string
d
Definition: rmse.py:171
const uvc_device_info _info
Definition: mf-uvc.h:126
GLdouble n
Definition: glext.h:1966
unsigned char uint8_t
Definition: stdint.h:78
GLenum GLfloat * buffer
void set_power_state(power_state state) override
Definition: mf-uvc.cpp:758
static const pu_control pu_controls[]
Definition: mf-uvc.cpp:464
#define LOG_HR(x)
Definition: win-helpers.h:24
GLenum GLsizei len
Definition: glext.h:3285
GLuint GLfloat * val
def info(name, value, persistent=False)
Definition: test.py:301
GLdouble f
CComPtr< IMFSourceReader > _reader
Definition: mf-uvc.h:129
unsigned char BYTE
Definition: lz4.c:145
static bool is_connected(const uvc_device_info &info)
Definition: mf-uvc.cpp:242
void stream_on(std::function< void(const notification &n)> error_handler=[](const notification &n){}) override
Definition: mf-uvc.cpp:1055
GLuint GLenum option
Definition: glext.h:5923
GLsizeiptr size
const GLubyte * c
Definition: glext.h:12690
CComPtr< IMFAttributes > create_reader_attrs()
Definition: mf-uvc.cpp:837
unsigned int uint32_t
Definition: stdint.h:80
const std::unordered_map< uint32_t, uint32_t > fourcc_map
Definition: uvc-types.h:59
static void safe_release(T &ppT)
Definition: mf-uvc.h:62
IKsControl * get_ks_control(const extension_unit &xu) const
Definition: mf-uvc.cpp:252
GLint GLsizei GLsizei height
CComPtr< IMFAttributes > _device_attrs
Definition: mf-uvc.h:131
bool set_pu(rs2_option opt, int value) override
Definition: mf-uvc.cpp:546
GLbitfield flags
def find(dir, mask)
Definition: file.py:25
def callback(frame)
Definition: t265_stereo.py:91
STDMETHODIMP_(ULONG) source_reader_callback
Definition: mf-uvc.cpp:155
CComPtr< IAMCameraControl > _camera_control
Definition: mf-uvc.h:134
void foreach_profile(std::function< void(const mf_profile &profile, CComPtr< IMFMediaType > media_type, bool &quit)> action) const
Definition: mf-uvc.cpp:881
#define RS2_DEFAULT_TIMEOUT
Definition: rs_config.h:13
bool parse_usb_path_multiple_interface(uint16_t &vid, uint16_t &pid, uint16_t &mi, std::string &unique_id, const std::string &path, std::string &device_guid)
virtual bool wait(DWORD timeout) const
#define did_guid
Definition: mf-uvc.cpp:46
void init_xu(const extension_unit &xu) override
Definition: mf-uvc.cpp:259
action
Definition: enums.py:62
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
STDMETHODIMP QueryInterface(REFIID iid, void **ppv) override
Definition: mf-uvc.cpp:142
IAMVideoProcAmp * get_video_proc() const
Definition: mf-uvc.cpp:1037
STDMETHODIMP OnEvent(DWORD, IMFMediaEvent *) override
Definition: mf-uvc.cpp:231
#define DEVICE_NOT_READY_ERROR
Definition: mf-uvc.cpp:48
std::function< void(stream_profile, frame_object, std::function< void()>)> frame_callback
Definition: backend.h:177
double monotonic_to_realtime(double monotonic)
Definition: backend.cpp:26
std::vector< frame_callback > _frame_callbacks
Definition: mf-uvc.h:151
unsigned char byte
Definition: src/types.h:52
std::vector< profile_and_callback > _streams
Definition: mf-uvc.h:143
CComPtr< IMFAttributes > create_device_attrs()
Definition: mf-uvc.cpp:827
std::vector< stream_profile > _profiles
Definition: mf-uvc.h:150
control_range get_pu_range(rs2_option opt) const override
Definition: mf-uvc.cpp:671
::realsense_legacy_msgs::metadata_< std::allocator< void > > metadata
static auto it
bool check(const char *call, HRESULT hr, bool to_throw)
Definition: win-helpers.cpp:79
int min(int a, int b)
Definition: lz4s.c:73
std::atomic< bool > _is_started
Definition: mf-uvc.h:153
bool get_xu(const extension_unit &xu, uint8_t ctrl, uint8_t *data, int len) const override
Definition: mf-uvc.cpp:304
GLint GLsizei count
bool get_pu(rs2_option opt, int32_t &value) const override
Definition: mf-uvc.cpp:499
static const FGuid GUID
std::vector< uint8_t > def
Definition: backend.h:90
#define MAX_PINS
Definition: mf-uvc.cpp:51
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
static const pu_control ct_controls[]
Definition: mf-uvc.cpp:479
float rs2_vector::* pos
std::vector< uint8_t > min
Definition: backend.h:87
#define TRUE
Definition: tinycthread.c:50
int i
GLenum GLuint GLenum GLsizei length
GLuint res
Definition: glext.h:8856
STDMETHODIMP OnFlush(DWORD) override
Definition: mf-uvc.cpp:232
signed int int32_t
Definition: stdint.h:77
IAMCameraControl * get_camera_control() const
Definition: mf-uvc.cpp:1046
void lock() const override
Definition: mf-uvc.h:99
long to_100micros(long v)
Definition: mf-uvc.cpp:483
STDMETHODIMP OnReadSample(HRESULT, DWORD dwStreamIndex, DWORD, LONGLONG, IMFSample *sample) override
Definition: mf-uvc.cpp:167
CComPtr< IMFMediaSource > _source
Definition: mf-uvc.h:130
std::vector< uint8_t > step
Definition: backend.h:89
#define FALSE
Definition: tinycthread.c:53
#define type_guid
Definition: mf-uvc.cpp:45
long from_100micros(long val)
Definition: mf-uvc.cpp:489
static void foreach_uvc_device(enumeration_callback action)
Definition: mf-uvc.cpp:710
GLuint64EXT * result
Definition: glext.h:10921
static const std::vector< std::vector< std::pair< GUID, GUID > > > attributes_params
Definition: mf-uvc.h:24
GLdouble v
Definition: parser.hpp:150
void probe_and_commit(stream_profile profile, frame_callback callback, int buffers) override
Definition: mf-uvc.cpp:1028
void play_profile(stream_profile profile, frame_callback callback)
Definition: mf-uvc.cpp:962
GLint GLsizei width
bool get_usb_descriptors(uint16_t device_vid, uint16_t device_pid, const std::string &device_uid, std::string &location, usb_spec &spec, std::string &serial)
void copy(void *dst, void const *src, size_t size)
Definition: types.cpp:836
void close(stream_profile profile) override
Definition: mf-uvc.cpp:1116
std::function< void(const uvc_device_info &, IMFActivate *)> enumeration_callback
Definition: mf-uvc.h:47
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:21