VideoUSB.cpp
上传用户:popouu88
上传日期:2013-02-11
资源大小:2894k
文件大小:9k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. // VideoUSB.cpp : implementation file
  2. //
  3. #include "../../stdafx.h"
  4. #include "VideoUSB.h"
  5. #include "SelectDriverDialog.h"
  6. #include "../../Conference.h""
  7. #ifdef _DEBUG
  8. #define new DEBUG_NEW
  9. #undef THIS_FILE
  10. static char THIS_FILE[] = __FILE__;
  11. #endif
  12. #pragma comment( lib , "vfw32.lib" )
  13. extern CConferenceApp theApp;
  14. /////////////////////////////////////////////////////////////////////////////
  15. // CVideoUSB
  16. CVideoUSB::CVideoUSB( )
  17. {
  18. this->OnCapture = NULL;
  19. this->pContext = NULL;
  20. memset( &this->header , 0 , sizeof( BITMAPINFOHEADER ) );
  21. this->m_bPreview = false;
  22. this->m_bCapture = false;
  23. this->send_buffer = NULL;
  24. this->m_bRecord = false;
  25. this->recordDir = "";
  26. }
  27. CVideoUSB::~CVideoUSB( )
  28. {
  29. this->StopPreview( );
  30. this->StopCapture( );
  31. this->ReleaseDraw( );
  32. }
  33. BEGIN_MESSAGE_MAP(CVideoUSB, CWnd )
  34. //{{AFX_MSG_MAP(CVideoUSB)
  35. ON_WM_CLOSE()
  36. ON_WM_TIMER()
  37. ON_WM_NCHITTEST()
  38. //}}AFX_MSG_MAP
  39. END_MESSAGE_MAP()
  40. /////////////////////////////////////////////////////////////////////////////
  41. // CVideoUSB message handlers
  42. //关闭窗口
  43. void CVideoUSB::OnClose( ) 
  44. {
  45. this->StopCapture( );
  46. this->StopPreview( );
  47. capDriverDisconnect( this->GetSafeHwnd( ) );
  48. this->ReleaseDraw( );
  49. CWnd::OnClose( );
  50. }
  51. /////////////////////////////////////////////////////////////////////////////////
  52. bool CVideoUSB::Init( HWND hWnd , void ( * OnCapture )( void * pContext , char * buffer , int size , bool m_bHeader ) , void * pContext )
  53. {   //选择驱动器
  54. int driver = CSelectDriverDialog::SelectDriver( );
  55. if( driver == -1 ) return false;
  56.     //如果没有设置驱动,那么先设置驱动
  57. if( ::IsWindow( hWnd ) )
  58. this->SubclassWindow( ::capCreateCaptureWindow( "本地视频窗口" , WS_CHILD | WS_VISIBLE , 0 , 0 , 1 , 1 , hWnd , 0 ) );
  59. else
  60. this->SubclassWindow( ::capCreateCaptureWindow( "本地视频窗口" , WS_OVERLAPPEDWINDOW | WS_VISIBLE , 0 , 0 , 320 , 240 , NULL , 0 ) );
  61. //连接驱动
  62.     capDriverConnect( this->GetSafeHwnd( ) , driver );
  63. //设置图像格式
  64. capGetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) );
  65. //图像的宽度
  66. this->header.biWidth = 320; 
  67.     //图像高度
  68. this->header.biHeight = 240;
  69.     //图像深度
  70. this->header.biBitCount = 24;
  71.     //如果设置失败,那么弹出对话框
  72. if( ! capSetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) ) )
  73. capDlgVideoFormat( this->GetSafeHwnd( ) );
  74. //取出视频格式
  75. capGetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) );
  76. this->ddraw.InitDirectDraw( this->GetSafeHwnd( ) , this->header.biWidth , this->header.biHeight , this->header.biBitCount );
  77.     //压缩视频
  78. BITMAPINFOHEADER * h = this->codec.InitEncode( this->header.biWidth , this->header.biHeight , this->header.biBitCount ,"MP42" );
  79.     //压缩失败,再次选择压缩器
  80. if( ! h && ! ( h = this->codec.InitEncode( this->header.biWidth , this->header.biHeight , this->header.biBitCount ) ) )
  81. return false;
  82.     //保存压缩后的图像
  83. memcpy( &this->header , h , sizeof( BITMAPINFOHEADER ) );
  84. //用户自定义信息
  85. capSetUserData( this->GetSafeHwnd( ) , ( long )this );
  86.    
  87. this->OnCapture = OnCapture;
  88. this->pContext = pContext;
  89. //开始捕捉图像
  90. CAPTUREPARMS setup;
  91. capCaptureGetSetup( this->GetSafeHwnd( ) , &setup , sizeof( setup ) );
  92. setup.dwRequestMicroSecPerFrame = 1000000 / 20 ; //帧速率
  93. setup.fYield = true;
  94. setup.fCaptureAudio = false;
  95. setup.vKeyAbort = 0;
  96. setup.fAbortLeftMouse = false;
  97. setup.fAbortRightMouse = false;
  98. setup.fLimitEnabled = false;
  99. setup.fMCIControl = false;
  100. //设定回调函数
  101. capSetCallbackOnVideoStream( this->GetSafeHwnd( ) , CVideoUSB::OnVideo );
  102. //安装捕捉驱动
  103. capCaptureSetSetup( this->GetSafeHwnd( ) , &setup , sizeof( setup ) );
  104. //开始捕捉
  105. capCaptureSequenceNoFile( this->GetSafeHwnd( ) );
  106. //录像文件夹
  107. this->recordDir = theApp.appIni.Left( theApp.appIni.ReverseFind( '\' ) + 1 ) + "录像文件夹";
  108. this->m_bRecord = ( bool )::GetPrivateProfileInt( "用户信息" , "运行时录像" , 0 , theApp.appIni );
  109. if( this->m_bRecord )
  110. { //创建录像文件夹
  111. ::CreateDirectory( this->recordDir , NULL );
  112. CTime tm = CTime::GetCurrentTime( );
  113. CString aviName;
  114. aviName.Format( "%s\%s.avi" , this->recordDir, tm.Format( "%Y-%m-%d %H:%M:%S" ) );
  115. //录像
  116. this->avi.OpenAVI( aviName , CAVI::AVI_WRITE );
  117. this->avi.SetAVIInfo( this->header , 15 );
  118. //启动定时器,要求每隔一个小时保存一个文件
  119. this->SetTimer( 1 , 3600000 , NULL );
  120. }
  121. return true;
  122. }
  123. //定时录像
  124. void CVideoUSB::OnTimer(UINT nIDEvent) 
  125. {
  126. CWnd ::OnTimer( nIDEvent );
  127. if( nIDEvent == 1 )
  128. {
  129. this->avi.CloseAVI( );
  130. //创建录像文件夹
  131. ::CreateDirectory( this->recordDir , NULL );
  132. CTime tm = CTime::GetCurrentTime( );
  133. CString aviName;
  134. aviName.Format( "%s\%s.avi" , this->recordDir, tm.Format( "%Y-%m-%d %H:%M:%S" ) );
  135. this->avi.OpenAVI( aviName , CAVI::AVI_WRITE );
  136. this->avi.SetAVIInfo( this->header , 15 );
  137. }
  138. }
  139. //获得视频头信息
  140. bool CVideoUSB::GetHeader( char ** header , int * size )
  141. {
  142. * header = NULL;
  143. * size = 0;
  144. if( this->GetSafeHwnd( ) )
  145. {
  146. * header = ( char * )&this->header;
  147. * size = sizeof( this->header );
  148. return true;
  149. }
  150. return false;
  151. }
  152. //开始预览
  153. bool CVideoUSB::StartPreview( int fps )
  154. {
  155. this->m_bPreview = true;
  156. return true;
  157. }
  158. //停止预览
  159. void CVideoUSB::StopPreview( void )
  160. {
  161. if( this->m_bPreview )
  162. this->m_bPreview = false;
  163. }
  164. //开始捕捉
  165. bool CVideoUSB::StartCapture( void )
  166. {
  167. if( ! this->m_bCapture && this->GetSafeHwnd( ) )
  168. {
  169. this->m_bCapture = true;
  170. ::AfxBeginThread( CVideoUSB::OnSend , this );
  171. }
  172. return true;
  173. }
  174. //停止捕捉
  175. void CVideoUSB::StopCapture( void )
  176. {
  177. if( this->m_bCapture )
  178. {
  179. this->m_bCapture = false;
  180. while( this->send_buffer ) ::Sleep( 100 );
  181. }
  182. }
  183. //视频信号回调函数
  184. LRESULT CALLBACK CVideoUSB::OnVideo( HWND hWnd , VIDEOHDR * lpVHdr )
  185. {
  186. CVideoUSB * pThis = ( CVideoUSB * )capGetUserData( hWnd );
  187. int size = lpVHdr->dwBufferLength;
  188. char * buffer = ( char * )lpVHdr->lpData;
  189.     //本地显示
  190. if( pThis->m_bPreview )
  191. pThis->Draw( buffer , size );
  192. //网络发送
  193. if( pThis->OnCapture && pThis->m_bCapture && ! pThis->send_buffer )
  194. {
  195. char * buf = new char[ sizeof( int ) + size ];
  196. if( buf )
  197. {
  198. *( int * )buf = size;
  199. memcpy( buf + sizeof( int ) , buffer , size );
  200. pThis->send_buffer = buf;
  201. }
  202. }//本地录像
  203. pThis->avi.AddFrame( buffer , size );
  204. return ( LRESULT ) true;
  205. }
  206. //发送视频数据
  207. UINT CVideoUSB::OnSend( void * wParam )
  208. {
  209. CVideoUSB * pThis = ( CVideoUSB * )wParam;
  210. char * buffer = NULL;
  211. char * buf;
  212. int s;
  213. while( pThis->m_bCapture && pThis->OnCapture )
  214. {
  215. try
  216. {
  217. if( pThis->send_buffer )
  218. {
  219. buffer = pThis->send_buffer;
  220. s = *( int * )buffer;
  221. buf = ( char * )pThis->codec.Encode( buffer + sizeof( int ) , &s );
  222. if( buf && s )
  223. pThis->OnCapture( pThis->pContext , buf , s , false );
  224. pThis->send_buffer = NULL;
  225. delete [ ]buffer;
  226. }
  227. else
  228. ::Sleep( 40 );
  229. }
  230. catch( ... )
  231. {
  232. }
  233. }
  234. try
  235. {
  236. delete pThis->send_buffer;
  237. }
  238. catch( ... )
  239. {
  240. }
  241. pThis->send_buffer = NULL;
  242. return 0;
  243. }
  244. bool CVideoUSB::InitDraw( HWND hWnd , char * buffer , int size )
  245. {
  246. if( ! ::IsWindow( hWnd ) )
  247. return false;
  248. memcpy( &this->header , buffer , sizeof( BITMAPINFOHEADER ) );
  249. //初始化解压器
  250. if( ! this->codec.InitDecode( &this->header ) )
  251. return false;
  252.     //如果不是窗口
  253. if( ! ::IsWindow( hWnd ) )
  254. { //界面处理
  255. const char  * className = ::AfxRegisterWndClass( 0 , ::AfxGetApp( )->LoadStandardCursor( IDC_ARROW ) , ::CreateSolidBrush( RGB( 10 , 10 , 10 ) ) , NULL );
  256. this->CreateEx( NULL , className , "显示视频窗口" , WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0 , 0 , 300 , 200 , NULL , NULL );
  257. ::SetProp( this->GetSafeHwnd( ) , "isCreateWindow" , (HANDLE)true );
  258. }
  259. else
  260. {
  261. this->m_hWnd = hWnd;
  262. ::SetProp( this->GetSafeHwnd( ) , "isCreateWindow" , (HANDLE)false );
  263. }
  264. return this->ddraw.InitDirectDraw( this->GetSafeHwnd( ) , this->header.biWidth , this->header.biHeight , this->header.biBitCount );
  265. }
  266. bool CVideoUSB::Draw( char * buffer , int size )
  267. {
  268. return this->ddraw.DrawDirectDraw( this->m_bPreview ? buffer : this->codec.Decode( buffer , size ) , true , 0 );
  269. }
  270. void CVideoUSB::ReleaseDraw( void )
  271. {
  272. this->ddraw.ReleaseDirectDraw( );
  273. this->codec.ReleaseDecode( );
  274. if( ::IsWindow( this->GetSafeHwnd( ) ) && ::GetProp( this->GetSafeHwnd( ) , "isCreateWindow" ) )
  275. this->DestroyWindow( );
  276. else
  277. {
  278. if( ::IsWindow( this->GetSafeHwnd( ) ) )
  279. this->Invalidate( );
  280. this->m_hWnd = NULL;
  281. }
  282. }
  283. UINT CVideoUSB::OnNcHitTest(CPoint point) 
  284. {
  285. UINT hitTest = CWnd ::OnNcHitTest( point );
  286. return ( hitTest == HTCLIENT || hitTest == HTCAPTION ) ? HTTRANSPARENT : hitTest;
  287. }