www.pudn.com > XvidQP.rar > CXvid.cpp


// CXvid.cpp: implementation of the CXvid class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "XvidQuantsParser.h" 
#include "CXvid.h" 
#include  
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CXvid::CXvid() 
{ 
	quants		= NULL; 
	isOpened	= false; 
	isAnalysed	= false; 
} 
 
//------------------------------------------------------------------------------ 
CXvid::~CXvid() 
{ 
	if (quants != NULL) 
	{ 
		delete[] quants; 
		quants = NULL; 
	} 
} 
 
 
//------------------------------------------------------------------------------ 
//打开Xvid文件 
int CXvid::Open(CString filepath) 
{ 
	HIC hic;				// HIC和ICINFO定义在VfW.H - Video for Windows头文件 
	ICINFO icinfo;			// 一般在\Microsoft Visual Studio\VC98\Include\目录下 
	 
	//InputFileAVI类 
	InputFileAVI* inputAVI = new InputFileAVI(false); 
	inputAVI->Init((char*)(LPCTSTR)filepath); 
	 
	VideoSourceAVI* inputVideoAVI; 
	inputVideoAVI = (VideoSourceAVI*)inputAVI->videoSrc; 
 
	//验证XVID中的fourCC 
	hic = inputVideoAVI->getDecompressorHandle();		//得到当前文件的解码器句柄 
	ICGetInfo(hic, &icinfo, sizeof(ICINFO)); 
	if(!icinfo.fccHandler == mmioFOURCC('X','V','I','D')) 
	{ 
		AfxMessageBox("Not a valid Xvid AVI File!"); 
		return 1; 
	} 
 
	//得到这个AVI文件的信息 
	//得到每秒钟的帧数 
	fps		= (float)inputVideoAVI->streamInfo.dwRate / (float)inputVideoAVI->streamInfo.dwScale; 
	height	= inputVideoAVI->getImageFormat()->biHeight;	//视频的高度 
	width	= inputVideoAVI->getImageFormat()->biWidth;		//视频的宽度 
	nframes	= inputVideoAVI->lSampleLast;					//帧的数目 
 
	if (nframes < 100) 
	{ 
		return 2;				//不允许小于100个视频帧 
	} 
 
	//一切正常 
	avipath	= filepath;			//设置文件路径 
	delete inputAVI; 
	 
	isAnalysed	= false;		//文件还没有被分析 
	isOpened = true;			//文件已经打开 
	return 0; 
} 
 
//------------------------------------------------------------------------------ 
//分析Xvid文件 
int CXvid::Analyze(CProgressCtrl &progress, CEdit &edit, bool log, int start, int stop) 
{ 
	//如果没有打开Xvid文件 
	if (!isOpened) 
	{ 
		AfxMessageBox("No Xvid AVI file opened!"); 
		return 1; 
	} 
 
	COleDateTime objOle; 
	CString strTime; 
	char buflog[50]; 
 
	LONG lActualBytes; 
	UCHAR* b=NULL; 
 
	int pbjump	= (stop-start)/100; 
	int pbcount = 0; 
	int pbpos	= 0; 
 
	icount=0; pcount=0; 
	nsum=0; isum=0; psum=0; 
	nmax=0; nmin=32; 
 
	nfsmax = 0; nfsmin = 999999999; 
	ifsmax = 0; ifsmin = 999999999; 
	pfsmax = 0; pfsmin = 999999999; 
 
	InputFileAVI *inputAVI = new InputFileAVI(false); 
	inputAVI->Init((char*)(LPCTSTR)avipath); 
	 
	VideoSourceAVI *inputVideoAVI; 
	inputVideoAVI = (VideoSourceAVI*) inputAVI->videoSrc; 
 
	progress.SetRange(0, 100); 
	progress.SetPos(0); 
	 
	//如果打开了分析日志 
	if (log) 
	{ 
		logfile.Open("analysis.log"); 
		logfile.Print("--------------------------------------------------------------------------------------\n"); 
		logfile.Print("Generated by Xvid Quants Parser v1.0\n"); 
		logfile.Print("--------------------------------------------------------------------------------------\n"); 
		logfile.Print("File: \t"); 
		logfile.Print((char*)(LPCTSTR)avipath); 
		logfile.Print("\n"); 
		logfile.Print("Frames:\t"); 
		_itoa(nframes, buflog, 10); 
		logfile.Print(buflog); 
		logfile.Print("\n"); 
		logfile.Print("Start:\t"); 
		_itoa(start, buflog, 10); 
		logfile.Print(buflog); 
		logfile.Print("\n"); 
		logfile.Print("End:\t"); 
		_itoa(stop, buflog, 10); 
		logfile.Print(buflog); 
		logfile.Print("\n"); 
		logfile.Print("Length:\t"); 
		_itoa(stop-start, buflog, 10); 
		logfile.Print(buflog); 
		logfile.Print("\n"); 
		logfile.Print("--------------------------------------------------------------------------------------\n"); 
		logfile.Print("Quantizer log:\n"); 
		logfile.Print("--------------------------------------------------------------------------------------\n"); 
	} 
	//--------------------------------------------------------------------------- 
	//删除以前的quants数组 
	if (quants != NULL) 
	{ 
		delete[] quants; 
		quants = NULL; 
	} 
	//创建新的quants数组 
	quants = new QUANTS[stop-start]; 
 
	//记录分析的开始时间 
	clock_t debut = clock(); 
 
	// 开始分析 
	for (int i=start; iread(i, 1, NULL, 0, &lActualBytes, NULL); 
		b = new UCHAR[lActualBytes]; 
		//把帧的数据读入到b中 
		inputVideoAVI->read(i, 1, b, lActualBytes, &lActualBytes, NULL); 
 
		//检查帧大小的最小/最大值 
		quants[i-start].framesize = lActualBytes; 
		if (lActualBytes>nfsmax) nfsmax = lActualBytes; 
		if (lActualBytesisKey(i)) 
		{ 
			quants[i-start].isIFrame = true; 
			icount++; 
			 
			//检查I帧大小的最小/最大值 
			if (lActualBytes>ifsmax) ifsmax = lActualBytes; 
			if (lActualBytes>1; 
				nsum += b[27]>>1; 
				quants[i-start].qvalue = b[27]>>1; 
				if (b[27]>>1 > nmax) nmax = b[27]>>1; 
				if (b[27]>>1 < nmin) nmin = b[27]>>1; 
			} 
			else 
			{ 
				isum += (b[27] & 0x3E)>>2; 
				nsum += (b[27] & 0x3E)>>2; 
				quants[i-start].qvalue = (b[27] & 0x3E)>>2; 
				if ((b[27] & 0x3E)>>2 > nmax) nmax = (b[27] & 0x3E)>>2; 
				if ((b[27] & 0x3E)>>2 < nmin) nmin = (b[27] & 0x3E)>>2; 
			} 
			//如果打开了分析日志 
			if (log) 
			{ 
				objOle = COleDateTime::GetCurrentTime(); 
				strTime = objOle.Format("%H:%M:%S"); 
				sprintf(buflog, "%s - %d\tIF:Q%d\t%d\n", strTime, i+1, quants[i-start].qvalue, lActualBytes); 
			} 
			 
		} 
		else										//如果不是关键帧(I帧) 
		{ 
			quants[i-start].isIFrame = false; 
			pcount++; 
 
			if (lActualBytes>pfsmax) pfsmax = lActualBytes; 
			if (lActualBytes nmax) nmax = b[7]; 
				if (b[7] < nmin) nmin = b[7]; 
			} 
			else 
			{ 
				psum += (b[7] & 0x3E)>>1; 
				nsum += (b[7] & 0x3E)>>1; 
				quants[i-start].qvalue = (b[7] & 0x3E)>>1; 
				if ((b[7] & 0x3E)>>1 > nmax) nmax = (b[7] & 0x3E)>>1; 
				if ((b[7] & 0x3E)>>1 < nmin) nmin = (b[7] & 0x3E)>>1; 
			} 
			//如果打开了分析日志 
			if (log) 
			{ 
				objOle = COleDateTime::GetCurrentTime(); 
				strTime = objOle.Format("%H:%M:%S"); 
				sprintf(buflog, "%s - %d\tPF:Q%d\t%d\n", strTime, i+1, quants[i-start].qvalue, lActualBytes); 
			} 
			 
		} 
 
		//如果打开了分析日志 
		if (log) logfile.Print(buflog); 
		 
 
		if (b!=NULL) 
		{ 
			delete[] b; 
			b=NULL; 
		} 
 
		if (pbcount == pbjump) 
		{ 
			pbcount = 0; 
			pbpos++; 
			progress.SetPos(pbpos); 
 
			char buf[50]; 
			sprintf(buf, "Analyzing: %d %% Completed", i*100/(stop-start-1)); 
			edit.SetSel(0, edit.LineLength()); 
			edit.ReplaceSel(buf); 
		} 
		pbcount++; 
	} 
 
	//记录分析的结束时间 
	clock_t fin = clock(); 
	//得到分析的时间 
	long temps = fin - debut; 
	 
	char buf[50]; 
	if (temps > 1000) 
		sprintf(buf, "Analyzed %d frames in %d seconds", nframes, temps/1000); 
	else 
		sprintf(buf, "Analyzed %d frames in %d milliseconds", (stop-start), temps); 
 
	edit.SetSel(0, edit.LineLength()); 
	edit.ReplaceSel(buf); 
 
	navg = (float)nsum/(stop-start); 
	pavg = (float)psum/pcount; 
	iavg = (float)isum/icount; 
 
	//如果打开了分析日志 
	if (log) 
	{ 
		logfile.Print("--------------------------------------------------------------------------------------\n"); 
		logfile.Print("End of log\n"); 
		logfile.Print("--------------------------------------------------------------------------------------\n"); 
		logfile.Close(); 
	} 
	 
 
	delete inputAVI; 
	isAnalysed = true; 
	return 0;	 
} 
 
//------------------------------------------------------------------------------ 
void CXvid::Close(void) 
{ 
	if (quants != NULL) 
	{ 
		delete[] quants; 
		quants = NULL; 
	} 
 
	isOpened	= false; 
	isAnalysed	= false; 
} 
 
//------------------------------------------------------------------------------ 
void CXvid::SetQuantsArray(CXvid::QUANTS* qvalues, int nelem) 
{ 
	if (quants != NULL) 
	{ 
		delete[] quants; 
		quants = NULL; 
	} 
 
	quants = qvalues; 
	nframes = nelem; 
}