VideoCodec.cpp
资源名称:视频会议系统.rar [点击查看]
上传用户:popouu88
上传日期:2013-02-11
资源大小:2894k
文件大小:8k
源码类别:
IP电话/视频会议
开发平台:
Visual C++
- // VideoCode.cpp: implementation of the CVideoCodec class.
- //
- //////////////////////////////////////////////////////////////////////
- #include "afx.h"
- #include "VideoCodec.h"
- #define SAFE_DELETE( p ) { if( p ) { try{ delete [] p;} catch(...){ } p = NULL ; } }
- #define SAFE_NEW( p ,size ) { SAFE_DELETE( p ) ; p = new char [ size ] ; ASSERT( p != NULL ) ; }
- #pragma comment(lib,"vfw32.lib")
- //////////////////////////////////////////////////////////////////////
- // Construction/Destruction
- //////////////////////////////////////////////////////////////////////
- CVideoCodec::CVideoCodec()
- { //压缩器标志
- this->codec_type = 0;
- //压缩时间
- this->encode_time = 0;
- //输出内存
- this->out_buffer = NULL;
- this->sequent_compress = true;
- //压缩器结构体
- memset( &this->cv , 0 , sizeof( this->cv ) );
- //位图头信息
- memset( &this->in , 0 , sizeof( this->in ) );
- //位图头信息
- memset( &this->out , 0 , sizeof( this->out ) );
- }
- CVideoCodec::~CVideoCodec()
- {
- switch(this->codec_type)
- {
- case ENCODE : this->ReleaseEncode() ; break;
- case DECODE : this->ReleaseDecode() ; break;
- }
- }
- //初始化解压器
- BITMAPINFOHEADER * CVideoCodec::InitDecode(int width , int height , int depth , const char * szType )
- { //如果压缩标志不为零或者压缩器的4个字节为空,则返回
- if( this->codec_type || !strlen( szType ) ) return NULL;
- //填写输入的位图头信息
- memset( &this->in , 0 , sizeof( this->in ) );
- this->in.biSize = sizeof( this->in );
- this->in.biPlanes = 1;
- this->in.biWidth = width ;
- this->in.biHeight = height ;
- this->in.biBitCount = depth;
- this->in.biCompression = mmioFOURCC(szType[0] , szType[1] , szType[2] , szType[3] );
- //填写输出的位图头信息
- memcpy( &this->out , & this->in , sizeof( this->out ) );
- this->out.biCompression = BI_RGB;
- this->out.biSizeImage = width * height * depth / 8 ;
- //打开解压器
- memset( &this->cv , 0 , sizeof( this->cv ) );
- this->cv.hic = ::ICOpen( ICTYPE_VIDEO , this->in.biCompression , ICMODE_FASTDECOMPRESS );
- if( !this->cv.hic )
- return NULL;
- //开始解压
- if( ::ICDecompressBegin( this->cv.hic , &in,&out ) == ICERR_OK)
- {
- this->codec_type = DECODE;
- SAFE_DELETE( this->out_buffer );
- //申请保存解压后的数据内存
- this->out_buffer = new char[this->out.biSizeImage];
- VERIFY( this->out_buffer != NULL );
- memset( this->out_buffer , 0 , sizeof( this->out.biSizeImage ) );
- return &this->out;
- }
- else
- {
- ::MessageBox( GetForegroundWindow() , "初始化解压器失败,请另外选择解压器","视频解压",MB_ICONSTOP | MB_OK);
- this->ReleaseDecode (); return NULL;
- }
- }
- //初始化解压器
- bool CVideoCodec::InitDecode(BITMAPINFOHEADER *header)
- {
- if( this->codec_type || ! header ) return false;
- char * szType = this->GetString( header->biCompression );
- BITMAPINFOHEADER * hret = this->InitDecode( header->biWidth , header->biHeight , header->biBitCount , szType );
- if( hret != NULL )
- {
- * header = * hret;
- return true;
- }
- return false;
- }
- //初始化压缩器
- BITMAPINFOHEADER * CVideoCodec::InitEncode(int width , int height , int depth , const char * szType ,int kbps )
- {
- if( this->codec_type ) return NULL;
- //填写压缩数据的位图头信息
- memset( & this->in , 0 , sizeof( this->in ) );
- this->in.biSize = sizeof( this->in );
- this->in.biPlanes = 1;
- this->in.biWidth = ( width + 3 ) / 4 * 4;
- this->in.biHeight = ( height + 3 ) / 4 * 4;
- this->in.biBitCount = depth ;
- this->in.biSizeImage = width * height * depth / 8;
- this->in.biCompression = BI_RGB ;
- memset(&this->cv , 0 , sizeof( this->cv ) );
- this->cv.cbSize = sizeof( this->cv );
- //选择压缩器
- if( ! szType )
- {
- if( ! ::ICCompressorChoose( ::GetForegroundWindow() ,
- ICMF_CHOOSE_DATARATE | ICMF_CHOOSE_KEYFRAME,
- NULL ,
- NULL ,
- &this->cv ,
- NULL))
- return NULL;
- }
- else //根据给定的压缩器来打开压缩器
- {
- this->cv.dwFlags = ICMF_COMPVARS_VALID;
- this->cv.fccType = ICTYPE_VIDEO;
- this->cv.fccHandler = mmioFOURCC( szType[0] , szType[1] , szType[2] , szType[3] );
- this->cv.hic = ::ICOpen( ICTYPE_VIDEO , this->cv.fccHandler , ICMODE_FASTCOMPRESS );
- this->cv.lKey = 8; // Key Frame Interval
- this->cv.lDataRate = kbps == 0 ? 300 : kbps; // kbps;
- this->cv.lQ = ICQUALITY_DEFAULT ; //Quality
- }
- if( !this->cv.hic )
- return NULL;
- //填写压缩后的位图头信息
- memcpy( &this->out , &this->in , sizeof( BITMAPINFOHEADER ) );
- this->out.biCompression = this->cv.fccHandler ;
- //顺序压缩
- if( ICSeqCompressFrameStart( &this->cv , ( BITMAPINFO * )&this->in ))
- {
- this->codec_type = ENCODE ;
- this->sequent_compress = true;
- return &this->out;
- }
- //单帧压缩:无法设定码流大小和 帧速率、关键帧 等等项
- else if ( ::ICCompressBegin( this->cv.hic , &this->in , &this->out ) == ICERR_OK )
- {
- this->codec_type = ENCODE ;
- this->sequent_compress = false;
- //缺省的压缩后图像大小
- this->cv.lDataRate = 0;
- SAFE_NEW( this->out_buffer , this->out.biSizeImage );
- memset( this->out_buffer , 0 , sizeof( this->out.biSizeImage ) );
- return &this->out;
- }
- else
- {
- ::MessageBox( ::GetForegroundWindow() , "初始化压缩器失败,请另外选择压缩器","视频压缩",MB_ICONSTOP | MB_OK);
- this->ReleaseEncode () ; return NULL;
- }
- }
- void * CVideoCodec::Decode(void *in_buffer , int size )
- {
- if( this->cv.hic && this->codec_type == DECODE )
- {
- size -= sizeof( int );
- this->encode_time = *( int * )( ( char * )in_buffer + size );
- this->in.biSizeImage = size;
- if( ICERR_OK != ::ICDecompress( this->cv.hic , 0 , &this->in , in_buffer , &this->out , this->out_buffer ) )
- memset( this->out_buffer , 0 , this->out.biSizeImage );
- return this->out_buffer;
- }
- return in_buffer;
- }
- void * CVideoCodec::Encode(void * in_buffer , int * size )
- {
- if( this->cv.hic && this->codec_type == ENCODE )
- { //顺序压缩
- if( this->sequent_compress )
- {
- * size = this->out.biSizeImage ;
- BOOL key;
- char * buf = ( char * )::ICSeqCompressFrame( &this->cv , 0 , in_buffer , &key , ( long * )size );
- if( buf )
- {
- *( int * )( buf + * size ) = this->GetEncodeTime( );
- * size += sizeof( int );
- }
- return buf;
- }
- else //单帧压缩
- {
- DWORD dwFlag ,ckID , s;
- //压缩
- s = this->out.biSizeImage;
- 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 )
- {
- * size = this->out.biSizeImage ;
- this->out.biSizeImage = s;
- *( int * )( this->out_buffer + * size ) = this->GetEncodeTime( );
- * size += sizeof( int );
- return this->out_buffer ;
- }
- }
- }
- return NULL ;
- }
- time_t CVideoCodec::GetEncodeTime( void )
- {
- if( this->codec_type == ENCODE )
- {
- CTime tm = CTime::GetCurrentTime( );
- return tm.GetTime( );
- }
- else if( this->codec_type == DECODE )
- return this->encode_time;
- else
- return 0;
- }
- bool CVideoCodec::ReleaseDecode()
- {
- if ( this->cv.hic && this->codec_type == DECODE )
- {
- try
- {
- ICDecompressEnd(this->cv.hic);
- ICCompressorFree(&this->cv);
- ICClose(this->cv.hic);
- }
- catch( ... )
- {
- }
- this->cv.hic = NULL;
- SAFE_DELETE( this->out_buffer );
- this->codec_type = 0;
- return true;
- }
- return false;
- }
- bool CVideoCodec::ReleaseEncode()
- {
- if( this->cv.hic && this->codec_type == ENCODE )
- {
- try
- {
- ::ICSeqCompressFrameEnd( &this->cv );
- ::ICCompressorFree( &this->cv );
- ::ICClose( this->cv.hic );
- }
- catch( ... )
- {
- }
- this->cv.hic = NULL;
- this->codec_type = 0;
- return true;
- }
- return false;
- }
- char * CVideoCodec::GetString( int word )
- {
- int a , b , c , d ;
- a = (char)word;
- b = (char)( word >> 8 );
- c = (char)( word >> 16 );
- d = (char)( word >> 24 );
- static char szType[ 5 ];
- sprintf( szType , "%c%c%c%c" , a , b , c , d );
- return szType;
- }