📄 xvid_vbr.c
字号:
{ oldquant = newquant; percent = (int)((n - state->average_frame) * 100.0 / state->average_frame); } } } } state->overflow = 0; state->KFoverflow = 0; state->KFoverflow_partial = 0; state->KF_idx = 1; for (n=0 ; n < 32 ; n++) { state->quant_error[n] = 0.0; state->quant_count[n] = 0; } state->curve_comp_error = 0.0; state->last_quant = 0; /* * Above this frame size limit, normal vbr rules will not apply * This means : * 1 - Quant can de/increase more than -/+2 between 2 frames * 2 - Leads to artifacts because of 1 */ state->max_framesize = state->twopass_max_bitrate/state->fps; /* Get back to the beginning of frame statistics */ fseek(state->pass1_file, pos_firstframe, SEEK_SET); /* * Small hack : We have to get next frame stats before the * getintra/quant calls * User clients update the data when they call vbrUpdate * we are just bypassing this because we don't have to update * the overflow and so on... */ { /* Fake vars */ int next_hbytes, next_kblocks, next_mblocks, next_ublocks; fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", &state->pass1_quant, &state->pass1_intra, &next_hbytes, &state->pass1_bytes, &next_kblocks, &next_mblocks, &next_ublocks); } /* Initialize the frame counter */ state->cur_frame = 0; state->last_keyframe = 0; return(0);}static int vbr_getquant_2pass2(void *sstate){ int quant; int intra; int bytes1, bytes2; int overflow; int capped_to_max_framesize = 0; int KFdistance, KF_min_size; vbr_control_t *state = sstate; bytes1 = state->pass1_bytes; overflow = state->overflow / 8; /* To shut up gcc warning */ bytes2 = bytes1; if (state->pass1_intra) { overflow = 0; } if (util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { switch (state->credits_mode) { case VBR_CREDITS_MODE_QUANT : if (state->credits_quant_i != state->credits_quant_p) { quant = state->pass1_intra ? state->credits_quant_i: state->credits_quant_p; } else { quant = state->credits_quant_p; } state->bytes1 = bytes1; state->bytes2 = bytes1; state->desired_bytes2 = bytes1; return(quant); default: case VBR_CREDITS_MODE_RATE : case VBR_CREDITS_MODE_SIZE : if(util_frametype(state) == FRAME_TYPE_STARTING_CREDITS) bytes2 = (int)(bytes1 / state->credits_start_curve); else bytes2 = (int)(bytes1 / state->credits_end_curve); break; } } else { /* Foxer: apply curve compression outside credits */ double dbytes, curve_temp; bytes2 = bytes1; if (state->pass1_intra) dbytes = ((int)(bytes2 + bytes2 * state->keyframe_boost / 100)) / state->movie_curve; else dbytes = bytes2 / state->movie_curve; /* spread the compression error accross payback_delay frames */ if (state->bitrate_payback_method == VBR_PAYBACK_BIAS) { bytes2 = (int)(state->curve_comp_error / state->bitrate_payback_delay); } else { bytes2 = (int)(state->curve_comp_error * dbytes / state->average_frame / state->bitrate_payback_delay); if (labs(bytes2) > fabs(state->curve_comp_error)) bytes2 = (int)state->curve_comp_error; } state->curve_comp_error -= bytes2; if (state->use_alt_curve) { if (!state->pass1_intra) { if (dbytes > state->average_frame) { if (dbytes >= state->alt_curve_high) curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev); else { switch(state->alt_curve_type) { case VBR_ALT_CURVE_AGGRESIVE: curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff))); break; default: case VBR_ALT_CURVE_LINEAR: curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * (dbytes - state->average_frame) / state->alt_curve_high_diff); break; case VBR_ALT_CURVE_SOFT: curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_high_diff)))); } } } else { if (dbytes <= state->alt_curve_low) curve_temp = dbytes; else { switch(state->alt_curve_type) { case VBR_ALT_CURVE_AGGRESIVE: curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * sin(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff))); break; default: case VBR_ALT_CURVE_LINEAR: curve_temp = dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev * (dbytes - state->average_frame) / state->alt_curve_low_diff); break; case VBR_ALT_CURVE_SOFT: curve_temp = dbytes * (state->alt_curve_mid_qual + state->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * ((dbytes - state->average_frame) * 90.0 / state->alt_curve_low_diff)))); } } } curve_temp = curve_temp * state->curve_comp_scale + state->curve_bias_bonus; bytes2 += ((int)curve_temp); state->curve_comp_error += curve_temp - ((int)curve_temp); } else { state->curve_comp_error += dbytes - ((int)dbytes); bytes2 += ((int)dbytes); } } else if ((state->curve_compression_high + state->curve_compression_low) && !state->pass1_intra) { if (dbytes > state->average_frame) { curve_temp = state->curve_comp_scale * ((double)dbytes + (state->average_frame - dbytes) * state->curve_compression_high / 100.0); } else { curve_temp = state->curve_comp_scale * ((double)dbytes + (state->average_frame - dbytes) * state->curve_compression_low / 100.0); } bytes2 += ((int)curve_temp); state->curve_comp_error += curve_temp - ((int)curve_temp); } else { state->curve_comp_error += dbytes - ((int)dbytes); bytes2 += ((int)dbytes); } /* cap bytes2 to first pass size, lowers number of quant=1 frames */ if (bytes2 > bytes1) { state->curve_comp_error += bytes2 - bytes1; bytes2 = bytes1; } else if (bytes2 < 1) { state->curve_comp_error += --bytes2; bytes2 = 1; } } state->desired_bytes2 = bytes2; /* Ugly dependance between getquant and getintra */ intra = state->getintra(state); if(intra) { KFdistance = state->keyframe_locations[state->KF_idx] - state->keyframe_locations[state->KF_idx - 1]; if (KFdistance < state->kftreshold) { KFdistance = KFdistance - state->min_key_interval; if (KFdistance >= 0) { KF_min_size = bytes2 * (100 - state->kfreduction) / 100; if (KF_min_size < 1) KF_min_size = 1; bytes2 = KF_min_size + (bytes2 - KF_min_size) * KFdistance / (state->kftreshold - state->min_key_interval); if (bytes2 < 1) bytes2 = 1; } } } /* * Foxer: scale overflow in relation to average size, so smaller frames don't get * too much/little bitrate */ overflow = (int)((double)overflow * bytes2 / state->average_frame); /* Foxer: reign in overflow with huge frames */ if (labs(overflow) > labs(state->overflow)) { overflow = state->overflow; } /* Foxer: make sure overflow doesn't run away */ if(overflow > bytes2 * state->twopass_max_overflow_improvement / 100) { bytes2 += (overflow <= bytes2) ? bytes2 * state->twopass_max_overflow_improvement / 100 : overflow * state->twopass_max_overflow_improvement / 100; } else if(overflow < bytes2 * state->twopass_max_overflow_degradation / -100) { bytes2 += bytes2 * state->twopass_max_overflow_degradation / -100; } else { bytes2 += overflow; } if(bytes2 > state->max_framesize) { capped_to_max_framesize = 1; bytes2 = state->max_framesize; } if(bytes2 < 1) { bytes2 = 1; } state->bytes1 = bytes1; state->bytes2 = bytes2; /* very 'simple' quant<->filesize relationship */ quant = state->pass1_quant * bytes1 / bytes2; if(quant < 1) quant = 1; else if(quant > 31) quant = 31; else if(!state->pass1_intra) { /* Foxer: aid desired quantizer precision by accumulating decision error */ state->quant_error[quant] += ((double)(state->pass1_quant * bytes1) / bytes2) - quant; if (state->quant_error[quant] >= 1.0) { state->quant_error[quant] -= 1.0; quant++; } } /* we're done with credits */ if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { return(quant); } if(intra) { if (quant < state->min_iquant) quant = state->min_iquant; if (quant > state->max_iquant) quant = state->max_iquant; } else { if(quant > state->max_pquant) quant = state->max_pquant; if(quant < state->min_pquant) quant = state->min_pquant; /* subsequent frame quants can only be +- 2 */ if(state->last_quant && capped_to_max_framesize == 0) { if (quant > state->last_quant + 2) quant = state->last_quant + 2; if (quant < state->last_quant - 2) quant = state->last_quant - 2; } } return(quant);}static int vbr_getintra_2pass2(void *sstate){ int intra; vbr_control_t *state = sstate; /* Get next intra state (fetched by update) */ intra = state->pass1_intra; /* During credits, XviD will decide itself */ if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { switch(state->credits_mode) { default: case VBR_CREDITS_MODE_RATE : case VBR_CREDITS_MODE_SIZE : intra = -1; break; case VBR_CREDITS_MODE_QUANT : /* Except in this case */ if (state->credits_quant_i == state->credits_quant_p) intra = -1; break; } } /* Force I Frame when max_key_interval is reached */ if((state->cur_frame - state->last_keyframe) > state->max_key_interval) intra = 1; /* * Force P or B Frames for frames whose distance is less than the * requested minimum */ if((state->cur_frame - state->last_keyframe) < state->min_key_interval) intra = 0; /* Return the given intra mode except for first frame */ return((state->cur_frame==0)?1:intra);}static int vbr_update_2pass2(void *sstate, int quant, int intra, int header_bytes, int total_bytes, int kblocks, int mblocks, int ublocks) { int next_hbytes, next_kblocks, next_mblocks, next_ublocks; int tempdiv; vbr_control_t *state = sstate; /* * We do not depend on getintra/quant because we have the real results * from the xvid core */ if (util_frametype(state) == FRAME_TYPE_NORMAL_MOVIE) { state->quant_count[quant]++; if (state->pass1_intra) { state->overflow += state->KFoverflow; state->KFoverflow = state->desired_bytes2 - total_bytes; tempdiv = (state->keyframe_locations[state->KF_idx] - state->keyframe_locations[state->KF_idx - 1]); /* redistribute correctly (by koepi) */ if (tempdiv > 1) { /* non-consecutive keyframes */ state->KFoverflow_partial = state->KFoverflow / (tempdiv - 1); } else { state->overflow += state->KFoverflow; state->KFoverflow = 0; state->KFoverflow_partial = 0; } state->KF_idx++; } else { state->overflow += state->desired_bytes2 - total_bytes + state->KFoverflow_partial; state->KFoverflow -= state->KFoverflow_partial; } } else { state->overflow += state->desired_bytes2 - total_bytes; state->overflow += state->KFoverflow; state->KFoverflow = 0; state->KFoverflow_partial = 0; } /* Save old quant */ state->last_quant = quant; /* Update next frame data */ fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", &state->pass1_quant, &state->pass1_intra, &next_hbytes, &state->pass1_bytes, &next_kblocks, &next_mblocks, &next_ublocks); /* Save the last Keyframe pos */ if(intra) state->last_keyframe = state->cur_frame; /* Ok next frame */ state->cur_frame++; return(0);}static int vbr_finish_2pass2(void *sstate){ vbr_control_t *state = sstate; if(state->pass1_file == NULL) return(-1); /* Close the file */ if(fclose(state->pass1_file) != 0) return(-1); /* Free the memory */ if(state->keyframe_locations) free(state->keyframe_locations); return(0);}/****************************************************************************** * Fixed quant mode - Most of the functions will be dummy functions *****************************************************************************/static int vbr_init_fixedquant(void *sstate){ vbr_control_t *state = sstate; if(state->fixed_quant < 1) state->fixed_quant = 1; if(state->fixed_quant > 31) state->fixed_quant = 31; state->cur_frame = 0; return(0);}static int vbr_getquant_fixedquant(void *sstate){ vbr_control_t *state = sstate; /* Credits' frame ? */ if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) { int quant; switch(state->credits_mode) { case VBR_CREDITS_MODE_RATE: quant = state->fixed_quant * state->credits_quant_ratio; break; case VBR_CREDITS_MODE_QUANT: quant = state->credits_fixed_quant; break; default: quant = state->fixed_quant; } return(quant); } /* No credit frame - return fixed quant */ return(state->fixed_quant);}static int vbr_getintra_fixedquant(void *state){ return(-1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -