DirectShow Filter verbinden
-
Hallo,
wieder mal ein DirectShow Problem, und zwar habe ich im GraphEdit meinen benötigten Filter zusammengebaut(Funktioniert auch). Wenn ich diesen Graphen nun versuche nach zu programmieren, bekomme ich immer einen Programmabsturz. Hier mein Quelltext(Fehler tritt bei der ersten Verwendung eines Filters auf):
const GUID CAM = {0xbbefb6c7, 0x2fc4, 0x4139, 0xbb8b, 0xa58bba724083}; const GUID TEE = {0xCC58E280, 0x8AA1, 0x11D1, 0xB3F1, 0x00AA003761C5}; const GUID AVI = {0xCF49D4E0, 0x1115, 0x11CE, 0xB03A, 0x0020AF0BA770}; const GUID CCOLOR = {0x1643E180, 0x90F5, 0x11CE, 0x97D5, 0x00AA0055595A}; const GUID RENDERER = {0x70E102B0, 0x5556, 0x11Ce, 0x97C0, 0x00AA0055595A}; IMoniker **devs = GetDevices(); ListDevices(); //Basis-Filter für jedes Filterobjekt IBaseFilter *logitechCam = NULL; CoCreateInstance(CAM, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&logitechCam); IBaseFilter *smartTee = NULL; CoCreateInstance(TEE, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&smartTee); IBaseFilter *aviDecompressor = NULL; CoCreateInstance(AVI, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&aviDecompressor); IBaseFilter *colorConverter = NULL; CoCreateInstance(CCOLOR, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&colorConverter); IBaseFilter *vidRenderer = NULL; CoCreateInstance(RENDERER, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&vidRenderer); //Pins abfragen IPin *capture = NULL; logitechCam->FindPin(TEXT("Capture"), (IPin **)capture); IPin *teeInput = NULL; smartTee->FindPin(TEXT("Input"), (IPin **)teeInput); IPin *teeCapture = NULL; smartTee->FindPin(TEXT("Capture"), (IPin **)teeCapture); IPin *aviIn = NULL; aviDecompressor->FindPin(TEXT("XForm In"), (IPin **)aviIn); IPin *aviOut = NULL; aviDecompressor->FindPin(TEXT("XForm Out"), (IPin **)aviOut); IPin *colorIn = NULL; colorConverter->FindPin(TEXT("Input"), (IPin **)colorIn); IPin *colorOut = NULL; colorConverter->FindPin(TEXT("XForm Out"), (IPin **)colorOut); IPin *vidInput = NULL; vidRenderer->FindPin(TEXT("VMR Input0"), (IPin **)vidInput); //GraphManager erstellen IGraphBuilder *graphManager = NULL; IMediaControl *graphControl = NULL; CoCreateInstance(CLSID_FilterGraph , NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&graphManager); //Pins verbinden graphManager->Connect(capture, teeInput); graphManager->Connect(teeCapture, aviIn); graphManager->Connect(aviOut, colorIn); graphManager->Connect(colorOut, vidInput); graphManager->AddFilter(logitechCam, TEXT("Logitech HD Webcam C510")); graphManager->AddFilter(smartTee, TEXT("Smart Tee")); //graphManager->AddFilter(baseFilter, TEXT("HD Webcam C510")); graphManager->AddFilter(aviDecompressor, TEXT("AVI Decompressor")); graphManager->AddFilter(colorConverter, TEXT("Color Space Converter")); graphManager->AddFilter(vidRenderer, TEXT("Video Renderer")); //graphManager->AddFilter(baseFilter, TEXT("Default DirectSound Device")); //graphManager->AddFilter(baseFilter, TEXT("Smart Tee")); //Basis-Filter freigeben logitechCam->Release(); smartTee->Release(); aviDecompressor->Release(); colorConverter->Release(); vidRenderer->Release(); graphManager->QueryInterface(IID_IMediaControl, (void **)graphControl); graphControl->Run();
Vllt hat jemand auch eine Idee, wie man die GUID's der Filter als Konstante bekommt(Momentan aus GraphEdit in der zweiten Gruppe die ID's genommen).
Über ein sehr ausführliches DirectShow Tutorial wäre ich auch sehr dankbar(Noch neu in DirectShow und COM)Mit freundlichen Grüßen
Anon
-
Problem gelöst, habe jedoch ein neues Problem, und zwar möchte ich den Stream meiner Webcam jetzt in einem Fenster darstellen, jedoch sehe ich immer nur kurz ein Fenster, das sich sofort wieder schleißt. Hier der Code:
#include <Windows.h> #include <dshow.h> #include <d3d9.h> #include <vmr9.h> #include <comutil.h> #include <stdlib.h> #include <InitGuid.h> #pragma comment(lib, "strmiids.lib") /* * Funktion zum Ermitteln aller ansprechbaren Devices. * Rückgabe VerketteteListe mit den Objekten. */ IMoniker** GetDevices() { IMoniker *dev = NULL; IMoniker **devList = NULL; IEnumMoniker *devs = NULL; ICreateDevEnum *enumDevs = NULL; HRESULT ret = NULL; ULONG fetched = NULL; int i = 0; //COMInitialisieren CoInitialize(NULL); //Speicher für DevList anfordern devList = (IMoniker **)malloc(sizeof(IMoniker)); //EnumListe erstelen für VideoDevices CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&enumDevs); //Alles gut ? if(SUCCEEDED(ret)) { //Enumerator für GeräteKlasse erstellen enumDevs->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &devs, 0); //Alles gut ? if(SUCCEEDED(ret)) { //Solange noch geräte vorhanden sind while(devs->Next(1, &dev, &fetched) == S_OK) { devList = (IMoniker **)realloc(devList, (i + 1) * sizeof(IMoniker)); devList[i] = dev; i++; } } } //Objekte freigeben enumDevs->Release(); devs->Release(); return devList; } /* * Funktion zur Ausgabe aller ermittelten DeviceNames. */ void ListDevices() { IMoniker **devs = GetDevices(); IPropertyBag *propBag; VARIANT deviceName; //Größe des arrays ermitteln int size = sizeof(devs) / sizeof(IMoniker); //Ausgabe aller Geräte for(int i = 0; i < size; i++) { devs[i]->BindToStorage(0, 0, IID_IPropertyBag, (void **)&propBag); VariantInit(&deviceName); propBag->Read(TEXT("FriendlyName"), &deviceName, 0); MessageBox(NULL, deviceName.bstrVal, TEXT("ID Von Device"), 0); VariantClear(&deviceName); } } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) { //const GUID CAM = {0xbbefb6c7, 0x2fc4, 0x4139, 0xbb8b, 0xa58bba724083}; //const GUID TEE = {0xCC58E280, 0x8AA1, 0x11D1, 0xB3F1, 0x00AA003761C5}; //const GUID AVI = {0xCF49D4E0, 0x1115, 0x11CE, 0xB03A, 0x0020AF0BA770}; //const GUID CCOLOR = {0x1643E180, 0x90F5, 0x11CE, 0x97D5, 0x00AA0055595A}; //const GUID RENDERER = {0x70E102B0, 0x5556, 0x11Ce, 0x97C0, 0x00AA0055595A}; IMoniker **devs = GetDevices(); ListDevices(); //Filter für den Stream ICaptureGraphBuilder2 *capGraph = NULL; CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&capGraph); //VideoWindow IVideoWindow *vidWindow = NULL; //Basis-Filter für jedes Filterobjekt IBaseFilter *logitechCam = NULL; devs[0]->BindToObject(0, 0, IID_IBaseFilter, (void **)&logitechCam); //CoCreateInstance(CAM, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&logitechCam); /*IBaseFilter *smartTee = NULL; CoCreateInstance(TEE, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&smartTee);*/ IBaseFilter *aviDecompressor = NULL; CoCreateInstance(CLSID_AVIDec, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&aviDecompressor); //IBaseFilter *colorConverter = NULL; /*CoCreateInstance(CCOLOR, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&colorConverter);*/ IBaseFilter *vidRenderer = NULL; CoCreateInstance(CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&vidRenderer); //Pins abfragen IPin *capture = NULL; logitechCam->FindPin(TEXT("Capture"), (IPin **)capture); //IPin *teeInput = NULL; //smartTee->FindPin(TEXT("Input"), (IPin **)teeInput); //IPin *teeCapture = NULL; //smartTee->FindPin(TEXT("Capture"), (IPin **)teeCapture); IPin *aviIn = NULL; aviDecompressor->FindPin(TEXT("XForm In"), (IPin **)aviIn); IPin *aviOut = NULL; aviDecompressor->FindPin(TEXT("XForm Out"), (IPin **)aviOut); //IPin *colorIn = NULL; //colorConverter->FindPin(TEXT("Input"), (IPin **)colorIn); //IPin *colorOut = NULL; //colorConverter->FindPin(TEXT("XForm Out"), (IPin **)colorOut); IPin *vidInput = NULL; vidRenderer->FindPin(TEXT("VMR Input0"), (IPin **)vidInput); //GraphManager erstellen IGraphBuilder *graphManager = NULL; IMediaControl *graphControl = NULL; CoCreateInstance(CLSID_FilterGraph , NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&graphManager); //Pins verbinden //graphManager->Connect(capture, teeInput); //graphManager->Connect(teeCapture, aviIn); //graphManager->Connect(aviOut, colorIn); //graphManager->Connect(colorOut, vidInput); graphManager->Connect(capture, aviIn); graphManager->Connect(aviOut, vidInput); graphManager->AddFilter(logitechCam, TEXT("Logitech HD Webcam C510")); //graphManager->AddFilter(smartTee, TEXT("Smart Tee")); //graphManager->AddFilter(baseFilter, TEXT("HD Webcam C510")); graphManager->AddFilter(aviDecompressor, TEXT("AVI Decompressor")); //graphManager->AddFilter(colorConverter, TEXT("Color Space Converter")); graphManager->AddFilter(vidRenderer, TEXT("Video Renderer")); //graphManager->AddFilter(baseFilter, TEXT("Default DirectSound Device")); //graphManager->AddFilter(baseFilter, TEXT("Smart Tee")); graphManager->QueryInterface(IID_IVideoWindow, (void **)&vidWindow); vidWindow->put_Visible(OATRUE); vidWindow->put_AutoShow(OATRUE); vidWindow->put_Owner((OAHWND)GetDesktopWindow()); vidWindow->SetWindowPosition(50, 50, 400, 400); vidWindow->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS); vidRenderer->QueryInterface(IID_IVideoWindow, (void **)&vidWindow); graphManager->QueryInterface(IID_IMediaControl, (void **)&graphControl); capGraph->SetFiltergraph(graphManager); capGraph->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, logitechCam, NULL, vidRenderer); graphControl->Run(); //vidRenderer->Run(0); /* //CaptureGraph erstellen für die Stream Wiedergabe ICaptureGraphBuilder2 *graphBuilder = NULL; CoCreateInstance(CLSID_CaptureGraphBuilder, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void **)&graphBuilder); //Graphbuilder für die Filter Erstellung IGraphBuilder *graph = NULL; CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&graph); //Mediaevent für die VideoKontrolle IMediaEvent *mediaEvent = NULL; graph->QueryInterface(IID_IMediaEvent, (void **)&mediaEvent); IMediaControl *mediaControl = NULL; graph->QueryInterface(IID_IMediaControl, (void **)&mediaControl); IVideoWindow *window = NULL; graph->QueryInterface(IID_IVideoWindow, (void **)&window); window->put_Owner((OAHWND)GetDesktopWindow()); window->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS); //Filter zuordnen graphBuilder->SetFiltergraph(graph); //Gerät an Filter binden IBaseFilter *baseFilter = NULL; devs[0]->BindToObject(0, 0, IID_IBaseFilter, (void **)&baseFilter); //Filter für die Wiedergabe binden graph->AddFilter(baseFilter, TEXT("Video Capture")); //Stream beginnen graphBuilder->RenderStream(NULL, NULL, NULL, baseFilter, NULL); //Stream laufen lassen. mediaControl->Run(); */ //Speicher wieder freigeben free(devs); //ComUninitialisieren CoUninitialize(); return 0; }
Mit freundlichen Grüßen
Anon
-
Schon mal was von nem debugger gehört?
Rückgabewerte prüfen wäre auch noch was für Dich.
-
Benutze nen Debugger, und schaue mir dort auch die Rückgabewerte an(Läuft ja auch, jedoch ist es mir unerklärlich, warum das Fenster wieder geschlossen wird. Übrigens sehr hilfreicher Beitrag)
-
Naja, Deine Anwendung beendet sich doch auch. Damit werden eben auch alle Fenster geschlossen, die die Anwendung erstellt hat (in Deinem Fall das Video-Window).
-
Das ist schon richtig, jedoch selbst wenn ich das Return Statement entferne, wird das Fenster geschlossen. Ich müsste als irgendeine Art Nachrichtenschleife oder Callback funktion haben, jedoch wüsste ich jetzt nicht, was man in DirectShow dort nehmen könnte.
-
Problem gelöst (hattes recht mit dem Return) habe jetzt ein Fenster erzeugt, in dem die Daten gecaptured werden.
Mit freundlichen Grüßen
Anon
-
Siehst du!