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

IP电话/视频会议

开发平台:

Visual C++

  1. // VideoUSB.cpp : implementation file
  2. //
  3. #include "stdafx.h"
  4. #include "VideoUSB.h"
  5. #include "SelectDriverDialog.h"
  6. #ifdef _DEBUG
  7. #define new DEBUG_NEW
  8. #undef THIS_FILE
  9. static char THIS_FILE[] = __FILE__;
  10. #endif
  11. #pragma comment( lib , "vfw32.lib" )
  12. /////////////////////////////////////////////////////////////////////////////
  13. // CVideoUSB
  14. CVideoUSB::CVideoUSB( )
  15. {
  16. this->OnCapture = NULL;
  17. this->pContext = NULL;
  18. memset( &this->header , 0 , sizeof( BITMAPINFOHEADER ) );
  19. this->m_bPreview = false;
  20. this->m_bCapture = false;
  21. }
  22. CVideoUSB::~CVideoUSB( )
  23. {
  24. this->StopPreview( );
  25. this->StopCapture( );
  26. this->ReleaseDraw( );
  27. // if( this->hDraw )
  28. // ::DrawDibClose( this->hDraw );
  29. }
  30. BEGIN_MESSAGE_MAP(CVideoUSB, CWnd )
  31. //{{AFX_MSG_MAP(CVideoUSB)
  32. ON_WM_CLOSE()
  33. //}}AFX_MSG_MAP
  34. END_MESSAGE_MAP()
  35. /////////////////////////////////////////////////////////////////////////////
  36. // CVideoUSB message handlers
  37. //关闭窗口
  38. void CVideoUSB::OnClose( ) 
  39. {
  40. this->StopCapture( );
  41. this->StopPreview( );
  42. capDriverDisconnect( this->GetSafeHwnd( ) );
  43. this->ReleaseDraw( );
  44. CWnd::OnClose( );
  45. }
  46. /////////////////////////////////////////////////////////////////////////////////
  47. bool CVideoUSB::Init( HWND hWnd , void ( * OnCapture )( void * pContext , char * buffer , int size , bool m_bHeader ) , void * pContext )
  48. {   //选择驱动器
  49. int driver = CSelectDriverDialog::SelectDriver( );
  50. if( driver == -1 ) return false;
  51.     //如果没有设置驱动,那么先设置驱动
  52. if( ::IsWindow( hWnd ) )
  53. {
  54. CRect rc;
  55. CWnd::FromHandle( hWnd )->GetClientRect( &rc );
  56. this->SubclassWindow( ::capCreateCaptureWindow( "本地视频窗口" , WS_CHILD | WS_VISIBLE , 0 , 0 , rc.Width( ) , rc.Height( ) , hWnd , 0 ) );
  57. }
  58. else
  59. this->SubclassWindow( ::capCreateCaptureWindow( "本地视频窗口" , WS_OVERLAPPEDWINDOW | WS_VISIBLE , 0 , 0 , 320 , 240 , NULL , 0 ) );
  60. //连接驱动
  61.     capDriverConnect( this->GetSafeHwnd( ) , driver );
  62. //设置图像格式
  63. capGetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) );
  64. //图像的宽度 
  65. this->header.biWidth = 320; 
  66.     //图像高度
  67. this->header.biHeight = 240;
  68.     //图像深度
  69. this->header.biBitCount = 24;
  70.     //如果设置失败,那么探出对话框
  71. if( ! capSetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) ) )
  72. capDlgVideoFormat( this->GetSafeHwnd( ) );
  73. //取出视频格式
  74. capGetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) );
  75.     //初始化显示
  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 , "3iv2");
  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. return true;
  107. }
  108. //获得视频头信息
  109. bool CVideoUSB::GetHeader( char ** header , int * size )
  110. {
  111. * header = NULL;
  112. * size = 0;
  113. if( this->GetSafeHwnd( ) )
  114. {
  115. * header = ( char * )&this->header;
  116. * size = sizeof( this->header );
  117. return true;
  118. }
  119. return false;
  120. }
  121. //开始预览
  122. bool CVideoUSB::StartPreview( int fps )
  123. {
  124. this->m_bPreview = true;
  125. return true;
  126. }
  127. //停止预览
  128. void CVideoUSB::StopPreview( void )
  129. {
  130. if( this->m_bPreview )
  131. this->m_bPreview = false;
  132. }
  133. //开始捕捉
  134. bool CVideoUSB::StartCapture( void )
  135. {
  136. this->m_bCapture = true;
  137. ::AfxBeginThread( CVideoUSB::OnSend , this );
  138. return true;
  139. }
  140. void CVideoUSB::StopCapture( void )
  141. {
  142. this->m_bCapture = false;
  143. while( ! this->buffer_list.empty( ) ) ::Sleep( 100 );
  144. }
  145. LRESULT CALLBACK CVideoUSB::OnVideo( HWND hWnd , VIDEOHDR * lpVHdr )
  146. {
  147. CVideoUSB * pThis = ( CVideoUSB * )capGetUserData( hWnd );
  148. int size = lpVHdr->dwBufferLength;
  149. char * buffer = ( char * )lpVHdr->lpData;
  150. //添加日期和时间
  151. CTime tm = CTime::GetCurrentTime( );
  152.     //使用第一个32位数保存
  153. *( int * )( buffer + size - sizeof( int ) ) = tm.GetTime( );
  154. if( pThis->m_bPreview )
  155. {
  156. pThis->Draw( buffer , size );
  157. }
  158. if( pThis->OnCapture && pThis->m_bCapture && pThis->buffer_list.size( ) < 10 )
  159. {
  160. char * buf = new char[ sizeof( int ) + size ];
  161. if( buf )
  162. {
  163. *( int * )buf = size;
  164. memcpy( buf + sizeof( int ) , buffer , size );
  165. pThis->buffer_list.push_back( buf );
  166. }
  167. }
  168. return ( LRESULT ) true;
  169. }
  170. //发送视频数据
  171. UINT CVideoUSB::OnSend( void * wParam )
  172. {
  173. CVideoUSB * pThis = ( CVideoUSB * )wParam;
  174. char * buffer = NULL;
  175. char * buf ;
  176. int s;
  177. while( pThis->m_bCapture && pThis->OnCapture )
  178. {
  179. if( ! pThis->buffer_list.empty( ) )
  180. {
  181. buffer = ( char * ) * pThis->buffer_list.begin( );
  182. pThis->buffer_list.pop_front( );
  183. buf = buffer + sizeof( int );
  184. s = * ( int * )buffer;
  185. buf = ( char * )pThis->codec.Encode( buf , &s );
  186. if( buf && s )
  187. { //添加日期和时间
  188. CTime tm = CTime::GetCurrentTime( );
  189. //使用第一个32位数保存
  190. *( int * )( buf + s - sizeof( int ) )= tm.GetTime( );
  191. pThis->OnCapture( pThis->pContext , buf , s , false );
  192. }
  193. delete []buffer;
  194. }
  195. }
  196. while( ! pThis->buffer_list.empty( ) )
  197. {
  198. buffer = ( char * ) * pThis->buffer_list.begin( );
  199. pThis->buffer_list.pop_front( );
  200. delete []buffer;
  201. }
  202. return 0;
  203. }
  204. bool CVideoUSB::InitDraw( HWND hWnd , char * buffer , int size )
  205. {
  206. memcpy( &this->header , buffer , sizeof( BITMAPINFOHEADER ) );
  207. //初始化解压器
  208. if( ! this->codec.InitDecode( &this->header ) )
  209. return false;
  210.     //如果不是窗口
  211. if( ! ::IsWindow( hWnd ) )
  212. { //界面处理
  213. const char  * className = ::AfxRegisterWndClass( 0 , ::AfxGetApp( )->LoadStandardCursor( IDC_ARROW ) , ::CreateSolidBrush( RGB( 10 , 10 , 10 ) ) , NULL );
  214. this->CreateEx( NULL , className , "显示视频窗口" , WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0 , 0 , 300 , 200 , NULL , NULL );
  215. ::SetProp( this->GetSafeHwnd( ) , "isCreateWindow" , (HANDLE)true );
  216. }
  217. else
  218. {
  219. this->m_hWnd = hWnd;
  220. ::SetProp( this->GetSafeHwnd( ) , "isCreateWindow" , (HANDLE)false );
  221. }
  222. this->ddraw.InitDirectDraw( this->GetSafeHwnd( ) , this->header.biWidth , this->header.biHeight , this->header.biBitCount );
  223. return true;
  224. }
  225. bool CVideoUSB::Draw( char * buffer , int size )
  226. {
  227. return this->ddraw.DrawDirectDraw( this->m_bPreview ? buffer : this->codec.Decode( buffer , size ) , true , this->codec.GetEncodeTime( ) );
  228. }
  229. void CVideoUSB::ReleaseDraw( void )
  230. {
  231. this->ddraw.ReleaseDirectDraw( );
  232. this->codec.ReleaseDecode( );
  233. if( ::IsWindow( this->GetSafeHwnd( ) ) && ::GetProp( this->GetSafeHwnd( ) , "isCreateWindow" ) )
  234. this->DestroyWindow( );
  235. this->m_hWnd = NULL;
  236. }