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

📄 2pass.cpp.svn-base

📁 ffshow源码
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
/************************************************************************** * *	XVID 2PASS CODE *	codec * *	This program is free software; you can redistribute it and/or modify *	it under the terms of the GNU General Public License as published by *	the Free Software Foundation; either version 2 of the License, or *	(at your option) any later version. * *	This program is distributed in the hope that it will be useful, *	but WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *	GNU General Public License for more details. * *	You should have received a copy of the GNU General Public License *	along with this program; if not, write to the Free Software *	Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA * *************************************************************************/#include "stdafx.h"#include "2pass.h"#include "TencStats.h"#include "ffdshow_constants.h"#include "IffdshowBase.h"#include "IffdshowEnc.h"#include "TffPict.h"//================================= TxvidStats =================================TxvidStats::TxvidStats(const char_t *Iflnm,bool write):flnm(Iflnm){ ok=false; fw=NULL; if (!flnm || !flnm[0]) return; if (write)  {   fw=fopen(flnm,_l("wb"));   if (!fw) return;   int32_t version=-20;   size_t len=fwrite(&version,1,4,fw);   ok=(len==4);  } else  {   FILE *f=fopen(flnm,_l("rb"));if (!f) return;   int ver;fread(&ver,1,4,f);if (ver!=-20) {fclose(f);return;}   fseek(f,0,SEEK_END);   long flen=ftell(f);   fseek(f,4,SEEK_SET);   while (!feof(f))    {     NNSTATS nns;     size_t len=fread(&nns,1,sizeof(nns),f);     if (len!=sizeof(NNSTATS)) break;     stats.push_back(nns);    }   fclose(f);   resetRead();  }  ok=true; }TxvidStats::~TxvidStats(){ if (fw) fclose(fw);}size_t TxvidStats::size(void) const{ return stats.size();}void TxvidStats::resetRead(void){ pos=0;}bool TxvidStats::readNext(NNSTATS *nns){ if (pos<size())  {   *nns=stats[pos++];   return true;  } else   return false; }const NNSTATS* TxvidStats::operator [](size_t i) const{ return (i<size())?&stats[i]:NULL;}TxvidStats::operator const NNSTATS* (void) const{ return stats.empty()?NULL:&*stats.begin();}size_t TxvidStats::write(const NNSTATS *nns){ stats.push_back(*nns); return flnm?fw?fwrite(nns,1,sizeof(NNSTATS),fw):0:sizeof(NNSTATS);}//================================= Txvid_2pass =================================int Txvid_2pass::codec_2pass_init(void){	int	frames = 0, bframes = 0, pframes = 0, credits_frames = 0, i_frames = 0, recminbsize = 0, recminpsize = 0, recminisize = 0;	int64_t bframe_total_ext = 0, pframe_total_ext = 0, pframe_total = 0, bframe_total = 0, i_total = 0, i_total_ext = 0, i_boost_total = 0, start = 0, end = 0, start_curved = 0, end_curved = 0;	int64_t desired = (int64_t)config.desiredSize * 1024;	double total1 = 0.0;	double total2 = 0.0;	double dbytes, dbytes2;	/* ensure free() is called safely */	twopass.nns1_array = NULL;	twopass.nns2_array = NULL;	switch (config.mode)	{	case DLG_MODE_2PASS_1 :		if (!statsWrite) statsWrite = ownStatsWrite=new TxvidStats(config.stats1flnm,true);		if (!statsWrite->ok)		{			DEBUGERR(_l("2pass init error - couldn't write to stats1"));			return ICERR_ERROR;		}		break;		case DLG_MODE_2PASS_2_INT :	case DLG_MODE_2PASS_2_EXT :		if (!statsRead) statsRead = ownStatsRead=new TxvidStats(config.stats1flnm,false);		if (!statsRead->ok) 		{			DEBUGERR(_l("2pass init error - couldn't open stats1"));			return ICERR_ERROR;		}		twopass.nns_array_length = 0;		twopass.nns_array_pos = 0;		// read the stats file(s) into array(s) and reorder them so they		// correctly represent the frames that the encoder will receive.		if (config.mode == DLG_MODE_2PASS_2_EXT)		{			if (!statsRead2) statsRead2=ownStatsRead2 = new TxvidStats(config.stats2flnm,false);			if (!statsRead2->ok) 			{				DEBUGERR(_l("2pass init error - couldn't open stats2"));				return ICERR_ERROR;			}                        twopass.nns1_array =*statsRead;                        twopass.nns2_array =*statsRead2;                        frames=(int)std::min(statsRead->size(),statsRead2->size());		}		else	// DLG_MODE_2PASS_2_INT		{		        twopass.nns1_array=*statsRead;			frames=(int)statsRead->size();		}		if (config.xvid2pass_use_write && !statsWrite)		        statsWrite=ownStatsWrite=new TxvidStats(config.stats1flnm,true);		twopass.nns_array_length = frames;		frames = 0;/* // this isn't necessary with the current core.		// reorder the array(s) so they are in the order that they were received		// IPBBPBB to		// IBBPBBP		for (i=0; i<twopass.nns_array_length; i++)		{			NNSTATS temp_nns, temp_nns2;			int k, num_bframes;			if (twopass.nns1_array[i].dd_v & NNSTATS_BFRAME)			{				num_bframes = 1;				for (k=i+1; k<twopass.nns_array_length; k++)				{					if (twopass.nns1_array[k].dd_v & NNSTATS_BFRAME)						num_bframes++;					else						k=twopass.nns_array_length;				}				i--;				memcpy (&temp_nns, &twopass.nns1_array[i], sizeof(NNSTATS));				if (config.mode == DLG_MODE_2PASS_2_EXT)					memcpy (&temp_nns2, &twopass.nns2_array[i], sizeof(NNSTATS));				for (k=0; k<num_bframes; k++)				{					memcpy(&twopass.nns1_array[i], &twopass.nns1_array[i+1], sizeof(NNSTATS));					if (config.mode == DLG_MODE_2PASS_2_EXT)						memcpy(&twopass.nns2_array[i], &twopass.nns2_array[i+1], sizeof(NNSTATS));					i++;				}				memcpy(&twopass.nns1_array[i], &temp_nns, sizeof(NNSTATS));				if (config.mode == DLG_MODE_2PASS_2_EXT)					memcpy(&twopass.nns2_array[i], &temp_nns2, sizeof(NNSTATS));			}		}*/		// continue with the initialization..		if (config.mode == DLG_MODE_2PASS_2_EXT)		{			while (1)			{				if (twopass.nns_array_pos >= twopass.nns_array_length)				{					twopass.nns_array_pos = 0;					break;				}				memcpy(&twopass.nns1, &twopass.nns1_array[twopass.nns_array_pos], sizeof(NNSTATS));				memcpy(&twopass.nns2, &twopass.nns2_array[twopass.nns_array_pos], sizeof(NNSTATS));				twopass.nns_array_pos++;				// skip unnecessary frames.				if (twopass.nns1.dd_v & NNSTATS_SKIPFRAME ||					twopass.nns1.dd_v & NNSTATS_PADFRAME ||					twopass.nns1.dd_v & NNSTATS_DELAYFRAME)					continue;				if (!codec_is_in_credits(frames))				{					if (twopass.nns1.quant & NNSTATS_KEYFRAME)					{						i_total += twopass.nns2.bytes;						i_boost_total += twopass.nns2.bytes * config.keyframe_boost / 100;						twopass.keyframe_locations[i_frames] = frames;						++i_frames;					}					else					{						if (twopass.nns1.dd_v & NNSTATS_BFRAME)						{							bframe_total += twopass.nns1.bytes;							bframe_total_ext += twopass.nns2.bytes;							bframes++;						}						else						{							pframe_total += twopass.nns1.bytes;							pframe_total_ext += twopass.nns2.bytes;							pframes++;						}					}				}				else					++credits_frames;				if (twopass.nns1.quant & NNSTATS_KEYFRAME)				{					// this test needs to be corrected..					if (!(twopass.nns1.kblk + twopass.nns1.mblk))						recminisize = twopass.nns1.bytes;				}				else if (twopass.nns1.dd_v & NNSTATS_BFRAME)				{					if (!(twopass.nns1.kblk + twopass.nns1.mblk))						recminbsize = twopass.nns1.bytes;				}				else				{					if (!(twopass.nns1.kblk + twopass.nns1.mblk))						recminpsize = twopass.nns1.bytes;				}				++frames;			}			twopass.keyframe_locations[i_frames] = frames;			twopass.movie_curve = ((double)(bframe_total_ext + pframe_total_ext + i_boost_total) /				(bframe_total_ext + pframe_total_ext));			if (bframes)				twopass.average_bframe = (double)bframe_total_ext / bframes / twopass.movie_curve;			if (pframes)				twopass.average_pframe = (double)pframe_total_ext / pframes / twopass.movie_curve;			else				if (bframes)					twopass.average_pframe = twopass.average_bframe;  // b-frame packed bitstream fix				else				{					DEBUGERR(_l("ERROR:  No p-frames or b-frames were present in the 1st pass.  Rate control cannot function properly!"));					return ICERR_ERROR;				}			// perform prepass to compensate for over/undersizing			frames = 0;			if (config.use_alt_curve)			{				twopass.alt_curve_low = twopass.average_pframe - twopass.average_pframe * (double)config.alt_curve_low_dist / 100.0;				twopass.alt_curve_low_diff = twopass.average_pframe - twopass.alt_curve_low;				twopass.alt_curve_high = twopass.average_pframe + twopass.average_pframe * (double)config.alt_curve_high_dist / 100.0;				twopass.alt_curve_high_diff = twopass.alt_curve_high - twopass.average_pframe;				if (config.alt_curve_use_auto)				{					if (bframe_total + pframe_total > bframe_total_ext + pframe_total_ext)					{						config.alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 /							((double)(bframe_total + pframe_total) / (double)(bframe_total_ext + pframe_total_ext))) *							(double)config.alt_curve_auto_str / 100.0);						if (config.alt_curve_min_rel_qual < 20)							config.alt_curve_min_rel_qual = 20;					}					else						config.alt_curve_min_rel_qual = 100;				}				twopass.alt_curve_mid_qual = (1.0 + (double)config.alt_curve_min_rel_qual / 100.0) / 2.0;				twopass.alt_curve_qual_dev = 1.0 - twopass.alt_curve_mid_qual;				if (config.alt_curve_low_dist > 100)				{					switch(config.alt_curve_type)					{					case 2: // Sine Curve (high aggressiveness)						twopass.alt_curve_qual_dev *= 2.0 / (1.0 + 							sin(DEG2RAD * (twopass.average_pframe * 90.0 / twopass.alt_curve_low_diff)));						twopass.alt_curve_mid_qual = 1.0 - twopass.alt_curve_qual_dev *							sin(DEG2RAD * (twopass.average_pframe * 90.0 / twopass.alt_curve_low_diff));						break;					case 1: // Linear (medium aggressiveness)						twopass.alt_curve_qual_dev *= 2.0 / (1.0 +							twopass.average_pframe / twopass.alt_curve_low_diff);						twopass.alt_curve_mid_qual = 1.0 - twopass.alt_curve_qual_dev *							twopass.average_pframe / twopass.alt_curve_low_diff;						break;					case 0: // Cosine Curve (low aggressiveness)						twopass.alt_curve_qual_dev *= 2.0 / (1.0 + 							(1.0 - cos(DEG2RAD * (twopass.average_pframe * 90.0 / twopass.alt_curve_low_diff))));						twopass.alt_curve_mid_qual = 1.0 - twopass.alt_curve_qual_dev *							(1.0 - cos(DEG2RAD * (twopass.average_pframe * 90.0 / twopass.alt_curve_low_diff)));					}				}			}			while (1)			{				if (twopass.nns_array_pos >= twopass.nns_array_length)				{					twopass.nns_array_pos = 0;					break;				}				memcpy(&twopass.nns1, &twopass.nns1_array[twopass.nns_array_pos], sizeof(NNSTATS));				memcpy(&twopass.nns2, &twopass.nns2_array[twopass.nns_array_pos], sizeof(NNSTATS));				twopass.nns_array_pos++;				if (frames == 0)				{					twopass.minbsize = (twopass.nns1.kblk + 88) / 8;					twopass.minpsize = (twopass.nns1.kblk + 88) / 8;					twopass.minisize = ((twopass.nns1.kblk * 22) + 240) / 8;					if (recminbsize > twopass.minbsize)						twopass.minbsize = recminbsize;					if (recminpsize > twopass.minpsize)						twopass.minpsize = recminpsize;					if (recminisize > twopass.minisize)						twopass.minisize = recminisize;				}				// skip unnecessary frames.				if (twopass.nns1.dd_v & NNSTATS_SKIPFRAME ||					twopass.nns1.dd_v & NNSTATS_PADFRAME ||					twopass.nns1.dd_v & NNSTATS_DELAYFRAME)					continue;				if (!codec_is_in_credits( frames) &&					!(twopass.nns1.quant & NNSTATS_KEYFRAME))				{					dbytes = twopass.nns2.bytes / twopass.movie_curve;					total1 += dbytes;					if (twopass.nns1.dd_v & NNSTATS_BFRAME)						dbytes *= twopass.average_pframe / twopass.average_bframe;					if (config.use_alt_curve)					{						if (dbytes > twopass.average_pframe)						{							if (dbytes >= twopass.alt_curve_high)								dbytes2 = dbytes * (twopass.alt_curve_mid_qual - twopass.alt_curve_qual_dev);							else							{								switch(config.alt_curve_type)								{								case 2:								dbytes2 = dbytes * (twopass.alt_curve_mid_qual - twopass.alt_curve_qual_dev *									sin(DEG2RAD * ((dbytes - twopass.average_pframe) * 90.0 / twopass.alt_curve_high_diff)));									break;								case 1:								dbytes2 = dbytes * (twopass.alt_curve_mid_qual - twopass.alt_curve_qual_dev *									(dbytes - twopass.average_pframe) / twopass.alt_curve_high_diff);									break;								case 0:								dbytes2 = dbytes * (twopass.alt_curve_mid_qual - twopass.alt_curve_qual_dev *									(1.0 - cos(DEG2RAD * ((dbytes - twopass.average_pframe) * 90.0 / twopass.alt_curve_high_diff))));								}							}						}						else						{							if (dbytes <= twopass.alt_curve_low)								dbytes2 = dbytes;							else							{								switch(config.alt_curve_type)								{								case 2:								dbytes2 = dbytes * (twopass.alt_curve_mid_qual - twopass.alt_curve_qual_dev *									sin(DEG2RAD * ((dbytes - twopass.average_pframe) * 90.0 / twopass.alt_curve_low_diff)));

⌨️ 快捷键说明

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