DirectShow |
It is a set of APIs for multimedia to perform operations with media files (audio and video) or streams. Es un conjunto de APis para multimedia para realizar operaciones con archivos de media (sonido y video). |
Problem 1 |
Create a Wintempla Window application called MyVideoX to test a digital video camera. After creating the application, select the App event (WM_APP), Close (WM_CLOSE), Size (WM_SIZE) and WindowPosChanged (WM_WINDOWPOSCHANGED) as shown. Cree una aplicación de Ventana de Wintempla llamada MyVideoX para probar una cámara de video digital. Después de crear la aplicación, selecciona el evento App (WM_APP), Close (WM_CLOSE), Size (WM_SIZE), WindowPosChanged (WM_WINDOWPOSCHANGED) cómo se muestra. |
Step A |
Edit the stdafx.h file as shown. Add the following code at the end of the file. Edite el archivo stdafx.h cómo se muestra. Agregue el siguiente código al final del archivo. |
stdafx.h |
... //_____________________________________________________ DirectShow Libraries #include "Dshow.h" #pragma comment(lib, "Strmiids.lib") _COM_SMARTPTR_TYPEDEF(ICaptureGraphBuilder2, __uuidof(ICaptureGraphBuilder2)); _COM_SMARTPTR_TYPEDEF(IGraphBuilder, __uuidof(IGraphBuilder)); _COM_SMARTPTR_TYPEDEF(IFilterGraph, __uuidof(IFilterGraph)); _COM_SMARTPTR_TYPEDEF(IEnumMoniker, __uuidof(IEnumMoniker)); _COM_SMARTPTR_TYPEDEF(IMoniker, __uuidof(IMoniker)); _COM_SMARTPTR_TYPEDEF(IPropertyBag, __uuidof(IPropertyBag)); _COM_SMARTPTR_TYPEDEF(IMediaControl, __uuidof(IMediaControl)); _COM_SMARTPTR_TYPEDEF(IVideoWindow, __uuidof(IVideoWindow)); _COM_SMARTPTR_TYPEDEF(IMediaEventEx, __uuidof(IMediaEventEx)); _COM_SMARTPTR_TYPEDEF(IBaseFilter, __uuidof(IBaseFilter)); _COM_SMARTPTR_TYPEDEF(ICreateDevEnum, __uuidof(ICreateDevEnum)); |
Step B |
Edit the files MyVideoX.h and MyVideoX.cpp. Edite los archivos MyVideoX.h y MyVideoX.cpp. |
MyVideoX.h |
#pragma once //______________________________________ MyVideoX.h #include "Resource.h" class MyVideoX: public Win::Window { public: MyVideoX() { ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); graphBuilder = NULL; captureGraphBuilder2 = NULL; filterGraph = NULL; mediaControl = NULL; videoWindow = NULL; mediaEventEx = NULL; playState = Stopped; } ~MyVideoX() { mediaEventEx = NULL; videoWindow = NULL; mediaControl = NULL; filterGraph = NULL; captureGraphBuilder2 = NULL; graphBuilder = NULL; ::CoUninitialize(); } enum PLAYSTATE { Stopped, Paused, Running, Init }; IGraphBuilderPtr graphBuilder; ICaptureGraphBuilder2Ptr captureGraphBuilder2; IFilterGraphPtr filterGraph; IMediaControlPtr mediaControl; IVideoWindowPtr videoWindow; IMediaEventExPtr mediaEventEx; PLAYSTATE playState = Stopped; // bool GetFirstVideoDevice(IBaseFilterPtr& baseFilter); HRESULT SetupVideoWindow(); void ResizeVideoWindow(); ... }; |
MyCap.cpp |
... void MyVideoX::Window_Open(Win::Event& e) { HRESULT hr; //____________________________________________________ 1. Create the ICaptureGraphBuilder2 hr = captureGraphBuilder2.CreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC); if (FAILED(hr)) { this->MessageBox(L"Unable to create ICaptureGraphBuilder2", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //____________________________________________________ 2. Create the IFilterGraph hr = filterGraph.CreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC); if (FAILED(hr)) { this->MessageBox(L"Unable to create IFilterGraph", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //____________________________________________________ 3. Get a IGraphBuilder graphBuilder = filterGraph; if (graphBuilder == NULL) { this->MessageBox(L"Unable to get IGraphBuilder", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //____________________________________________________ 4. Get a IMediaControl interface mediaControl = filterGraph; if (mediaControl == NULL) { this->MessageBox(L"Unable to get IMediaControl", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //____________________________________________________ 5. Get a IVideoWindow interface videoWindow = filterGraph; if (videoWindow == NULL) { this->MessageBox(L"Unable to get IVideoWindow", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //____________________________________________________ 6. Get a IMediaEventEx interface mediaEventEx = filterGraph; if (mediaEventEx == NULL) { this->MessageBox(L"Unable to get IMediaEventEx", L"MyVideoX", MB_OK | MB_ICONERROR); return; } hr = mediaEventEx->SetNotifyWindow((OAHWND)hWnd, WM_APP, 0); if (FAILED(hr)) { this->MessageBox(L"Error mediaEventEx->SetNotifyWindow", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //____________________________________________________ 7. Attach the IFilterGraph to the ICaptureGraphBuilder2 hr = captureGraphBuilder2->SetFiltergraph(graphBuilder); if (FAILED(hr)) { this->MessageBox(L"Error captureGraphBuilder2->SetFiltergraph", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //_____________________________________________________ 8. Set window handle used to process graph events IBaseFilterPtr baseFilter; if (GetFirstVideoDevice(baseFilter) == false) { this->MessageBox(L"No video device is available", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //_____________________________________________________ 9. RenderStream hr = captureGraphBuilder2->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, baseFilter, NULL, NULL); if (FAILED(hr)) { this->MessageBox(L"The capture device may already be in use by another application.", L"MyVideoX", MB_OK | MB_ICONERROR); return; } baseFilter = NULL; hr = SetupVideoWindow(); if (FAILED(hr)) { this->MessageBox(L"Couldn't initialize video window!", L"MyVideoX", MB_OK | MB_ICONERROR); return; } //#ifdef REGISTER_FILTERGRAPH // // Add our graph to the running object table, which will allow // // the GraphEdit application to "spy" on our graph // hr = AddGraphToRot(g_pGraph, &g_dwGraphRegister); // if (FAILED(hr)) // { // Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr); // g_dwGraphRegister = 0; // } //#endif hr = mediaControl->Run(); if (FAILED(hr)) { this->MessageBox(L"mediaControl->Run()", L"MyVideoX", MB_OK | MB_ICONERROR); return; } playState = Running; } void MyVideoX::Window_App(Win::Event& e) { if (mediaEventEx == NULL) { HRESULT hr; LONG code; LONG_PTR param1, param2; hr = mediaEventEx->GetEvent(&code, ¶m1, ¶m2, 0); if (SUCCEEDED(hr)) { hr = mediaEventEx->FreeEventParams(code, param1, param2); } } } bool MyVideoX::GetFirstVideoDevice(IBaseFilterPtr& baseFilter) { HRESULT hr; //_________________________________________________ 1. Create the ICreateDevEnumPtr ICreateDevEnumPtr createDevEnum = NULL; hr = createDevEnum.CreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER); if (FAILED(hr)) { this->MessageBox(L"Unable to create ICreateDevEnumPtr", L"MyVideoX", MB_OK | MB_ICONERROR); return false; } IEnumMonikerPtr enumMoniker; //hr = createDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &enumMoniker, 0); hr = createDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &enumMoniker, 0); if (SUCCEEDED(hr)) { if (enumMoniker == NULL) return false; IMonikerPtr moniker = NULL; IPropertyBagPtr propertyBag = NULL; VARIANT var; VariantInit(&var); //_____________________________________________ 2. List Devices while (enumMoniker->Next(1, &moniker, NULL) == S_OK) { hr = moniker->BindToStorage(0, 0, IID_PPV_ARGS(&propertyBag)); if (FAILED(hr)) { moniker = NULL; continue; } hr = propertyBag->Read(L"Description", &var, 0); if (FAILED(hr)) { hr = propertyBag->Read(L"FriendlyName", &var, 0); } if (SUCCEEDED(hr)) { this->Text = var.bstrVal; VariantClear(&var); baseFilter = NULL; hr = moniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&baseFilter); if (SUCCEEDED(hr)) { hr = filterGraph->AddFilter(baseFilter, L"Capture Filter"); return true; } break; } moniker = NULL; } } return false; } void MyVideoX::Window_Size(Win::Event& e) { ResizeVideoWindow(); } void MyVideoX::Window_Close(Win::Event& e) { this->Show(SW_HIDE); mediaControl->StopWhenReady(); playState = Stopped; mediaEventEx->SetNotifyWindow(NULL, WM_APP, 0); if (videoWindow != NULL) { videoWindow->put_Visible(OAFALSE); videoWindow->put_Owner(NULL); } #ifdef REGISTER_FILTERGRAPH // Remove filter graph from the running object table if (g_dwGraphRegister) RemoveGraphFromRot(g_dwGraphRegister); #endif this->Destroy(); } void MyVideoX::Window_WindosPosChanged(Win::Event& e) { if (mediaControl == NULL) return; HRESULT hr = S_OK; if (IsIconic(hWnd) == FALSE) { if (playState != Running) { //_________________ 1. Start previewing video data hr = mediaControl->Run(); playState = Running; } } else { //___________________ 2. Stop previewing video data hr = mediaControl->StopWhenReady(); playState = Stopped; } } HRESULT MyVideoX::SetupVideoWindow() { HRESULT hr; //_____________________________________ 1. Set the video window to be a child of the main window hr = videoWindow->put_Owner((OAHWND)hWnd); if (FAILED(hr)) return hr; //_____________________________________ 2. Set video window style hr = videoWindow->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); if (FAILED(hr)) return hr; ResizeVideoWindow(); hr = videoWindow->put_Visible(OATRUE); if (FAILED(hr)) return hr; return hr; } void MyVideoX::ResizeVideoWindow() { if (videoWindow != NULL) { RECT rc; this->GetClientRect(rc); videoWindow->SetWindowPosition(0, 0, rc.right, rc.bottom); } } |