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. }
  28. BEGIN_MESSAGE_MAP(CVideoUSB, CWnd )
  29. //{{AFX_MSG_MAP(CVideoUSB)
  30. ON_WM_CLOSE()
  31. //}}AFX_MSG_MAP
  32. END_MESSAGE_MAP()
  33. /////////////////////////////////////////////////////////////////////////////
  34. // CVideoUSB message handlers
  35. //关闭窗口
  36. void CVideoUSB::OnClose( ) 
  37. {
  38. this->StopCapture( );
  39. this->StopPreview( );
  40. capDriverDisconnect( this->GetSafeHwnd( ) );
  41. this->ReleaseDraw( );
  42. CWnd::OnClose( );
  43. }
  44. /////////////////////////////////////////////////////////////////////////////////
  45. bool CVideoUSB::Init( HWND hWnd , void ( * OnCapture )( void * pContext , char * buffer , int size , bool m_bHeader ) , void * pContext )
  46. {   //选择驱动器
  47. int driver = CSelectDriverDialog::SelectDriver( );
  48. if( driver == -1 ) return false;
  49.     //如果没有设置驱动,那么先设置驱动
  50. if( ::IsWindow( hWnd ) )
  51. {
  52. CRect rc;
  53. CWnd::FromHandle( hWnd )->GetClientRect( &rc );
  54. this->SubclassWindow( ::capCreateCaptureWindow( "本地视频窗口" , WS_CHILD | WS_VISIBLE , 0 , 0 , rc.Width( ) , rc.Height( ) , hWnd , 0 ) );
  55. }
  56. else
  57. this->SubclassWindow( ::capCreateCaptureWindow( "本地视频窗口" , WS_OVERLAPPEDWINDOW | WS_VISIBLE , 0 , 0 , 320 , 240 , NULL , 0 ) );
  58. //连接驱动
  59.     capDriverConnect( this->GetSafeHwnd( ) , driver );
  60. //设置图像格式
  61. capGetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) );
  62. //图像的宽度 
  63. this->header.biWidth = 320; 
  64.     //图像高度
  65. this->header.biHeight = 240;
  66.     //图像深度
  67. this->header.biBitCount = 24;
  68.     //如果设置失败,那么探出对话框
  69. if( ! capSetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) ) )
  70. capDlgVideoFormat( this->GetSafeHwnd( ) );
  71. //取出视频格式
  72. capGetVideoFormat( this->GetSafeHwnd( ) , &this->header , sizeof( BITMAPINFOHEADER ) );
  73.     //初始化显示
  74. this->ddraw.InitDirectDraw( this->GetSafeHwnd( ) , this->header.biWidth , this->header.biHeight , this->header.biBitCount );
  75.     //压缩视频
  76. BITMAPINFOHEADER * h = this->codec.InitEncode( this->header.biWidth , this->header.biHeight , this->header.biBitCount , "3iv2");
  77.     //压缩失败,再次选择压缩器
  78. if( ! h && ! ( h = this->codec.InitEncode( this->header.biWidth , this->header.biHeight , this->header.biBitCount ) ) )
  79. return false;
  80.     //保存压缩后的图像
  81. memcpy( &this->header , h , sizeof( BITMAPINFOHEADER ) );
  82. //用户自定义信息
  83. capSetUserData( this->GetSafeHwnd( ) , ( long )this );
  84.    
  85. this->OnCapture = OnCapture;
  86. this->pContext = pContext;
  87. //开始捕捉图像
  88. CAPTUREPARMS setup;
  89. capCaptureGetSetup( this->GetSafeHwnd( ) , &setup , sizeof( setup ) );
  90. setup.dwRequestMicroSecPerFrame = 1000000 / 20 ; //帧速率
  91. setup.fYield = true;
  92. setup.fCaptureAudio = false;
  93. setup.vKeyAbort = 0;
  94. setup.fAbortLeftMouse = false;
  95. setup.fAbortRightMouse = false;
  96. setup.fLimitEnabled = false;
  97. setup.fMCIControl = false;
  98. //设定回调函数
  99. capSetCallbackOnVideoStream( this->GetSafeHwnd( ) , CVideoUSB::OnVideo );
  100. //安装捕捉驱动
  101. capCaptureSetSetup( this->GetSafeHwnd( ) , &setup , sizeof( setup ) );
  102. //开始捕捉
  103. capCaptureSequenceNoFile( this->GetSafeHwnd( ) );
  104. return true;
  105. }
  106. //获得视频头信息
  107. bool CVideoUSB::GetHeader( char ** header , int * size )
  108. {
  109. * header = NULL;
  110. * size = 0;
  111. if( this->GetSafeHwnd( ) )
  112. {
  113. * header = ( char * )&this->header;
  114. * size = sizeof( this->header );
  115. return true;
  116. }
  117. return false;
  118. }
  119. //开始预览
  120. bool CVideoUSB::StartPreview( int fps )
  121. {
  122. this->m_bPreview = true;
  123. return true;
  124. }
  125. //停止预览
  126. void CVideoUSB::StopPreview( void )
  127. {
  128. if( this->m_bPreview )
  129. this->m_bPreview = false;
  130. }
  131. //开始捕捉
  132. bool CVideoUSB::StartCapture( void )
  133. {
  134. this->m_bCapture = true;
  135. ::AfxBeginThread( CVideoUSB::OnSend , this );
  136. return true;
  137. }
  138. void CVideoUSB::StopCapture( void )
  139. {
  140. this->m_bCapture = false;
  141. while( ! this->buffer_list.empty( ) ) ::Sleep( 100 );
  142. }
  143. LRESULT CALLBACK CVideoUSB::OnVideo( HWND hWnd , VIDEOHDR * lpVHdr )
  144. {
  145. CVideoUSB * pThis = ( CVideoUSB * )capGetUserData( hWnd );
  146. int size = lpVHdr->dwBufferLength;
  147. char * buffer = ( char * )lpVHdr->lpData;
  148. //添加日期和时间
  149. CTime tm = CTime::GetCurrentTime( );
  150.     //使用第一个32位数保存
  151. *( int * )( buffer + size - sizeof( int ) ) = tm.GetTime( );
  152. if( pThis->m_bPreview )
  153. {
  154. pThis->Draw( buffer , size );
  155. }
  156. if( pThis->OnCapture && pThis->m_bCapture && pThis->buffer_list.size( ) < 10 )
  157. {
  158. char * buf = new char[ sizeof( int ) + size ];
  159. if( buf )
  160. {
  161. *( int * )buf = size;
  162. memcpy( buf + sizeof( int ) , buffer , size );
  163. pThis->buffer_list.push_back( buf );
  164. }
  165. }
  166. return ( LRESULT ) true;
  167. }
  168. //发送视频数据
  169. UINT CVideoUSB::OnSend( void * wParam )
  170. {
  171. CVideoUSB * pThis = ( CVideoUSB * )wParam;
  172. char * buffer = NULL;
  173. char * buf ;
  174. int s;
  175. while( pThis->m_bCapture && pThis->OnCapture )
  176. {
  177. if( ! pThis->buffer_list.empty( ) )
  178. {
  179. buffer = ( char * ) * pThis->buffer_list.begin( );
  180. pThis->buffer_list.pop_front( );
  181. buf = buffer + sizeof( int );
  182. s = * ( int * )buffer;
  183. buf = ( char * )pThis->codec.Encode( buf , &s );
  184. if( buf && s )
  185. { //添加日期和时间
  186. CTime tm = CTime::GetCurrentTime( );
  187. //使用第一个32位数保存
  188. *( int * )( buf + s - sizeof( int ) )= tm.GetTime( );
  189. pThis->OnCapture( pThis->pContext , buf , s , false );
  190. }
  191. delete []buffer;
  192. }
  193. }
  194. while( ! pThis->buffer_list.empty( ) )
  195. {
  196. buffer = ( char * ) * pThis->buffer_list.begin( );
  197. pThis->buffer_list.pop_front( );
  198. delete []buffer;
  199. }
  200. return 0;
  201. }
  202. bool CVideoUSB::InitDraw( HWND hWnd , char * buffer , int size )
  203. {
  204. memcpy( &this->header , buffer , sizeof( BITMAPINFOHEADER ) );
  205. //初始化解压器
  206. if( ! this->codec.InitDecode( &this->header ) )
  207. return false;
  208.     //如果不是窗口
  209. if( ! ::IsWindow( hWnd ) )
  210. { //界面处理
  211. const char  * className = ::AfxRegisterWndClass( 0 , ::AfxGetApp( )->LoadStandardCursor( IDC_ARROW ) , ::CreateSolidBrush( RGB( 10 , 10 , 10 ) ) , NULL );
  212. this->CreateEx( NULL , className , "显示视频窗口" , WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0 , 0 , 300 , 200 , NULL , NULL );
  213. ::SetProp( this->GetSafeHwnd( ) , "isCreateWindow" , (HANDLE)true );
  214. }
  215. else
  216. {
  217. this->m_hWnd = hWnd;
  218. ::SetProp( this->GetSafeHwnd( ) , "isCreateWindow" , (HANDLE)false );
  219. }
  220. this->ddraw.InitDirectDraw( this->GetSafeHwnd( ) , this->header.biWidth , this->header.biHeight , this->header.biBitCount );
  221. return true;
  222. }
  223. bool CVideoUSB::Draw( char * buffer , int size )
  224. {
  225. return this->ddraw.DrawDirectDraw( this->m_bPreview ? buffer : this->codec.Decode( buffer , size ) , true , this->codec.GetEncodeTime( ) );
  226. }
  227. void CVideoUSB::ReleaseDraw( void )
  228. {
  229. this->ddraw.ReleaseDirectDraw( );
  230. this->codec.ReleaseDecode( );
  231. if( ::IsWindow( this->GetSafeHwnd( ) ) && ::GetProp( this->GetSafeHwnd( ) , "isCreateWindow" ) )
  232. this->DestroyWindow( );
  233. this->m_hWnd = NULL;
  234. }