23 |
* |
* |
24 |
* History: |
* History: |
25 |
* |
* |
26 |
|
* 17.04.2002 changed 1st pass quant to always be 2 (2pass_update()) |
27 |
|
* 07.04.2002 added max bitrate constraint, overflow controls (foxer) |
28 |
* 31.03.2002 inital version; |
* 31.03.2002 inital version; |
29 |
* |
* |
30 |
*************************************************************************/ |
*************************************************************************/ |
161 |
{ |
{ |
162 |
if (twopass->nns1.quant & NNSTATS_KEYFRAME) |
if (twopass->nns1.quant & NNSTATS_KEYFRAME) |
163 |
{ |
{ |
164 |
i_boost_total = twopass->nns2.bytes * codec->config.keyframe_boost / 100; |
i_boost_total += twopass->nns2.bytes * codec->config.keyframe_boost / 100; |
165 |
i_total += twopass->nns2.bytes; |
i_total += twopass->nns2.bytes; |
166 |
|
twopass->keyframe_locations[i_frames] = frames; |
167 |
++i_frames; |
++i_frames; |
168 |
} |
} |
169 |
|
|
175 |
|
|
176 |
++frames; |
++frames; |
177 |
} |
} |
178 |
|
twopass->keyframe_locations[i_frames] = frames; |
179 |
|
|
180 |
twopass->movie_curve = ((double)(total_ext + i_boost_total) / total_ext); |
twopass->movie_curve = ((double)(total_ext + i_boost_total) / total_ext); |
181 |
twopass->average_frame = ((double)(total_ext - i_total) / (frames - credits_frames - i_frames) / twopass->movie_curve); |
twopass->average_frame = ((double)(total_ext - i_total) / (frames - credits_frames - i_frames) / twopass->movie_curve); |
373 |
{ |
{ |
374 |
i_total += twopass->nns1.bytes + twopass->nns1.bytes * codec->config.keyframe_boost / 100; |
i_total += twopass->nns1.bytes + twopass->nns1.bytes * codec->config.keyframe_boost / 100; |
375 |
total += twopass->nns1.bytes * codec->config.keyframe_boost / 100; |
total += twopass->nns1.bytes * codec->config.keyframe_boost / 100; |
376 |
|
twopass->keyframe_locations[i_frames] = frames; |
377 |
++i_frames; |
++i_frames; |
378 |
} |
} |
379 |
|
|
381 |
|
|
382 |
++frames; |
++frames; |
383 |
} |
} |
384 |
|
twopass->keyframe_locations[i_frames] = frames; |
385 |
|
|
386 |
// compensate for avi frame overhead |
// compensate for avi frame overhead |
387 |
desired -= frames * 24; |
desired -= frames * 24; |
686 |
} |
} |
687 |
|
|
688 |
twopass->overflow = 0; |
twopass->overflow = 0; |
689 |
|
twopass->KFoverflow = 0; |
690 |
|
twopass->KFoverflow_partial = 0; |
691 |
|
twopass->KF_idx = 1; |
692 |
|
|
693 |
break; |
break; |
694 |
} |
} |
709 |
int bytes1, bytes2; |
int bytes1, bytes2; |
710 |
int overflow; |
int overflow; |
711 |
int credits_pos; |
int credits_pos; |
712 |
|
int capped_to_max_framesize = 0; |
713 |
|
int KFdistance, KF_min_size; |
714 |
|
|
715 |
if (codec->framenum == 0) |
if (codec->framenum == 0) |
716 |
{ |
{ |
719 |
for (i=0 ; i<32 ; ++i) |
for (i=0 ; i<32 ; ++i) |
720 |
{ |
{ |
721 |
quant_error[i] = 0.0; |
quant_error[i] = 0.0; |
722 |
|
twopass->quant_count[i] = 0; |
723 |
} |
} |
724 |
|
|
725 |
curve_comp_error = 0.0; |
curve_comp_error = 0.0; |
794 |
} |
} |
795 |
else // DLG_MODE_2PASS_2_EXT |
else // DLG_MODE_2PASS_2_EXT |
796 |
{ |
{ |
797 |
|
if (codec->config.credits_mode == CREDITS_MODE_QUANT) |
798 |
|
{ |
799 |
|
if (codec->config.credits_quant_i != codec->config.credits_quant_p) |
800 |
|
{ |
801 |
|
frame->quant = frame->intra ? |
802 |
|
codec->config.credits_quant_i : |
803 |
|
codec->config.credits_quant_p; |
804 |
|
} |
805 |
|
else |
806 |
|
{ |
807 |
|
frame->quant = codec->config.credits_quant_p; |
808 |
|
frame->intra = -1; |
809 |
|
} |
810 |
|
|
811 |
|
twopass->bytes1 = bytes1; |
812 |
|
twopass->bytes2 = bytes1; |
813 |
|
twopass->desired_bytes2 = bytes1; |
814 |
|
return ICERR_OK; |
815 |
|
} |
816 |
|
else |
817 |
bytes2 = twopass->nns2.bytes; |
bytes2 = twopass->nns2.bytes; |
818 |
} |
} |
819 |
} |
} |
950 |
|
|
951 |
twopass->desired_bytes2 = bytes2; |
twopass->desired_bytes2 = bytes2; |
952 |
|
|
953 |
|
// if this keyframe is too close to the next, |
954 |
|
// reduce it's byte allotment |
955 |
|
if (frame->intra && !credits_pos) |
956 |
|
{ |
957 |
|
KFdistance = codec->twopass.keyframe_locations[codec->twopass.KF_idx] - |
958 |
|
codec->twopass.keyframe_locations[codec->twopass.KF_idx - 1]; |
959 |
|
|
960 |
|
if (KFdistance < codec->config.kftreshold) |
961 |
|
{ |
962 |
|
KFdistance = KFdistance - codec->config.min_key_interval; |
963 |
|
|
964 |
|
if (KFdistance >= 0) |
965 |
|
{ |
966 |
|
KF_min_size = bytes2 * (100 - codec->config.kfreduction) / 100; |
967 |
|
if (KF_min_size < 1) |
968 |
|
KF_min_size = 1; |
969 |
|
|
970 |
|
bytes2 = KF_min_size + (bytes2 - KF_min_size) * KFdistance / |
971 |
|
(codec->config.kftreshold - codec->config.min_key_interval); |
972 |
|
|
973 |
|
if (bytes2 < 1) |
974 |
|
bytes2 = 1; |
975 |
|
} |
976 |
|
} |
977 |
|
} |
978 |
|
|
979 |
// Foxer: scale overflow in relation to average size, so smaller frames don't get |
// Foxer: scale overflow in relation to average size, so smaller frames don't get |
980 |
// too much/little bitrate |
// too much/little bitrate |
981 |
overflow = (int)((double)overflow * bytes2 / twopass->average_frame); |
overflow = (int)((double)overflow * bytes2 / twopass->average_frame); |
987 |
} |
} |
988 |
|
|
989 |
// Foxer: make sure overflow doesn't run away |
// Foxer: make sure overflow doesn't run away |
990 |
if (overflow > bytes2 * 6 / 10) |
if (overflow > bytes2 * codec->config.twopass_max_overflow_improvement / 100) |
991 |
{ |
{ |
992 |
bytes2 += (overflow <= bytes2) ? bytes2 * 6 / 10 : overflow * 6 / 10; |
bytes2 += (overflow <= bytes2) ? bytes2 * codec->config.twopass_max_overflow_improvement / 100 : |
993 |
|
overflow * codec->config.twopass_max_overflow_improvement / 100; |
994 |
} |
} |
995 |
else if (overflow < bytes2 * -6 / 10) |
else if (overflow < bytes2 * codec->config.twopass_max_overflow_degradation / -100) |
996 |
{ |
{ |
997 |
bytes2 += bytes2 * -6 / 10; |
bytes2 += bytes2 * codec->config.twopass_max_overflow_degradation / -100; |
998 |
} |
} |
999 |
else |
else |
1000 |
{ |
{ |
1001 |
bytes2 += overflow; |
bytes2 += overflow; |
1002 |
} |
} |
1003 |
|
|
1004 |
|
if (bytes2 > twopass->max_framesize) |
1005 |
|
{ |
1006 |
|
capped_to_max_framesize = 1; |
1007 |
|
bytes2 = twopass->max_framesize; |
1008 |
|
} |
1009 |
|
|
1010 |
if (bytes2 < 1) |
if (bytes2 < 1) |
1011 |
{ |
{ |
1012 |
bytes2 = 1; |
bytes2 = 1; |
1070 |
} |
} |
1071 |
|
|
1072 |
// subsequent frame quants can only be +- 2 |
// subsequent frame quants can only be +- 2 |
1073 |
if (last_quant) |
if (last_quant && capped_to_max_framesize == 0) |
1074 |
{ |
{ |
1075 |
if (frame->quant > last_quant + 2) |
if (frame->quant > last_quant + 2) |
1076 |
{ |
{ |
1085 |
} |
} |
1086 |
} |
} |
1087 |
|
|
1088 |
|
if (capped_to_max_framesize == 0) |
1089 |
last_quant = frame->quant; |
last_quant = frame->quant; |
1090 |
|
|
1091 |
if (codec->config.quant_type == QUANT_MODE_MOD) |
if (codec->config.quant_type == QUANT_MODE_MOD) |
1104 |
|
|
1105 |
NNSTATS nns1; |
NNSTATS nns1; |
1106 |
DWORD wrote; |
DWORD wrote; |
1107 |
|
int credits_pos, tempdiv; |
1108 |
char* quant_type; |
char* quant_type; |
1109 |
|
|
1110 |
if (codec->framenum == 0) |
if (codec->framenum == 0) |
1127 |
nns1.md_u = nns1.md_y = 0; |
nns1.md_u = nns1.md_y = 0; |
1128 |
nns1.mk_u = nns1.mk_y = 0; |
nns1.mk_u = nns1.mk_y = 0; |
1129 |
|
|
1130 |
nns1.quant = stats->quant; |
// nns1.quant = stats->quant; |
1131 |
|
nns1.quant = 2; // ugly fix for lumi masking in 1st pass returning new quant |
1132 |
if (frame->intra) |
if (frame->intra) |
1133 |
{ |
{ |
1134 |
nns1.quant |= NNSTATS_KEYFRAME; |
nns1.quant |= NNSTATS_KEYFRAME; |
1151 |
|
|
1152 |
case DLG_MODE_2PASS_2_INT : |
case DLG_MODE_2PASS_2_INT : |
1153 |
case DLG_MODE_2PASS_2_EXT : |
case DLG_MODE_2PASS_2_EXT : |
1154 |
|
credits_pos = codec_is_in_credits(&codec->config, codec->framenum); |
1155 |
|
if (!credits_pos) |
1156 |
|
{ |
1157 |
|
codec->twopass.quant_count[frame->quant]++; |
1158 |
|
if ((codec->twopass.nns1.quant & NNSTATS_KEYFRAME)) |
1159 |
|
{ |
1160 |
|
// calculate how much to distribute per frame in |
1161 |
|
// order to make up for this keyframe's overflow |
1162 |
|
|
1163 |
|
codec->twopass.overflow += codec->twopass.KFoverflow; |
1164 |
|
codec->twopass.KFoverflow = codec->twopass.desired_bytes2 - frame->length; |
1165 |
|
|
1166 |
|
tempdiv = (codec->twopass.keyframe_locations[codec->twopass.KF_idx] - |
1167 |
|
codec->twopass.keyframe_locations[codec->twopass.KF_idx - 1]); |
1168 |
|
|
1169 |
|
if (tempdiv > 1) |
1170 |
|
{ |
1171 |
|
// non-consecutive keyframes |
1172 |
|
codec->twopass.KFoverflow_partial = codec->twopass.KFoverflow / (tempdiv - 1); |
1173 |
|
} |
1174 |
|
else |
1175 |
|
{ |
1176 |
|
// consecutive keyframes |
1177 |
|
codec->twopass.overflow += codec->twopass.KFoverflow; |
1178 |
|
codec->twopass.KFoverflow = 0; |
1179 |
|
codec->twopass.KFoverflow_partial = 0; |
1180 |
|
} |
1181 |
|
codec->twopass.KF_idx++; |
1182 |
|
} |
1183 |
|
else |
1184 |
|
{ |
1185 |
|
// distribute part of the keyframe overflow |
1186 |
|
|
1187 |
|
codec->twopass.overflow += codec->twopass.desired_bytes2 - frame->length + |
1188 |
|
codec->twopass.KFoverflow_partial; |
1189 |
|
codec->twopass.KFoverflow -= codec->twopass.KFoverflow_partial; |
1190 |
|
} |
1191 |
|
} |
1192 |
|
else |
1193 |
|
{ |
1194 |
codec->twopass.overflow += codec->twopass.desired_bytes2 - frame->length; |
codec->twopass.overflow += codec->twopass.desired_bytes2 - frame->length; |
1195 |
DEBUG2ND(frame->quant, quant_type, frame->intra, codec->twopass.bytes1, codec->twopass.desired_bytes2, frame->length, codec->twopass.overflow, codec_is_in_credits(&codec->config, codec->framenum)) |
|
1196 |
|
// ugly fix for credits.. |
1197 |
|
codec->twopass.overflow += codec->twopass.KFoverflow; |
1198 |
|
codec->twopass.KFoverflow = 0; |
1199 |
|
codec->twopass.KFoverflow_partial = 0; |
1200 |
|
// end of ugly fix. |
1201 |
|
} |
1202 |
|
|
1203 |
|
DEBUG2ND(frame->quant, quant_type, frame->intra, codec->twopass.bytes1, codec->twopass.desired_bytes2, frame->length, codec->twopass.overflow, credits_pos) |
1204 |
break; |
break; |
1205 |
|
|
1206 |
default: |
default: |
1210 |
return ICERR_OK; |
return ICERR_OK; |
1211 |
} |
} |
1212 |
|
|
1213 |
|
void codec_2pass_finish(CODEC* codec) |
1214 |
|
{ |
1215 |
|
int i; |
1216 |
|
char s[100]; |
1217 |
|
if (codec->config.mode == DLG_MODE_2PASS_2_EXT || codec->config.mode == DLG_MODE_2PASS_2_INT) |
1218 |
|
{ |
1219 |
|
// output the quantizer distribution for this encode. |
1220 |
|
|
1221 |
|
OutputDebugString("Quantizer distribution for 2nd pass:"); |
1222 |
|
for (i=1; i<=31; i++) |
1223 |
|
{ |
1224 |
|
if (codec->twopass.quant_count[i]) |
1225 |
|
{ |
1226 |
|
wsprintf(s, "Q:%i:%i", i, codec->twopass.quant_count[i]); |
1227 |
|
OutputDebugString(s); |
1228 |
|
} |
1229 |
|
} |
1230 |
|
return; |
1231 |
|
} |
1232 |
|
} |