📄 plugin_2pass2.c
字号:
if (rc->param.vbv_size > 0) { const double fps = (double)create->fbase/(double)create->fincr; int status = check_curve_for_vbv_compliancy(rc, fps); if (status) { DPRINTF(XVID_DEBUG_RC, "[xvid rc] Underflow detected - Scaling Curve for compliancy.\n"); } status = scale_curve_for_vbv_compliancy(rc, fps); if (status == 0) { DPRINTF(XVID_DEBUG_RC, "[xvid rc] VBV compliant curve scaling done.\n"); } else { DPRINTF(XVID_DEBUG_RC, "[xvid rc] VBV compliant curve scaling impossible.\n"); } } *handle = rc; return(0);}/*---------------------------------------------------------------------------- *--------------------------------------------------------------------------*/static intrc_2pass2_destroy(rc_2pass2_t * rc, xvid_plg_destroy_t * destroy){ DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- target_total:%lld desired_total:%.2f (%.2f%%) actual_total:%.2f (%.2f%%)\n", rc->target, rc->desired_total, 100*rc->desired_total/(double)rc->target, rc->real_total, 100*rc->real_total/(double)rc->target); free(rc->keyframe_locations); free(rc->stats); free(rc); return(0);}/*---------------------------------------------------------------------------- *--------------------------------------------------------------------------*/static intrc_2pass2_before(rc_2pass2_t * rc, xvid_plg_data_t * data){ twopass_stat_t * s = &rc->stats[data->frame_num]; double dbytes; double scaled_quant; double overflow; int capped_to_max_framesize = 0; /* This function is quite long but easy to understand. In order to simplify * the code path (a bit), we treat 3 cases that can return immediatly. */ /* First case: Another plugin has already set a quantizer */ if (data->quant > 0) return(0); /* Second case: insufficent stats data * We can't guess much what we should do, let core decide all alone */ if (data->frame_num >= rc->num_frames) { DPRINTF(XVID_DEBUG_RC,"[xvid rc] -- stats file too short (now processing frame %d)", data->frame_num); return(0); } /* Third case: We are in a Quant zone * Quant zones must just ensure we use the same settings as first pass * So set the quantizer and the type */ if (s->zone_mode == XVID_ZONE_QUANT) { /* Quant stuff */ rc->fq_error += s->weight; data->quant = (int)rc->fq_error; rc->fq_error -= data->quant; /* The type stuff */ data->type = s->type; /* The only required data for AFTER step is this one for the overflow * control */ s->desired_length = s->length; return(0); } /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /*------------------------------------------------------------------------- * Frame bit allocation first part * * First steps apply user settings, just like it is done in the theoritical * scaled_curve_apply_advanced_parameters *-----------------------------------------------------------------------*/ /* Set desired to what we are wanting to obtain for this frame */ dbytes = (double)s->scaled_length; /* IFrame user settings*/ if (s->type == XVID_TYPE_IVOP) { /* Keyframe boosting -- All keyframes benefit from it */ dbytes += dbytes*rc->param.keyframe_boost / 100;#if 0 /* ToDo: decide how to apply kfthresholding */#endif } else { /* P/S/B frames must reserve some bits for iframe boosting */ dbytes *= rc->pb_iboost_tax_ratio; /* Apply assymetric curve compression */ if (rc->param.curve_compression_high || rc->param.curve_compression_low) { double assymetric_delta; /* Compute the assymetric delta, this is computed before applying * the tax, as done in the pre_process function */ if (dbytes > rc->avg_length[s->type-1]) assymetric_delta = (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_high / 100.0; else assymetric_delta = (rc->avg_length[s->type-1] - dbytes) * rc->param.curve_compression_low / 100.0; /* Now we must apply the assymetric tax, else our curve compression * would not give a theoritical target size equal to what it is * expected */ dbytes *= rc->assymetric_tax_ratio; /* Now we can add the assymetric delta */ dbytes += assymetric_delta; } } /* That is what we would like to have -- Don't put that chunk after * overflow control, otherwise, overflow is counted twice and you obtain * half sized bitrate sequences */ s->desired_length = (int)dbytes; rc->desired_total += dbytes; /*------------------------------------------------------------------------ * Frame bit allocation: overflow control part. * * Unlike the theoritical scaled_curve_apply_advanced_parameters, here * it's real encoding and we need to make sure we don't go so far from * what is our ideal scaled curve. *-----------------------------------------------------------------------*/ /* Compute the overflow we should compensate */ if (s->type != XVID_TYPE_IVOP || rc->overflow > 0) { double frametype_factor; double framesize_factor; /* Take only the desired part of overflow */ overflow = rc->overflow; /* Factor that will take care to decrease the overflow applied * according to the importance of this frame type in term of * overall size */ frametype_factor = rc->count[XVID_TYPE_IVOP-1]*rc->avg_length[XVID_TYPE_IVOP-1]; frametype_factor += rc->count[XVID_TYPE_PVOP-1]*rc->avg_length[XVID_TYPE_PVOP-1]; frametype_factor += rc->count[XVID_TYPE_BVOP-1]*rc->avg_length[XVID_TYPE_BVOP-1]; frametype_factor /= rc->count[s->type-1]*rc->avg_length[s->type-1]; frametype_factor = 1/frametype_factor; /* Factor that will take care not to compensate too much for this frame * size */ framesize_factor = dbytes; framesize_factor /= rc->avg_length[s->type-1]; /* Treat only the overflow part concerned by this frame type and size */ overflow *= frametype_factor;#if 0 /* Leave this one alone, as it impacts badly on quality */ overflow *= framesize_factor;#endif /* Apply the overflow strength imposed by the user */ overflow *= (rc->param.overflow_control_strength/100.0f); } else { /* no negative overflow applied in IFrames because: * - their role is important as they're references for P/BFrames. * - there aren't much in typical sequences, so if an IFrame overflows too * much, this overflow may impact the next IFrame too much and generate * a sequence of poor quality frames */ overflow = 0; } /* Make sure we are not trying to compensate more overflow than we even have */ if (fabs(overflow) > fabs(rc->overflow)) overflow = rc->overflow; /* Make sure the overflow doesn't make the frame size to get out of the range * [-max_degradation..+max_improvment] */ if (overflow > dbytes*rc->param.max_overflow_improvement / 100) { if(overflow <= dbytes) dbytes += dbytes * rc->param.max_overflow_improvement / 100; else dbytes += overflow * rc->param.max_overflow_improvement / 100; } else if (overflow < - dbytes * rc->param.max_overflow_degradation / 100) { dbytes -= dbytes * rc->param.max_overflow_degradation / 100; } else { dbytes += overflow; } /*------------------------------------------------------------------------- * Frame bit allocation last part: * * Cap frame length so we don't reach neither bigger frame sizes than first * pass nor smaller than the allowed minimum. *-----------------------------------------------------------------------*/#ifdef PASS_SMALLER if (dbytes > s->length) { dbytes = s->length; }#endif /* Prevent stupid desired sizes under logical values */ if (dbytes < rc->min_length[s->type-1]) { dbytes = rc->min_length[s->type-1]; } /*------------------------------------------------------------------------ * Desired frame length <-> quantizer mapping *-----------------------------------------------------------------------*/#ifdef BQUANT_PRESCALE /* For bframes we prescale the quantizer to avoid too high quant scaling */ if(s->type == XVID_TYPE_BVOP) { twopass_stat_t *b_ref = s; /* Find the reference frame */ while(b_ref != &rc->stats[0] && b_ref->type == XVID_TYPE_BVOP) b_ref--; /* Compute the original quant */ s->quant = 2*(100*s->quant - data->bquant_offset); s->quant += data->bquant_ratio - 1; /* to avoid rounding issues */ s->quant = s->quant/data->bquant_ratio - b_ref->quant; }#endif /* Don't laugh at this very 'simple' quant<->size relationship, it * proves to be acurate enough for our algorithm */ scaled_quant = (double)s->quant*(double)s->length/(double)dbytes;#ifdef COMPENSATE_FORMULA /* We know xvidcore will apply the bframe formula again, so we compensate * it right now to make sure we would not apply it twice */ if(s->type == XVID_TYPE_BVOP) { twopass_stat_t *b_ref = s; /* Find the reference frame */ while(b_ref != &rc->stats[0] && b_ref->type == XVID_TYPE_BVOP) b_ref--; /* Compute the quant it would be if the core did not apply the bframe * formula */ scaled_quant = 100*scaled_quant - data->bquant_offset; scaled_quant += data->bquant_ratio - 1; /* to avoid rouding issues */ scaled_quant /= data->bquant_ratio; }#endif /* Quantizer has been scaled using floating point operations/results, we * must cast it to integer */ data->quant = (int)scaled_quant; /* Let's clip the computed quantizer, if needed */ if (data->quant < 1) { data->quant = 1; } else if (data->quant > 31) { data->quant = 31; } else { /* The frame quantizer has not been clipped, this appears to be a good * computed quantizer, do not loose quantizer decimal part that we * accumulate for later reuse when its sum represents a complete * unit. */ rc->quant_error[s->type-1][data->quant] += scaled_quant - (double)data->quant; if (rc->quant_error[s->type-1][data->quant] >= 1.0) { rc->quant_error[s->type-1][data->quant] -= 1.0; data->quant++; } else if (rc->quant_error[s->type-1][data->quant] <= -1.0) { rc->quant_error[s->type-1][data->quant] += 1.0; data->quant--; } } /* Now we have a computed quant that is in the right quante range, with a * possible +1 correction due to cumulated error. We can now safely clip * the quantizer again with user's quant ranges. "Safely" means the Rate * Control could learn more about this quantizer, this knowledge is useful * for future frames even if it this quantizer won't be really used atm, * that's why we don't perform this clipping earlier. */ if (data->quant < data->min_quant[s->type-1]) { data->quant = data->min_quant[s->type-1]; } else if (data->quant > data->max_quant[s->type-1]) { data->quant = data->max_quant[s->type-1]; } if (data->quant < rc->min_quant) data->quant = rc->min_quant; /* To avoid big quality jumps from frame to frame, we apply a "security" * rule that makes |last_quant - new_quant| <= 2. This rule only applies * to predicted frames (P and B) */ if (s->type != XVID_TYPE_IVOP && rc->last_quant[s->type-1] && capped_to_max_framesize == 0) { if (data->quant > rc->last_quant[s->type-1] + 2) { data->quant = rc->last_quant[s->type-1] + 2; DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- frame %d p/b-frame quantizer prevented from rising too steeply\n", data->frame_num); } if (data->quant < rc->last_quant[s->type-1] - 2) { data->quant = rc->last_quant[s->type-1] - 2; DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- frame:%d p/b-frame quantizer prevented from falling too steeply\n", data->frame_num); } } /* We don't want to pollute the RC histerisis when our computed quant has * been computed from a capped frame size */ if (capped_to_max_framesize == 0) rc->last_quant[s->type-1] = data->quant; /* Don't forget to force 1st pass frame type ;-) */ data->type = s->type; return 0;}/*---------------------------------------------------------------------------- *--------------------------------------------------------------------------*/static intrc_2pass2_after(rc_2pass2_t * rc, xvid_plg_data_t * data){ const char frame_type[4] = { 'i', 'p', 'b', 's'}; twopass_stat_t * s = &rc->stats[data->frame_num]; /* Insufficent stats data */ if (data->frame_num >= rc->num_frames) return 0; /* Update the quantizer counter */ rc->quant_count[s->type-1][data->quant]++; /* Update the frame type overflow */ if (data->type == XVID_TYPE_IVOP) { int kfdiff = 0; if(rc->KF_idx != rc->num_frames -1) { kfdiff = rc->keyframe_locations[rc->KF_idx+1]; kfdiff -= rc->keyframe_locations[rc->KF_idx]; } /* Flush Keyframe overflow accumulator */ rc->overflow += rc->KFoverflow; /* Store the frame overflow to the keyframe accumulator */ rc->KFoverflow = s->desired_length - data->length; if (kfdiff > 1) { /* Non-consecutive keyframes case: * We can then divide this total keyframe overflow into equal parts * that we will distribute into regular overflow at each frame * between the sequence bounded by two IFrames */ rc->KFoverflow_partial = rc->KFoverflow / (kfdiff - 1); } else { /* Consecutive keyframes case: * Flush immediatly the keyframe overflow and reset keyframe * overflow */ rc->overflow += rc->KFoverflow; rc->KFoverflow = 0; rc->KFoverflow_partial = 0; } rc->KF_idx++; } else { /* Accumulate the frame overflow */ rc->overflow += s->desired_length - data->length; /* Distribute part of the keyframe overflow */ rc->overflow += rc->KFoverflow_partial; /* Don't forget to substract that same amount from the total keyframe * overflow */ rc->KFoverflow -= rc->KFoverflow_partial; } s->error = s->desired_length - data->length; rc->real_total += data->length; DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- frame:%d type:%c quant:%d stats:%d scaled:%d desired:%d actual:%d error:%d overflow:%.2f\n", data->frame_num, frame_type[data->type-1], data->quant, s->length, s->scaled_length, s->desired_length, s->desired_length - s->error, -s->error, rc->overflow); return(0);}/***************************************************************************** * Helper functions definition ****************************************************************************//* Default buffer size for reading lines */#define BUF_SZ 1024/* Helper functions for reading/parsing the stats file */static char *skipspaces(char *string);static int iscomment(char *string);static char *readline(FILE *f);/* This function counts the number of frame entries in the stats file * It also counts the number of I Frames */static intstatsfile_count_frames(rc_2pass2_t * rc, char * filename){ FILE * f; char *line; int lines; rc->num_frames = 0; rc->num_keyframes = 0; if ((f = fopen(filename, "rb")) == NULL) return(-1); lines = 0; while ((line = readline(f)) != NULL) { char *ptr; char type; int fields; lines++; /* We skip spaces */ ptr = skipspaces(line); /* Skip coment lines or empty lines */ if(iscomment(ptr) || *ptr == '\0') { free(line); continue; } /* Read the stat line from buffer */ fields = sscanf(ptr, "%c", &type); /* Valid stats files have at least 7 fields */ if (fields == 1) { switch(type) { case 'i': case 'I': rc->num_keyframes++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -