3410|1

565

帖子

513

TA的资源

裸片初长成(中级)

楼主
 

基于wince的网络音视频通信(简单易明版) [复制链接]

本文来自http://blog.csdn.net/hellogv/




   由于这个学期的期末将至,因此期末大作业也要开始做了。这次做的是N个月前就做过的网络音视频通信,不过这次做了不少改进。
   在这里,先要感谢一下 MacintoshM 大侠,他的帖子给我提供了最原始的源代码,我现在的代码也是在他代码的基础上做出修改的。
OK,现在进入主题,先来介绍一下这个东东:
  •    下位机为 mini2440 ,其操作系统是WINCE 5.0,需要在下位机上插入USB摄像头(中星微301,驱动为15分钟限制版),以及插入麦克风耳机;
  •    上位机为普通的PC,需要插入麦克风耳机;
  •    上位机和下位机的开发环境为Visual Studio 2005。
接下来,说说这个东东的功能,和工作原理:
  • 网络视频传输,首先把mini2440与USB摄像头连接在一起,通过USB摄像头捕捉图像(320 x 240,15fps),然后通过UDP协议发送至PC端,在PC屏幕上以15fps的速度显示。
  • 网络音频传输,首先在mini2440和PC上都插入麦克风耳机,两者都同时录音,并以G.726编码,然后把压缩包通过UDP协议发送至对方,而在录音的同时,也对来自对方的压缩包用G.726解码,然后再在耳机播放音频。
最后,说说这个版本相对于以前的改进:
  • 把以前的RTP改为UDP,实践证明,在这个系统中,用UDP的效率会比RTP好,毕竟不需要用到RTP的流量监测等高级功能,仅仅能通信就行了;
  • 以前版本基于100M网卡,现在支持10M网卡了,在100M网卡的机器上,可以直接把JPEG图片发过去,但是,在10M的网卡是,每次数据包最大为1440比特,因此要兼容10M网卡,就需要把图像分割成多个1440大小的数据包,分别发送了。
源代码可以到这里下载(2008.12.01才可以下载):
http://download.csdn.net/user/hellogv
网络音视频通信

下面说说关键的源代码:

以下是WINCE部分的代码






  1. #pragma once
  2. #include "winsock2.h"
  3. //RTP支持
  4. #include "..\UDP\UDP.h"

  5. //音频支持
  6. #include "WaveIn.h"
  7. #include "WaveOut.h"

  8. //G726支持
  9. #include "g726.h"

  10. //摄像头支持
  11. #include ".\video\\zc030xlib.h"

  12. #define Video_Width 320 //视频宽度
  13. #define Video_Height 240 //视频长度
  14. #define AudioData_Size 960  //每块音频数据包的大小
  15. #define Compr_AudioData_Size 120  //压缩后音频块的大小


  16. //音频输入输出变量
  17. CWaveIn *g_pIn;
  18. CWaveOut *g_pOut;   
  19. char pin[AudioData_Size],pout[Compr_AudioData_Size];
  20. char waveout[AudioData_Size];
  21. //摄像头输入变量
  22. DWORD dwSize;
  23. DWORD dwJpg;
  24. DWORD dwRtnSize[2];/* 0 - for bmp, 1 - for jpeg */
  25. LPBYTE lpFrameBuffer;
  26. LPBYTE lpJpgBuffer ;
  27. //控制变量
  28. bool isCameraEnabled;
  29. //UDP
  30. CUDP_CE m_CEUdp;

  31. class AVClass
  32. {
  33. public:

  34.     //=====================================================================
  35.     //  语法格式:   void InitAV(CWnd * p)
  36.     //  实现功能:   初始化音频和视频,用于录音、播放音频,以及播放视频
  37.     //  参数:     p为窗口类指针
  38.     //  返回值:    无
  39.     //=====================================================================
  40.     void InitAV(CWnd * p,int local_port,CString remote_ip,int remote_port)
  41.     {

  42.        //-----------------------初始化UDP-----------------------//
  43.        m_CEUdp.m_OnUdpRecv = OnUdpCERecv;
  44.        DWORD nResult = m_CEUdp.Open(p,local_port,remote_ip,remote_port);
  45.        if (nResult <=0)
  46.        {
  47.            AfxMessageBox(_T("打开端口失败"));
  48.            return;
  49.        }

  50.         //------------------------控制变量-----------------------//
  51.         isCameraEnabled=false;
  52.         //-------------------------视频--------------------------//
  53.         int i = capInitCamera();
  54.         dwSize = 320 * 240 * 3;
  55.         dwJpg = 40960;
  56.         lpFrameBuffer = (LPBYTE) malloc (dwSize);   
  57.         lpJpgBuffer = (LPBYTE) malloc (dwJpg);
  58.         if(i<=0)
  59.         {
  60.             //::MessageBox(NULL, L"Init camera error ", L"Notice", 0);
  61.             goto video_error;//出错,释放空间
  62.         }
  63.         if (0 != capSetVideoFormat(0, VIDEO_PALETTE_RGB24, VIDEO_SIZE_SIF))
  64.         {
  65.             //::MessageBox(NULL, L"SetVideoFormat error ", L"Notice", 0);
  66.             goto video_error;//出错,释放空间
  67.         }

  68.         if (capStartCamera(0) != 0)
  69.         {
  70.             //::MessageBox(NULL, L"StartCamera error ", L"Notice", 0);
  71.             capStopCamera(0);
  72.             goto video_error;//出错,释放空间
  73.         }
  74.         //没出错,进行视频(控制状态)、音频设置
  75.         isCameraEnabled=true;
  76.         goto audio;
  77. video_error:   
  78.         free (lpFrameBuffer);
  79.         lpFrameBuffer = NULL;
  80.         free (lpJpgBuffer);
  81.         lpJpgBuffer = NULL;
  82.         //-------------------------音频--------------------------//
  83. audio:  
  84.         g_pOut = new CWaveOut();
  85.         g_pIn = new CWaveIn();
  86.         g_pOut->StartPlay();
  87.         g_pIn->StartRec(OnRecCapAndSend,(DWORD)p);
  88.         

  89.     }

  90.     //=====================================================================
  91.     //  语法格式:   void FreeAV()
  92.     //  实现功能:   释放音频、视频
  93.     //  参数:     无
  94.     //  返回值:    无
  95.     //=====================================================================
  96.     void FreeAV()
  97.     {
  98.         //-------------------------视频--------------------------//
  99.         if(isCameraEnabled)
  100.             capStopCamera(0);
  101.         //-------------------------音频--------------------------//
  102.         g_pOut->StopPlay();
  103.         g_pIn->StopRec();
  104.         delete g_pOut;
  105.         delete g_pIn;
  106.         //------------------------UDP------------------------//
  107.         m_CEUdp.Close();
  108.     }



  109.     //=====================================================================
  110.     //  语法格式:   void RecAndPlay(WPARAM wParam,LPARAM lParam)
  111.     //  实现功能:   接收网络传来的音频,以及播放
  112.     //  参数:     wParam,表示数据;lParam,表示数据长度
  113.     //  返回值:    无
  114.     //=====================================================================
  115.     static void CALLBACK OnUdpCERecv(CWnd * pWnd,char* buf,int nLen,sockaddr * addr)
  116.     {
  117.         g726_Decode(buf,(unsigned char*)waveout);
  118.         
  119.         g_pOut->lay(waveout,AudioData_Size);
  120.     }


  121.     //=====================================================================
  122.     //  语法格式:   static void OnRecCapAndSend(char *data,int length,DWORD userdata)
  123.     //  实现功能:   录音,摄像并且发送
  124.     //  参数:     data表示数据,length表示数据长度,userdata暂时没用
  125.     //  返回值:    无
  126.     //=====================================f================================
  127.     static void OnRecCapAndSend(char *data,int length,DWORD userdata)
  128.     {
  129.         //-------------------------音频--------------------------//
  130.         memcpy(pin,g_pIn->buffer,AudioData_Size);   
  131.         g726_Encode((unsigned char*)pin,pout);
  132.         m_CEUdp.SendData(pout,Compr_AudioData_Size);

  133.         //-------------------------视频--------------------------//
  134.         if(isCameraEnabled==false)//如果程序不能用摄像头
  135.             return;
  136.         Sleep(15);
  137.         int index=0;
  138.         memset(lpFrameBuffer, 0, dwSize);
  139.         memset(lpJpgBuffer, 0, dwJpg);
  140.         dwRtnSize[0] = dwRtnSize[1] = 0;
  141.         if (capGetPicture(index, lpFrameBuffer, dwSize, lpJpgBuffer, dwJpg, dwRtnSize) == 0)
  142.         {
  143.             /// m_CEUdp.SendData((const char *)lpJpgBuffer,dwRtnSize[1]);
  144.             char tmp[1440];
  145.             int tmp_i=0;
  146.             for(int i=0;i
  147.             {
  148.                 tmp[tmp_i]=lpJpgBuffer;
  149.                 tmp_i++;
  150.                 if(tmp_i==1440)
  151.                 {
  152.                     m_CEUdp.SendData(tmp,1440);
  153.                     tmp_i=0;
  154.                     
  155.                 }
  156.                 else if(i==dwRtnSize[1]-1)
  157.                 {
  158.     m_CEUdp.SendData(tmp,dwRtnSize[1]-(dwRtnSize[1]/1440)*1440);
  159.                     tmp_i=0;
  160.                 }
  161.             }
  162.         }
  163.     }
  164. };
复制代码
点赞 关注
 

回复
举报

565

帖子

513

TA的资源

裸片初长成(中级)

沙发
 
以下是PC部分的关键代码

  1. 1. #pragma once
  2. 2. #include "winsock2.h"
  3. 3.
  4. 4. //UDP支持
  5. 5. #include "..\UDP\UDP.h"
  6. 6.
  7. 7. //音频支持
  8. 8. #include "WaveIn.h"
  9. 9. #include "waveout.h"
  10. 10.
  11. 11. //G726支持
  12. 12. #include "g726.h"
  13. 13.
  14. 14. //视频支持
  15. 15. #include "Gdiplus.h"
  16. 16. using namespace Gdiplus;
  17. 17.
  18. 18.
  19. 19. #define VideoData_Size 1440 //每块视频数据包的大小
  20. 20. #define Video_Width 320 //视频宽度
  21. 21. #define Video_Height 240 //视频长度
  22. 22. #define AudioData_Size 960 //每块音频数据包的大小
  23. 23. #define Compr_AudioData_Size 120 //压缩后音频块的大小
  24. 24.
  25. 25.
  26. 26. //音频输入输出变量
  27. 27. CWaveIn *g_pIn;
  28. 28. CWaveOut *g_pOut;
  29. 29. char pin[AudioData_Size],pout[Compr_AudioData_Size];
  30. 30. char wave_data[AudioData_Size];
  31. 31.
  32. 32. //UDP变量
  33. 33. CUDP_CE m_CEUdp;
  34. 34.
  35. 35.
  36. 36. //视频输入变量
  37. 37. GdiplusStartupInput m_gdiPlusInPut;
  38. 38. ULONG_PTR m_gdiPlusToken;
  39. 39. char video_data[Video_Width*Video_Height];
  40. 40. int index;//视频数据当前索引
  41. 41. class AVClass
  42. 42. {
  43. 43. private:
  44. 44.
  45. 45. public:
  46. 46. //=====================================================================
  47. 47. // 语法格式: void InitAV(CWnd * p)
  48. 48. // 实现功能: 初始化音频和视频,用于录音、播放音频,以及播放视频
  49. 49. // 参数: p为窗口类指针
  50. 50. // 返回值: 无
  51. 51. //=====================================================================
  52. 52. void InitAV(CWnd * p,int local_port,CString remote_ip,int remote_port)
  53. 53. {
  54. 54. //-------------------------UDP连接--------------------------//
  55. 55. m_CEUdp.m_OnUdpRecv = OnUdpCERecv;
  56. 56. DWORD nResult = m_CEUdp.Open(p,local_port,remote_ip,remote_port);
  57. 57. if (nResult <=0)
  58. 58. {
  59. 59. AfxMessageBox(_T("打开端口失败"));
  60. 60. return;
  61. 61. }
  62. 62.
  63. 63. //-------------------------音频--------------------------//
  64. 64. g_pOut = new CWaveOut();
  65. 65. g_pIn = new CWaveIn();
  66. 66. g_pOut->StartPlay();
  67. 67. g_pIn->StartRec(OnRecording,(DWORD)p);
  68. 68. //-------------------------视频--------------------------//
  69. 69. GdiplusStartup( &m_gdiPlusToken, &m_gdiPlusInPut, NULL ); //初始化GDI+
  70. 70. memset(video_data,0,Video_Width*Video_Height);
  71. 71. index=0;
  72. 72.
  73. 73. }
  74. 74.
  75. 75. //=====================================================================
  76. 76. // 语法格式: void FreeAV()
  77. 77. // 实现功能: 释放音频、视频
  78. 78. // 参数: 无
  79. 79. // 返回值: 无
  80. 80. //=====================================================================
  81. 81. void FreeAV()
  82. 82. {
  83. 83.
  84. 84. //-------------------------音频--------------------------//
  85. 85. g_pOut->StopPlay();
  86. 86. g_pIn->StopRec();
  87. 87. delete g_pOut;
  88. 88. delete g_pIn;
  89. 89. //-------------------------视频--------------------------//
  90. 90. GdiplusShutdown(m_gdiPlusToken); //销毁GDI+
  91. 91.
  92. 92. //------------------------UDP--------------------------//
  93. 93. m_CEUdp.Close();
  94. 94.
  95. 95. }
  96. 96. //=====================================================================
  97. 97. // 语法格式: void RecAndPlay(WPARAM wParam,LPARAM lParam,HWND hwnd)
  98. 98. // 实现功能: 接收网络传来的音频,以及播放
  99. 99. // 参数: wParam,表示数据;lParam,表示数据长度;hwnd,表示显示视频的窗口句柄
  100. 100. // 返回值: 无
  101. 101. //=====================================================================
  102. 102. static void CALLBACK OnUdpCERecv(CWnd *pWnd,char* buf,int nLen,sockaddr * addr)
  103. 103. {
  104. 104. /*测试收到的数据大小
  105. 105.
  106. 106. CString tmp;
  107. 107. tmp.Format(L"%d",nLen);
  108. 108. MessageBox(0,tmp,0,0);
  109. 109. return;*/
  110. 110.
  111. 111. //-------------------------如果是音频数据--------------------------//
  112. 112. if(nLen==Compr_AudioData_Size)
  113. 113. {
  114. 114. g726_Decode(buf,(unsigned char*)wave_data);
  115. 115. g_pOut->Play(wave_data,AudioData_Size);
  116. 116. return;
  117. 117. }
  118. 118. //-------------------------如果是视频数据--------------------------//
  119. 119.
  120. 120. if(nLen==VideoData_Size)//完整的视频数据块
  121. 121. {
  122. 122. for(int i=0;i
  123. 123. {
  124. 124. video_data[index]=buf[i];
  125. 125. index++;
  126. 126. }
  127. 127. return;
  128. 128. }
  129. 129.
  130. 130. //视频数据块的最后一块
  131. 131. for(int i=0;i
  132. 132. {
  133. 133. video_data[index]=buf[i];
  134. 134. index++;
  135. 135. }
  136. 136.
  137. 137. //如果JPEG图像特别大,则肯定是出错,则抛弃
  138. 138. if(index>Video_Width*Video_Height)
  139. 139. {
  140. 140. //MessageBox(0,"缓冲区出错","错误信息",0);
  141. 141. return;
  142. 142. }
  143. 143.
  144. 144.
  145. 145. try{
  146. 146. IPicture *pPic;
  147. 147. IStream *pStm ;
  148. 148. //分配全局存储空间
  149. 149. HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,index);
  150. 150. LPVOID pvData=NULL ;
  151. 151. //锁定分配内存块
  152. 152. pvData=GlobalLock(hGlobal);
  153. 153. //复制数据包video_data到pvData
  154. 154. memcpy(pvData,video_data,index);
  155. 155.
  156. 156. GlobalUnlock(hGlobal);
  157. 157. CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);
  158. 158.
  159. 159. ULARGE_INTEGER pSeek;
  160. 160. LARGE_INTEGER dlibMove ={ 0 } ;
  161. 161. pStm->Seek(dlibMove,STREAM_SEEK_SET ,&pSeek);
  162. 162. // Sleep(15);
  163. 163.
  164. 164. //装入图形文件
  165. 165. if(FAILED(OleLoadPicture(pStm,index,TRUE,IID_IPicture,(LPVOID*)&pPic)))
  166. 166. {//附:如果video_data这个数组包含的图像有错,则OleLoadPicture 容易产生读写内存错误
  167. 167. // pPic->Release();
  168. 168. // pStm->Release();
  169. 169. return ;
  170. 170. }
  171. 171.
  172. 172. Image img(pStm,0);
  173. 173. Graphics mGraphics(GetDC(pWnd->m_hWnd));
  174. 174. mGraphics.DrawImage(&img, 0, 0, Video_Width, Video_Height);
  175. 175. img.~Image();//会出错
  176. 176. mGraphics.~Graphics();
  177. 177. pPic->Release();
  178. 178. pStm->Release();
  179. 179. }
  180. 180. catch(CException * e)
  181. 181. {}
  182. 182. memset(video_data,0,Video_Width*Video_Height);
  183. 183. index=0;
  184. 184. }
  185. 185.
  186. 186. //=====================================================================
  187. 187. // 语法格式: static void OnRecording(char *data,int length,DWORD userdata)
  188. 188. // 实现功能: 释放音频
  189. 189. // 参数: data表示数据,length表示数据长度,userdata暂时没用
  190. 190. // 返回值: 无
  191. 191. //=====================================================================
  192. 192. static void OnRecording(char *data,int length,DWORD userdata)
  193. 193. {
  194. 194. memcpy(pin,g_pIn->buffer,AudioData_Size);
  195. 195. g726_Encode((unsigned char*)pin,pout);
  196. 196. m_CEUdp.SendData(pout,Compr_AudioData_Size);
  197. 197. }
  198. 198. };
复制代码
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
Microchip 直播|利用motorBench开发套件高效开发电机磁场定向控制方案 报名中!
直播主题:利用motorBench开发套件高效开发电机磁场定向控制方案
直播时间:2025年3月25日(星期二)上午10:30-11:30
快来报名!

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表