//NetTalk
/*------------------------------------------------------------------------------*\
 =============================
   模块名称: CodecMgr.cpp
 =============================
 
 [版权]
 
   2000-2002  115软件工厂  版权所有
                                              
\*------------------------------------------------------------------------------*/
#include "WndX.h"

#include "g729a.h"
#include "UDPSocket.h"
#include "AVIOMgr.h"
#include "CodecMgr.h"

/*------------------------------------------------------------------------------*/


CCodecMgr::CCodecMgr()
{
	//VoiceAge g729a codec初始化
	va_g729a_init_encoder();
	va_g729a_init_decoder();
	m_hIC=NULL;
	
	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 ;
	m_cv.fccHandler=859189837;
	m_cv.lpbiOut=0;
	m_cv.lKey=10;
	m_cv.lDataRate=6;
	m_cv.lQ=10000;
//将视频格式固定（这是非常常用的格式，一般的视频捕捉设备应该会支持）
	ZeroMemory(&m_BmpU,sizeof(m_BmpU));
	m_BmpU.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
	m_BmpU.bmiHeader.biWidth=176;
	m_BmpU.bmiHeader.biHeight=144;
	m_BmpU.bmiHeader.biPlanes=1;	
	m_BmpU.bmiHeader.biBitCount=24;	
	m_BmpU.bmiHeader.biSizeImage=m_BmpU.bmiHeader.biWidth * m_BmpU.bmiHeader.biHeight * m_BmpU.bmiHeader.biBitCount / 8;
	m_BmpU.bmiHeader.biCompression = 0;//MAKEFOURCC('I', '4', '2', '0');
	
}
/*------------------------------------------------------------------------------*/
CCodecMgr::~CCodecMgr()
{
	DestroyCodecA();
	DestroyCodecV();
	
}
/*------------------------------------------------------------------------------*/
//初始化视频编码解码器
BOOL CCodecMgr::InitCodecV()
{
	
	DestroyCodecV();
	BOOL bRet=FALSE;
	//
	m_hIC=ICOpen(ICTYPE_VIDEO,m_cv.fccHandler,ICMODE_COMPRESS|ICMODE_DECOMPRESS);
	if(!m_hIC)
		goto RET;
	
	ICCompressGetFormat(m_hIC,&m_BmpU,&m_BmpC);
	//微软的H.263 codec需要消息确认，得到这个不容易
	ICSendMessage(m_hIC,0x60c9,0xf7329ace,0xacdeaea2);

	m_cv.hic=m_hIC;
	m_cv.dwFlags=ICMF_COMPVARS_VALID;
	//star sequence of frames compression
	if(!ICSeqCompressFrameStart(&m_cv,&m_BmpU))
		goto RET;
	//star decompression;
	if(ICDecompressBegin(m_hIC,&m_BmpC,&m_BmpU)!=ICERR_OK)
		goto RET;

	bRet=TRUE;
	
RET:
	if(!bRet)
		DestroyCodecV();
	return bRet;
}

/*------------------------------------------------------------------------------*/
void CCodecMgr::DestroyCodecV()
{	
	if(m_hIC)
	{
		ICDecompressEnd(m_hIC);
		ICSeqCompressFrameEnd(&m_cv);
		ICCompressorFree(&m_cv);
		ICClose(m_hIC);
		m_hIC=NULL;
	}	
	
}
/*------------------------------------------------------------------------------*/
BOOL CCodecMgr::InitCodecA()
{	
	return TRUE;
}
/*------------------------------------------------------------------------------*/
void CCodecMgr::DestroyCodecA()
{
	

}
/*------------------------------------------------------------------------------*/
//压缩音频帧
BOOL CCodecMgr::EncodeAudioData(char *pin,int len,char* pout,int* lenr)
{
	BOOL bRet=FALSE;
	if(!pin||len!=SIZE_AUDIO_FRAME||!pout)
		goto RET;
	//encode the audio frames
	va_g729a_encoder((short*)pin,(BYTE*)pout);
	va_g729a_encoder((short*)(pin+160),(BYTE*)pout+10);
	va_g729a_encoder((short*)(pin+320),(BYTE*)pout+20);
	va_g729a_encoder((short*)(pin+480),(BYTE*)pout+30);
	va_g729a_encoder((short*)(pin+640),(BYTE*)pout+40);
	va_g729a_encoder((short*)(pin+800),(BYTE*)pout+50);

	if(lenr)
		*lenr=SIZE_AUDIO_PACKED;

	bRet=TRUE;
RET:
	return bRet;
}
/*------------------------------------------------------------------------------*/
//解压缩音频帧
BOOL CCodecMgr::DecodeAudioData(char *pin,int len,char* pout,int* lenr)
{
	
	BOOL bRet=FALSE;
	if(!pin||len!=SIZE_AUDIO_PACKED||!pout)
		goto RET;
	//decode the audio frames
	va_g729a_decoder((BYTE*)pin,(short*)(pout),0);
	va_g729a_decoder((BYTE*)pin+10,(short*)(pout+160),0);
	va_g729a_decoder((BYTE*)pin+20,(short*)(pout+320),0);
	va_g729a_decoder((BYTE*)pin+30,(short*)(pout+480),0);
	va_g729a_decoder((BYTE*)pin+40,(short*)(pout+640),0);
	va_g729a_decoder((BYTE*)pin+50,(short*)(pout+800),0);

	if(lenr)
		*lenr=SIZE_AUDIO_FRAME;
	
	bRet=TRUE;
RET:
	return bRet;	
}
/*------------------------------------------------------------------------------*/
//解压缩视频帧
BOOL CCodecMgr::DecodeVideoData(char *pin,int len,char* pout,int *lenr,DWORD flag)
{
	
	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;	
}
/*------------------------------------------------------------------------------*/
//压缩视频帧
BOOL CCodecMgr::EncodeVideoData(char* pin,int len,char* pout,int* lenr,BOOL* pKey)
{
	
	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;
	if(s>MAX_UDP_SIZE-sizeof(PACK_VIDEO))
		goto RET;
	
	CopyMemory(pout,p,s);
	bRet=TRUE;
RET:
	return bRet;	
}
