《QQ视频语音原码.docx》由会员分享,可在线阅读,更多相关《QQ视频语音原码.docx(16页珍藏版)》请在优知文库上搜索。
1、QQ视频语音原码QQ视频语音原码用DirectShow实现QQ的音视频闲聊功能开发者在线Builder更新时间:2007T0T7作者:才智的鱼来源:天极网本文关健词:DirectShowQQ音视频闲聊当下比较流行的即时通信工具,比如MSN,QQ等都实现了视音频的功能,通过视频,音频,我们可以更好的和挚友通过网络进行沟通,本文通过DirectShow技术模拟QQ实现了视频和音频的采集,传输,基本实现了QQ的视音频闲聊的功能。网络视音频系统主要功能就在于视音频的采集,网络传输两个方面,通过VideoCapture系列APl函数,你就可以轻松的搞定视频捕获,但是对于视频的网络传输,则要费一番功夫了。
2、对于视音频数据的传输,只简洁地运用数据报套接字传输音视频数据是不行行的,还必需在UDP层上采纳RTP(实时传输协议)和RTCP(实时传输限制协议)来改善服务质量。实时传输协议供应具有实时特征的、端到端的数据传输服务。我们在音视频数据前插入包含有载荷标识、序号、时间戳和同步源标识符的RTP包头,然后利用数据报套接字在IP网络上传输RTP包,以此改善连续重放效果和音视频同步。实时传输限制协议RTCP用于RTP的限制,它最基本的功能是利用发送者报告和接收者报告来推断网络的服务质量,若拥塞状况严峻,则改用低速率编码标准或降低数据传输比特率,以削减网络负荷,供应较好的Q.S保证。Directshow对于
3、音视频的采集供应了很好的接口,利用ICaptureGraphBuilder2接口可以很轻松的建立起视频捕获的graph图,通过枚举音频设备Filter,也可以很轻松的实现音频的捕获,有点麻烦的是音视频数据的传输,我们可以自己封装RTP和RTCP的协议,来Fl己实现一个filter,用来发送和接收音视频数据,当然了Directshow也供应了一组支持运用RTP协议的网络传输多媒体流的Filterso你也完全可以用DireCtShoW供应的RTP系列的filter实现数据的传输。下面分析一下这些RTPFilters0新定义的Fi1ter包括RTPSourceFilter,RTPRenderFi1t
4、er,RTPDcmuxFi1ter,RTPReceivePlayloadHandler(RPH)filter,RTPSendPayload(SPH)filter,运用这5个filter构建一个通过RTP协议传输音视频数据的Graph是没有问题的。RTPSourcefilter被用来从一个单独的RTP会话中接收RTP和RTCP包。这个filter供应一个指定发送给其它主机RTCP接收器报告和指定网络地址和端口接口来接收RTP会话的接口。RTPRendfilter是用来将数据发到网络上的一个filter,这个filter也供应了和RTPsourceFilter类似的接口。RTPDemuxfilte
5、r用来多路分别来自RTPSourcefilter的RTP包,这个filter有一个或者多个输出的pin。这个Filter供应了如何限制多路分别和如何安排到特定输出Pin的接口。RTPRPHFilter是用来网络过来的RTP包还原成原来的数据格式,主要支持H.261,H.263,Indeo,G.711,G.723和G.729和常见的多种音视频负载类型。RTPSPHfilter则和RPHfilter的功能相对,它的任务是将音视频压缩filter输出的数据分解为RTP包,它供应的接口有指定最大生成包大小和Pt值。下面我们看看如何用这些filter来搭建我们采集和传输的graph图。图1和图2展示了D
6、irectShowRTP中定义的filters如何运用。图1是一个采集本地多媒体数据并运用RTP协议通过网络发送的filtergraph0它包含一个输出原始视频帧的视频采集filter,紧跟一个压缩帧的编码filter。一旦压缩,这些帧就会被发送到RTPSPHfiIter,分片打包,生成RTP包,对应的发送到RTPRenderfilter,通过网络传输这些包。图2呈现了一个filtergraph,用来接收包含视频流RTP包,播放视频。这个graph由一个用来接收包的RTPSourcefilter,一个依据源和负载类型进行分类的RTPDemuxfilter,一个把RTP包转为压缩视频帧的RTPR
7、PHfilter组成。这些filter随后的是用来解压帧的解码filter,一个显示未压缩帧的渲染filter。有了RTPfilter的帮助我们就可以完成类似qq的功能了,可以实现在网络上进行视频和音频的交互了,下面我给出在网络上两个客户端A和B进行音频和视频交互的GraPh图。这里我对图1和图2中的RTPfilter进行了自己封装,将编解码filter干脆封装到了RTpSourcefilter和RTPRenderfi1ter中,这样Graph图就显得很简洁,RTPSourcefilter只是用来接收网络过来的音视频数据,然后将数据传递给客户程序,RTPRenderfilter则是将采集到的音
8、视频数据发送到网络上的另一个客户端,编解码则的工作则封装到这两个filter之中。图3网络视频和音频交互的Graph图假如你也想自己封装自己的Source和Renderfilter,首先你要选择自己的编解码,视频编解码是选择H261,H263,还是MEPG4,音频是选择G729还是G711.要首先确定好。选好编解码,封装的工作就箍洁了。不多说了,下面看看我给出的代码吧。首先要定义一下用到的四个RTPfilter的C1.SlDoCComPtrIGraphBuilderm_pVi(IeoGraphBuiIder;视频图形管理器CComPtrICaptureGraphBuidcr2HcpVideoC
9、apGraphBuiIder;CComPtrIBaseFilterm_pFi1terVideoCap;CComPtrIVideoWindowm_pVidcoWindow;CComPtrIMediaControlm_pVideoMediaCtr1:CComPtrIBaseFilterm_pVideoRcnderFi1ter:!RESU1.TCMyDialog:IVideoGraphInitAndSendOHRESU1.Thr;hr=m_pVidcoGraphBui1tier.CoCreatcInstance(C1.SID_FiItcrGraph);if(FAI1.ED(hr)returnhr:h
10、r=m_pVideoCapGraphBui1der.CoCreateInstance(C1.SID_CapturcGraphBui)dcr2);if(FAI1.ED(hr)returnhr;m_pVideoCapGraphBuiIder-SetFi1Iergraph(m_pVidcoGraphBui1dor);m_pVidcoGraphBui1der-QucryInterface(IID_IMediaControl,(void*)m_pVideoMediaCtr1);m_pVidcoGraphBuiIder-QucryInterface(IID_IVideoWindow,(void*)m_pV
11、ideoWindow)FindDeviceFiIter(m_pFiIterVidcoCap,C1.siD-VideolnputDeviceCategory);if(m_pFi1terVideoCap)m_pVidcoGraphBuilder-AddFilter(m_pFi1terVideoCap,T2W(VideoCap);创建预览的filterhr=m_pRenderFi1terVidoo.CoCreaIeInstancc(C1.SID_VidcoRcnderer);if(FAI1.ED(hr)returnhr;m_pVideoGraphBui1dcr-AtidFilter(m_pRende
12、rFi1terVideo,1.VideoRenderFi1ter);Connect(m_pFiIterVideoCap,m_pRcnderFiIterVideo);/设置预览的窗口CRectrc;GetClientRect(m_hOwnerWnd,rc):intiWidth=rc.right-rc.left;intiHeight=rc.bottom-rc.top;inti1.eft,iTop:if(iHeight*l.O)/(iWidth*l.O)=O.75)/按宽度算inttmpiHeight=iWidth*34;iTop=(iHeight-tmpiHeight)/2;iHeight=tmp
13、iHeight;i1.eft=O:else按高度算intImpiWidth=iHeight*43;i1.eft=(iWidth-tmpiWidth)/2;iWidth=tmpiWidth;iTop=O;m_pVideoWindow-put-Owner(OAHWND)m_hPreviewWnd):m_pVideoWindow-put_Visib1e(OTRUE);m_pVideoWindow-put_WindowStyle(WS_CHI1.DWsjxipsiblings):连接到网络并发送CCOmPtrIRtpOptionpRenderOption;CComPtrIVideoOptionpVId
14、eoOption;IagVideoInfovif(160,120,24);intt=(int)(m_iFrameRate5)*5)+5;vif.nBitCount=24:vif.nWidth=160;vif.nHeight=120:hr:CoCreateInstance(C1.SIDFH263Render,NU1.1.,C1.SCTX_INPROC,IIDJBaseFilter,(void*)m_pVidcoRtpRender);if(FAI1.ED(hr)returnhr;m_pVideoRtpRender-QueryInterface(IID_IJRTPOption,(void*)pRen
15、derOption);m_pVideoRtpRender-QueryInterface(11DVideo0ption,(voicl*)pVideoOption);pVideo0ption-SetProperty(vif);pVideo0ption-SetSendFrameRate(m_iFrameRate,1);/1不发送数据,0实际发送数据ConnCCtGn_pFiIterVideoCap,m_pVideoRtpRender);连接对方hr=PRenderOption-Connect(szClientA,iVideoPort,1024);if(FAI1.ED(hr)returnhr;m_pVideoMediaCtrI-RunO;视频的接收CComPtrIGraphBuiIderm_pVideoGraphBui1dcr:视频图形管理器CComPtrIBaseFilterm_pFi11erVideoCap;CComPtrIVideoWindowm_pVideoWindow;CComPtrIMediaControlm_pVideoMediaCtr1;CComPtrIBaseFilterm_pVideoRenderPliter;HWNDm_hRcnderWnd;!RESU1.TVideoReciveO(HRESU1.Thr;