gusucode.com > 基于VC++的局域网视频聊天系统源码程序 > 基于VC++的局域网视频聊天系统源码程序/code/ChatClient/VideoCodec.cpp

    // VideoCodec.cpp: implementation of the CVideoCodec class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "VideoCodec.h"
#include "videoCapture.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CVideoCodec::CVideoCodec()
{
	m_Codec = -1;
//	ugly MS_H261 !
	m_CodecType[0].codec  =	MS_H261;
	m_CodecType[0].Fourcc = "M261";
//	MS_H263 176*144*24 20 kbps ,acceptabl for wan,but 320*240*24 failed
	m_CodecType[1].codec  =	MS_H263;
	m_CodecType[1].Fourcc = "M263";
//	DIVX_MPEG4 eat tooooooooooooooo much bandwidth 176*144*24 500 kbps!
	m_CodecType[2].codec  =	DIVX_MPEG4;	
	m_CodecType[2].Fourcc = "DIVX";
//	eat MS_MPEG4Vx too much bandwidth 176*144*24 120 kbps,just for lan !
	m_CodecType[3].codec  =	MS_MPEG4V1;	
	m_CodecType[3].Fourcc = "MPG4";
	m_CodecType[4].codec  =	MS_MPEG4V2;	
	m_CodecType[4].Fourcc = "MP42";
	m_CodecType[5].codec  =	MS_MPEG4V3;	
	m_CodecType[5].Fourcc = "MP43";
//	I think XVID_MPEG4 nerver had a release version,the 1st time nice,2nd? BULL shxt!
//	176*144*24 20 kbps,nice graghic!
	m_CodecType[6].codec  =	XVID_MPEG4;	
	m_CodecType[6].Fourcc = "XVID";
//	following 2 ugly codecs,no one will suggest,or IDIOT !
	m_CodecType[7].codec  =	MS_VIDC	;	
	m_CodecType[7].Fourcc = "MSVC";
	m_CodecType[8].codec  =RADIUS_CVID;	
	m_CodecType[8].Fourcc = "CVID";


}

CVideoCodec::~CVideoCodec()
{

}

BOOL CVideoCodec::SetCodecType(int type)
{
	// change range if codec added !
	if(type>=MS_H261 && type <=RADIUS_CVID)		m_Codec=type;
	return (m_Codec!=-1);

}

BOOL CVideoCodec::Init()
{
	//	TRACE("CVideoCodec::Init\n");
	Destroy();
	BOOL bRet=FALSE;

	if(m_Codec == -1)	return FALSE;


//	图像压缩/解压缩参数 m_cv 初始化,lKey建议多一点
	ZeroMemory(&m_cv,sizeof(m_cv));
	m_cv.cbSize=sizeof(m_cv);
	m_cv.dwFlags=ICMF_COMPVARS_VALID ;
	m_cv.hic=m_hIC;
	m_cv.fccType=ICTYPE_VIDEO ;	//"vidc"
	m_cv.fccHandler=
		mmioFOURCC(m_CodecType[m_Codec].Fourcc[0],m_CodecType[m_Codec].Fourcc[1],
		m_CodecType[m_Codec].Fourcc[2],m_CodecType[m_Codec].Fourcc[3]);
	m_cv.lpbiOut=0;
	m_cv.lKey=64;		// I帧产生速率
	m_cv.lDataRate=20;	// KBPS
	m_cv.lQ=1000;//1-10000
	
	//将视频格式固定,一般的视频捕捉设备应该会支持(176*144/320x240),I pray... >:-/
	ZeroMemory(&m_BmpU,sizeof(m_BmpU));
	m_BmpU.bmiHeader.biSize=sizeof(BITMAPINFOHEADER); //176*144*24
	m_BmpU.bmiHeader.biWidth=IMAGE_WIDTH;//176
	m_BmpU.bmiHeader.biHeight=IMAGE_HEIGHT;//144
	m_BmpU.bmiHeader.biPlanes=1;	
	m_BmpU.bmiHeader.biBitCount=24;	
	m_BmpU.bmiHeader.biSizeImage=IMAGE_WIDTH * IMAGE_HEIGHT * (m_BmpU.bmiHeader.biBitCount/8);
//	View your local 'vidc'
	ICCompressorChoose(pDlg->m_hWnd ,ICMF_CHOOSE_ALLCOMPRESSORS,&m_BmpU,NULL,&m_cv,NULL);

	m_hIC=ICOpen(ICTYPE_VIDEO,m_cv.fccHandler,ICMODE_COMPRESS|ICMODE_DECOMPRESS);
	if(!m_hIC)
		goto RET;
	
	ICCompressGetFormat(m_hIC,&m_BmpU,&m_BmpC);
//	MS H.263 需要消息确认! MPEG4可不用
	ICSendMessage(m_hIC,0x60c9,0xf7329ace,0xacdeaea2);

	m_cv.hic=m_hIC;
	m_cv.dwFlags=ICMF_COMPVARS_VALID;

	if(!ICSeqCompressFrameStart(&m_cv,&m_BmpU))		
		goto RET;
	if(ICDecompressBegin(m_hIC,&m_BmpC,&m_BmpU)!=ICERR_OK)		
		goto RET;
	bRet=TRUE;
RET:
	if(!bRet)		Destroy();
	return bRet;	

}

void CVideoCodec::Destroy()
{
    //	TRACE("CVideoCodec::Destroy\n");
	if(m_hIC)
	{
		ICDecompressEnd(m_hIC);
		ICSeqCompressFrameEnd(&m_cv);
		ICCompressorFree(&m_cv);
		ICClose(m_hIC);
	}
	m_hIC=NULL;
}

BOOL CVideoCodec::EncodeVideoData(char *pin, int len, char *pout, int *lenr, BOOL *pKey)
{
	//	TRACE("CVideoCodec::EncodeVideoData\n");
	BOOL bRet=FALSE;
	char*p;
	long s=2000;
	BOOL k;
	if(!pin||!pout||len!=(int)m_BmpU.bmiHeader.biSizeImage||!m_hIC)
		goto RET;
	
	p=(char*)ICSeqCompressFrame(&m_cv,0,pin,&k,&s);
	if(!p)		goto RET;
	if(lenr)	*lenr=s;
	if(pKey)	*pKey=k;
	
	memcpy(pout, p, s);
	bRet=TRUE;
RET:
	return bRet;	

}

BOOL CVideoCodec::DecodeVideoData(char *pin, int len, char *pout, int *lenr, DWORD flag)
{
	//TRACE("CVideoCodec::DecodeVideoData\n");
	BOOL bRet=FALSE;
	if(!pin||!pout||!m_hIC)		
		goto RET;

	if(ICDecompress(m_hIC,flag,&m_BmpC.bmiHeader,pin,&m_BmpU.bmiHeader,pout)!=ICERR_OK)
		goto RET;
	if(lenr)	
		*lenr=m_BmpU.bmiHeader.biSizeImage;
	
	bRet=TRUE;
RET:
	return bRet;

}

void CVideoCodec::SetParent(CDialog *dlg)
{
	pDlg=dlg;
}