📄 plugin_2pass2.c
字号:
rc->param.overflow_control_strength *= 3; } else if (scaler > 0.6) { rc->param.max_overflow_degradation *= 2; rc->param.max_overflow_improvement *= 2; rc->param.overflow_control_strength *= 2; } else { rc->min_quant = 2; }#endif /* Compute min frame lengths (for each frame type) according to the number * of MBs. We sum all block type counters of frame 0, this gives us the * number of MBs. * * We compare these hardcoded values with observed values in first pass * (determined in pre_process0).Then we keep the real minimum. */ /* Number of MBs */ num_MBs = rc->stats[0].blks[0]; num_MBs += rc->stats[0].blks[1]; num_MBs += rc->stats[0].blks[2]; /* Minimum for I frames */ if(rc->min_length[XVID_TYPE_IVOP-1] > ((num_MBs*22) + 240) / 8) rc->min_length[XVID_TYPE_IVOP-1] = ((num_MBs*22) + 240) / 8; /* Minimum for P/S frames */ if(rc->min_length[XVID_TYPE_PVOP-1] > ((num_MBs) + 88) / 8) rc->min_length[XVID_TYPE_PVOP-1] = ((num_MBs) + 88) / 8; /* Minimum for B frames */ if(rc->min_length[XVID_TYPE_BVOP-1] > 8) rc->min_length[XVID_TYPE_BVOP-1] = 8; /* Perform an initial scale pass. * * If a frame size is scaled underneath our hardcoded minimums, then we * force the frame size to the minimum, and deduct the original & scaled * frame length from the original and target total lengths */ for (i=0; i<rc->num_frames; i++) { twopass_stat_t * s = &rc->stats[i]; int len; /* No need to scale frame length for which a specific quantizer is * specified thanks to zones */ if (s->zone_mode == XVID_ZONE_QUANT) { s->scaled_length = s->length; continue; } /* Compute the scaled length -- only non invariant data length is scaled */ len = s->invariant + (int)((double)(s->length-s->invariant) * scaler * s->weight); /* Compare with the computed minimum */ if (len < rc->min_length[s->type-1]) { /* This is a 'forced size' frame, set its frame size to the * computed minimum */ s->scaled_length = rc->min_length[s->type-1]; /* Remove both scaled and original size from their respective * total counters, as we prepare a second pass for 'regular' * frames */ target -= s->scaled_length; } else { /* Do nothing for now, we'll scale this later */ s->scaled_length = 0; } } /* The first pass on data substracted all 'forced size' frames from the * total counters. Now, it's possible to scale the 'regular' frames. */ /* Scaling factor for 'regular' frames */ scaler = (double)(target - total_invariant) / (double)(rc->tot_weighted); /* Do another pass with the new scaler */ for (i=0; i<rc->num_frames; i++) { twopass_stat_t * s = &rc->stats[i]; /* Ignore frame with forced frame sizes */ if (s->scaled_length == 0) s->scaled_length = s->invariant + (int)((double)(s->length-s->invariant) * scaler * s->weight); } /* Job done */ return;}/* Apply all user settings to the scaled curve * This implies: * keyframe boosting * high/low compression */static voidscaled_curve_apply_advanced_parameters(rc_2pass2_t * rc){ int i; int64_t ivop_boost_total; /* Reset the rate controller (per frame type) total byte counters */ for (i=0; i<3; i++) rc->tot_scaled_length[i] = 0; /* Compute total bytes for each frame type */ for (i=0; i<rc->num_frames;i++) { twopass_stat_t *s = &rc->stats[i]; rc->tot_scaled_length[s->type-1] += s->scaled_length; } /* First we compute the total amount of bits needed, as being described by * the scaled distribution. During this pass over the complete stats data, * we see how much bits two user settings will get/give from/to p&b frames: * - keyframe boosting * - keyframe distance penalty */ rc->KF_idx = 0; ivop_boost_total = 0; for (i=0; i<rc->num_frames; i++) { twopass_stat_t * s = &rc->stats[i]; /* Some more work is needed for I frames */ if (s->type == XVID_TYPE_IVOP) { int ivop_boost; /* Accumulate bytes needed for keyframe boosting */ ivop_boost = s->scaled_length*rc->param.keyframe_boost/100;#if 0 /* ToDo: decide how to apply kfthresholding */#endif /* If the frame size drops under the minimum length, then cap ivop_boost */ if (ivop_boost + s->scaled_length < rc->min_length[XVID_TYPE_IVOP-1]) ivop_boost = rc->min_length[XVID_TYPE_IVOP-1] - s->scaled_length; /* Accumulate the ivop boost */ ivop_boost_total += ivop_boost; /* Don't forget to update the keyframe index */ rc->KF_idx++; } } /* Initialize the IBoost tax ratio for P/S/B frames * * This ratio has to be applied to p/b/s frames in order to reserve * additional bits for keyframes (keyframe boosting) or if too much * keyframe distance is applied, bits retrieved from the keyframes. * * ie pb_length *= rc->pb_iboost_tax_ratio; * * gives the ideal length of a p/b frame */ /* Compute the total length of p/b/s frames (temporary storage into * movie_curve) */ rc->pb_iboost_tax_ratio = (double)rc->tot_scaled_length[XVID_TYPE_PVOP-1]; rc->pb_iboost_tax_ratio += (double)rc->tot_scaled_length[XVID_TYPE_BVOP-1]; /* Compute the ratio described above * taxed_total = sum(0, n, tax*scaled_length) * <=> taxed_total = tax.sum(0, n, scaled_length) * <=> tax = taxed_total / original_total */ rc->pb_iboost_tax_ratio = (rc->pb_iboost_tax_ratio - ivop_boost_total) / rc->pb_iboost_tax_ratio; DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- IFrame boost tax ratio:%.2f\n", rc->pb_iboost_tax_ratio); /* Compute the average size of frames per frame type */ for(i=0; i<3; i++) { /* Special case for missing type or weird case */ if (rc->count[i] == 0 || rc->pb_iboost_tax_ratio == 0) { rc->avg_length[i] = 1; } else { rc->avg_length[i] = rc->tot_scaled_length[i]; if (i == (XVID_TYPE_IVOP-1)) { /* I Frames total has to be added the boost total */ rc->avg_length[i] += ivop_boost_total; } else { /* P/B frames has to taxed */ rc->avg_length[i] *= rc->pb_iboost_tax_ratio; } /* Finally compute the average frame size */ rc->avg_length[i] /= (double)rc->count[i]; } } /* Assymetric curve compression */ if (rc->param.curve_compression_high || rc->param.curve_compression_low) { double symetric_total; double assymetric_delta_total; /* Like I frame boosting, assymetric curve compression modifies the total * amount of needed bits, we must compute the ratio so we can prescale lengths */ symetric_total = 0; assymetric_delta_total = 0; for (i=0; i<rc->num_frames; i++) { double assymetric_delta; double dbytes; twopass_stat_t * s = &rc->stats[i]; /* I Frames are not concerned by assymetric scaling */ if (s->type == XVID_TYPE_IVOP) continue; /* During the real run, we would have to apply the iboost tax */ dbytes = s->scaled_length * rc->pb_iboost_tax_ratio; /* Update the symmetric curve compression total */ symetric_total += dbytes; /* Apply assymetric curve compression */ if (dbytes > rc->avg_length[s->type-1]) assymetric_delta = (rc->avg_length[s->type-1] - dbytes) * (double)rc->param.curve_compression_high / 100.0f; else assymetric_delta = (rc->avg_length[s->type-1] - dbytes) * (double)rc->param.curve_compression_low / 100.0f; /* Cap to the minimum frame size if needed */ if (dbytes + assymetric_delta < rc->min_length[s->type-1]) assymetric_delta = rc->min_length[s->type-1] - dbytes; /* Accumulate after assymetric curve compression */ assymetric_delta_total += assymetric_delta; } /* Compute the tax that all p/b frames have to pay in order to respect the * bit distribution changes that the assymetric compression curve imposes * We want assymetric_total = sum(0, n-1, tax.scaled_length) * ie assymetric_total = ratio.sum(0, n-1, scaled_length) * ratio = assymetric_total / symmetric_total */ rc->assymetric_tax_ratio = ((double)symetric_total - (double)assymetric_delta_total) / (double)symetric_total; } else { rc->assymetric_tax_ratio = 1.0f; } DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Assymetric tax ratio:%.2f\n", rc->assymetric_tax_ratio); /* Last bits that need to be reset */ rc->overflow = 0; rc->KFoverflow = 0; rc->KFoverflow_partial = 0; rc->KF_idx = 0; rc->desired_total = 0; rc->real_total = 0; /* Job done */ return;}/***************************************************************************** * Still more low level stuff (nothing to do with stats treatment) ****************************************************************************//* This function returns an allocated string containing a complete line read * from the file starting at the current position */static char *readline(FILE *f){ char *buffer = NULL; int buffer_size = 0; int pos = 0; do { int c; /* Read a character from the stream */ c = fgetc(f); /* Is that EOF or new line ? */ if(c == EOF || c == '\n') break; /* Do we have to update buffer ? */ if(pos >= buffer_size - 1) { buffer_size += BUF_SZ; buffer = (char*)realloc(buffer, buffer_size); if (buffer == NULL) return(NULL); } buffer[pos] = c; pos++; } while(1); /* Read \n or EOF */ if (buffer == NULL) { /* EOF, so we reached the end of the file, return NULL */ if(feof(f)) return(NULL); /* Just an empty line with just a newline, allocate a 1 byte buffer to * store a zero length string */ buffer = (char*)malloc(1); if(buffer == NULL) return(NULL); } /* Zero terminated string */ buffer[pos] = '\0'; return(buffer);}/* This function returns a pointer to the first non space char in the given * string */static char *skipspaces(char *string){ const char spaces[] = { ' ','\t','\0' }; const char *spacechar = spaces; if (string == NULL) return(NULL); while (*string != '\0') { /* Test against space chars */ while (*spacechar != '\0') { if (*string == *spacechar) { string++; spacechar = spaces; break; } spacechar++; } /* No space char */ if (*spacechar == '\0') return(string); } return(string);}/* This function returns a boolean that tells if the string is only a * comment */static intiscomment(char *string){ const char comments[] = { '#',';', '%', '\0' }; const char *cmtchar = comments; int iscomment = 0; if (string == NULL) return(1); string = skipspaces(string); while(*cmtchar != '\0') { if(*string == *cmtchar) { iscomment = 1; break; } cmtchar++; } return(iscomment);}#if 0static voidstats_print(rc_2pass2_t * rc){ int i; const char frame_type[4] = { 'i', 'p', 'b', 's'}; for (i=0; i<rc->num_frames; i++) { twopass_stat_t *s = &rc->stats[i]; DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- frame:%d type:%c quant:%d stats:%d scaled:%d desired:%d actual:%d overflow(%c):%.2f\n", i, frame_type[s->type-1], -1, s->length, s->scaled_length, s->desired_length, -1, frame_type[s->type-1], -1.0f); }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -