├── .gitignore ├── EtLib.dll ├── README.md ├── TouchPlusLib.sln ├── TouchPlusLib.vcxproj ├── TouchPlusLib.vcxproj.filters ├── curllib.dll ├── eSPAEAWBCtrl.dll ├── eSPDI.dll ├── jpeg62.dll ├── libeay32.dll ├── libsasl.dll ├── libssl32.dll ├── libusb-1.0.dll ├── libusb0.dll ├── nuron.dll ├── opencv_calib3d248.dll ├── opencv_core248.dll ├── opencv_features2d248.dll ├── opencv_flann248.dll ├── opencv_gpu248.dll ├── opencv_highgui248.dll ├── opencv_imgproc248.dll ├── opencv_ml248.dll ├── opencv_nonfree248.dll ├── opencv_objdetect248.dll ├── opencv_ocl248.dll ├── opencv_video248.dll ├── openldap.dll ├── padlock.dll ├── pthreadGC2.dll ├── pthreadGCE2.dll ├── pthreadVC2.dll ├── pthreadVSE2.dll ├── src ├── DSVideoCapture.cpp ├── DSVideoCapture.h ├── Main.cpp ├── TouchPlus.h └── qedit.h ├── ssleay32.dll ├── turbojpeg.dll └── uvc.dll /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # Build results 11 | [Dd]ebug/ 12 | [Dd]ebugPublic/ 13 | [Rr]elease/ 14 | [Rr]eleases/ 15 | x64/ 16 | x86/ 17 | build/ 18 | bld/ 19 | [Bb]in/ 20 | [Oo]bj/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | # TODO: Comment the next line if you want to checkin your web deploy settings 130 | # but database connection strings (with potential passwords) will be unencrypted 131 | *.pubxml 132 | *.publishproj 133 | 134 | # NuGet Packages 135 | *.nupkg 136 | # The packages folder can be ignored because of Package Restore 137 | **/packages/* 138 | # except build/, which is used as an MSBuild target. 139 | !**/packages/build/ 140 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 141 | #!**/packages/repositories.config 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | bower_components/ 163 | 164 | # RIA/Silverlight projects 165 | Generated_Code/ 166 | 167 | # Backup & report files from converting an old project file 168 | # to a newer Visual Studio version. Backup files are not needed, 169 | # because we have git ;-) 170 | _UpgradeReport_Files/ 171 | Backup*/ 172 | UpgradeLog*.XML 173 | UpgradeLog*.htm 174 | 175 | # SQL Server files 176 | *.mdf 177 | *.ldf 178 | 179 | # Business Intelligence projects 180 | *.rdl.data 181 | *.bim.layout 182 | *.bim_*.settings 183 | 184 | # Microsoft Fakes 185 | FakesAssemblies/ -------------------------------------------------------------------------------- /EtLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/EtLib.dll -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | TouchPlusLib 2 | ============ 3 | 4 | Code to access video stream for Ractiv Touch+ 5 | -------------------------------------------------------------------------------- /TouchPlusLib.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TouchPlusLib", "TouchPlusLib.vcxproj", "{79C8312E-E2F2-42F8-BA21-1EDA2EA77E76}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Win32 = Debug|Win32 9 | Release|Win32 = Release|Win32 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {79C8312E-E2F2-42F8-BA21-1EDA2EA77E76}.Debug|Win32.ActiveCfg = Debug|Win32 13 | {79C8312E-E2F2-42F8-BA21-1EDA2EA77E76}.Debug|Win32.Build.0 = Debug|Win32 14 | {79C8312E-E2F2-42F8-BA21-1EDA2EA77E76}.Release|Win32.ActiveCfg = Release|Win32 15 | {79C8312E-E2F2-42F8-BA21-1EDA2EA77E76}.Release|Win32.Build.0 = Release|Win32 16 | EndGlobalSection 17 | GlobalSection(SolutionProperties) = preSolution 18 | HideSolutionNode = FALSE 19 | EndGlobalSection 20 | EndGlobal 21 | -------------------------------------------------------------------------------- /TouchPlusLib.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | {79C8312E-E2F2-42F8-BA21-1EDA2EA77E76} 24 | Win32Proj 25 | RactivTest2 26 | 27 | 28 | 29 | Application 30 | true 31 | v110 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v110 38 | true 39 | Unicode 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | true 53 | 54 | 55 | false 56 | 57 | 58 | 59 | 60 | 61 | Level3 62 | Disabled 63 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 64 | E:\ImageAnalysis\opencv\build\include;C:\Program Files %28x86%29\Windows Kits\8.0\Include;E:\Programming\libuvc\include;E:\Programming\libusb-1.0;%(AdditionalIncludeDirectories) 65 | 66 | 67 | Console 68 | true 69 | E:\ImageAnalysis\opencv\build\lib\Debug;E:\Programming\libusb-win32-bin-1.2.6.0\lib\msvc;%(AdditionalLibraryDirectories) 70 | libusb.lib;opencv_stitching248d.lib;opencv_contrib248d.lib;opencv_videostab248d.lib;opencv_superres248d.lib;opencv_nonfree248d.lib;opencv_gpu248d.lib;opencv_ocl248d.lib;opencv_legacy248d.lib;opencv_ts248d.lib;opencv_calib3d248d.lib;opencv_features2d248d.lib;opencv_objdetect248d.lib;opencv_highgui248d.lib;opencv_video248d.lib;opencv_photo248d.lib;opencv_imgproc248d.lib;opencv_flann248d.lib;opencv_ml248d.lib;opencv_core248d.lib;%(AdditionalDependencies) 71 | 72 | 73 | 74 | 75 | Level3 76 | 77 | 78 | MaxSpeed 79 | true 80 | true 81 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 82 | 83 | 84 | Console 85 | true 86 | true 87 | true 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /TouchPlusLib.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | Source Files 34 | 35 | 36 | -------------------------------------------------------------------------------- /curllib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/curllib.dll -------------------------------------------------------------------------------- /eSPAEAWBCtrl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/eSPAEAWBCtrl.dll -------------------------------------------------------------------------------- /eSPDI.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/eSPDI.dll -------------------------------------------------------------------------------- /jpeg62.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/jpeg62.dll -------------------------------------------------------------------------------- /libeay32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/libeay32.dll -------------------------------------------------------------------------------- /libsasl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/libsasl.dll -------------------------------------------------------------------------------- /libssl32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/libssl32.dll -------------------------------------------------------------------------------- /libusb-1.0.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/libusb-1.0.dll -------------------------------------------------------------------------------- /libusb0.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/libusb0.dll -------------------------------------------------------------------------------- /nuron.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/nuron.dll -------------------------------------------------------------------------------- /opencv_calib3d248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_calib3d248.dll -------------------------------------------------------------------------------- /opencv_core248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_core248.dll -------------------------------------------------------------------------------- /opencv_features2d248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_features2d248.dll -------------------------------------------------------------------------------- /opencv_flann248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_flann248.dll -------------------------------------------------------------------------------- /opencv_gpu248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_gpu248.dll -------------------------------------------------------------------------------- /opencv_highgui248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_highgui248.dll -------------------------------------------------------------------------------- /opencv_imgproc248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_imgproc248.dll -------------------------------------------------------------------------------- /opencv_ml248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_ml248.dll -------------------------------------------------------------------------------- /opencv_nonfree248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_nonfree248.dll -------------------------------------------------------------------------------- /opencv_objdetect248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_objdetect248.dll -------------------------------------------------------------------------------- /opencv_ocl248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_ocl248.dll -------------------------------------------------------------------------------- /opencv_video248.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/opencv_video248.dll -------------------------------------------------------------------------------- /openldap.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/openldap.dll -------------------------------------------------------------------------------- /padlock.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/padlock.dll -------------------------------------------------------------------------------- /pthreadGC2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/pthreadGC2.dll -------------------------------------------------------------------------------- /pthreadGCE2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/pthreadGCE2.dll -------------------------------------------------------------------------------- /pthreadVC2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/pthreadVC2.dll -------------------------------------------------------------------------------- /pthreadVSE2.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/pthreadVSE2.dll -------------------------------------------------------------------------------- /src/DSVideoCapture.cpp: -------------------------------------------------------------------------------- 1 | #include "DSVideoCapture.h" 2 | 3 | //change this macro to fit your style of error handling 4 | #define CHECK_HR(hr, msg) if (hrcheck(hr, msg)) return hr; 5 | 6 | BOOL hrcheck(HRESULT hr, TCHAR* errtext) 7 | { 8 | if (hr >= S_OK) 9 | return FALSE; 10 | 11 | printf("Error %x: %s\n", hr, errtext); 12 | 13 | return TRUE; 14 | } 15 | 16 | CComPtr DSVideoCapture::GetPin(IBaseFilter *pFilter, LPCOLESTR pinname) 17 | { 18 | IEnumPins *pEnum = NULL; 19 | CComPtr pPin; 20 | 21 | HRESULT hr = pFilter->EnumPins(&pEnum); 22 | if (hrcheck(hr, L"Can't enumerate pins.")) 23 | return NULL; 24 | 25 | while(pEnum->Next(1, &pPin, 0) == S_OK) 26 | { 27 | PIN_INFO pinfo; 28 | pPin->QueryPinInfo(&pinfo); 29 | BOOL found = !_wcsicmp(pinname, pinfo.achName); 30 | 31 | if (pinfo.pFilter) pinfo.pFilter->Release(); 32 | 33 | if (found) 34 | return pPin; 35 | 36 | pPin.Release(); 37 | } 38 | printf("Pin not found!\n"); 39 | return NULL; 40 | } 41 | 42 | HRESULT DSVideoCapture::EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum) 43 | { 44 | // Create the System Device Enumerator. 45 | ICreateDevEnum *pDevEnum; 46 | HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, 47 | CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pDevEnum)); 48 | 49 | if (SUCCEEDED(hr)) 50 | { 51 | // Create an enumerator for the category. 52 | hr = pDevEnum->CreateClassEnumerator(category, ppEnum, 0); 53 | if (hr == S_FALSE) 54 | { 55 | hr = VFW_E_NOT_FOUND; // The category is empty. Treat as an error. 56 | } 57 | pDevEnum->Release(); 58 | } 59 | return hr; 60 | } 61 | 62 | 63 | IBaseFilter* DSVideoCapture::FindTouchFilter(IEnumMoniker *pEnum) 64 | { 65 | IMoniker *pMoniker = NULL; 66 | 67 | while (pEnum->Next(1, &pMoniker, NULL) == S_OK) 68 | { 69 | IPropertyBag *pPropBag; 70 | HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag)); 71 | if (FAILED(hr)) 72 | { 73 | pMoniker->Release(); 74 | continue; 75 | } 76 | 77 | VARIANT var; 78 | VariantInit(&var); 79 | 80 | // Get description or friendly name. 81 | hr = pPropBag->Read(L"Description", &var, 0); 82 | if (FAILED(hr)) 83 | { 84 | hr = pPropBag->Read(L"FriendlyName", &var, 0); 85 | } 86 | if (SUCCEEDED(hr)) 87 | { 88 | if(0 == wcscmp(var.bstrVal, L"Touch+ Camera")) 89 | { 90 | printf("Found Touch+ Camera\n"); 91 | 92 | IBaseFilter *pCap = NULL; 93 | hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pCap); 94 | 95 | VariantClear(&var); 96 | pPropBag->Release(); 97 | pMoniker->Release(); 98 | 99 | return pCap; 100 | } 101 | 102 | printf("%S\n", var.bstrVal); 103 | VariantClear(&var); 104 | } 105 | 106 | hr = pPropBag->Write(L"FriendlyName", &var); 107 | 108 | // WaveInID applies only to audio capture devices. 109 | hr = pPropBag->Read(L"WaveInID", &var, 0); 110 | if (SUCCEEDED(hr)) 111 | { 112 | printf("WaveIn ID: %d\n", var.lVal); 113 | VariantClear(&var); 114 | } 115 | 116 | hr = pPropBag->Read(L"DevicePath", &var, 0); 117 | if (SUCCEEDED(hr)) 118 | { 119 | // The device path is not intended for display. 120 | printf("Device path: %S\n", var.bstrVal); 121 | VariantClear(&var); 122 | } 123 | 124 | pPropBag->Release(); 125 | pMoniker->Release(); 126 | } 127 | 128 | return false; 129 | } 130 | 131 | HRESULT DSVideoCapture::BuildGraph(IGraphBuilder *pGraph) 132 | { 133 | HRESULT hr = S_OK; 134 | 135 | CComPtr pTouchCamera; 136 | CComPtr pSampleGrabberF; 137 | 138 | IEnumMoniker *pEnum; 139 | 140 | //graph builder 141 | CComPtr pBuilder; 142 | hr = pBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder2); 143 | CHECK_HR(hr, L"Can't create Capture Graph Builder"); 144 | hr = pBuilder->SetFiltergraph(pGraph); 145 | CHECK_HR(hr, L"Can't SetFiltergraph"); 146 | 147 | //add Touch+ Camera 148 | hr = EnumerateDevices(CLSID_VideoInputDeviceCategory, &pEnum); 149 | if (SUCCEEDED(hr)) 150 | { 151 | pTouchCamera = FindTouchFilter(pEnum); 152 | pEnum->Release(); 153 | } 154 | 155 | hr = pGraph->AddFilter(pTouchCamera, L"Touch+ Camera"); 156 | CHECK_HR(hr, L"Can't add Touch+ Camera to graph"); 157 | 158 | //add SampleGrabber 159 | // Initialize core variables 160 | hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pSampleGrabberF)); 161 | CHECK_HR(hr, L"Can't create SampleGrabber"); 162 | hr = pSampleGrabberF->QueryInterface(IID_ISampleGrabber, (void**)&pSampleGrabber); 163 | CHECK_HR(hr, L"Can't get SampleGrabber from filter"); 164 | 165 | // Setup media format 166 | AM_MEDIA_TYPE pSampleGrabber_pmt; 167 | ZeroMemory(&pSampleGrabber_pmt, sizeof(AM_MEDIA_TYPE)); 168 | pSampleGrabber_pmt.majortype = MEDIATYPE_Video; 169 | pSampleGrabber_pmt.subtype = MEDIASUBTYPE_RGB24; 170 | pSampleGrabber_pmt.formattype = FORMAT_VideoInfo; 171 | pSampleGrabber_pmt.bFixedSizeSamples = TRUE; 172 | pSampleGrabber_pmt.cbFormat = 88; 173 | pSampleGrabber_pmt.lSampleSize = 2457600; 174 | pSampleGrabber_pmt.bTemporalCompression = FALSE; 175 | VIDEOINFOHEADER pSampleGrabber_format; 176 | ZeroMemory(&pSampleGrabber_format, sizeof(VIDEOINFOHEADER)); 177 | pSampleGrabber_format.dwBitRate = 1179652719; 178 | pSampleGrabber_format.AvgTimePerFrame = 166666; 179 | pSampleGrabber_format.bmiHeader.biSize = 40; 180 | pSampleGrabber_format.bmiHeader.biWidth = 1280; 181 | pSampleGrabber_format.bmiHeader.biHeight = 480; 182 | pSampleGrabber_format.bmiHeader.biPlanes = 1; 183 | pSampleGrabber_format.bmiHeader.biBitCount = 24; 184 | pSampleGrabber_format.bmiHeader.biSizeImage = 2457600; 185 | pSampleGrabber_pmt.pbFormat = (BYTE*)&pSampleGrabber_format; 186 | 187 | 188 | AM_MEDIA_TYPE pCam_pmt; 189 | ZeroMemory(&pCam_pmt, sizeof(AM_MEDIA_TYPE)); 190 | pCam_pmt.majortype = MEDIATYPE_Video; 191 | pCam_pmt.subtype = MEDIASUBTYPE_MJPG; 192 | pCam_pmt.formattype = FORMAT_VideoInfo; 193 | pCam_pmt.bFixedSizeSamples = TRUE; 194 | pCam_pmt.cbFormat = 88; 195 | pCam_pmt.lSampleSize = 1843200; 196 | pCam_pmt.bTemporalCompression = FALSE; 197 | VIDEOINFOHEADER pCamFmt; 198 | ZeroMemory(&pCamFmt, sizeof(VIDEOINFOHEADER)); 199 | pCamFmt.dwBitRate = 884736000; 200 | pCamFmt.AvgTimePerFrame = 166666; 201 | pCamFmt.bmiHeader.biSize = 40; 202 | pCamFmt.bmiHeader.biWidth = 1280; 203 | pCamFmt.bmiHeader.biHeight = 480; 204 | pCamFmt.bmiHeader.biPlanes = 1; 205 | pCamFmt.bmiHeader.biBitCount = 24; 206 | pCamFmt.bmiHeader.biCompression = 1196444237; 207 | pCamFmt.bmiHeader.biSizeImage = 1843200; 208 | pCam_pmt.pbFormat = (BYTE*)&pCamFmt; 209 | 210 | // Get pins for sample grabber and camera 211 | CComPtr camPin = GetPin(pTouchCamera, L"Capture"); 212 | CComPtr sampleInput = GetPin(pSampleGrabberF, L"Input"); 213 | CComPtr sampleOutput = GetPin(pSampleGrabberF, L"Output"); 214 | 215 | // Set media type for sample grabber and camera 216 | hr = pSampleGrabber->SetMediaType(&pSampleGrabber_pmt); 217 | CHECK_HR(hr, L"Can't set media type to sample grabber"); 218 | 219 | pSampleGrabber->SetBufferSamples( TRUE ); 220 | 221 | 222 | CComQIPtr camConfig(camPin); 223 | hr = camConfig->SetFormat(&pCam_pmt); 224 | CHECK_HR(hr, L"Can't set camera pin format"); 225 | 226 | 227 | // Add sample grabber filter 228 | hr = pGraph->AddFilter(pSampleGrabberF, L"SampleGrabber"); 229 | CHECK_HR(hr, L"Can't add SampleGrabber to graph"); 230 | 231 | 232 | 233 | printf("add MJPEG Decompressor\n"); 234 | //add MJPEG Decompressor 235 | CComPtr pMJPEGDecompressor; 236 | hr = pMJPEGDecompressor.CoCreateInstance(CLSID_MjpegDec); 237 | CHECK_HR(hr, L"Can't create MJPEG Decompressor"); 238 | hr = pGraph->AddFilter(pMJPEGDecompressor, L"MJPEG Decompressor"); 239 | 240 | CHECK_HR(hr, L"Can't add MJPEG Decompressor to graph"); 241 | //connect SampleGrabber and MJPEG Decompressor 242 | 243 | //connect Touch+ Camera and SampleGrabber 244 | hr = pGraph->ConnectDirect(camPin, GetPin(pMJPEGDecompressor, L"XForm In"), NULL); 245 | CHECK_HR(hr, L"Can't connect Touch+ Camera and SampleGrabber"); 246 | 247 | hr = pGraph->ConnectDirect(GetPin(pMJPEGDecompressor, L"XForm Out"), sampleInput, NULL); 248 | CHECK_HR(hr, L"Can't connect SampleGrabber and MJPEG Decompressor"); 249 | 250 | //add Video Renderer 251 | CComPtr pVideoRenderer; 252 | //hr = pVideoRenderer.CoCreateInstance(CLSID_VideoRenderer); 253 | hr = pVideoRenderer.CoCreateInstance(CLSID_NullRenderer); 254 | CHECK_HR(hr, L"Can't create Video Renderer"); 255 | hr = pGraph->AddFilter(pVideoRenderer, L"Video Renderer"); 256 | CHECK_HR(hr, L"Can't add Video Renderer to graph"); 257 | 258 | hr = pGraph->ConnectDirect(sampleOutput, GetPin(pVideoRenderer, L"In"), NULL); 259 | 260 | VIDEOINFOHEADER *pVideoHeader = (VIDEOINFOHEADER *)pSampleGrabber_pmt.pbFormat; 261 | 262 | // STEP18: Copy the BMP infomation to BITMAPINFO structure 263 | ZeroMemory( &bitmapInfo, sizeof(bitmapInfo) ); 264 | CopyMemory( &bitmapInfo.bmiHeader, &(pVideoHeader->bmiHeader), sizeof(BITMAPINFOHEADER) ); 265 | 266 | printf ("Built Filter graph successfully\n"); 267 | 268 | return S_OK; 269 | } 270 | 271 | HRESULT DSVideoCapture::Start() 272 | { 273 | HRESULT hr; 274 | 275 | bSize = 0; 276 | 277 | CoInitialize(NULL); 278 | 279 | CComPtr graph; 280 | graph.CoCreateInstance(CLSID_FilterGraph); 281 | printf("Building graph...\n"); 282 | 283 | hr = BuildGraph(graph); 284 | CHECK_HR(hr, L"Can't run the graph"); 285 | if (hr==S_OK) 286 | { 287 | printf("Running\n"); 288 | CComQIPtr mediaControl(graph); 289 | hr = mediaControl->Run(); 290 | 291 | mediaEvent = CComQIPtr(graph); 292 | 293 | initSuccess = true; 294 | 295 | return S_OK; 296 | } 297 | } 298 | 299 | bool DSVideoCapture::GrabFrame(long* frameData) 300 | { 301 | if (initSuccess) 302 | { 303 | // Update Camera Input 304 | long ev=0, p1=0, p2=0; 305 | Sleep(50); 306 | printf("."); 307 | while(PeekMessage(&msg, NULL, 0,0, PM_REMOVE)) 308 | DispatchMessage(&msg); 309 | while (mediaEvent->GetEvent(&ev, &p1, &p2, 0)==S_OK) 310 | if (ev == EC_COMPLETE || ev == EC_USERABORT) 311 | { 312 | printf("Done!\n"); 313 | stop = TRUE; 314 | } 315 | else if (ev == EC_ERRORABORT) 316 | { 317 | printf("An error occured: HRESULT=%x\n", p1); 318 | mediaControl->Stop(); 319 | stop = TRUE; 320 | } 321 | mediaEvent->FreeEventParams(ev, p1, p2); 322 | 323 | if (bSize == 0) 324 | { 325 | // Try to get current buffer size 326 | pSampleGrabber->GetCurrentBuffer(&bSize, NULL); 327 | 328 | // If the buffer is null return 329 | if (bSize == 0) 330 | return false; 331 | } 332 | 333 | HRESULT hr = pSampleGrabber->GetCurrentBuffer( &bSize, (long*)frameData); 334 | 335 | return true; 336 | } 337 | else 338 | return false; 339 | } 340 | 341 | void DSVideoCapture::Finish() 342 | { 343 | printf("Finishing"); 344 | 345 | mediaControl->Stop(); 346 | CoUninitialize(); 347 | } 348 | 349 | int DSVideoCapture::GetSampleWidth() 350 | { 351 | return bitmapInfo.bmiHeader.biWidth; 352 | } 353 | 354 | int DSVideoCapture::GetSampleHeight() 355 | { 356 | return bitmapInfo.bmiHeader.biHeight; 357 | } 358 | 359 | int DSVideoCapture::GetSampleChannels() 360 | { 361 | return bitmapInfo.bmiHeader.biBitCount / 8; 362 | } 363 | -------------------------------------------------------------------------------- /src/DSVideoCapture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #pragma comment(lib, "strmiids") 3 | //#pragma comment(linker, "/alternatename:_pWeakValue=_pDefaultWeakValue") 4 | 5 | #include 6 | #include 7 | #include 8 | #include "qedit.h" 9 | #include 10 | 11 | class __declspec(uuid("6B652FFF-11FE-4fce-92AD-0266B5D7C78F")) SampleGrabber; 12 | class __declspec(uuid("0579154A-2B53-4994-B0D0-E773148EFF85")) SampleGrabberCB; 13 | 14 | //class __declspec(uuid("17CCA71B-ECD7-11D0-B908-00A0C9223196")) CLSID_TouchCamera; 15 | //class __declspec(uuid("C1F400A0-3F08-11D3-9F0B-006008039E37")) CLSID_SampleGrabber; 16 | //class __declspec(uuid("B87BEB7B-8D29-423F-AE4D-6582C10175AC")) CLSID_VideoRenderer; 17 | 18 | //{17CCA71B-ECD7-11D0-B908-00A0C9223196} 19 | 20 | DEFINE_GUID(CLSID_TouchCamera, 0x17CCA71B, 0xECD7, 0x11D0, 0xB9, 0x08, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96); //ksproxy.ax 21 | 22 | //{C1F400A0-3F08-11D3-9F0B-006008039E37} 23 | DEFINE_GUID(CLSID_SampleGrabber2, 0xC1F400A0, 0x3F08, 0x11D3, 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37); //qedit.dll 24 | 25 | //{B87BEB7B-8D29-423F-AE4D-6582C10175AC} 26 | DEFINE_GUID(CLSID_VideoRenderer, 0xB87BEB7B, 0x8D29, 0x423F, 0xAE, 0x4D, 0x65, 0x82, 0xC1, 0x01, 0x75, 0xAC); //quartz.dll 27 | 28 | 29 | class DSVideoCapture 30 | { 31 | public: 32 | HRESULT Start(); 33 | bool GrabFrame(long* byteData); 34 | void Finish(); 35 | 36 | int GetSampleWidth(); 37 | int GetSampleHeight(); 38 | int GetSampleChannels(); 39 | 40 | 41 | private: 42 | HRESULT BuildGraph(IGraphBuilder *pGraph); 43 | 44 | CComPtr GetPin(IBaseFilter *pFilter, LPCOLESTR pinname); 45 | 46 | HRESULT EnumerateDevices(REFGUID category, IEnumMoniker **ppEnum); 47 | IBaseFilter* FindTouchFilter(IEnumMoniker *pEnum); 48 | 49 | // Members 50 | BITMAPINFO bitmapInfo; 51 | bool initSuccess; 52 | CComPtr pSampleGrabber; 53 | CComQIPtr mediaControl; 54 | 55 | CComQIPtr mediaEvent; 56 | 57 | // Window Parameters 58 | long bSize; 59 | bool stop; 60 | MSG msg; 61 | }; -------------------------------------------------------------------------------- /src/Main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "DSVideoCapture.h" 3 | #include "TouchPlus.h" 4 | 5 | #include "opencv2\highgui\highgui.hpp" 6 | #include "opencv2\opencv.hpp" 7 | 8 | using namespace cv; 9 | 10 | int main() 11 | { 12 | if (!UnlockSoftware()) 13 | printf("Failed to unlock\n"); 14 | 15 | DSVideoCapture* vc = new DSVideoCapture(); 16 | vc->Start(); 17 | 18 | int height = vc->GetSampleHeight(); 19 | int width = vc->GetSampleWidth(); 20 | int channels = vc->GetSampleChannels(); 21 | Mat frame = Mat(height, width, CV_8UC3); 22 | 23 | assert(frame.isContinuous()); 24 | 25 | Mat frameL, frameR; 26 | 27 | while (1) 28 | { 29 | cvWaitKey(10); 30 | vc->GrabFrame((long*)frame.data); 31 | 32 | frameL = Mat(frame, Rect(0,0,width/2,height)); 33 | frameR = Mat(frame, Rect(width/2,0,width/2,height)); 34 | 35 | imshow( "FrameL", frameL ); 36 | imshow( "FrameR", frameR ); 37 | } 38 | 39 | vc->Finish(); 40 | lockDevice(0); 41 | 42 | return 0; 43 | } -------------------------------------------------------------------------------- /src/TouchPlus.h: -------------------------------------------------------------------------------- 1 | 2 | #include "DSVideoCapture.h" 3 | 4 | typedef int (CALLBACK* SPAEWB_EnumDevice)(int* param); 5 | typedef int (CALLBACK* SPAEWB_GetDeviceName)(int id, char* name, char* data); 6 | typedef int (CALLBACK* SPAEWB_SelectDevice)(int param); 7 | typedef int (CALLBACK* SPAEWB_UnlockDevice)(int param); 8 | typedef int (CALLBACK* SPAEWB_LockDevice)(int param); 9 | typedef int (CALLBACK* SPAEWB_SetSensorType)(int type); 10 | typedef int (CALLBACK* SPAEWB_DisableAE)(); 11 | typedef int (CALLBACK* SPAEWB_DisableAWB)(); 12 | 13 | SPAEWB_EnumDevice enumDevice; // Function pointer 14 | SPAEWB_GetDeviceName getDeviceName; // Function pointer 15 | SPAEWB_SelectDevice selectDevice; // Function pointer 16 | SPAEWB_UnlockDevice unlockDevice; // Function pointer 17 | SPAEWB_LockDevice lockDevice; // Function pointer 18 | SPAEWB_SetSensorType setSensorType; 19 | SPAEWB_DisableAE disableAE; 20 | SPAEWB_DisableAWB disableAWB; 21 | 22 | bool InitSPAEAWB() 23 | { 24 | HINSTANCE hDLL; // Handle to DLL 25 | 26 | hDLL = LoadLibrary(L"eSPAEAWBCtrl"); 27 | if (hDLL != NULL) 28 | { 29 | enumDevice = (SPAEWB_EnumDevice)GetProcAddress(hDLL, 30 | "_eSPAEAWB_EnumDevice@4"); 31 | 32 | getDeviceName = (SPAEWB_GetDeviceName)GetProcAddress(hDLL, 33 | "_eSPAEAWB_GetDevicename@12"); 34 | 35 | selectDevice = (SPAEWB_SelectDevice)GetProcAddress(hDLL, 36 | "_eSPAEAWB_SelectDevice@4"); 37 | 38 | unlockDevice = (SPAEWB_UnlockDevice)GetProcAddress(hDLL, 39 | "_eSPAEAWB_SWUnlock@4"); 40 | 41 | lockDevice = (SPAEWB_LockDevice)GetProcAddress(hDLL, 42 | "_eSPAEAWB_SWLock@4"); 43 | 44 | setSensorType = (SPAEWB_SetSensorType)GetProcAddress(hDLL, 45 | "_eSPAEAWB_SetSensorType@4"); 46 | 47 | disableAE = (SPAEWB_DisableAE)GetProcAddress(hDLL, 48 | "_eSPAEAWB_DisableAE@0"); 49 | 50 | disableAWB = (SPAEWB_DisableAWB)GetProcAddress(hDLL, 51 | "_eSPAEAWB_DisableAWB@0"); 52 | 53 | if (!enumDevice || !getDeviceName || !selectDevice || !unlockDevice ||!lockDevice ||!setSensorType || !disableAE || !disableAWB) 54 | { 55 | // handle the error 56 | FreeLibrary(hDLL); 57 | printf("Error opening eSPAEAWBCtrl\n"); 58 | } 59 | else 60 | return true; 61 | } 62 | else 63 | printf("Failed opening eSPDI.dll\n"); 64 | 65 | return false; 66 | } 67 | 68 | 69 | typedef void* (WINAPIV* SPDI_Init)(void *ptr); 70 | typedef int (WINAPIV* SPDI_GetDeviceNumber)(void* ptr); 71 | typedef int (WINAPIV* SPDI_FindDevice)(void* ptr, int id); 72 | 73 | SPDI_Init spdi_init; // Function pointer 74 | SPDI_GetDeviceNumber spdi_getDeviceNumber; // Function pointer 75 | SPDI_FindDevice spdi_findDevice; // Function pointer 76 | 77 | bool InitSPDI() 78 | { 79 | HINSTANCE hDLL; // Handle to DLL 80 | 81 | hDLL = LoadLibrary(L"eSPDI.dll"); 82 | if (hDLL != NULL) 83 | { 84 | spdi_init = (SPDI_Init)GetProcAddress(hDLL, 85 | "EtronDI_Init"); 86 | 87 | spdi_getDeviceNumber = (SPDI_GetDeviceNumber)GetProcAddress(hDLL, 88 | "EtronDI_GetDeviceNumber"); 89 | 90 | spdi_findDevice = (SPDI_FindDevice)GetProcAddress(hDLL, 91 | "EtronDI_FindDevice"); 92 | 93 | if (!spdi_init || !spdi_getDeviceNumber || !spdi_findDevice) 94 | { 95 | // handle the error 96 | FreeLibrary(hDLL); 97 | printf("Error opening SPDI\n"); 98 | } 99 | else 100 | return true; 101 | } 102 | else 103 | printf("Failed opening eSPDI.dll\n"); 104 | 105 | return false; 106 | } 107 | 108 | void* passPtr = 0; 109 | 110 | bool UnlockSoftware() 111 | { 112 | printf("Sizes: int %i char %i bool %i short %i pointer %i\n", sizeof(int), sizeof(char), sizeof(bool), sizeof(short), sizeof(void*)); 113 | 114 | int result = 0; 115 | 116 | if (!InitSPAEAWB()) 117 | return false; 118 | 119 | if (!InitSPDI()) 120 | return false; 121 | 122 | printf("Loaded libraries\n"); 123 | 124 | int deviceCount; 125 | 126 | void* temp; 127 | spdi_init(&passPtr); 128 | printf("spdi_init %i\n", result); 129 | 130 | 131 | deviceCount = spdi_getDeviceNumber(passPtr); 132 | printf("spdi_getDeviceNumber %i\n", deviceCount); 133 | result = spdi_findDevice(passPtr, deviceCount); 134 | printf("spdi_findDevice %i\n", result); 135 | 136 | int numDevices = 0; 137 | // call the function 138 | int ret = enumDevice(&numDevices); 139 | 140 | 141 | printf("Found %i devices - Return %i\n", numDevices, ret); 142 | for (int i=0;i // for IMediaSample 11 | 12 | /////////////////////////////////////////////////////////////////////////////////// 13 | 14 | interface ISampleGrabberCB : public IUnknown 15 | { 16 | virtual STDMETHODIMP SampleCB( double SampleTime, IMediaSample *pSample ) = 0; 17 | virtual STDMETHODIMP BufferCB( double SampleTime, BYTE *pBuffer, long BufferLen ) = 0; 18 | }; 19 | 20 | /////////////////////////////////////////////////////////////////////////////////// 21 | 22 | static 23 | const 24 | IID IID_ISampleGrabberCB = { 0x0579154A, 0x2B53, 0x4994, { 0xB0, 0xD0, 0xE7, 0x73, 0x14, 0x8E, 0xFF, 0x85 } }; 25 | 26 | /////////////////////////////////////////////////////////////////////////////////// 27 | 28 | interface 29 | ISampleGrabber 30 | : 31 | public IUnknown 32 | { 33 | virtual HRESULT STDMETHODCALLTYPE SetOneShot( BOOL OneShot ) = 0; 34 | virtual HRESULT STDMETHODCALLTYPE SetMediaType( const AM_MEDIA_TYPE *pType ) = 0; 35 | virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType( AM_MEDIA_TYPE *pType ) = 0; 36 | virtual HRESULT STDMETHODCALLTYPE SetBufferSamples( BOOL BufferThem ) = 0; 37 | virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer( long *pBufferSize, long *pBuffer ) = 0; 38 | virtual HRESULT STDMETHODCALLTYPE GetCurrentSample( IMediaSample **ppSample ) = 0; 39 | virtual HRESULT STDMETHODCALLTYPE SetCallback( ISampleGrabberCB *pCallback, long WhichMethodToCallback ) = 0; 40 | }; 41 | 42 | /////////////////////////////////////////////////////////////////////////////////// 43 | 44 | static 45 | const 46 | IID IID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } }; 47 | 48 | /////////////////////////////////////////////////////////////////////////////////// 49 | 50 | static 51 | const 52 | CLSID CLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; 53 | 54 | /////////////////////////////////////////////////////////////////////////////////// 55 | 56 | static 57 | const 58 | CLSID CLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } }; 59 | 60 | /////////////////////////////////////////////////////////////////////////////////// 61 | 62 | static 63 | const 64 | CLSID CLSID_VideoEffects1Category = { 0xcc7bfb42, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; 65 | 66 | /////////////////////////////////////////////////////////////////////////////////// 67 | 68 | static 69 | const 70 | CLSID CLSID_VideoEffects2Category = { 0xcc7bfb43, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; 71 | 72 | /////////////////////////////////////////////////////////////////////////////////// 73 | 74 | static 75 | const 76 | CLSID CLSID_AudioEffects1Category = { 0xcc7bfb44, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; 77 | 78 | /////////////////////////////////////////////////////////////////////////////////// 79 | 80 | static 81 | const 82 | CLSID CLSID_AudioEffects2Category = { 0xcc7bfb45, 0xf175, 0x11d1, { 0xa3, 0x92, 0x0, 0xe0, 0x29, 0x1f, 0x39, 0x59 } }; 83 | 84 | /////////////////////////////////////////////////////////////////////////////////// 85 | 86 | #endif 87 | 88 | /////////////////////////////////////////////////////////////////////////////////// -------------------------------------------------------------------------------- /ssleay32.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/ssleay32.dll -------------------------------------------------------------------------------- /turbojpeg.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/turbojpeg.dll -------------------------------------------------------------------------------- /uvc.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umarniz/TouchPlusLib/176f2744a533f517b97b39274682adccefef6037/uvc.dll --------------------------------------------------------------------------------