Qt + Win SDK + DirectShow

Alles rund um die Programmierung mit Qt
Antworten
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Qt + Win SDK + DirectShow

Beitrag von Pixtar »

Hallo Leute,

ich versuche derzeit eine Programm zu schreiben, welches meine Webcam initialisiert/connected und Bilder von der Webcam abholt.

Zuerst habe ich OpenCV versucht - nach einer halben Stunde lief alles einwandfrei und ich konnte mir das Livebild ansehen.
Leider habe ich aber keine Googletreffer oder ähnliches finden können, das es mir erlaubt mit OpenCV Parameter der Webcam zu ändern wie zum Beispiel den (Hardware-)Weißabgleich abzuschalten.

Daher bin ich dann auf DirectShow umgeschwenkt und mich traf der Knüppel auf den Kopf.
Ein kleines Snippet im Internet hat mir den Einstieg erleichtert - jedoch fehlte mir die streams.h (um die GUIDs auflösen zu können wie z.B. CLSID_VideoInputDeviceCategory), welche nur mit der Windows SDK geliefert wird.
Windows SDK gezogen und installiert

Weiterhin hatte ich keine sal.h, welche aus dem VB kommt
VB gezogen und installiert.

Sooo, nun steh ich da mit meinem Snippet und MinGW(3.15.2)/GCC(4.4.0) und der Compiler meckert nur rum, das er die Abhängigkeiten nicht auflösen kann:

Damit GCC die <streams.h> finden kann habe ich den INCLUDEPATH wie folgt gesetzt:
WINSTREAM = $$quote(C:\Programme\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses)
INCLUDEPATH = $${WINSTREAM}

Jetzt nörgelt er rum, dass er die Abhängigkeiten wie z.B. die intsafe.h nicht auflösen kann, weil sie woanders liegt: C:\Programme\Microsoft SDKs\Windows\v7.1\Include
Um das zu lösen habe ich dem .pro-File auch diesen Pfad übergeben und noch einen weiteren:

WINSTREAM = $$quote(C:\Programme\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses)
WINSDK = $$quote(C:\Programme\Microsoft SDKs\Windows\v7.1\Include)
VBSDK = $$quote(C:\Programme\Microsoft Visual Studio 10.0\VC\Include)
INCLUDEPATH = $${WINSTREAM} \
$${WINSDK} \
$${VBSDK}

Nach dem nicht erfolgreichen Kompilieren, springen mich ca. 3000 neue Fehler an.
Beispielsweise: C:/logitech_cam/../Programme/Microsoft SDKs/Windows/v7.1/Include/winnt.h:1202: error: pasting "(" and "__drv_nop" does not give a valid preprocessing token
oder C:/logitech_cam/../Programme/Microsoft SDKs/Windows/v7.1/Include/oleauto.h:546: error: expected primary-expression before '*' token

Was mache ich falsch? Meine Idee ist, den DEPENDPATH dafür zu nutzen, der aber bislang keinerlei Änderungen hervorgerufen hat.

Andere Vermutung wäre, dass sich VB-Source und Win SDK sich einfach nicht mit MinGW vertragen.

Hoffentlich kennt sich jemand mit QT in Verbindung mit DirectShow für Webcams aus.

Grüße Pixtar
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Re: Qt + Win SDK + DirectShow

Beitrag von Christian81 »

Soweit ich weiß kann MinGW keine WinAPI-Header, welche für MSVC ausgelegt sind, verarbeiten.
Aber MinGW bringt eigene WinAPI - Header mit bzw. sind im Netz verfügbar (z.B. auf der MinGW - Projekthomepage)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Re: Qt + Win SDK + DirectShow

Beitrag von Pixtar »

Danke Christian für den Hinweis.
Das ist doch schon einmal eine neue Richtung die ich einschlagen kann. Werde dahingehend mal weitersuchen.
Pixtar
Beiträge: 97
Registriert: 5. Mai 2010 15:32

Re: Qt + Win SDK + DirectShow

Beitrag von Pixtar »

Bin nun auf VisualStudio umgestiegen und nach einigen Kämpfen mit den Libraries kann ich nun eigentlich jede OEM-Webcam ansprechen.

Wer also Bandwurm-Code zum Testen seiner Webcam benutzen will, here it comes as console program: (no header-file needed)
[Includes:Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses; Libraries: Microsoft SDKs\Windows\v7.1\Lib]

<webcam.cpp>

Code: Alles auswählen

#pragma once

#pragma comment(lib, "strmiids")
#pragma comment(lib, "strmbase")  //must be created out of "directshow\baseclasses"-folder and copied to "\Lib"-folder
#pragma comment(lib, "Rpcrt4")

#include <windows.h>
#include <cstring>
#include <tchar.h>
#include <streams.h>
#include <stdio.h>
#include <comdef.h>
#include <conio.h>
#include <dshow.h>
#include <vector>
#include <iostream>

using namespace std;

GUID mediaSubtypes[30];

int main(){

	mediaSubtypes[0] = MEDIASUBTYPE_CLPL;
	mediaSubtypes[1] = MEDIASUBTYPE_YUYV;
	mediaSubtypes[2] = MEDIASUBTYPE_IYUV;
	mediaSubtypes[3] = MEDIASUBTYPE_YVU9;
	mediaSubtypes[4] = MEDIASUBTYPE_Y411;
	mediaSubtypes[5] = MEDIASUBTYPE_Y41P;
	mediaSubtypes[6] = MEDIASUBTYPE_YUY2;
	mediaSubtypes[7] = MEDIASUBTYPE_YVYU;
	mediaSubtypes[8] = MEDIASUBTYPE_UYVY;
	mediaSubtypes[9] = MEDIASUBTYPE_Y211;
	mediaSubtypes[10] = MEDIASUBTYPE_CLJR;
	mediaSubtypes[11] = MEDIASUBTYPE_IF09;
	mediaSubtypes[12] = MEDIASUBTYPE_CPLA;
	mediaSubtypes[13] = MEDIASUBTYPE_MJPG;
	mediaSubtypes[14] = MEDIASUBTYPE_TVMJ;
	mediaSubtypes[15] = MEDIASUBTYPE_WAKE;
	mediaSubtypes[16] = MEDIASUBTYPE_CFCC;
	mediaSubtypes[17] = MEDIASUBTYPE_IJPG;
	mediaSubtypes[18] = MEDIASUBTYPE_Plum;
	mediaSubtypes[19] = MEDIASUBTYPE_DVCS;
	mediaSubtypes[20] = MEDIASUBTYPE_H264;
	mediaSubtypes[21] = MEDIASUBTYPE_DVSD;
	mediaSubtypes[22] = MEDIASUBTYPE_MDVF;
	mediaSubtypes[23] = MEDIASUBTYPE_RGB1;
	mediaSubtypes[24] = MEDIASUBTYPE_RGB4;
	mediaSubtypes[25] = MEDIASUBTYPE_RGB8;
	mediaSubtypes[26] = MEDIASUBTYPE_RGB565;
	mediaSubtypes[27] = MEDIASUBTYPE_RGB555;
	mediaSubtypes[28] = MEDIASUBTYPE_RGB24;
	mediaSubtypes[29] = MEDIASUBTYPE_RGB32;
	string mediaSubtypesStr[30] = {"CLPL","YUYV","IYUV","YVU9","Y411","Y41P","YUY2","YVYU","UYVY","Y211","CLJR","IF09","CPLA","MJPG","TVMJ","WAKE","CFCC","IJPG","Plum","DVCS","H264","DVSD","MDVF","RGB1","RGB4","RGB8","RGB565","RGB555","RGB24","RGB32"};

	system("cls");
	printf("\n\nUSB-Videodevice and Capturing\n_______________________________________________________\n\n");

	 // for playing
	 IGraphBuilder *pGraphBuilder;
	 ICaptureGraphBuilder2 *pCaptureGraphBuilder2;
	 IMediaControl *pMediaControl;
	 IBaseFilter *pDeviceFilter = NULL;

	 // to select a video input device
	 ICreateDevEnum *pCreateDevEnum = NULL;
	 IEnumMoniker *pEnumMoniker = NULL;
	 IMoniker *pMoniker = NULL;
	 ULONG nFetched = 0;

	 // initialize COM
	 CoInitialize(NULL);

	 //
	 // selecting a device
	 //

	 // Create CreateDevEnum to list device
	 CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (PVOID *)&pCreateDevEnum);
    
	 // Create EnumMoniker to list VideoInputDevice 
	 pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumMoniker, 0);
	 if (pEnumMoniker == NULL) {
		// this will be shown if there is no capture device
		printf("No Device Found!\n");
		return 0;
	 }

	 // reset EnumMoniker
	 pEnumMoniker->Reset();

	 // get each Moniker
	 while (pEnumMoniker->Next(1, &pMoniker, &nFetched) == S_OK) {
		IPropertyBag *pPropertyBag;
		TCHAR devname[256];

		// bind to IPropertyBag
		pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropertyBag);

		VARIANT var;

		// get FriendlyName
		var.vt = VT_BSTR;
		pPropertyBag->Read(L"FriendlyName", &var, 0);
		WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, devname, sizeof(devname), 0, 0);
		VariantClear(&var);

		printf("Devicename: %s\n", devname);
		printf("Do you want to select this device? [y] or [n]\n>> ");
		int ch = getchar();

		// you can start playing by 'y' + return key
		// if you press the other key, it will not be played.
		if (ch == 'y') {
		// Bind Monkier to Filter
			pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pDeviceFilter );
		}
		printf("_______________________________________________________\n\n");

		// release
		pMoniker->Release();
		pPropertyBag->Release();

		// go out of loop if getchar() returns 'y'
		if (pDeviceFilter != NULL) { break; }
	}

	if (pDeviceFilter != NULL) {
		// create FilterGraph
		CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (LPVOID *)&pGraphBuilder);

		// create CaptureGraphBuilder2
		CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (LPVOID *)&pCaptureGraphBuilder2);

		// Initialize the IAMStream structure
		HRESULT hr = CoInitialize(0);
		IAMStreamConfig *pConfig = NULL;
		hr = pCaptureGraphBuilder2->FindInterface(&PIN_CATEGORY_CAPTURE, 0, pDeviceFilter, IID_IAMStreamConfig, (void**)&pConfig);

		int iCount = 0, iSize = 0;
		hr = pConfig->GetNumberOfCapabilities(&iCount, &iSize);

		// Check the size to make sure we pass in the correct structure.
		if (iSize == sizeof(VIDEO_STREAM_CONFIG_CAPS)){

			// Use the video capabilities structure.
			printf("\n\nPossible camera resolution\n");
			printf("_______________________________________________________\n");
			for (int iFormat = 0; iFormat < iCount; iFormat++){
				VIDEO_STREAM_CONFIG_CAPS scc;
				AM_MEDIA_TYPE *pmtConfig;
				hr = pConfig->GetStreamCaps(iFormat, &pmtConfig, (BYTE*)&scc);
				if (SUCCEEDED(hr)){
					/* Examine the format, and possibly use it. */
					if(pmtConfig->majortype == MEDIATYPE_Video){
						VIDEOINFOHEADER *pVih = (VIDEOINFOHEADER*)pmtConfig->pbFormat;
						// pVih contains the detailed format information.
						LONG lWidth = pVih->bmiHeader.biWidth;
						LONG lHeight = pVih->bmiHeader.biHeight;

						/* Run through all possible formats of the device and list them */
						if(lWidth!=0){

							printf("\n%i. Format\n\tWidth=%i\tHeight=%i\n\tType=%s\t", iFormat+1, lWidth, lHeight, "Video");
							int k=0;
							while(mediaSubtypes[k]!=pmtConfig->subtype)
								k++;

							char * buffer = new char[mediaSubtypesStr[k].length()];
							strcpy(buffer,mediaSubtypesStr[k].c_str());

							printf("Subtype=%s\n", buffer);

						}
					}

					DeleteMediaType(pmtConfig);
				}
			}
			printf("\n_______________________________________________________\n\n");
			printf("Attention: Not all listed formats are accessable!\nAdvice: Type in the format number.\n\nPlease choose you favourite resolution:\n>>");
			/* Choose a listed format for device */
			int df = 0;
			cin >> df;
			VIDEO_STREAM_CONFIG_CAPS scc;
			AM_MEDIA_TYPE *pmtConfig;
			hr = pConfig->GetStreamCaps(df-1, &pmtConfig, (BYTE*)&scc);
			hr = pConfig->SetFormat(pmtConfig);
			printf("\n\n");
		}


		// Query the capture filter for the IAMCameraControl interface.
		IAMCameraControl *pCameraControl = 0;
		hr = pDeviceFilter->QueryInterface(IID_IAMCameraControl, (void**)&pCameraControl);
		if (FAILED(hr)){
			printf("\nDevice does not support IAMVideoProcAmp!\n");
			// The device does not support IAMCameraControl
		}else{

			long Min, Max, Step, Default, Flags, Val;
			string camPropStr[7] = {"Pan","Tilt","Shutter","Zoom","Exposure","Iris","Focus"};
			int camProp[7] = {0,0,0,0,0,0,0};

			/*////////////////Read camera properties///////////////*/
			printf("\n\nRead camera properties (ranges/defaults/flags)\n");
			printf("_______________________________________________________\n\n");
			for(int fooInt = CameraControl_Pan; fooInt != CameraControl_Focus+1; fooInt++){
				CameraControlProperty foo = static_cast<CameraControlProperty>(fooInt);
				hr = pCameraControl->GetRange(foo, &Min, &Max, &Step, &Default, &Flags);
				char * buffer = new char[camPropStr[fooInt].length()];
				strcpy(buffer,camPropStr[fooInt].c_str());
				if (SUCCEEDED(hr))
					printf("%s:\n\tMin=%i; Max=%i; Step=%i; Default=%i; Flags=%i\n", buffer, Min, Max, Step, Default, Flags);
				else
					printf("%s:\n\tCamera has no %s property!\n", buffer, buffer);
			}
			printf("\n--Camera properties were read successfuly!--\n");
			printf("_______________________________________________________\n\n");
			////////////////////////////////////////////////////////


			/*//////////////Write camera properties//////////////*/
			printf("\n\nWrite camera properties (values)\n");
			printf("_______________________________________________________\n\n");
			for(int fooInt = CameraControl_Pan; fooInt != CameraControl_Focus+1; fooInt++){
				CameraControlProperty foo = static_cast<CameraControlProperty>(fooInt);
				hr = pCameraControl->Set(foo, camProp[fooInt], CameraControl_Flags_Manual );
				char * buffer = new char[camPropStr[fooInt].length()];
				strcpy(buffer,camPropStr[fooInt].c_str());
				if (SUCCEEDED(hr)){
					hr = pCameraControl->Get(foo, &Default, &Flags);
					printf("%s (Set):\n\tCurrent=%i; Flags=%i\n", buffer, camProp[fooInt], Flags);
				}else
					printf("%s (Set):\n\tCamera has no %s property!\n", buffer, buffer);
			}
			printf("\n--All camera properties got assigned!--\n");
			printf("_______________________________________________________\n\n");
			////////////////////////////////////////////////////////

		}


		// Query the capture filter for the IAMVideoProcAmp interface.
		IAMVideoProcAmp *pProcAmp = 0;
		hr = pDeviceFilter->QueryInterface(IID_IAMVideoProcAmp, (void**)&pProcAmp);
		if (FAILED(hr)){
			printf("\nDevice does not support IAMVideoProcAmp!\n");
			// The device does not support IAMVideoProcAmp
		}else{

			long Min, Max, Step, Default, Flags, Val;
			string vidPropStr[10] = {"Brightness","Contrast","Hue","Saturation","Sharpness","Gamma","ColorEnable","WhiteBalance","Backlight","Gain"};
			int vidProp[10] = {128,32,0,32,24,0,0,0,0,0};

			/*////////////////Read video properties///////////////*/
			printf("\n\nRead video properties (ranges/defaults/flags)\n");
			printf("_______________________________________________________\n\n");
			for(int fooInt = VideoProcAmp_Brightness; fooInt != VideoProcAmp_Gain+1; fooInt++){
				VideoProcAmpProperty foo = static_cast<VideoProcAmpProperty>(fooInt);
				hr = pProcAmp->GetRange(foo, &Min, &Max, &Step, &Default, &Flags);
				char * buffer = new char[vidPropStr[fooInt].length()];
				strcpy(buffer,vidPropStr[fooInt].c_str());
				if (SUCCEEDED(hr))
					printf("%s:\n\tMin=%i; Max=%i; Step=%i; Default=%i; Flags=%i\n", buffer, Min, Max, Step, Default, Flags);
				else
					printf("%s:\n\tThere is no video %s property!\n", buffer, buffer);
			}
			printf("\n--Video properties were read successfuly!--\n");
			printf("_______________________________________________________\n\n");
			////////////////////////////////////////////////////////


			/*////////////////Write video properties///////////////*/
			printf("\n\nWrite video properties (values)\n");
			printf("_______________________________________________________\n\n");
			for(int fooInt = VideoProcAmp_Brightness; fooInt != VideoProcAmp_Gain+1; fooInt++){
				VideoProcAmpProperty foo = static_cast<VideoProcAmpProperty>(fooInt);
				hr = pProcAmp->Set(foo, vidProp[fooInt], VideoProcAmp_Flags_Manual );
				char * buffer = new char[vidPropStr[fooInt].length()];
				strcpy(buffer,vidPropStr[fooInt].c_str());
				if (SUCCEEDED(hr)){
					hr = pProcAmp->Get(foo, &Default, &Flags);
					printf("%s (Set):\n\tCurrent=%i; Flags=%i\n", buffer, vidProp[fooInt], Flags);
				}else
					printf("%s (Set):\n\tThere is no video %s property!\n", buffer, buffer);
			}
			printf("\n--All video properties got assigned!--\n");
			printf("_______________________________________________________\n\n\n\n");
			////////////////////////////////////////////////////////
		}


		// set FilterGraph
		pCaptureGraphBuilder2->SetFiltergraph(pGraphBuilder);

		// get MediaControl interface
		pGraphBuilder->QueryInterface(IID_IMediaControl, (LPVOID *)&pMediaControl);

		// add device filter to FilterGraph
		pGraphBuilder->AddFilter(pDeviceFilter, L"Device Filter");

		// create Graph
		pCaptureGraphBuilder2->RenderStream(&PIN_CATEGORY_PREVIEW, NULL, pDeviceFilter, NULL, NULL);

		// start playing
		pMediaControl->Run();

		// to block execution
		// without this messagebox, the graph will be stopped immediately
		/*
			MessageBox(NULL,
			"Block Execution",
			"Block",
			MB_OK);
		*/
		system("pause");

		// release
		pMediaControl->Release();
		pCaptureGraphBuilder2->Release();
		pGraphBuilder->Release();
	}

	// release
	pEnumMoniker->Release();
	pCreateDevEnum->Release();

	// finalize COM
	CoUninitialize();

	return 0;
}
Antworten