织梦CMS - 轻松建站从此开始!

罗索

EMIPLIB使用入门(2)

落鹤生 发布于 2010-09-08 10:49 点击:次 
Library core 部分。 第四步:一个语音会议的demo 最后我们来做一个局域网的语音会议的demo,也算做个入门结业。 我们的语音会议的demo设计为这样:没有服
TAG:

Library core部分。

 第四步:一个语音会议的demo

 最后我们来做一个局域网的语音会议的demo,也算做个入门结业。

 我们的语音会议的demo设计为这样:没有服务器,会议中每一方都可以listen来自局域网的声音,也可以往自己的列表中添加目标位置,向它(们)发送你的语音。

这样要完成一个三人的对话,我们需要三方都打开listen,并且添加另外两个人的地址,发送自己的声音。

我们开两个独立的线程,一个负责在端口12000接受来自局域网的声音,一个负责往发送列表中的目的地发送本地语音。

之前我们的例子中只是在本地做了一个wav文件的播放,我们需要解决另外几个问题:得到声卡输入、如何向目的地发送RTP、如何接收RTP。

第一个问题比较好解决,我们仿照例子中声卡播放使用的对象,找到了这个类:MIPWAVInput,把它放在某个chain的最开始处,我们就可以得到声音的输入了。

代码类似于下面:

 

  1. MIPWinMMInput sndCardInput; 
  2.  
  3. bool returnValue; 
  4.  
  5. int samplingRate = 8000; 
  6. int numChannels = 1; 
  7. returnValue=sndCardInput.open(samplingRate,numChannels,interval,buffertime,false); 

在初始化chain时候:

  1. chain.setChainStart(&sndCardInput);  

就可以了。

RTP的发送和接收主要是对于RTPsession的参数设置。接收端代码我们设置端口为监听端口,发送端SetPortbase(portBase)为发送端口,而在RTPSession::AddDestination函数中端口使用目的地的监听端口;

我们的发送语音的线程大致是这样的:

  1. DWORD WINAPI WorkerThread(LPVOID lpParameter) 
  2.  IpAddrList *ipl=(IpAddrList*)lpParameter; //把目的列表传过来鸟 
  3.  
  4.  WSADATA dat; 
  5.  WSAStartup(MAKEWORD(2,2),&dat); 
  6.  
  7.  MIPTime interval(0.020); // We'll use 20 millisecond intervals. 
  8.  MIPTime buffertime(10); 
  9.  MIPAverageTimer timer(interval); 
  10.  MIPWAVInput sndFileInput; 
  11.  MIPSamplingRateConverter sampConv; 
  12.  MIPSampleEncoder sampEnc; 
  13.  MIPULawEncoder uLawEnc; 
  14.  MIPRTPULawEncoder rtpEnc; 
  15.  MIPRTPComponent rtpComp; 
  16.  
  17.   
  18.  MIPWinMMInput sndCardInput; 
  19.  MIPWinMMOutput sndCardOutput; 
  20.  MyChain chain("MPVC"); 
  21.  RTPSession rtpSession; 
  22.  bool returnValue; 
  23.  
  24.  int samplingRate = 8000; 
  25.  int numChannels = 1; 
  26.  
  27.  //We'll start microphone 
  28.  returnValue=sndCardInput.open(samplingRate,numChannels,interval,buffertime,false); 
  29.  returnValue = sampEnc.init(MIPRAWAUDIOMESSAGE_TYPE_S16); 
  30.  returnValue = uLawEnc.init(); 
  31.  returnValue = rtpEnc.init(); 
  32.  
  33.  RTPUDPv4TransmissionParams transmissionParams; 
  34.  RTPSessionParams sessionParams; 
  35.  int portBase = BASEPORT_SEND; 
  36.  int status; 
  37.   
  38.  transmissionParams.SetPortbase(portBase); 
  39.  sessionParams.SetOwnTimestampUnit(1.0/((double)samplingRate)); 
  40.  sessionParams.SetMaximumPacketSize(64000); 
  41.  
  42.  status = rtpSession.Create(sessionParams,&transmissionParams); 
  43.  
  44.  for(int i=0;i<ipl->count;i++)
  45. //这个for是从一个列表中读目的地址,大家可以自己按自己的要求实现,几个目的地就调用几个AddDestination。 
  46.  { 
  47.   status = rtpSession.AddDestination(RTPIPv4Address(ntohl(inet_addr(ipl->ipaddr[i]))
  48. ,BASEPORT_LISTEN)); 
  49.  } 
  50.   
  51.  returnValue = rtpComp.init(&rtpSession); 
  52.  returnValue = chain.setChainStart(&sndCardInput); 
  53.  returnValue = chain.addConnection(&sndCardInput, &sampEnc); 
  54.  returnValue = chain.addConnection(&sampEnc, &uLawEnc); 
  55.  returnValue = chain.addConnection(&uLawEnc, &rtpEnc); 
  56.  returnValue = chain.addConnection(&rtpEnc, &rtpComp); 
  57.  returnValue = chain.start(); 
  58.  
  59.  while(stop_f) 
  60.  { 
  61.   Sleep(SLEEP_TIME); 
  62.  } 
  63.  
  64.  rtpSession.BYEDestroy(RTPTime(10,0),0,0); 
  65.  returnValue = chain.stop(); 
  66.  rtpSession.Destroy(); 
  67.  
  68.  WSACleanup(); 
  69.  return 0; 

listen端的代码类似下面:

  1. DWORD WINAPI WorkerThread_Listen(LPVOID lpParameter) 
  2.  WSADATA dat; 
  3.  WSAStartup(MAKEWORD(2,2),&dat); 
  4.  
  5.  MIPTime interval(0.020); // We'll use 20 millisecond intervals. 
  6.  MIPTime buffertime(10); 
  7.  MIPAverageTimer timer(interval); 
  8.  MIPWAVInput sndFileInput; 
  9.  MIPSamplingRateConverter sampConv, sampConv2; 
  10.  MIPSampleEncoder sampEnc, sampEnc2, sampEnc3; 
  11.  MIPULawEncoder uLawEnc; 
  12.  MIPRTPULawEncoder rtpEnc; 
  13.  MIPRTPComponent rtpComp; 
  14.  MIPRTPDecoder rtpDec; 
  15.  MIPRTPULawDecoder rtpULawDec; 
  16.  MIPULawDecoder uLawDec; 
  17.  MIPAudioMixer mixer; 
  18.   
  19.  MIPWinMMOutput sndCardOutput; 
  20.  MyChain chain("MPVClisten"); 
  21.  RTPSession rtpSession; 
  22.  bool returnValue; 
  23.  
  24.  int samplingRate = 8000; 
  25.  int numChannels = 1; 
  26.  
  27.   
  28.  RTPUDPv4TransmissionParams transmissionParams; 
  29.  RTPSessionParams sessionParams; 
  30.  
  31.  int portBase = BASEPORT_LISTEN; 
  32.  int status; 
  33.  
  34.  transmissionParams.SetPortbase(portBase); 
  35.  sessionParams.SetOwnTimestampUnit(1.0/((double)samplingRate)); 
  36.  sessionParams.SetMaximumPacketSize(64000); 
  37.  status = rtpSession.Create(sessionParams,&transmissionParams); 
  38.   
  39.  returnValue = rtpComp.init(&rtpSession); 
  40.  returnValue = rtpDec.init(true, 0, &rtpSession); 
  41.  returnValue = rtpDec.setPacketDecoder(0,&rtpULawDec); 
  42.  returnValue = uLawDec.init(); 
  43.  returnValue = sampEnc2.init(MIPRAWAUDIOMESSAGE_TYPE_FLOAT); 
  44.  returnValue = sampConv2.init(samplingRate, numChannels); 
  45.  returnValue = mixer.init(samplingRate, numChannels, interval); 
  46.  returnValue = sndCardOutput.open(samplingRate, numChannels, interval); 
  47.  returnValue = sampEnc3.init(MIPRAWAUDIOMESSAGE_TYPE_S16LE); 
  48.  returnValue = chain.setChainStart(&timer); 
  49.  returnValue = chain.addConnection(&timer, &rtpComp); 
  50.  returnValue = chain.addConnection(&rtpComp, &rtpDec); 
  51.  returnValue = chain.addConnection(&rtpDec, &uLawDec, true); 
  52.  returnValue = chain.addConnection(&uLawDec, &sampEnc2, true); 
  53.  returnValue = chain.addConnection(&sampEnc2, &sampConv2, true); 
  54.  returnValue = chain.addConnection(&sampConv2, &mixer, true); 
  55.  returnValue = chain.addConnection(&mixer, &sampEnc3); 
  56.  returnValue = chain.addConnection(&sampEnc3, &sndCardOutput); 
  57.  
  58.  // Start the chain 
  59.  returnValue = chain.start(); 
  60.  
  61.  while(lstop_f) 
  62.  { 
  63.   Sleep(SLEEP_TIME); 
  64.  } 
  65.    
  66.  rtpSession.BYEDestroy(RTPTime(10,0),0,0); 
  67.  returnValue = chain.stop(); 
  68.  rtpSession.Destroy(); 
  69.  
  70.  WSACleanup(); 
  71.  return 0; 
  72. }  

其他的一些UI方面的事情大家随意吧...

你要是在你的局域网里面已经已经成功实现了一个语音会议demo...呵呵,恭喜你。我的文章就先写到这里。更高级的...等我会了就写。

大家如果在上面这章有什么问题,可以看看 源代码src\sessions目录下的mipaudiosession.cpp,里面有MIPAudioSession类的实现,它对我们理解这个chain很有帮助。

接下来,我要去搞视频了,妈呀~前几天搞了搞QT...现在比较头疼4版本和3版本之间的一些隔阂。

 

(arden1019)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201009/10112.html]
本文出处:CSDN博客 作者:arden1019
顶一下
(2)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容