Problem mit IVideoWindow bei DirectShow
-
Hallo,
ich habe versucht das DirectX-Sample PlayCap nachzuarbeiten.
Leider tritt bei mir der Fehler in der folgenden Anweisung auf:// Set the video window to be a child of the main window hr = pVW->put_Owner((OAHWND)hWnd); if (FAILED(hr)) { MessageBox(NULL, "Test", "Test", MB_ICONINFORMATION | MB_OK); return hr; }d.h. mein Fenster kann nicht als Videoausgabefenster genutzt werden, warum?
Lasse ich die Methode SetupVideoWindow weg, funktioniert alles, nur das ich ein extra Fenster zur ausgabe bekomme.
Hier der gesamte Code:
// DSTest.cpp : Definiert den Einsprungpunkt für die Anwendung. // #include "stdafx.h" #include "resource.h" #include "Dshow.h" #include "string" using namespace std; #define MAX_LOADSTRING 100 // Globale Variablen: HINSTANCE hInst; // aktuelle Instanz TCHAR szTitle[MAX_LOADSTRING]; // Text der Titelzeile TCHAR szWindowClass[MAX_LOADSTRING]; // Text der Titelzeile IGraphBuilder *pGraph = NULL; ICaptureGraphBuilder2 *pCap = NULL; IBaseFilter *pFilter = NULL; IVideoWindow * pVW = NULL; IMediaControl * pMC = NULL; HWND hWnd; // Vorausdeklarationen von Funktionen, die in diesem Code-Modul enthalten sind: ATOM MyRegisterClass( HINSTANCE hInstance ); BOOL InitInstance( HINSTANCE, int ); LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); LRESULT CALLBACK About( HWND, UINT, WPARAM, LPARAM ); HRESULT Init(void); HRESULT InitCaptureDevice(void); HRESULT SetupVideoWindow(void); void ResizeVideoWindow(void); void CleanUp(void); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ) { // ZU ERLEDIGEN: Fügen Sie hier den Code ein. MSG msg; HACCEL hAccelTable; // Globale Zeichenfolgen initialisieren LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_DSTEST, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Initialisierung der Anwendung durchführen: if( !InitInstance( hInstance, nCmdShow ) ) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_DSTEST); //Startausführungen Init(); // Hauptnachrichtenschleife: while( GetMessage(&msg, NULL, 0, 0) ) { if( !TranslateAccelerator (msg.hwnd, hAccelTable, &msg) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); } } //Säuberung CleanUp(); return msg.wParam; } // // FUNKTION: MyRegisterClass() // // AUFGABE: Registriert die Fensterklasse. // // KOMMENTARE: // // Diese Funktion und ihre Verwendung sind nur notwendig, wenn dieser Code // mit Win32-Systemen vor der 'RegisterClassEx'-Funktion kompatibel sein soll, // die zu Windows 95 hinzugefügt wurde. Es ist wichtig diese Funktion aufzurufen, // damit der Anwendung kleine Symbole mit den richtigen Proportionen zugewiesen // werden. // ATOM MyRegisterClass( HINSTANCE hInstance ) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DSTEST); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = (LPCSTR)IDC_DSTEST; wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL); return RegisterClassEx(&wcex); } // // FUNKTION: InitInstance(HANDLE, int) // // AUFGABE: Speichert die Instanzzugriffsnummer und erstellt das Hauptfenster // // KOMMENTARE: // // In dieser Funktion wird die Instanzzugriffsnummer in einer globalen Variable // gespeichert und das Hauptprogrammfenster erstellt und angezeigt. // BOOL InitInstance( HINSTANCE hInstance, int nCmdShow ) { hInst = hInstance; // Instanzzugriffsnummer in unserer globalen Variable speichern hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if( !hWnd ) { return FALSE; } ShowWindow( hWnd, nCmdShow ); UpdateWindow( hWnd ); return TRUE; } // // FUNKTION: WndProc(HWND, unsigned, WORD, LONG) // // AUFGABE: Verarbeitet Nachrichten für das Hauptfenster. // // WM_COMMAND - Anwendungsmenü verarbeiten // WM_PAINT - Hauptfenster darstellen // WM_DESTROY - Beendigungsnachricht ausgeben und zurückkehren // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; TCHAR szHello[MAX_LOADSTRING]; LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING); switch( message ) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Menüauswahlen analysieren: switch( wmId ) { case IDM_\1: DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About); break; case IDM_EXIT: DestroyWindow( hWnd ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } break; case WM_PAINT: hdc = BeginPaint (hWnd, &ps); // ZU ERLEDIGEN: Hier beliebigen Code zum Zeichnen hinzufügen... RECT rt; GetClientRect( hWnd, &rt ); DrawText( hdc, szHello, strlen(szHello), &rt, DT_CENTER ); EndPaint( hWnd, &ps ); break; case WM_DESTROY: PostQuitMessage( 0 ); break; default: return DefWindowProc( hWnd, message, wParam, lParam ); } return 0; } // Nachrichtenbehandlungsroutine für "Info"-Feld. LRESULT CALLBACK About( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam ) { switch( message ) { case WM_INITDIALOG: return TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return TRUE; } break; } return FALSE; } HRESULT Init(void) { CoInitialize(NULL); HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pCap); if (SUCCEEDED(hr)) { // Create the Filter Graph Manager. hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&pGraph); if (SUCCEEDED(hr)) { // Initialize the Capture Graph Builder. pCap->SetFiltergraph(pGraph); hr = pGraph->QueryInterface(IID_IMediaControl,(LPVOID *) &pMC); if (FAILED(hr)) return hr; //Device initialisieren hr = InitCaptureDevice(); if (SUCCEEDED(hr)) { MessageBox(NULL, "CaptureDevice initialisiert", "Information", MB_ICONINFORMATION | MB_OK ); hr = pCap->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, pFilter, NULL, NULL); // Obtain interfaces for media control and Video Window hr = pMC->Run(); } return S_OK; } else MessageBox(NULL, "Fehler bei der Initialisierung des GraphBuilders", "Fehler", MB_ICONSTOP | MB_OK); } else MessageBox(NULL, "Fehler bei der Initialisierung des CaptureGraphBuilders", "Fehler", MB_ICONSTOP | MB_OK); return hr; }
-
Hier der Rest:
HRESULT InitCaptureDevice(void) { ICreateDevEnum *pDevEnum = NULL; IEnumMoniker *pEnum = NULL; IMoniker *pMoniker = NULL; // Create the System Device Enumerator. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast<void**>(&pDevEnum)); if (SUCCEEDED(hr)) { // Create an enumerator for the video capture category. hr = pDevEnum->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &pEnum, 0); if (FAILED(hr)) { MessageBox(NULL, "Fehler bei der Initialisierung des VideoDeviceEnumerator", "Fehler", MB_ICONSTOP | MB_OK); return hr; } else { //Device auswählen while (pEnum->Next(1, &pMoniker, NULL) == S_OK) { IPropertyBag *pPropBag; hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void**)(&pPropBag)); if (FAILED(hr)) { pMoniker->Release(); continue; // Skip this one, maybe the next one will work. } if (SUCCEEDED(hr)) { //Devicename ausgeben und setzen VARIANT varName; hr = pPropBag->Read(L"FriendlyName", &varName, 0); //MessageBox(NULL, varName.bstrVal, "Device gefunden", MB_ICONINFORMATION | MB_OK); //Capturefilter dem CaptureGraphBuilder hinzufügen hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&pFilter); if (SUCCEEDED(hr)) { hr = pGraph->AddFilter(pFilter, L"Capture Filter"); hr = SetupVideoWindow(); return hr; } } } } } else MessageBox(NULL, "Fehler bei der Initialisierung des SystemDeviceEnumerator", "Fehler", MB_ICONSTOP | MB_OK); return hr; } void CleanUp(void) { pCap->Release(); pGraph->Release(); pFilter->Release(); pVW->Release(); } HRESULT SetupVideoWindow(void) { HRESULT hr; hr = pGraph->QueryInterface(IID_IVideoWindow, (LPVOID *) &pVW); if (FAILED(hr)) { return hr; } // Set the video window to be a child of the main window hr = pVW->put_Owner((OAHWND)hWnd); if (FAILED(hr)) { MessageBox(NULL, "Test", "Test", MB_ICONINFORMATION | MB_OK); return hr; } // Set video window style hr = pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); if (FAILED(hr)) return hr; // Use helper function to position video window in client rect // of main application window ResizeVideoWindow(); // Make the video window visible, now that it is properly positioned hr = pVW->put_Visible(OATRUE); if (FAILED(hr)) return hr; return hr; } void ResizeVideoWindow(void) { // Resize the video preview window to match owner window size if (pVW) { RECT rc; // Make the preview video fill our window GetClientRect(hWnd, &rc); pVW->SetWindowPosition(0, 0, rc.right, rc.bottom); } }
-
Da wäre es sicher auch hilfreich, wenn du den genauen Fehlercode angeben könntest, den put_Owner ausspuckt.
(was mir nach einem Blick in die MSDN einfällt wäre höchstens ein VFW_E_NOT_CONNECTED - d.h. du müsstest erst deinen Graphen zusammenbauen und dann das Videofenster festlegen)
-
Falls Du Dein Problem gelöst hast wär's ganz nett, wenn Du kurz für Nachfolger schreibst, WIE...

-
Hallo,
hab das Problem gefunden, das VideoWindow muss ganz als letztes gestartet werden.