⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cxvid.cpp

📁 Xvid Quants parser(XvidQP)用来分析编码Xvid AVI文件中每侦的量化(quantization)值。分析结束后
💻 CPP
字号:
// CXvid.cpp: implementation of the CXvid class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "XvidQuantsParser.h"
#include "CXvid.h"
#include <time.h>

#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; i<stop; i++)
	{
		//得到帧的大小等数据
		inputVideoAVI->read(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 (lActualBytes<nfsmin) nfsmin = lActualBytes;
		// 如果是关键帧-I帧
		if (inputVideoAVI->isKey(i))
		{
			quants[i-start].isIFrame = true;
			icount++;
			
			//检查I帧大小的最小/最大值
			if (lActualBytes>ifsmax) ifsmax = lActualBytes;
			if (lActualBytes<ifsmin) ifsmin = lActualBytes;

			if (b[24] == 0x28)
			{
				isum += b[27]>>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<pfsmin) pfsmin = lActualBytes;

			if (b[4] == 0x68)
			{
				psum += b[7];
				nsum += b[7];
				quants[i-start].qvalue = b[7];
				if (b[7] > 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;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -