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. //单帧压缩:无法设定码流大小和 帧速率、关键帧 等等项
  137. else if ( ::ICCompressBegin( this->cv.hic , &this->in , &this->out ) == ICERR_OK )
  138. {
  139. this->codec_type = ENCODE ;
  140. this->sequent_compress = false;
  141.         //缺省的压缩后图像大小
  142. this->cv.lDataRate = 0; 
  143. SAFE_NEW( this->out_buffer , this->out.biSizeImage );
  144. memset( this->out_buffer , 0 , sizeof( this->out.biSizeImage ) );
  145. return &this->out;
  146. }
  147. else
  148. {
  149. ::MessageBox( ::GetForegroundWindow() , "初始化压缩器失败,请另外选择压缩器","视频压缩",MB_ICONSTOP | MB_OK);
  150. this->ReleaseEncode () ; return NULL;
  151. }
  152. }
  153. void * CVideoCodec::Decode(void *in_buffer , int size )
  154. {
  155. if( this->cv.hic && this->codec_type == DECODE )
  156. {
  157. size -= sizeof( int );
  158. this->encode_time = *( int * )( ( char * )in_buffer + size );
  159. this->in.biSizeImage = size;
  160. if( ICERR_OK != ::ICDecompress( this->cv.hic , 0 , &this->in , in_buffer , &this->out , this->out_buffer ) )
  161. memset( this->out_buffer , 0 , this->out.biSizeImage );
  162. return this->out_buffer;
  163. }
  164. return in_buffer;
  165. }
  166. void * CVideoCodec::Encode(void * in_buffer , int * size )
  167. {
  168. if( this->cv.hic && this->codec_type == ENCODE )
  169. { //顺序压缩
  170. if( this->sequent_compress )
  171. {
  172. * size = this->out.biSizeImage ;
  173. BOOL key;
  174. char * buf = ( char * )::ICSeqCompressFrame( &this->cv , 0 , in_buffer , &key , ( long * )size );
  175. if( buf )
  176. {
  177. *( int * )( buf + * size ) = this->GetEncodeTime( );
  178. * size += sizeof( int );
  179. }
  180. return buf;
  181. }
  182. else //单帧压缩
  183. {
  184. DWORD dwFlag ,ckID , s;
  185. //压缩
  186. s = this->out.biSizeImage;
  187. 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 )
  188. {
  189. * size = this->out.biSizeImage ; 
  190. this->out.biSizeImage = s;
  191. *( int * )( this->out_buffer + * size ) = this->GetEncodeTime( );
  192. * size += sizeof( int );
  193. return this->out_buffer ;
  194. }
  195. }
  196. }
  197. return NULL ;
  198. }
  199. time_t CVideoCodec::GetEncodeTime( void )
  200. {
  201. if( this->codec_type == ENCODE )
  202. {
  203. CTime tm = CTime::GetCurrentTime( );
  204. return tm.GetTime( );
  205. }
  206. else if( this->codec_type == DECODE )
  207. return this->encode_time;
  208. else 
  209. return 0;
  210. }
  211. bool CVideoCodec::ReleaseDecode()
  212. {
  213. if ( this->cv.hic && this->codec_type == DECODE )
  214. {
  215. try
  216. {
  217. ICDecompressEnd(this->cv.hic);
  218. ICCompressorFree(&this->cv);
  219. ICClose(this->cv.hic);
  220. }
  221. catch( ... )
  222. {
  223. }
  224. this->cv.hic = NULL;
  225. SAFE_DELETE( this->out_buffer );
  226. this->codec_type = 0;
  227. return true;
  228. }
  229. return false;
  230. }
  231. bool CVideoCodec::ReleaseEncode()
  232. {
  233. if( this->cv.hic && this->codec_type == ENCODE )
  234. {
  235. try
  236. {
  237. ::ICSeqCompressFrameEnd( &this->cv );
  238. ::ICCompressorFree( &this->cv );
  239. ::ICClose( this->cv.hic );
  240. }
  241. catch( ... )
  242. {
  243. }
  244. this->cv.hic = NULL;
  245. this->codec_type = 0;
  246. return true;
  247. }
  248. return false;
  249. }
  250. char * CVideoCodec::GetString( int word )
  251. {
  252. int a , b , c , d ;
  253. a = (char)word;
  254. b = (char)( word >> 8 );
  255. c = (char)( word >> 16 );
  256. d = (char)( word >> 24 );
  257. static char szType[ 5 ];
  258. sprintf( szType , "%c%c%c%c" , a , b , c , d );
  259. return szType;
  260. }