[XviD-devel] dev-api-3 vfw 2pass fix

suxen_drol xvid-devel@xvid.org
Mon, 27 Jan 2003 18:28:24 +1100


On Mon, 27 Jan 2003 07:50:41 +0100 Dirk Knop <dknop@gwdg.de> wrote:

> Good morning everyone,
> 
> good news!
> I hacked an ugly fix for our issue that 2pass is broken in dev-api-3/vfw 
> since the xvid-core pFrame->intra reports are "messed up". Just use this 
> 2pass.c which treats all frame types different from intra/inter as 
> bframes - thus scaling correctly again.
> This is only a temporary solution as the core does dynamic 
> I/P/B-decision even in 2nd pass, it'll sure break things when this 
> behaviour of the core gets fixed.
> This is no permanent solution, but it works for me (and now).


i havent really been following this (or doing any 2pass tests lately),
but what exactly is broken? fixing it at the core is a better solution.




Index: 2pass.c
===================================================================
RCS file: /xvid/vfw/src/2pass.c,v
retrieving revision 1.7.2.7
diff -u -r1.7.2.7 2pass.c
--- 2pass.c	20 Dec 2002 05:35:56 -0000	1.7.2.7
+++ 2pass.c	27 Jan 2003 07:26:13 -0000
@@ -285,12 +285,12 @@
 				memcpy(&twopass->nns2, &twopass->nns2_array[twopass->nns_array_pos], sizeof(NNSTATS));
 				twopass->nns_array_pos++;
 
-				// skip unnecessary frames.
+/*				// skip unnecessary frames.
 				if (twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
 					twopass->nns1.dd_v & NNSTATS_PADFRAME ||
 					twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					continue;
-
+*/  // we need to treat it like usual frames now - someone broke core's reports
 				if (!codec_is_in_credits(&codec->config, frames))
 				{
 					if (twopass->nns1.quant & NNSTATS_KEYFRAME)
@@ -302,7 +302,10 @@
 					}
 					else
 					{
-						if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+						if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+							twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+							twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+							twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 						{
 							bframe_total += twopass->nns1.bytes;
 							bframe_total_ext += twopass->nns2.bytes;
@@ -434,19 +437,22 @@
 						twopass->minisize = recminisize;
 				}
 
-				// skip unnecessary frames.
+/*				// skip unnecessary frames.
 				if (twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
 					twopass->nns1.dd_v & NNSTATS_PADFRAME ||
 					twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					continue;
-
+*/ // broken in core, need to treat it differently now :-(
 				if (!codec_is_in_credits(&codec->config, frames) &&
 					!(twopass->nns1.quant & NNSTATS_KEYFRAME))
 				{
 					dbytes = twopass->nns2.bytes / twopass->movie_curve;
 					total1 += dbytes;
 
-					if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+					if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+						twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+						twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+						twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 						dbytes *= twopass->average_pframe / twopass->average_bframe;
 
 					if (codec->config.use_alt_curve)
@@ -510,7 +516,10 @@
 						}
 					}
 
-					if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+					if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+						twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+						twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+						twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					{
 						dbytes2 *= twopass->average_bframe / twopass->average_pframe;
 						if (dbytes2 < twopass->minbsize)
@@ -553,12 +562,12 @@
 				memcpy(&twopass->nns1, &twopass->nns1_array[twopass->nns_array_pos], sizeof(NNSTATS));
 				twopass->nns_array_pos++;
 
-				// skip unnecessary frames.
+/*				// skip unnecessary frames.
 				if (twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
 					twopass->nns1.dd_v & NNSTATS_PADFRAME ||
 					twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					continue;
-
+*/  // broken in core, have to treat this stuff differently now
 				if (codec_is_in_credits(&codec->config, frames) == CREDITS_START)
 				{
 					start += twopass->nns1.bytes;
@@ -577,7 +586,10 @@
 				}
 				else
 				{
-					if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+					if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+						twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+						twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+						twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					{
 						bframe_total += twopass->nns1.bytes;
 						bframes++;
@@ -595,7 +607,10 @@
 					if (!(twopass->nns1.kblk + twopass->nns1.mblk))
 						recminisize = twopass->nns1.bytes;
 				}
-				else if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+				else if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+						twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+						twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+						twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 				{
 					if (!(twopass->nns1.kblk + twopass->nns1.mblk))
 						recminbsize = twopass->nns1.bytes;
@@ -752,19 +767,22 @@
 						twopass->minisize = recminisize;
 				}
 
-				// skip unnecessary frames.
+/*				// skip unnecessary frames.
 				if (twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
 					twopass->nns1.dd_v & NNSTATS_PADFRAME ||
 					twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					continue;
-
+*/  // broken in core, we need to handle it differently now :-((
 				if (!codec_is_in_credits(&codec->config, frames) &&
 					!(twopass->nns1.quant & NNSTATS_KEYFRAME))
 				{
 					dbytes = twopass->nns1.bytes / twopass->movie_curve;
 					total1 += dbytes;
 
-					if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+					if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+						twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+						twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+						twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 						dbytes *= twopass->average_pframe / twopass->average_bframe;
 
 					if (codec->config.use_alt_curve)
@@ -828,7 +846,10 @@
 						}
 					}
 
-					if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+					if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+						twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+						twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+						twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					{
 						dbytes2 *= twopass->average_bframe / twopass->average_pframe;
 						if (dbytes2 < twopass->minbsize)
@@ -1013,7 +1034,7 @@
 
 	bytes1 = twopass->nns1.bytes;
 
-	// skip unnecessary frames.
+/*	// skip unnecessary frames.
 	if (twopass->nns1.dd_v & NNSTATS_SKIPFRAME)
 	{
 		twopass->bytes1 = bytes1;
@@ -1038,13 +1059,16 @@
 		frame->intra = 5;
 		return ICERR_OK;
 	}
-		
+*/ // broken in core, need to treat it differently :-((		
 	overflow = twopass->overflow / 8;
 
 	// override codec i-frame choice (reenable in credits)
 	if (twopass->nns1.quant & NNSTATS_KEYFRAME)
 		frame->intra=1;
-	else if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+	else if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+			twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+			twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+			twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 		frame->intra=2;
 	else
 		frame->intra=0;
@@ -1136,7 +1160,10 @@
 			dbytes = bytes2 / twopass->movie_curve;
 		}
 
-		if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+		if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+			twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+			twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+			twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 			dbytes *= twopass->average_pframe / twopass->average_bframe;
 
 		// spread the compression error across payback_delay frames
@@ -1205,7 +1232,10 @@
 						}
 					}
 				}
-				if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+				if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+					twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+					twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+					twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					curve_temp *= twopass->average_bframe / twopass->average_pframe;
 
 				curve_temp = curve_temp * twopass->curve_comp_scale + twopass->curve_bias_bonus;
@@ -1215,7 +1245,10 @@
 			}
 			else
 			{
-				if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+				if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+					twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+					twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+					twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 					dbytes *= twopass->average_bframe / twopass->average_pframe;
 
 				bytes2 += ((int)dbytes);
@@ -1238,7 +1271,10 @@
 					codec->config.curve_compression_low / 100.0);
 			}
 
-			if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+			if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+				twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+				twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+				twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 				curve_temp *= twopass->average_bframe / twopass->average_pframe;
 
 			bytes2 += ((int)curve_temp);
@@ -1246,7 +1282,10 @@
 		}
 		else
 		{
-			if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+			if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+				twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+				twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+				twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 				dbytes *= twopass->average_bframe / twopass->average_pframe;
 
 			bytes2 += ((int)dbytes);
@@ -1269,7 +1308,10 @@
 					bytes2 = twopass->minisize;
 				}
 			}
-			else if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+			else if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+					twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+					twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+					twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 			{
 				if (bytes2 < twopass->minbsize)
 					bytes2 = twopass->minbsize;
@@ -1347,7 +1389,10 @@
 		if (bytes2 < twopass->minisize)
 			bytes2 = twopass->minisize;
 	}
-	else if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+	else if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+			twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+			twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+			twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 	{
 		if (bytes2 < twopass->minbsize)
 			bytes2 = twopass->minbsize;
@@ -1375,7 +1420,10 @@
 	else if (!(frame->intra==1))
 	{
 		// Foxer: aid desired quantizer precision by accumulating decision error
-		if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+		if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+			twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+			twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+			twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 		{
 			bquant_error[frame->quant] += ((double)((twopass->nns1.quant & ~NNSTATS_KEYFRAME) * 
 				bytes1) / bytes2) - frame->quant;
@@ -1432,7 +1480,10 @@
 		// subsequent frame quants can only be +- 2
 		if ((last_pquant || last_bquant) && capped_to_max_framesize == 0)
 		{
-			if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+			if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+				twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+				twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+				twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 			{
 				// this bframe quantizer variation
 				// restriction needs to be redone.
@@ -1470,7 +1521,10 @@
 			last_bquant = frame->quant;
 			last_pquant = frame->quant;
 		}
-		else if (twopass->nns1.dd_v & NNSTATS_BFRAME)
+		else if (twopass->nns1.dd_v & NNSTATS_BFRAME ||
+				twopass->nns1.dd_v & NNSTATS_SKIPFRAME ||
+				twopass->nns1.dd_v & NNSTATS_PADFRAME ||
+				twopass->nns1.dd_v & NNSTATS_DELAYFRAME)
 			last_bquant = frame->quant;
 		else
 			last_pquant = frame->quant;
@@ -1565,10 +1619,10 @@
 	case DLG_MODE_2PASS_2_INT :
 	case DLG_MODE_2PASS_2_EXT :
 		credits_pos = codec_is_in_credits(&codec->config, codec->framenum);
-		if (!(codec->twopass.nns1.dd_v & NNSTATS_SKIPFRAME) &&
+/*		if (!(codec->twopass.nns1.dd_v & NNSTATS_SKIPFRAME) &&
 			!(codec->twopass.nns1.dd_v & NNSTATS_PADFRAME) &&
 			!(codec->twopass.nns1.dd_v & NNSTATS_DELAYFRAME))
-		{
+		{ */
 			if (!credits_pos)
 			{
 				codec->twopass.quant_count[frame->quant]++;
@@ -1616,16 +1670,19 @@
 				codec->twopass.KFoverflow_partial = 0;
 				// end of ugly fix.
 			}
-		}
+//		}
 
 		frame_type="inter";
 		if (frame->intra==1) {
 			frame_type="intra";
 		}
-		else if (codec->twopass.nns1.dd_v & NNSTATS_BFRAME) {
+		else if (codec->twopass.nns1.dd_v & NNSTATS_BFRAME ||
+				codec->twopass.nns1.dd_v & NNSTATS_SKIPFRAME ||
+				codec->twopass.nns1.dd_v & NNSTATS_PADFRAME ||
+				codec->twopass.nns1.dd_v & NNSTATS_DELAYFRAME) {
 			frame_type="bframe";
 		}
-		else if (codec->twopass.nns1.dd_v & NNSTATS_SKIPFRAME) {
+/*		else if (codec->twopass.nns1.dd_v & NNSTATS_SKIPFRAME) {
 			frame_type="skipped";
 			frame->quant = 2;
 			codec->twopass.bytes1 = 1;
@@ -1645,8 +1702,8 @@
 			codec->twopass.bytes1 = 1;
 			codec->twopass.desired_bytes2 = 1;
 			frame->length = 1;
-		}
-
+		} 
+*/ // all broken in core... *grmblfx*
 		DEBUG2ND(frame->quant, quant_type, frame_type, codec->twopass.bytes1, codec->twopass.desired_bytes2, frame->length, codec->twopass.overflow, credits_pos)
 		break;
 


-- pete; life is like a box of ammo