扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
作者:智慧的鱼 来源:天极网 2007年10月17日
关键字: DirectShow QQ 音视频聊天
![]() ![]() |
![]() 图3 网络视频和音频交互的Graph图 |
static const GUID CLSID_FG729Render = { 0x3556f7d8, 0x5b5, 0x4015, { 0xb9, 0x40, 0x65, 0xb8, 0x8, 0x94, 0xc8, 0xf9 } }; //音频发送 static const GUID CLSID_FG729Source = { 0x290bf11a, 0x93b4, 0x4662, { 0xb1, 0xa3, 0xa, 0x53, 0x51, 0xeb, 0xe5, 0x8e } };//音频接收 static const GUID CLSID_FH263Source = { 0xa0431ccf, 0x75db, 0x463e, { 0xb1, 0xcd, 0xe, 0x9d, 0xb6, 0x67, 0xba, 0x72 } };//视频接收 static const GUID CLSID_FH263Render = { 0x787969cf, 0xc1b6, 0x41c5, { 0xba, 0xa8, 0x4e, 0xff, 0xa3, 0xdb, 0xe4, 0x1f } };//视频发送 //发送和接收音视频数据的filter CComPtr< IBaseFilter > m_pAudioRtpRender ; CComPtr< IBaseFilter > m_pAudioRtpSource ; CComPtr< IBaseFilter > m_pVideoRtpRender ; CComPtr< IBaseFilter > m_pVideoRtpSource ; char szClientA[100]; int iVideoPort = 9937; int iAudioPort = 9938; //构建视频的graph图,并发送数据 CComPtr< IGraphBuilder > m_pVideoGraphBuilder; //视频图形管理器 CComPtr< ICaptureGraphBuilder2 > m_pVideoCapGraphBuilder; CComPtr< IBaseFilter > m_pFilterVideoCap; CComPtr< IVideoWindow > m_pVideoWindow; CComPtr< IMediaControl > m_pVideoMediaCtrl ; CComPtr< IBaseFilter > m_pVideoRenderFilter; HRESULT CMyDialog::VideoGraphInitAndSend() { HRESULT hr; hr =m_pVideoGraphBuilder.CoCreateInstance( CLSID_FilterGraph ); if(FAILED(hr)) return hr; hr =m_pVideoCapGraphBuilder.CoCreateInstance( CLSID_CaptureGraphBuilder2); if(FAILED (hr)) return hr; m_pVideoCapGraphBuilder->SetFiltergraph(m_pVideoGraphBuilder); m_pVideoGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&m_pVideoMediaCtrl); m_pVideoGraphBuilder->QueryInterface(IID_IVideoWindow,(void**)&m_pVideoWindow) FindDeviceFilter(&m_pFilterVideoCap,CLSID_VideoInputDeviceCategory); if(m_pFilterVideoCap) m_pVideoGraphBuilder->AddFilter( m_pFilterVideoCap,T2W("VideoCap") ) ; //创建预览的filter hr = m_pRenderFilterVideo.CoCreateInstance(CLSID_VideoRenderer); if(FAILED(hr)) return hr; m_pVideoGraphBuilder->AddFilter( m_pRenderFilterVideo, L"VideoRenderFilter" ); Connect(m_pFilterVideoCap ,m_pRenderFilterVideo) ; //设置预览的窗口 CRect rc ; GetClientRect(m_hOwnerWnd, &rc ); int iWidth = rc.right - rc.left ; int iHeight = rc.bottom - rc.top ; int iLeft, iTop; if((iHeight*1.0)/(iWidth*1.0) >= 0.75) { //按宽度算 int tmpiHeight = iWidth*3/4; iTop = (iHeight - tmpiHeight)/2; iHeight = tmpiHeight; iLeft = 0; } else { //按高度算 int tmpiWidth = iHeight*4/3; iLeft = (iWidth - tmpiWidth)/2; iWidth = tmpiWidth; iTop = 0; } m_pVideoWindow->put_Owner( (OAHWND) m_hPreviewWnd ) ; m_pVideoWindow->put_Visible( OATRUE ); m_pVideoWindow->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS ) ; //连接到网络并发送 CComPtr< IRtpOption > pRenderOption; CComPtr< IVideoOption > pVideoOption; tagVideoInfo vif(160,120,24); int t=((int)(m_iFrameRate/5)*5)+5; vif.nBitCount=24; vif.nWidth=160; vif.nHeight=120; hr = ::CoCreateInstance(CLSID_FH263Render, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_pVideoRtpRender); if(FAILED(hr)) return hr; m_pVideoRtpRender->QueryInterface(IID_IJRTPOption, (void**)&pRenderOption); m_pVideoRtpRender->QueryInterface(IID_IVideoOption,(void**)&pVideoOption); pVideoOption->SetProperty(&vif); pVideoOption->SetSendFrameRate(m_iFrameRate,1);//1 不发送数据,0 实际发送数据 Connect(m_pFilterVideoCap ,m_pVideoRtpRender) ; //连接对方 hr= pRenderOption->Connect(szClientA,iVideoPort,1024); if(FAILED(hr)) return hr; m_pVideoMediaCtrl->Run(); } //视频的接收 CComPtr< IGraphBuilder > m_pVideoGraphBuilder; //视频图形管理器 CComPtr< IBaseFilter > m_pFilterVideoCap; CComPtr< IVideoWindow > m_pVideoWindow; CComPtr< IMediaControl > m_pVideoMediaCtrl ; CComPtr< IBaseFilter > m_pVideoRenderFilter; HWND m_hRenderWnd ; HRESULT VideoRecive() { HRESULT hr; hr=CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC, IID_IFilterGraph,(void**)&m_pVideoGraphBuilder); m_pVideoGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&m_pVideoMediaCtrl); m_pVideoGraphBuilder->QueryInterface(IID_IVideoWindow,(void**)&m_pVideoWindow) hr = ::CoCreateInstance(CLSID_FH263Source, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void **)&m_pVideoRtpSource); if(FAILED(hr)) return hr; m_pVideoGraphBuilder->AddFilter(m_pVideoRtpSource, L"My Custom Source"); CComPtr< IRtpOption > m_pRtpOption; CComPtr< IVideoOption > m_pVideoOption; m_pVideoRtpSource->QueryInterface(IID_IJRTPOption, (void **)&m_pRtpOption); m_pVideoRtpSource->QueryInterface(IID_IVideoOption, (void **)&m_pVideoOption); tagVideoInfo vif(160, 120 ,24); m_pVideoOption->SetProperty(&vif); hr= pRenderOption->Connect(szClientA,iVideoPort +1,1024); if(FAILED(hr)) return hr; //创建预览的filter hr = m_pRenderFilterVideo.CoCreateInstance(CLSID_VideoRenderer); if(FAILED(hr)) return hr; m_pVideoGraphBuilder->AddFilter( m_pRenderFilterVideo, L"VideoRenderFilter" ); Connect(m_pVideoRtpSource ,m_pRenderFilterVideo) ; CRect rc ; GetClientRect(m_hOwnerWnd, &rc ); int iWidth = rc.right - rc.left ; int iHeight = rc.bottom - rc.top ; int iLeft, iTop; if((iHeight*1.0)/(iWidth*1.0) >= 0.75) { //按宽度算 int tmpiHeight = iWidth*3/4; iTop = (iHeight - tmpiHeight)/2; iHeight = tmpiHeight; iLeft = 0; } else { //按高度算 int tmpiWidth = iHeight*4/3; iLeft = (iWidth - tmpiWidth)/2; iWidth = tmpiWidth; iTop = 0; } m_pVideoWindow->put_Owner( (OAHWND) m_hRenderWnd ) ; m_pVideoWindow->put_Visible( OATRUE ); m_pVideoWindow->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS ) ; m_pVideoMediaCtrl->Run(); return S_OK; } // HRESULT FindDeviceFilter(IBaseFilter ** ppSrcFilter,GUID deviceGUID) { HRESULT hr; IBaseFilter * pSrc = NULL; CComPtr <IMoniker> pMoniker =NULL; ULONG cFetched; if (!ppSrcFilter) return E_POINTER; // Create the system device enumerator CComPtr <ICreateDevEnum> pDevEnum =NULL; hr = CoCreateInstance (CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **) &pDevEnum); if (FAILED(hr)) return hr; // Create an enumerator for the video capture devices CComPtr <IEnumMoniker> pClassEnum = NULL; hr = pDevEnum->CreateClassEnumerator (deviceGUID, &pClassEnum, 0); if (FAILED(hr)) return hr; if (pClassEnum == NULL) return E_FAIL; if (S_OK == (pClassEnum->Next (1, &pMoniker, &cFetched))) { hr = pMoniker->BindToObject(0,0,IID_IBaseFilter, (void**)&pSrc); if (FAILED(hr)) return hr; } else return E_FAIL; *ppSrcFilter = pSrc; return S_OK; } //构建音频Graph图,并发送 CComPtr< IGraphBuilder > m_pAudioGraphBuilder; //音频图形管理器 CComPtr< ICaptureGraphBuilder2 > m_pCapAudioGraphBuilder; CComPtr< IBaseFilter > m_pFilterAudioCap; CComPtr< IMediaControl > m_pAudioMediaCtrl ; HRESULT AudioGraphInit() { HRESULT hr; hr =m_pAudioGraphBuilder.CoCreateInstance( CLSID_FilterGraph ); if(FAILED(hr)) return hr; hr =m_pCapAudioGraphBuilder.CoCreateInstance( CLSID_CaptureGraphBuilder2); if(FAILED (hr)) return hr; m_pAudioGraphBuilder->SetFiltergraph(m_pCapAudioGraphBuilder); m_pAudioGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&m_pAudioMediaCtrl); FindDeviceFilter(&m_pFilterVideoCap,CLSID_AudioInputDeviceCategory); if(m_pFilterAudioCap) m_pAudioGraphBuilder->AddFilter( m_pFilterAudioCap,T2W("AudioCap") ) ; //发送到网络 hr =::CoCreateInstance(CLSID_FG729Render,NULL,CLSCTX_INPROC, IID_IBaseFilter,(void**)&m_pFilterRtpSendAudio) if(FAILED(hr)) return hr; m_pAudioGraphBuilder->AddFilter(m_pAudioRtpRender, L"FilterRtpSendAudio"); Connect(m_pFilterAudioCap,m_pAudioRtpRender); CComPtr< IRtpOption > pOption ; m_pAudioRtpRender->QueryInterface(IID_IJRTPOption,(void**)&pOption) hr =pOption->Connect(szClientA,iAudioPort,1024); if(FAILED(hr)) return hr; m_pAudioMediaCtrl->Run(); return S_OK; } //音频的接收 CComPtr< IGraphBuilder > m_pAudioGraphBuilder; //音频图形管理器 CComPtr< ICaptureGraphBuilder2 > m_pCapAudioGraphBuilder; CComPtr< IBaseFilter > m_pFilterAudioCap; CComPtr< IMediaControl > m_pAudioMediaCtrl ; CComPtr<IBaseFilter> m_pAudioRender; HRESULT AudioRecive() { HRESULT hr; hr =m_pAudioGraphBuilder.CoCreateInstance( CLSID_FilterGraph ); if(FAILED(hr)) return hr; m_pAudioGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&m_pAudioMediaCtrl); hr = m_pAudioRtpSource->CoCreateInstance(CLSID_FG729Source) ; if(FAILED(hr)) return hr; m_pAudioGraphBuilder->AddFilter(m_pAudioRtpSource,L"AudioRtp"); //创建声卡Renderfilter FindDeviceFilter(&m_pAudioRender,CLSID_AudioRendererCategory); m_pAudioGraphBuilder->AddFilter(m_pAudioRender,L"AudioRender"); CComPtr< IRtpOption > pRtpOption ; m_pAudioRtpSource->QueryInterface(IID_IJRTPOption,(void**)&pRtpOption) hr= pRtpOption->Connect(szClientA,iAudioPort+2,1024); if(FAILED (hr)) return hr; Connect(m_pAudioRtpSource,m_pAudioRender); m_pAudioMediaCtrl->Run(); return S_OK; } |
婵犵數濮烽弫鍛婃叏閻戝鈧倹绂掔€n亞鍔﹀銈嗗坊閸嬫捇鏌涢悢閿嬪仴闁糕斁鍋撳銈嗗坊閸嬫挾绱撳鍜冭含妤犵偛鍟灒閻犲洩灏欑粣鐐烘⒑瑜版帒浜伴柛鎾寸洴閹儳煤椤忓應鎷洪梻鍌氱墛閸楁洟宕奸妷銉ф煣濠电姴锕ょ€氼參宕h箛鏃傜瘈濠电姴鍊绘晶娑㈡煕鐎c劌濡介柕鍥у瀵粙濡歌閳ь剚甯¢弻鐔兼寠婢跺﹥娈婚梺鍝勭灱閸犳牠骞冨⿰鍫濈厸闁稿本绋撹ぐ瀣煟鎼淬値娼愭繛鍙壝悾婵堢矙鐠恒劍娈鹃梺鍓插亝濞叉牠鎮″☉銏$厱閻忕偛澧介惌瀣箾閸喐鍊愭慨濠勭帛閹峰懐绮电€n亝鐣伴梻浣规偠閸斿宕¢崘鑼殾闁靛繈鍊曢崘鈧銈嗗姂閸庡崬鐨梻鍌欑劍鐎笛呯矙閹寸姭鍋撳鐓庡籍鐎规洑鍗冲畷鍗炍熼梹鎰泿闂備線娼ч悧鍡涘箠鎼淬垺鍙忔い鎺嗗亾闁宠鍨块崺銉╁幢濡炲墽鍑规繝鐢靛О閸ㄦ椽鏁嬮柧鑽ゅ仦娣囧﹪濡堕崨顔兼闂佺ǹ顑呴崐鍦崲濞戙垹骞㈡俊顖濐嚙绾板秹鏌f惔銏e妞わ妇鏁诲璇差吋閸偅顎囬梻浣告啞閹搁箖宕版惔顭戞晪闁挎繂顦介弫鍡椼€掑顒婂姛闁活厽顨嗙换娑㈠箻閺夋垹鍔伴梺绋款儐閹瑰洭寮婚敐鍛婵炲棙鍔曠壕鎶芥⒑閸濆嫭婀扮紒瀣灴閸╃偤骞嬮敃鈧婵囥亜閺囩偞鍣洪柍璇诧功缁辨捇宕掑▎鎴濆濡炪們鍔岄幊姗€骞嗗畝鍕<闁绘劙娼х粊锕傛煙閸忚偐鏆橀柛鏂跨焸閹偤宕归鐘辩盎闂佸湱鍎ら崹鐢割敂閳哄懏鍊垫慨姗嗗墻濡插綊鏌曢崶褍顏€殿喕绮欐俊姝岊槼闁革絻鍎崇槐鎾存媴缁涘娈┑鈽嗗亝缁诲牆顕f繝姘亜缁炬媽椴搁弲锝夋偡濠婂啰效闁诡喗锕㈤幊鐘活敆閸屾粣绱查梺鍝勵槸閻楀嫰宕濇惔锝囦笉闁绘劗鍎ら悡娑㈡倶閻愯泛袚闁哥姵锕㈤弻鈩冩媴閻熸澘顫掗悗瑙勬礈閸犳牠銆佸鈧幃鈺呮惞椤愩倝鎷婚梻鍌氬€峰ù鍥х暦閸偅鍙忛柟鎯板Г閳锋梻鈧箍鍎遍ˇ顖炲垂閸岀偞鐓㈡俊顖滃皑缁辨岸鏌ㄥ┑鍡╂Ц缂佲偓鐎n偁浜滈柡宥冨妿閳藉绻涢崼鐔虹煉婵﹨娅e☉鐢稿川椤斾勘鈧劕顪冮妶搴′簼婵炶尙鍠栧畷娲焵椤掍降浜滈柟鍝勬娴滈箖姊洪幐搴㈢┛濠碘€虫搐鍗遍柟鐗堟緲缁秹鏌涢锝囩畼妞ゆ挻妞藉铏圭磼濡搫顫岄悗娈垮櫘閸撴瑨鐏冮梺鍛婁緱閸犳岸宕㈤幖浣光拺闁告挻褰冩禍浠嬫煕鐎n亜顏柟顔斤耿閺佸啴宕掑☉姘箞闂佽鍑界紞鍡涘磻閸℃ɑ娅犳い鎺戝€荤壕濂告煕鐏炲墽鈽夌紒妞﹀洦鐓欓柣鐔告緲椤忣參鏌熼悡搴㈣础闁瑰弶鎸冲畷鐔兼濞戞瑦鐝¢梻鍌氬€搁崐椋庣矆娓氣偓楠炴牠顢曢妶鍌氫壕婵ê宕崢瀵糕偓瑙勬礀缂嶅﹪寮婚崱妤婂悑闁告侗鍨界槐閬嶆煟鎼达紕鐣柛搴ㄤ憾钘濆ù鍏兼綑绾捐法鈧箍鍎遍ˇ浼存偂閺囥垺鐓涢柛銉e劚婵$厧顭胯閸ㄤ即婀侀梺缁樓圭粔顕€顢旈崼鐔虹暢闂傚倷鐒︾€笛呮崲閸屾娑樜旈崨顓犲幒闂佸搫娲㈤崹娲偂閸愵亝鍠愭繝濠傜墕缁€鍫熸叏濡寧纭鹃柦鍐枛閺屾洘绻涜鐎氱兘宕戦妸鈺傗拺缂備焦锚婵洦銇勯弴銊ュ籍闁糕斂鍨藉鎾閳ユ枼鍋撻悽鍛婄叆婵犻潧妫楅埀顒傛嚀閳诲秹宕堕妸锝勭盎闂婎偄娲︾粙鎰板箟妤e啯鐓涢悘鐐靛亾缁€瀣偓瑙勬礋娴滃爼銆佸鈧幃銏$附婢跺澶�