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

IP电话/视频会议

开发平台:

Visual C++

  1. // VideoCode.cpp: implementation of the CVideoCodec class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "afx.h"
  5. #include "VideoCodec.h"
  6. #define SAFE_DELETE( p ) { if( p ) { try{ delete [] p;} catch(...){ }  p = NULL ; } }
  7. #define   SAFE_NEW( p ,size )  { SAFE_DELETE( p ) ; p = new char [ size ] ; ASSERT( p != NULL ) ; }
  8. #pragma comment(lib,"vfw32.lib")
  9. //////////////////////////////////////////////////////////////////////
  10. // Construction/Destruction
  11. //////////////////////////////////////////////////////////////////////
  12. CVideoCodec::CVideoCodec()
  13. {   //压缩器标志
  14. this->codec_type = 0;
  15. //压缩时间
  16. this->encode_time = 0;
  17.     //输出内存
  18. this->out_buffer = NULL;
  19. this->sequent_compress = true;
  20.     //压缩器结构体
  21. memset( &this->cv , 0 , sizeof( this->cv ) );
  22.     //位图头信息
  23. memset( &this->in , 0 , sizeof( this->in ) );
  24.     //位图头信息
  25. memset( &this->out , 0 , sizeof( this->out ) );
  26. }
  27. CVideoCodec::~CVideoCodec()
  28. {
  29. switch(this->codec_type)
  30. {
  31. case ENCODE : this->ReleaseEncode() ; break;
  32. case DECODE : this->ReleaseDecode() ; break;
  33. }
  34. }
  35. //初始化解压器
  36. BITMAPINFOHEADER *  CVideoCodec::InitDecode(int width , int height , int depth , const char * szType )
  37. {   //如果压缩标志不为零或者压缩器的4个字节为空,则返回
  38. if( this->codec_type || !strlen( szType ) ) return NULL;
  39. //填写输入的位图头信息
  40. memset( &this->in , 0 , sizeof( this->in ) );
  41. this->in.biSize = sizeof( this->in );
  42. this->in.biPlanes = 1;
  43. this->in.biWidth = width ;
  44.     this->in.biHeight = height ; 
  45. this->in.biBitCount = depth;
  46. this->in.biCompression = mmioFOURCC(szType[0] , szType[1] , szType[2] , szType[3] );
  47.     //填写输出的位图头信息
  48. memcpy( &this->out , & this->in , sizeof( this->out ) );
  49. this->out.biCompression = BI_RGB;
  50.   
  51. this->out.biSizeImage = width * height * depth / 8 ;
  52.     //打开解压器
  53. memset( &this->cv , 0 , sizeof( this->cv ) );
  54.     
  55. this->cv.hic = ::ICOpen( ICTYPE_VIDEO , this->in.biCompression , ICMODE_FASTDECOMPRESS );
  56. if( !this->cv.hic )
  57. return NULL;
  58. //开始解压
  59. if( ::ICDecompressBegin( this->cv.hic , &in,&out ) == ICERR_OK)
  60. {
  61. this->codec_type = DECODE;
  62. SAFE_DELETE( this->out_buffer );
  63. //申请保存解压后的数据内存
  64. this->out_buffer = new char[this->out.biSizeImage];
  65. ASSERT( this->out_buffer != NULL );
  66. memset( this->out_buffer , 0 , sizeof( this->out.biSizeImage ) );
  67. return &this->out;
  68. }
  69. else
  70. {
  71. ::MessageBox( GetForegroundWindow() , "初始化解压器失败,请另外选择解压器","视频解压",MB_ICONSTOP | MB_OK);
  72. this->ReleaseDecode (); return NULL;
  73. }
  74. }
  75. //初始化解压器
  76. bool CVideoCodec::InitDecode(BITMAPINFOHEADER *header)
  77. {
  78. if( this->codec_type || ! header ) return false;
  79. char * szType = this->GetString( header->biCompression );
  80. BITMAPINFOHEADER * hret = this->InitDecode( header->biWidth , header->biHeight , header->biBitCount , szType );
  81. if( hret != NULL )
  82. {
  83. * header =  * hret;
  84. return true;
  85. }
  86. return false;
  87. }
  88. //初始化压缩器
  89. BITMAPINFOHEADER *  CVideoCodec::InitEncode(int width , int height , int depth , const char * szType ,int kbps )
  90. {
  91. if( this->codec_type ) return NULL;
  92.     //填写压缩数据的位图头信息
  93. memset( & this->in , 0 , sizeof( this->in ) );
  94. this->in.biSize = sizeof( this->in );
  95. this->in.biPlanes = 1;
  96. this->in.biWidth = ( width + 3 ) / 4 * 4;
  97. this->in.biHeight = ( height + 3 ) / 4 * 4;
  98. this->in.biBitCount = depth ;
  99. this->in.biSizeImage = width * height * depth / 8;
  100. this->in.biCompression = BI_RGB ;
  101. memset(&this->cv , 0 , sizeof( this->cv ) );
  102. this->cv.cbSize = sizeof( this->cv );
  103.     //选择压缩器
  104. if( ! szType )
  105. {
  106. if( ! ::ICCompressorChoose( ::GetForegroundWindow() ,
  107. ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME,
  108.     NULL ,
  109.     NULL ,
  110.     &this->cv ,
  111.     NULL))
  112. return NULL;
  113. }
  114. else  //根据给定的压缩器来打开压缩器
  115. {
  116. this->cv.dwFlags = ICMF_COMPVARS_VALID;
  117. this->cv.fccType = ICTYPE_VIDEO;
  118. this->cv.fccHandler = mmioFOURCC( szType[0] , szType[1] , szType[2] , szType[3] );
  119. this->cv.hic = ::ICOpen( ICTYPE_VIDEO , this->cv.fccHandler , ICMODE_FASTCOMPRESS );
  120. this->cv.lKey = 8; // Key Frame Interval 
  121. this->cv.lDataRate = kbps == 0 ? 300 : kbps; // kbps;
  122. this->cv.lQ = ICQUALITY_DEFAULT ; //Quality 
  123. }
  124. if( !this->cv.hic )
  125. return NULL;
  126.     //填写压缩后的位图头信息
  127. memcpy( &this->out , &this->in , sizeof( BITMAPINFOHEADER ) );
  128. this->out.biCompression = this->cv.fccHandler ;
  129. //顺序压缩
  130. if( ICSeqCompressFrameStart( &this->cv , ( BITMAPINFO * )&this->in ))
  131. {
  132. this->codec_type = ENCODE ;
  133. this->sequent_compress = true;
  134. return &this->out;
  135. }//单帧压缩:无法设定码流大小和 帧速率、关键帧 等等项
  136. else if ( ::ICCompressBegin( this->cv.hic , &this->in , &this->out ) == ICERR_OK )
  137. {
  138. this->codec_type = ENCODE ;
  139. this->sequent_compress = false;
  140.         //缺省的压缩后图像大小
  141. this->cv.lDataRate = 0; 
  142. SAFE_NEW( this->out_buffer , this->out.biSizeImage );
  143. memset( this->out_buffer , 0 , sizeof( this->out.biSizeImage ) );
  144. return &this->out;
  145. }
  146. else
  147. {
  148. ::MessageBox( ::GetForegroundWindow() , "初始化压缩器失败,请另外选择压缩器","视频压缩",MB_ICONSTOP | MB_OK);
  149. this->ReleaseEncode () ; return NULL;
  150. }
  151. }
  152. bool CVideoCodec::InitEncode( BITMAPINFOHEADER header )
  153. {
  154. return NULL != CVideoCodec::InitEncode( header.biWidth , header.biHeight , header.biBitCount , CVideoCodec::GetString( header.biCompression ) );
  155. }
  156. void * CVideoCodec::Decode(void *in_buffer , int size )
  157. {
  158. if( this->cv.hic && this->codec_type == DECODE )
  159. {
  160. size -= sizeof( int );
  161. this->encode_time = *( int * )( ( char * )in_buffer + size );
  162. this->in.biSizeImage = size;
  163. if( ICERR_OK != ::ICDecompress( this->cv.hic , 0 , &this->in , in_buffer , &this->out , this->out_buffer ) )
  164. memset( this->out_buffer , 0 , this->out.biSizeImage );
  165. return this->out_buffer;
  166. }
  167. return in_buffer;
  168. }
  169. void * CVideoCodec::Encode(void * in_buffer , int * size )
  170. {
  171. if( this->cv.hic && this->codec_type == ENCODE )
  172. { //顺序压缩
  173. if( this->sequent_compress )
  174. {
  175. * size = this->out.biSizeImage ;
  176. BOOL key;
  177. char * buf = ( char * )::ICSeqCompressFrame( &this->cv , 0 , in_buffer , &key , ( long * )size );
  178. if( buf )
  179. {
  180. *( int * )( buf + * size ) = this->GetEncodeTime( );
  181. * size += sizeof( int );
  182. }
  183. return buf;
  184. }
  185. else //单帧压缩
  186. {
  187. DWORD dwFlag ,ckID , s;
  188. //压缩
  189. s = this->out.biSizeImage;
  190. if ( ::ICCompress( this->cv.hic ,0 , &this->out , this->out_buffer , &this->in , in_buffer , &ckID , &dwFlag , 0 , this->cv.lDataRate , this->cv.lQ , NULL , NULL ) ==  ICERR_OK )
  191. {
  192. * size = this->out.biSizeImage ; 
  193. this->out.biSizeImage = s;
  194. *( int * )( this->out_buffer + * size ) = this->GetEncodeTime( );
  195. * size += sizeof( int );
  196. return this->out_buffer ;
  197. }
  198. }
  199. }
  200. return NULL ;
  201. }
  202. time_t CVideoCodec::GetEncodeTime( void )
  203. {
  204. if( this->codec_type == ENCODE )
  205. {
  206. CTime tm = CTime::GetCurrentTime( );
  207. return tm.GetTime( );
  208. }
  209. else if( this->codec_type == DECODE )
  210. return this->encode_time;
  211. else 
  212. return 0;
  213. }
  214. bool CVideoCodec::ReleaseDecode()
  215. {
  216. if ( this->cv.hic && this->codec_type == DECODE )
  217. {
  218. try
  219. {
  220. ICDecompressEnd(this->cv.hic);
  221. ICCompressorFree(&this->cv);
  222. ICClose(this->cv.hic);
  223. }
  224. catch( ... )
  225. {
  226. }
  227. this->cv.hic = NULL;
  228. SAFE_DELETE( this->out_buffer );
  229. this->codec_type = 0;
  230. return true;
  231. }
  232. return false;
  233. }
  234. bool CVideoCodec::ReleaseEncode()
  235. {
  236. if( this->cv.hic && this->codec_type == ENCODE )
  237. {
  238. try
  239. {
  240. ::ICSeqCompressFrameEnd( &this->cv );
  241. ::ICCompressorFree( &this->cv );
  242. ::ICClose( this->cv.hic );
  243. }
  244. catch( ... )
  245. {
  246. }
  247. this->cv.hic = NULL;
  248. this->codec_type = 0;
  249. return true;
  250. }
  251. return false;
  252. }
  253. char * CVideoCodec::GetString( int word )
  254. {
  255. int a , b , c , d ;
  256. a = (char)word;
  257. b = (char)( word >> 8 );
  258. c = (char)( word >> 16 );
  259. d = (char)( word >> 24 );
  260. static char szType[ 5 ];
  261. sprintf( szType , "%c%c%c%c" , a , b , c , d );
  262. return szType;
  263. }