4 #if (_MSC_FULL_VER < 180031101) 5 #error At least Visual Studio 2013 Update 4 is required to compile this backend 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") 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 18 #define METADATA_SUPPORT 19 #endif // (WinSDK 8.1) 25 #define DEVICE_ID_MAX_SIZE 256 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") 45 #define type_guid MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID 46 #define did_guid MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK 48 #define DEVICE_NOT_READY_ERROR _HRESULT_TYPEDEF_(0x80070015L) 49 #define MF_E_SHUTDOWN_ERROR _HRESULT_TYPEDEF_(0xC00D3E85) 58 #ifdef METADATA_SUPPORT 61 struct ms_proprietary_md_blob
70 struct ms_metadata_header
72 KSCAMERA_METADATA_ITEMHEADER ms_header;
73 ms_proprietary_md_blob ms_blobs[2];
77 constexpr
uint8_t ms_header_size =
sizeof(ms_metadata_header);
79 bool try_read_metadata(IMFSample *pSample,
uint8_t& metadata_size,
byte** bytes)
81 CComPtr<IUnknown> spUnknown;
82 CComPtr<IMFAttributes> spSample;
85 CHECK_HR(hr = pSample->QueryInterface(IID_PPV_ARGS(&spSample)));
86 LOG_HR(hr = spSample->GetUnknown(MFSampleExtension_CaptureMetadata, IID_PPV_ARGS(&spUnknown)));
90 CComPtr<IMFAttributes> spMetadata;
91 CComPtr<IMFMediaBuffer> spBuffer;
92 PKSCAMERA_METADATA_ITEMHEADER pMetadata =
nullptr;
93 DWORD dwMaxLength = 0;
94 DWORD dwCurrentLength = 0;
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));
100 if (
nullptr == pMetadata)
103 if (pMetadata->MetadataId != MetadataId_UsbVideoHeader)
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);
114 memcpy(&(uvc_hdr->timestamp), &ms_hdr->ms_blobs[0], 10);
122 auto payload_length = ms_hdr->ms_header.Size - ms_header_size;
126 << payload_length <<
", expected [0-" <<
int(md_lenth_max -
uvc_header_size) <<
"]");
129 uvc_hdr->length =
static_cast<uint8_t>(payload_length);
133 *bytes = (
byte*)uvc_hdr;
140 #endif // METADATA_SUPPORT 144 #pragma warning( push ) 145 #pragma warning(disable : 4838) 146 static const QITAB qit[] =
151 return QISearch(
this, qit, iid, ppv);
152 #pragma warning( pop ) 158 ULONG
count = InterlockedDecrement(&_refCount);
170 LONGLONG llTimestamp,
173 auto owner = _owner.lock();
174 if (owner && owner->_reader)
176 if (FAILED(hrStatus))
178 owner->_readsample_result = hrStatus;
179 if (dwStreamFlags == MF_SOURCE_READERF_ERROR)
185 owner->_has_started.set();
187 LOG_HR(owner->_reader->ReadSample(dwStreamIndex, 0,
nullptr,
nullptr,
nullptr,
nullptr));
189 if (!owner->_is_started)
194 CComPtr<IMFMediaBuffer>
buffer =
nullptr;
195 if (SUCCEEDED(sample->GetBufferByIndex(0, &buffer)))
197 byte* byte_buffer=
nullptr;
198 DWORD max_length{}, current_length{};
199 if (SUCCEEDED(buffer->Lock(&byte_buffer, &max_length, ¤t_length)))
203 #ifdef METADATA_SUPPORT 204 try_read_metadata(sample, metadata_size, &metadata);
208 auto&
stream = owner->_streams[dwStreamIndex];
209 std::lock_guard<std::mutex>
lock(owner->_streams_mutex);
213 auto continuation = [
buffer,
this]()
234 auto owner = _owner.lock();
237 owner->_is_flushed.set();
247 if (i == info)
result =
true;
254 auto it = _ks_controls.find(xu.
node);
256 throw std::runtime_error(
"Extension control must be initialized before use!");
262 throw std::runtime_error(
"Could not initialize extensions controls!");
265 CComPtr<IKsTopologyInfo> ks_topology_info =
nullptr;
266 CHECK_HR(_source->QueryInterface(__uuidof(IKsTopologyInfo),
267 reinterpret_cast<void **>(&ks_topology_info)));
270 check(
"get_NumNodes", ks_topology_info->get_NumNodes(&nNodes));
272 CComPtr<IUnknown> unknown =
nullptr;
273 CHECK_HR(ks_topology_info->CreateNodeInstance(xu.
node, IID_IUnknown,
274 reinterpret_cast<LPVOID *>(&unknown)));
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;
284 auto ks_control = get_ks_control(xu);
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;
293 ULONG bytes_received = 0;
294 auto hr = ks_control->KsProperty(reinterpret_cast<PKSPROPERTY>(&node),
295 sizeof(KSP_NODE), (
void*)data, len, &bytes_received);
306 auto ks_control = get_ks_control(xu);
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;
315 ULONG bytes_received = 0;
316 auto hr = ks_control->KsProperty(reinterpret_cast<PKSPROPERTY>(&node),
317 sizeof(node), data, len, &bytes_received);
323 if (bytes_received != len)
324 throw std::runtime_error(
to_string() <<
"Get XU n:" << (
int)ctrl <<
" received " << bytes_received <<
"/" << len <<
" bytes");
333 PKSPROPERTY_DESCRIPTION pDesc =
reinterpret_cast<PKSPROPERTY_DESCRIPTION
>(next_struct);
334 next_struct +=
sizeof(KSPROPERTY_DESCRIPTION);
336 if (pDesc->MembersListCount < 1)
337 throw std::exception(
"no data ksprop");
339 PKSPROPERTY_MEMBERSHEADER pHeader =
reinterpret_cast<PKSPROPERTY_MEMBERSHEADER
>(next_struct);
340 next_struct +=
sizeof(KSPROPERTY_MEMBERSHEADER);
342 if (pHeader->MembersCount < 1)
343 throw std::exception(
"no data ksprop");
347 auto option_range_size = std::max(
sizeof(
uint32_t), (
size_t)length);
348 switch (pHeader->MembersFlags)
351 case KSPROPERTY_MEMBER_RANGES:
352 case KSPROPERTY_MEMBER_STEPPEDRANGES:
354 if (pDesc->DescriptionSize <
sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) + 3 *
sizeof(UCHAR))
356 throw std::exception(
"no data ksprop");
359 auto pStruct = next_struct;
360 cfg.
step.resize(option_range_size);
363 cfg.
min.resize(option_range_size);
366 cfg.
max.resize(option_range_size);
370 case KSPROPERTY_MEMBER_VALUES:
377 if (pHeader->Flags == KSPROPERTY_MEMBER_FLAG_DEFAULT && pHeader->MembersCount == 1)
379 if (pDesc->DescriptionSize <
sizeof(KSPROPERTY_DESCRIPTION) +
sizeof(KSPROPERTY_MEMBERSHEADER) +
sizeof(UCHAR))
381 throw std::exception(
"no data ksprop");
384 cfg.
def.resize(option_range_size);
390 throw std::exception(
"unsupported");
396 auto ks_control = get_ks_control(xu);
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;
406 KSPROPERTY_DESCRIPTION description;
407 unsigned long bytes_received = 0;
409 reinterpret_cast<PKSPROPERTY>(&node),
412 sizeof(KSPROPERTY_DESCRIPTION),
415 auto size = description.DescriptionSize;
416 std::vector<BYTE>
buffer(static_cast<long>(size));
419 reinterpret_cast<PKSPROPERTY>(&node),
425 if (bytes_received != size) {
throw std::runtime_error(
"wrong data"); }
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;
439 reinterpret_cast<PKSPROPERTY>(&node),
442 sizeof(KSPROPERTY_DESCRIPTION),
445 size = description.DescriptionSize;
450 reinterpret_cast<PKSPROPERTY>(&node),
456 if (bytes_received != size) {
throw std::runtime_error(
"wrong data"); }
485 double res = pow(2.0, v);
486 return static_cast<long>(res * 10000);
491 double d = val * 0.0001;
492 double l = (d != 0) ? std::log2(d) : 1;
493 long v =
static_cast<long>(std::roundl(l));
504 auto hr = get_camera_control()->Get(CameraControl_Exposure, &val, &
flags);
513 for (
auto & pu : pu_controls)
515 if (opt == pu.option)
517 auto hr = get_video_proc()->Get(pu.property, &val, &
flags);
521 value = (pu.enable_auto) ? (
flags == VideoProcAmp_Flags_Auto) :
val;
528 for (
auto & ct : ct_controls)
530 if (opt == ct.option)
532 auto hr = get_camera_control()->Get(ct.property, &val, &
flags);
543 throw std::runtime_error(
to_string() <<
"Unsupported control - " << opt);
550 auto hr = get_camera_control()->Set(CameraControl_Exposure,
from_100micros(value), CameraControl_Flags_Manual);
561 auto hr = get_camera_control()->Set(CameraControl_Exposure, 0, CameraControl_Flags_Auto);
569 long min, max, step, def, caps;
570 auto hr = get_camera_control()->GetRange(CameraControl_Exposure, &min, &max, &step, &def, &caps);
576 hr = get_camera_control()->Set(CameraControl_Exposure, def, CameraControl_Flags_Manual);
586 for (
auto & pu : pu_controls)
588 if (opt == pu.option)
594 auto hr = get_video_proc()->Set(pu.property, 0, VideoProcAmp_Flags_Auto);
602 long min, max, step, def, caps;
603 auto hr = get_video_proc()->GetRange(pu.property, &min, &max, &step, &def, &caps);
609 hr = get_video_proc()->Set(pu.property, def, VideoProcAmp_Flags_Manual);
618 auto hr = get_video_proc()->Set(pu.property, value, VideoProcAmp_Flags_Manual);
627 for (
auto & ct : ct_controls)
629 if (opt == ct.option)
635 auto hr = get_camera_control()->Set(ct.property, 0, CameraControl_Flags_Auto);
643 long min, max, step, def, caps;
644 auto hr = get_camera_control()->GetRange(ct.property, &min, &max, &step, &def, &caps);
650 hr = get_camera_control()->Set(ct.property, def, CameraControl_Flags_Manual);
659 auto hr = get_camera_control()->Set(ct.property, value, CameraControl_Flags_Manual);
668 throw std::runtime_error(
to_string() <<
"Unsupported control - " << opt);
676 static const int32_t min = 0, max = 1, step = 1, def = 1;
681 long minVal = 0, maxVal = 0, steppingDelta = 0, defVal = 0, capsFlag = 0;
684 CHECK_HR(get_camera_control()->GetRange(CameraControl_Exposure, &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
689 for (
auto & pu : pu_controls)
691 if (opt == pu.option)
693 CHECK_HR(get_video_proc()->GetRange(pu.property, &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
698 for (
auto & ct : ct_controls)
700 if (opt == ct.option)
702 CHECK_HR(get_camera_control()->GetRange(ct.property, &minVal, &maxVal, &steppingDelta, &defVal, &capsFlag));
707 throw std::runtime_error(
"unsupported control");
714 CComPtr<IMFAttributes> pAttributes =
nullptr;
715 CHECK_HR(MFCreateAttributes(&pAttributes, 1));
716 for (
auto attribute_params : attributes_params_set)
718 CHECK_HR(pAttributes->SetGUID(attribute_params.first, attribute_params.second));
721 IMFActivate ** ppDevices;
723 CHECK_HR(MFEnumDeviceSources(pAttributes, &ppDevices, &numDevices));
725 for (UINT32
i = 0;
i < numDevices; ++
i)
727 CComPtr<IMFActivate> pDevice;
728 *&pDevice = ppDevices[
i];
730 WCHAR * wchar_name =
nullptr; UINT32
length;
731 CHECK_HR(pDevice->GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_SYMBOLIC_LINK, &wchar_name, &length));
733 CoTaskMemFree(wchar_name);
754 CoTaskMemFree(ppDevices);
760 if (state == _power_state)
765 case D0: set_d0();
break;
766 case D3: set_d3();
break;
768 throw std::runtime_error(
"illegal power state request");
773 std::shared_ptr<const wmf_backend>
backend)
774 : _streamIndex(
MAX_PINS), _info(info), _is_flushed(), _has_started(), _backend(
std::
move(backend)),
776 _location(
""), _device_usb_spec(
usb3_type)
780 throw std::runtime_error(
"Camera not connected!");
786 LOG_WARNING(
"Could not retrieve USB descriptor for device " << std::hex << info.
vid <<
":" 792 LOG_WARNING(
"Accessing USB info failed for " << std::hex << info.
vid <<
":" 797 if (i ==
_info && device)
810 flush(MF_SOURCE_READER_ALL_STREAMS);
819 _ks_controls.clear();
823 LOG_WARNING(
"Exception thrown while flushing MF source");
829 CComPtr<IMFAttributes> device_attrs =
nullptr;
831 CHECK_HR(MFCreateAttributes(&device_attrs, 2));
839 CComPtr<IMFAttributes> reader_attrs =
nullptr;
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,
865 CHECK_HR(
_reader->SetStreamSelection(static_cast<DWORD>(MF_SOURCE_READER_ALL_STREAMS),
TRUE));
877 elem.callback =
nullptr;
884 CComPtr<IMFMediaType> pMediaType =
nullptr;
885 for (
unsigned int sIndex = 0; sIndex <
_streams.size(); ++sIndex)
887 for (
auto k = 0;; k++)
889 auto hr =
_reader->GetNativeMediaType(sIndex, k, &pMediaType.p);
890 if (FAILED(hr) || pMediaType ==
nullptr)
893 if (hr != MF_E_NO_MORE_TYPES)
894 check(
"_reader->GetNativeMediaType(sIndex, k, &pMediaType.p)", hr,
false);
900 CHECK_HR(pMediaType->GetGUID(MF_MT_SUBTYPE, &subtype));
905 CHECK_HR(MFGetAttributeSize(pMediaType, MF_MT_FRAME_SIZE, &width, &height));
928 sp.
format = device_fourcc;
936 action(mfp, pMediaType, quit);
951 throw std::runtime_error(
"Device must be powered to query supported profiles!");
953 std::vector<stream_profile> results;
956 results.push_back(mfp.
profile);
964 bool profile_found =
false;
965 foreach_profile([
this, profile, callback, &profile_found](
const mf_profile& mfp, CComPtr<IMFMediaType> media_type,
bool& quit)
978 auto hr =
_reader->SetCurrentMediaType(mfp.
index,
nullptr, media_type);
979 if (SUCCEEDED(hr) && media_type)
994 throw std::runtime_error(
"Camera already streaming via this stream index!");
1010 LOG_WARNING(
"First frame took more then " << timeout_ms <<
"ms to arrive!");
1012 profile_found =
true;
1018 throw std::runtime_error(
"Could not set Media Type. Device may be locked");
1025 throw std::runtime_error(
"Stream profile not found!");
1031 throw std::runtime_error(
"Device is already streaming!");
1040 throw std::runtime_error(
"Device must be powered to query video_proc!");
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.");
1049 throw std::runtime_error(
"Device must be powered to query camera_control!");
1051 throw std::runtime_error(
"The device does not support camera settings such as zoom, pan, aperture adjustment, or shutter speed.");
1058 throw std::runtime_error(
"Stream not configured");
1061 throw std::runtime_error(
"Device is already streaming!");
1096 elem->callback =
nullptr;
1097 elem->profile.format = 0;
1098 elem->profile.fps = 0;
1099 elem->profile.width = 0;
1100 elem->profile.height = 0;
1124 return (pac.profile == profile && (pac.callback));
1128 throw std::runtime_error(
"Camera is not streaming!");
1151 auto sts =
_reader->Flush(sIndex);
1154 if (sts == MF_E_HW_MFT_FAILED_START_STREAMING)
1155 throw std::runtime_error(
"Camera already streaming");
1157 throw std::runtime_error(
to_string() <<
"Flush failed" << sts);
1168 throw std::runtime_error(
"Camera is no longer connected!");
1178 close(elem.profile);
static const textual_icon lock
GLuint const GLchar * name
#define DEVICE_ID_MAX_SIZE
rs2_option
Defines general configuration controls. These can generally be mapped to camera UVC controls...
#define WAIT_FOR_MUTEX_TIME_OUT
GLsizei const GLchar *const * string
def info(name, value, persistent=False)
const std::unordered_map< uint32_t, uint32_t > fourcc_map
GLint GLsizei GLsizei height
#define RS2_DEFAULT_TIMEOUT
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
#define DEVICE_NOT_READY_ERROR
double monotonic_to_realtime(double monotonic)
::realsense_legacy_msgs::metadata_< std::allocator< void > > metadata
typename::boost::move_detail::remove_reference< T >::type && move(T &&t) BOOST_NOEXCEPT
GLenum GLuint GLenum GLsizei length
static const std::vector< std::vector< std::pair< GUID, GUID > > > attributes_params
void copy(void *dst, void const *src, size_t size)
std::string to_string(T value)