www.pudn.com > VideoSender.rar > Video.cpp
// Video.cpp: implementation of the CVideo class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "VideoSender.h" #include "Video.h" #pragma comment (lib ,"Quartz.lib") #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #include#include #define SAFE_RELEASE(x) { if (x) x->Release(); x = NULL; } ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// //{CE3B76CB-9540-48FA-9974-69A625D478E3} DEFINE_GUID(CLSID_NetSource, 0xCE3B76CB,0x9540,0x48FA,0x99,0x74,0x69,0xa6,0x25,0xd4,0x78,0xe3); DEFINE_GUID(CLSID_Divx, 0x78766964,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); //{D76E2820-1563-11CF-AC98-00AA004C0FA9}{D76E2820-1563-11CF-AC98-00AA004C0FA9} DEFINE_GUID(CLSID_EDivx, 0xD76E2820,0x1563,0x11CF,0xAC,0x98,0x00,0xAA,0x00,0x4C,0x0F,0xA9); DEFINE_GUID(CLSID_IPMulticastSendProppage, 0x3ec9c19, 0x13c4, 0x43d7, 0xb1, 0x83, 0x89, 0x5c, 0xb8, 0x9e, 0x76, 0x1c); //{0x1CB42CC8,0xD32C,0x4f73,{0x92,0x67,0xC1,0x14,0xDA,0x47,0x03,0x78}}; //DEFINE_GUID(IID_IVideoWindow, //0x56a868b4,0x0ad4,0x11ce,0xb0,0x3a,0x00,0x20,0xaf,0x0b,0xa7,0x70); ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// DEFINE_GUID(CLSID_AVIDecopress, 0xCF49D4E0, 0x1115, 0x11CE, 0xb0, 0x3a, 0x00, 0x20, 0xaf, 0x0b, 0xa7, 0x70); //{CF49D4E0-1115-11CE-B03A-0020AF0BA770} DEFINE_GUID(CLSID_device, 0x17CCA71B, 0xECD7, 0x11D0, 0xb9, 0x08, 0x00, 0xa0, 0xc9, 0x22, 0x31, 0x96); //{17CCA71B-ECD7-11D0-B908-00A0C9223196} DEFINE_GUID(CLSID_DDivx, 0x78766964,0x0000,0x0010,0x80,0x00,0x00,0xAA,0x00,0x38,0x9B,0x71); //{CC58E280-8AA1-11D1-B3F1-00AA003761C5} DEFINE_GUID(CLSID_SMartTree, 0xCC58E280,0x8AA1,0x11D1,0xb3,0xf1,0x00,0xAA,0x00,0x37,0x61,0xc5); //{D76E2820-1563-11CF-AC98-00AA004C0FA9} DEFINE_GUID(CLSID_Divx_4_Encoder, 0xD76E2820,0x1563,0x11CF,0xAC,0x98,0x00,0xAA,0x00,0x4c,0x0f,0xa9); CVideo::CVideo() { } CVideo::~CVideo() { RemoveGraphFromRot(dwRegister); } BOOL CVideo::Init() { HRESULT hr; hr=CoInitialize(NULL); if(S_OK!=hr) return FALSE; return TRUE; } BOOL CVideo::Run() { HRESULT hr; hr=InitCaptureGraphBuilder(&pGraph,&pBuilder); if(FAILED(hr)) return false; ICreateDevEnum *pSysDevEnum=NULL; hr=CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,IID_ICreateDevEnum,(void **)&pSysDevEnum); if(FAILED(hr)) return false; hr=AddGraphToRot(pGraph,&dwRegister); IEnumMoniker *pEnumCat=NULL; hr=pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnumCat,0); if(hr==S_OK) { IMoniker *pMoniker=NULL; ULONG cFetched; while(pEnumCat->Next(1,&pMoniker,&cFetched)==S_OK) { IPropertyBag *pPropBag; hr=pMoniker->BindToStorage(0,0,IID_IPropertyBag,(void **)&pPropBag); if(SUCCEEDED(hr)) { VARIANT varName; VariantInit(&varName); hr=pPropBag->Read(L"FriendlyName",&varName,0); if(SUCCEEDED(hr)) { //desplay the name } VariantClear(&varName); hr=pMoniker->BindToObject(NULL,NULL,IID_IBaseFilter,(void **)&Device); pGraph->AddFilter(Device,L"video source"); pPropBag->Release(); } pMoniker->Release(); } pEnumCat->Release(); } pSysDevEnum->Release(); /// IBaseFilter *avicompress,*Render,*DDcoder,*Tree,*DivxEncorder4; /* hr=AddFilterByCLSID(pGraph,CLSID_AVIDecopress,L"AVI COMPRESS",&avicompress); if(FAILED(hr)) { ShowErrMsg(hr,"add avi filter"); return false; } hr=AddFilterByCLSID(pGraph,CLSID_VideoRenderer,L"Video Renderer",&Render); if(FAILED(hr)) { ShowErrMsg(hr,"添加播放视频滤镜失败"); return FALSE; }*/ /* IBaseFilter *te; hr=AddFilterByCLSID(pGraph,CLSID_EDivx,L"Divx Video Codec V3",&te); if(FAILED(hr)) { ShowErrMsg(hr,"add Encoder filter"); return false; } SetDivxCompressorProp(te); /* hr=AddFilterByCLSID(pGraph,CLSID_SMartTree,L"SMart Tree",&Tree); if(FAILED(hr)) { ShowErrMsg(hr,"add Encoder filter"); return false; } */ hr=AddFilterByCLSID(pGraph,CLSID_NetSource,L"Divx Multicast Sender",&Sender); if(FAILED(hr)) { ShowErrMsg(hr,"add sender filter"); return false; } /* hr=AddFilterByCLSID(pGraph,CLSID_DDivx,L"Divx Decorder",&DDcoder); if(FAILED(hr)) { ShowErrMsg(hr,"add sender filter"); return false; } */ hr=AddFilterByCLSID(pGraph,CLSID_Divx_4_Encoder,L"Divx-4 Encorder",&ECoder); if(FAILED(hr)) { ShowErrMsg(hr,"add sender filter"); return false; } SetDivxCompressorProp(ECoder); //TEST 5.10 /* IAMStreamConfig *pSC; hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, gcap.pVCap, IID_IAMStreamConfig, (void **)&pSC); if(hr != NOERROR) hr = gcap.pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, gcap.pVCap, IID_IAMStreamConfig, (void **)&pSC); ISpecifyPropertyPages *pSpec; CAUUID cauuid; hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); if(hr == S_OK) { hr = pSpec->GetPages(&cauuid); hr = OleCreatePropertyFrame(ghwndApp, 30, 30, NULL, 1, (IUnknown **)&pSC, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL); // !!! What if changing output formats couldn't reconnect // and the graph is broken? Shouldn't be possible... if(gcap.pVSC) { AM_MEDIA_TYPE *pmt; // get format being used NOW hr = gcap.pVSC->GetFormat(&pmt); // DV capture does not use a VIDEOINFOHEADER if(hr == NOERROR) { if(pmt->formattype == FORMAT_VideoInfo) { // resize our window to the new capture size ResizeWindow(HEADER(pmt->pbFormat)->biWidth, abs(HEADER(pmt->pbFormat)->biHeight)); } DeleteMediaType(pmt); } } CoTaskMemFree(cauuid.pElems); pSpec->Release(); } pSC->Release(); IAMVfwCaptureDialogs *pvfdia=NULL; hr=Device->QueryInterface(IID_IAMVfwCaptureDialogs,(void **)&pvfdia); if(SUCCEEDED(hr)) { hr=pvfdia->ShowDialog(VfwCaptureDialog_Source,NULL); } if(IsWDMCard(Device)) {//vdm card IAMStreamConfig *pConfig=NULL; AfxMessageBox("vdm"); } else {//vfm card AfxMessageBox("vfm"); } */ hr=ConnectFilters(pGraph,Device,ECoder); if(FAILED(hr)) { ShowErrMsg(hr,"connect device and Tree"); return false; } // hr=ConnectFilters(pGraph,Tree,ECoder); // if(FAILED(hr)) // { // ShowErrMsg(hr,"connect Tree and ECoder"); // return false; // } // hr=ConnectFilters(pGraph,avicompress,DDcoder); // if(FAILED(hr)) // { // ShowErrMsg(hr,"connect ECoder and Sender"); // return false; // } // hr=ConnectFilters(pGraph,DDcoder,avicompress); // if(FAILED(hr)) // { // ShowErrMsg(hr,"connect Tree and avicompress"); // return false; // } hr=ConnectFilters(pGraph,ECoder,Sender); if(FAILED(hr)) { ShowErrMsg(hr,"connect avicompress and Render"); return false; } DisplayPropertyPage("Divx Multicast Sender",false); hr=pGraph->QueryInterface(IID_IMediaControl,(void **)&pControl); if(FAILED(hr)) { ShowErrMsg(hr,"播放控制滤镜加载失败"); return FALSE; } hr=pControl->Pause (); if(FAILED(hr)) { ShowErrMsg(hr,"control filter run"); return false; } return TRUE; } HRESULT CVideo::AddFilterByCLSID(IGraphBuilder *pGraph,const GUID &clsid,LPCWSTR wszName,IBaseFilter **ppF) { if(!pGraph ||!ppF) return E_POINTER; *ppF=0; IBaseFilter *pF=0; HRESULT hr=CoCreateInstance(clsid,0,CLSCTX_INPROC_SERVER,IID_IBaseFilter,reinterpret_cast (&pF)); if(SUCCEEDED(hr)) { hr=pGraph->AddFilter(pF,wszName); if(SUCCEEDED(hr)) *ppF=pF; else pF->Release(); } return hr; } HRESULT CVideo::GetUnconnectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin) { *ppPin=0; IEnumPins *pEnum=0; IPin *pPin=0; HRESULT hr=pFilter->EnumPins(&pEnum); if(FAILED(hr))return hr; while(pEnum->Next(1,&pPin,NULL)==S_OK) { PIN_DIRECTION ThisPinDir; pPin->QueryDirection(&ThisPinDir); if(ThisPinDir==PinDir) { IPin *pTmp=0; hr=pPin->ConnectedTo(&pTmp); if(SUCCEEDED(hr)) pTmp->Release(); else { pEnum->Release(); *ppPin=pPin; return S_OK; } } pPin->Release(); } pEnum->Release(); return E_FAIL; } HRESULT CVideo::ConnectFilters(IGraphBuilder *pGraph, IPin *pOut, IBaseFilter *pDest) { if((pGraph==NULL)||(pOut==NULL)||(pDest==NULL)) return E_POINTER; IPin *pIn=0; HRESULT hr=GetUnconnectedPin(pDest,PINDIR_INPUT,&pIn); if(FAILED(hr)) { ShowErrMsg(hr,"df"); return hr; } PIN_INFO pof,pif; pOut->QueryPinInfo(&pof); pIn->QueryPinInfo(&pif); hr=pGraph->Connect(pOut,pIn); if(FAILED(hr)) { ShowErrMsg(hr,"df"); return hr; } pIn->Release(); return hr; } HRESULT CVideo::ConnectFilters(IGraphBuilder *pGraph, IBaseFilter *pSrc, IBaseFilter *pDest) { if((pGraph==NULL)||(pSrc==NULL)||(pDest==NULL)) return E_POINTER; IPin *pOut=0; HRESULT hr=GetUnconnectedPin(pSrc,PINDIR_OUTPUT,&pOut); if(FAILED(hr)) return hr; /* //test begin PIN_INFO pin_info; FILTER_INFO filter_info; pOut->QueryPinInfo(&pin_info); CString msg,str1,str2; str1.Format("Source Pin%s",pin_info.achName); pDest->QueryFilterInfo(&filter_info); str2.Format("connect with filter:%s",filter_info.achName); msg=str1+str2; AfxMessageBox(msg); //test end */ hr=ConnectFilters(pGraph,pOut,pDest); if(FAILED(hr)) { ShowErrMsg(hr,"df"); return hr; } pOut->Release(); return hr; } void CVideo::ShowProperPage() { DisplayPropertyPage("Divx Multicast Sender",false); } HRESULT CVideo::SetDivxCompressorProp(IBaseFilter *pFilter) { /* HRESULT hr = S_OK; ISpecifyPropertyPages *pProp = NULL; hr = pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pProp); if (SUCCEEDED(hr)) { // Get the filter's name and IUnknown pointer. FILTER_INFO FilterInfo; hr = pFilter->QueryFilterInfo(&FilterInfo); IUnknown *pFilterUnk; pFilter->QueryInterface(IID_IUnknown, (void **)&pFilterUnk); // Show the page. CAUUID caGUID; pProp->GetPages(&caGUID); pProp->Release(); OleCreatePropertyFrame( NULL, // Parent window 0, 0, // Reserved FilterInfo.achName, // Caption for the dialog box 1, // Number of objects (just the filter) &pFilterUnk, // Array of object pointers. caGUID.cElems, // Number of property pages caGUID.pElems, // Array of property page CLSIDs 0, // Locale identifier 0, NULL // Reserved ); // Clean up. pFilterUnk->Release(); FilterInfo.pGraph->Release(); CoTaskMemFree(caGUID.pElems); } return hr; */ /* IAMVfwCompressDialogs *pDivxSet; HRESULT hr = pFilter->QueryInterface(IID_IAMVfwCompressDialogs, (void **)&pDivxSet); hr =pDivxSet->ShowDialog(VfwCompressDialog_Config,NULL); if(FAILED(hr)) AfxMessageBox("falild"); pDivxSet->Release(); IAMVideoCompression *pVideoCom; WCHAR ver[20]; int version; WCHAR pDescription[40]; int de; long Keframrate; long dkeframrate; double qulity; long capli; HRESULT hr=pFilter->QueryInterface(IID_IAMVideoCompression,(void **)&pVideoCom); if(SUCCEEDED(hr)) { hr=pVideoCom->GetInfo(ver,&version,pDescription,&de,&Keframrate,&dkeframrate,&qulity,&capli); } else { ShowErrMsg(hr,"sow"); } return hr; */ IEnumPins *pEnum=NULL; IPin *pPin=NULL; HRESULT hr; IAMVideoCompression *pCompress=NULL; pFilter->EnumPins(&pEnum); while(S_OK==pEnum->Next(1,&pPin,NULL)) { hr = pPin->QueryInterface(IID_IAMVideoCompression, (void**)&pCompress); pPin->Release(); if (SUCCEEDED(hr)) // Found the interface. { break; } } if(SUCCEEDED(hr)) { long ICap; long IKeyFrame,IPFrame; double m_Quality; long IKeyFrameDef,IPFrameDef; double QualityDef; hr = pCompress->GetInfo(0, 0, 0, 0, &IKeyFrameDef, &IPFrameDef, &QualityDef, &ICap); if (SUCCEEDED(hr)) { if (ICap & CompressionCaps_CanKeyFrame) { hr = pCompress->get_KeyFrameRate(&IKeyFrame); if (FAILED(hr) || IKeyFrame < 0) IKeyFrame = IKeyFrameDef; hr=pCompress->put_KeyFrameRate(5); } if (ICap & CompressionCaps_CanBFrame) { hr = pCompress->get_PFramesPerKeyFrame(&IPFrame); if (FAILED(hr) || IPFrame < 0) IPFrame = IPFrameDef; } if (ICap & CompressionCaps_CanQuality) { hr = pCompress->get_Quality(&m_Quality); if (FAILED(hr) || m_Quality < 0) m_Quality = QualityDef; } } } return hr; } IBaseFilter* CVideo::FindFilterFromName(const char *pszFilterName) { IEnumFilters *pEnum = NULL; IBaseFilter *pFilter = NULL; ULONG cFetched; bool bFound = false; DWORD hr; hr=pGraph->EnumFilters(&pEnum); if(FAILED(hr)) return NULL; while((pEnum->Next(1, &pFilter, &cFetched) == S_OK) && (!bFound)) { FILTER_INFO FilterInfo; char szName[_MAX_PATH]; hr=pFilter->QueryFilterInfo(&FilterInfo); if(FAILED(hr)) { pFilter->Release(); pEnum->Release(); return NULL; } WideCharToMultiByte(CP_ACP, 0, FilterInfo.achName, -1, szName, _MAX_PATH, 0, 0); if(! lstrcmp(szName, pszFilterName)) bFound = true; FilterInfo.pGraph->Release(); if(!bFound) pFilter->Release(); else break; } pEnum->Release(); return (bFound ? pFilter : NULL); } bool CVideo::DisplayPropertyPage(const char *pszFilterName, bool test) { HRESULT hr; IBaseFilter * pFilter = NULL; ISpecifyPropertyPages * pSpecify; bool bReturn = false; pFilter = FindFilterFromName(pszFilterName); if(!pFilter) return false; hr=pFilter->QueryInterface(IID_ISpecifyPropertyPages, (void**) &pSpecify); if(SUCCEEDED(hr)) { bReturn = true; do { FILTER_INFO FilterInfo; hr=pFilter->QueryFilterInfo(&FilterInfo); if(FAILED(hr)) { bReturn = false; break; } CAUUID caGUID; hr=pSpecify->GetPages(&caGUID); if(FAILED(hr)) { bReturn = false; break; } pSpecify->Release(); if(test==false) { HWND m_hWnd= GetForegroundWindow(); CString str; str="IDS_STRING_PROPERTY_TITLE"; SetActiveWindow(m_hWnd); OleCreatePropertyFrame( m_hWnd, //NULL,// Parent window 0, // (Reserved) 0, // (Reserved) CComBSTR(str),//FilterInfo.achName, // Caption for the dialog box 1, // Number of filters (IUnknown**)&pFilter, // Pointer to the filter 1,//caGUID.cElems, // // Number of property pages caGUID.pElems, // Pointer to property page CLSIDs 0, // Locale identifier 0, // Reserved NULL // Reserved ); } CoTaskMemFree(caGUID.pElems); FilterInfo.pGraph->Release(); }while(0); } pFilter->Release(); return bReturn; } void CVideo::ShowErrMsg(HRESULT hr,CString str) { TCHAR szErr[256]; CString msg,errmsg; DWORD res = AMGetErrorText(hr, szErr, 256); if (res == 0) { AfxMessageBox(szErr); } errmsg.Format("错误原因为:%s",szErr); msg=str+errmsg; AfxMessageBox(msg); } void CVideo::Unload() { CoUninitialize(); } void CVideo::RunVideo() { pControl->Run(); } void CVideo::OnSelchangeListDevices() { HRESULT hr; IEnumMoniker *pEnumCat = NULL; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&m_pSysDevEnum); if FAILED(hr) { CoUninitialize(); return ; } hr = m_pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); ASSERT(SUCCEEDED(hr)); if FAILED(hr) return; hr = EnumFilters(pEnumCat); } HRESULT CVideo::EnumFilters(IEnumMoniker *pEnumCat) { HRESULT hr=S_OK; IMoniker *pMoniker; ULONG cFetched; VARIANT varName={0}; int nFilters=0; if (!pEnumCat) { return S_FALSE; } while(pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { IPropertyBag *pPropBag; ASSERT(pMoniker); hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); ASSERT(SUCCEEDED(hr)); ASSERT(pPropBag); if (FAILED(hr)) continue; varName.vt = VT_BSTR; hr = pPropBag->Read(L"FriendlyName", &varName, 0); if (FAILED(hr)) continue; CString str(varName.bstrVal); SysFreeString(varName.bstrVal); nFilters++; VARIANT varFilterClsid; varFilterClsid.vt = VT_BSTR; hr = pPropBag->Read(L"CLSID", &varFilterClsid, 0); if(SUCCEEDED(hr)) { CLSID clsidFilter; if(CLSIDFromString(varFilterClsid.bstrVal, &clsidFilter) == S_OK) { IBaseFilter *temp,*Render,*avi; hr=AddFilterByCLSID(pGraph,CLSID_device,L"source",&temp); hr=AddFilterByCLSID(pGraph,CLSID_AVIDecopress,L"Divx Multicast Sender",&avi); hr=AddFilterByCLSID(pGraph,CLSID_VideoRenderer,L"Video Renderer",&Render); hr=ConnectFilters(pGraph,temp,avi); hr=ConnectFilters(pGraph,avi,Render); } SysFreeString(varFilterClsid.bstrVal); } SAFE_RELEASE(pPropBag); SAFE_RELEASE(pMoniker); } return hr; } BOOL CVideo::IsWDMCard(IBaseFilter *pDeviceFilter) { IAMVfwCaptureDialogs *pVfw=NULL; HRESULT hr=pDeviceFilter->QueryInterface(IID_IAMVfwCaptureDialogs,(void **)&pVfw); if(SUCCEEDED(hr)) { pVfw->Release(); return false; } else { IAMAnalogVideoDecoder *pWdm=NULL; pDeviceFilter->QueryInterface(IID_IAMAnalogVideoDecoder,(void **)&pWdm); if(SUCCEEDED(hr)) { pWdm->Release(); return true; } else { return false; } } return false; } HRESULT CVideo::AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister) { IMoniker * pMoniker; IRunningObjectTable *pROT; WCHAR wsz[128]; HRESULT hr; if (!pUnkGraph || !pdwRegister) return E_POINTER; if(FAILED(GetRunningObjectTable(0, &pROT))) return E_FAIL; wsprintfW(wsz, L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph, GetCurrentProcessId()); hr = CreateItemMoniker(L"!", wsz, &pMoniker); if(SUCCEEDED(hr)) { hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph, pMoniker, pdwRegister); pMoniker->Release(); } pROT->Release(); return hr; } void CVideo::RemoveGraphFromRot(DWORD pdwRegister) { IRunningObjectTable *pROT; if(SUCCEEDED(GetRunningObjectTable(0, &pROT))) { pROT->Revoke(pdwRegister); pROT->Release(); } } HRESULT CVideo::InitCaptureGraphBuilder(IGraphBuilder **ppGraph,ICaptureGraphBuilder2 **ppBuild) { if(!ppGraph ||!ppBuild) return E_POINTER; IGraphBuilder *pGraph=NULL; ICaptureGraphBuilder2 *pBuild=NULL; HRESULT hr=CoCreateInstance(CLSID_CaptureGraphBuilder2,NULL,CLSCTX_INPROC_SERVER,IID_ICaptureGraphBuilder2,(void**)&pBuild); if(SUCCEEDED(hr)) { hr=CoCreateInstance(CLSID_FilterGraph,0,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void**)&pGraph); if(SUCCEEDED(hr)) { pBuild->SetFiltergraph(pGraph); *ppBuild=pBuild; *ppGraph=pGraph; return S_OK; } else { pBuild->Release(); } } return hr; } void CVideo::ShowPinProperty() { IAMStreamConfig *pSC; pControl->Stop(); HRESULT hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Interleaved, Device, IID_IAMStreamConfig, (void **)&pSC); if(FAILED(hr)) { hr = pBuilder->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, Device, IID_IAMStreamConfig, (void **)&pSC); ISpecifyPropertyPages *pSpec; CAUUID cauuid; hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec); if(hr == S_OK) { hr = pSpec->GetPages(&cauuid); hr = OleCreatePropertyFrame(NULL, 30, 30, NULL, 1, (IUnknown **)&pSC, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL); } CoTaskMemFree(cauuid.pElems); pSpec->Release(); pSC->Release(); } else { ShowErrMsg(hr,"show pin properpage"); pControl->Run(); return ; } // pControl->Run(); } void CVideo::ShowFilterProperty() { ISpecifyPropertyPages *pSpec; CAUUID cauuid; pControl->Stop(); HRESULT hr=Device->QueryInterface(IID_ISpecifyPropertyPages,(void**)&pSpec); if(SUCCEEDED(hr)) { hr=pSpec->GetPages(&cauuid); hr=OleCreatePropertyFrame(NULL,20,20,NULL,1,(IUnknown **)&Device,cauuid.cElems, (GUID *)cauuid.pElems,0,0,NULL); CoTaskMemFree(cauuid.pElems); pSpec->Release(); } // pControl->Run(); } void CVideo::Pause() { pControl->Pause(); } void CVideo::ShowSenderProperty() { DisplayPropertyPage("Divx Multicast Sender",false); }