--- 2pass.c 2002/07/27 21:36:07 1.6 +++ 2pass.c 2002/09/28 02:01:56 1.11 @@ -41,12 +41,13 @@ DWORD version = -20; DWORD read, wrote; - int frames = 0, credits_frames = 0, i_frames = 0; + int frames = 0, credits_frames = 0, i_frames = 0, recminpsize = 0, recminisize = 0; __int64 total_ext = 0, total = 0, i_total = 0, i_boost_total = 0, start = 0, end = 0, start_curved = 0, end_curved = 0; __int64 desired = (__int64)codec->config.desired_size * 1024; double total1 = 0.0; double total2 = 0.0; + double dbytes, dbytes2; if (codec->config.hinted_me) { @@ -161,7 +162,7 @@ { if (twopass->nns1.quant & NNSTATS_KEYFRAME) { - i_boost_total = twopass->nns2.bytes * codec->config.keyframe_boost / 100; + i_boost_total += twopass->nns2.bytes * codec->config.keyframe_boost / 100; i_total += twopass->nns2.bytes; twopass->keyframe_locations[i_frames] = frames; ++i_frames; @@ -173,6 +174,17 @@ else ++credits_frames; + if (twopass->nns1.quant & NNSTATS_KEYFRAME) + { + if (!(twopass->nns1.kblk + twopass->nns1.mblk)) + recminisize = twopass->nns1.bytes; + } + else + { + if (!(twopass->nns1.kblk + twopass->nns1.mblk)) + recminpsize = twopass->nns1.bytes; + } + ++frames; } twopass->keyframe_locations[i_frames] = frames; @@ -252,10 +264,20 @@ } } + if (frames == 0) + { + twopass->minpsize = (twopass->nns1.kblk + 88) / 8; + twopass->minisize = ((twopass->nns1.kblk * 22) + 240) / 8; + if (recminpsize > twopass->minpsize) + twopass->minpsize = recminpsize; + if (recminisize > twopass->minisize) + twopass->minisize = recminisize; + } + if (!codec_is_in_credits(&codec->config, frames) && !(twopass->nns1.quant & NNSTATS_KEYFRAME)) { - double dbytes = twopass->nns2.bytes / twopass->movie_curve; + dbytes = twopass->nns2.bytes / twopass->movie_curve; total1 += dbytes; if (codec->config.use_alt_curve) @@ -263,21 +285,21 @@ if (dbytes > twopass->average_frame) { if (dbytes >= twopass->alt_curve_high) - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev); + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev); else { switch(codec->config.alt_curve_type) { case 2: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff))); break; case 1: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * (dbytes - twopass->average_frame) / twopass->alt_curve_high_diff); break; case 0: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff)))); } } @@ -285,21 +307,21 @@ else { if (dbytes <= twopass->alt_curve_low) - total2 += dbytes; + dbytes2 = dbytes; else { switch(codec->config.alt_curve_type) { case 2: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff))); break; case 1: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * (dbytes - twopass->average_frame) / twopass->alt_curve_low_diff); break; case 0: - total2 += dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff)))); } } @@ -309,15 +331,20 @@ { if (dbytes > twopass->average_frame) { - total2 += ((double)dbytes + (twopass->average_frame - dbytes) * + dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) * codec->config.curve_compression_high / 100.0); } else { - total2 += ((double)dbytes + (twopass->average_frame - dbytes) * + dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) * codec->config.curve_compression_low / 100.0); } } + + if (dbytes2 < twopass->minpsize) + dbytes2 = twopass->minpsize; + + total2 += dbytes2; } ++frames; @@ -379,6 +406,17 @@ total += twopass->nns1.bytes; + if (twopass->nns1.quant & NNSTATS_KEYFRAME) + { + if (!(twopass->nns1.kblk + twopass->nns1.mblk)) + recminisize = twopass->nns1.bytes; + } + else + { + if (!(twopass->nns1.kblk + twopass->nns1.mblk)) + recminpsize = twopass->nns1.bytes; + } + ++frames; } twopass->keyframe_locations[i_frames] = frames; @@ -511,10 +549,20 @@ } } + if (frames == 0) + { + twopass->minpsize = (twopass->nns1.kblk + 88) / 8; + twopass->minisize = ((twopass->nns1.kblk * 22) + 240) / 8; + if (recminpsize > twopass->minpsize) + twopass->minpsize = recminpsize; + if (recminisize > twopass->minisize) + twopass->minisize = recminisize; + } + if (!codec_is_in_credits(&codec->config, frames) && !(twopass->nns1.quant & NNSTATS_KEYFRAME)) { - double dbytes = twopass->nns1.bytes / twopass->movie_curve; + dbytes = twopass->nns1.bytes / twopass->movie_curve; total1 += dbytes; if (codec->config.use_alt_curve) @@ -522,21 +570,21 @@ if (dbytes > twopass->average_frame) { if (dbytes >= twopass->alt_curve_high) - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev); + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev); else { switch(codec->config.alt_curve_type) { case 2: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff))); break; case 1: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * (dbytes - twopass->average_frame) / twopass->alt_curve_high_diff); break; case 0: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_high_diff)))); } } @@ -544,21 +592,21 @@ else { if (dbytes <= twopass->alt_curve_low) - total2 += dbytes; + dbytes2 = dbytes; else { switch(codec->config.alt_curve_type) { case 2: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff))); break; case 1: - total2 += dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual - twopass->alt_curve_qual_dev * (dbytes - twopass->average_frame) / twopass->alt_curve_low_diff); break; case 0: - total2 += dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev * + dbytes2 = dbytes * (twopass->alt_curve_mid_qual + twopass->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - twopass->average_frame) * 90.0 / twopass->alt_curve_low_diff)))); } } @@ -568,15 +616,20 @@ { if (dbytes > twopass->average_frame) { - total2 += ((double)dbytes + (twopass->average_frame - dbytes) * + dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) * codec->config.curve_compression_high / 100.0); } else { - total2 += ((double)dbytes + (twopass->average_frame - dbytes) * + dbytes2 = ((double)dbytes + (twopass->average_frame - dbytes) * codec->config.curve_compression_low / 100.0); } } + + if (dbytes2 < twopass->minpsize) + dbytes2 = twopass->minpsize; + + total2 += dbytes2; } ++frames; @@ -794,7 +847,27 @@ } else // DLG_MODE_2PASS_2_EXT { - bytes2 = twopass->nns2.bytes; + if (codec->config.credits_mode == CREDITS_MODE_QUANT) + { + if (codec->config.credits_quant_i != codec->config.credits_quant_p) + { + frame->quant = frame->intra ? + codec->config.credits_quant_i : + codec->config.credits_quant_p; + } + else + { + frame->quant = codec->config.credits_quant_p; + frame->intra = -1; + } + + twopass->bytes1 = bytes1; + twopass->bytes2 = bytes1; + twopass->desired_bytes2 = bytes1; + return ICERR_OK; + } + else + bytes2 = twopass->nns2.bytes; } } else // Foxer: apply curve compression outside credits @@ -921,16 +994,26 @@ curve_comp_error += bytes2 - bytes1; bytes2 = bytes1; } - else if (bytes2 < 1) + else { - curve_comp_error += --bytes2; - bytes2 = 1; + if (frame->intra) + { + if (bytes2 < twopass->minisize) + { + curve_comp_error -= twopass->minisize - bytes2; + bytes2 = twopass->minisize; + } + } + else if (bytes2 < twopass->minpsize) + bytes2 = twopass->minpsize; } } twopass->desired_bytes2 = bytes2; - if (frame->intra) + // if this keyframe is too close to the next, + // reduce it's byte allotment + if (frame->intra && !credits_pos) { KFdistance = codec->twopass.keyframe_locations[codec->twopass.KF_idx] - codec->twopass.keyframe_locations[codec->twopass.KF_idx - 1]; @@ -985,10 +1068,14 @@ bytes2 = twopass->max_framesize; } - if (bytes2 < 1) + // make sure to not scale below the minimum framesize + if (twopass->nns1.quant & NNSTATS_KEYFRAME) { - bytes2 = 1; + if (bytes2 < twopass->minisize) + bytes2 = twopass->minisize; } + else if (bytes2 < twopass->minpsize) + bytes2 = twopass->minpsize; twopass->bytes1 = bytes1; twopass->bytes2 = bytes2; @@ -1135,6 +1222,9 @@ codec->twopass.quant_count[frame->quant]++; if ((codec->twopass.nns1.quant & NNSTATS_KEYFRAME)) { + // calculate how much to distribute per frame in + // order to make up for this keyframe's overflow + codec->twopass.overflow += codec->twopass.KFoverflow; codec->twopass.KFoverflow = codec->twopass.desired_bytes2 - frame->length; @@ -1157,6 +1247,8 @@ } else { + // distribute part of the keyframe overflow + codec->twopass.overflow += codec->twopass.desired_bytes2 - frame->length + codec->twopass.KFoverflow_partial; codec->twopass.KFoverflow -= codec->twopass.KFoverflow_partial; @@ -1202,4 +1294,5 @@ } return; } -} \ No newline at end of file +} +