📄 plugin_2pass2.c
字号:
/* 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; } rc->overflow += (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++; case 'p': case 'P': case 'b': case 'B': case 's': case 'S': rc->num_frames++; break; default: DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- WARNING: L%d unknown frame type used (%c).\n", lines, type); } } else { DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- WARNING: L%d misses some stat fields (%d).\n", lines, 7-fields); } /* Free the line buffer */ free(line); } /* We are done with the file */ fclose(f); return(0);}/* open stats file(s) and read into rc->stats array */static intstatsfile_load(rc_2pass2_t *rc, char * filename){ FILE * f; int processed_entries; /* Opens the file */ if ((f = fopen(filename, "rb"))==NULL) return(-1); processed_entries = 0; while(processed_entries < rc->num_frames) { char type; int fields; twopass_stat_t * s = &rc->stats[processed_entries]; char *line, *ptr; /* Read the line from the file */ if((line = readline(f)) == NULL) break; /* We skip spaces */ ptr = skipspaces(line); /* Skip comment lines or empty lines */ if(iscomment(ptr) || *ptr == '\0') { free(line); continue; } /* Reset this field that is optional */ s->scaled_length = 0; /* Convert the fields */ fields = sscanf(ptr, "%c %d %d %d %d %d %d %d\n", &type, &s->quant, &s->blks[0], &s->blks[1], &s->blks[2], &s->length, &s->invariant /* not really yet */, &s->scaled_length); /* Free line buffer, we don't need it anymore */ free(line); /* Fail silently, this has probably been warned in * statsfile_count_frames */ if(fields != 7 && fields != 8) continue; /* Convert frame type and compute the invariant length part */ switch(type) { case 'i': case 'I': s->type = XVID_TYPE_IVOP; s->invariant /= INVARIANT_HEADER_PART_IVOP; break; case 'p': case 'P': case 's': case 'S': s->type = XVID_TYPE_PVOP; s->invariant /= INVARIANT_HEADER_PART_PVOP; break; case 'b': case 'B': s->type = XVID_TYPE_BVOP; s->invariant /= INVARIANT_HEADER_PART_BVOP; break; default: /* Same as before, fail silently */ continue; } /* Ok it seems it's been processed correctly */ processed_entries++; } /* Close the file */ fclose(f); return(0);}/* pre-process the statistics data * - for each type, count, tot_length, min_length, max_length * - set keyframes_locations, tot_prescaled */static voidfirst_pass_stats_prepare_data(rc_2pass2_t * rc){ int i,j; /* *rc fields initialization * NB: INT_MAX and INT_MIN are used in order to be immediately replaced * with real values of the 1pass */ for (i=0; i<3; i++) { rc->count[i]=0; rc->tot_length[i] = 0; rc->tot_invariant[i] = 0; rc->min_length[i] = INT_MAX; } rc->max_length = INT_MIN; rc->tot_weighted = 0; /* Loop through all frames and find/compute all the stuff this function * is supposed to do */ for (i=j=0; i<rc->num_frames; i++) { twopass_stat_t * s = &rc->stats[i]; rc->count[s->type-1]++; rc->tot_length[s->type-1] += s->length; rc->tot_invariant[s->type-1] += s->invariant; if (s->zone_mode != XVID_ZONE_QUANT) rc->tot_weighted += (int)(s->weight*(s->length - s->invariant)); if (s->length < rc->min_length[s->type-1]) { rc->min_length[s->type-1] = s->length; } if (s->length > rc->max_length) { rc->max_length = s->length; } if (s->type == XVID_TYPE_IVOP) { rc->keyframe_locations[j] = i; j++; } } /* NB: * The "per sequence" overflow system considers a natural sequence to be * formed by all frames between two iframes, so if we want to make sure * the system does not go nuts during last sequence, we force the last * frame to appear in the keyframe locations array. */ rc->keyframe_locations[j] = i; DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Min 1st pass IFrame length: %d\n", rc->min_length[0]); DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Min 1st pass PFrame length: %d\n", rc->min_length[1]); DPRINTF(XVID_DEBUG_RC, "[xvid rc] -- Min 1st pass BFrame length: %d\n", rc->min_length[2]);}/* calculate zone weight "center" */static voidzone_process(rc_2pass2_t *rc, const xvid_plg_create_t * create){ int i,j; int n = 0; rc->tot_quant = 0; rc->tot_quant_invariant = 0; if (create->num_zones == 0) { for (j = 0; j < rc->num_frames; j++) { rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; rc->stats[j].weight = 1.0; } n += rc->num_frames; } for(i=0; i < create->num_zones; i++) { int next = (i+1<create->num_zones) ? create->zones[i+1].frame : rc->num_frames; /* Zero weight make no sense */ if (create->zones[i].increment == 0) create->zones[i].increment = 1; /* And obviously an undetermined infinite makes even less sense */ if (create->zones[i].base == 0) create->zones[i].base = 1; if (i==0 && create->zones[i].frame > 0) { for (j = 0; j < create->zones[i].frame && j < rc->num_frames; j++) { rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; rc->stats[j].weight = 1.0; } n += create->zones[i].frame; } if (create->zones[i].mode == XVID_ZONE_WEIGHT) { for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { rc->stats[j].zone_mode = XVID_ZONE_WEIGHT; rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; } next -= create->zones[i].frame; n += next; } else{ /* XVID_ZONE_QUANT */ for (j = create->zones[i].frame; j < next && j < rc->num_frames; j++ ) { rc->stats[j].zone_mode = XVID_ZONE_QUANT; rc->stats[j].weight = (double)create->zones[i].increment / (double)create->zones[i].base; rc->tot_quant += rc->stats[j].length; rc->tot_quant_invariant += rc->stats[j].invariant; } } }}/* scale the curve */static voidfirst_pass_scale_curve_internal(rc_2pass2_t *rc){ int64_t target; int64_t total_invariant; double scaler; int i, num_MBs; /* We only scale texture data ! */ total_invariant = rc->tot_invariant[XVID_TYPE_IVOP-1]; total_invariant += rc->tot_invariant[XVID_TYPE_PVOP-1]; total_invariant += rc->tot_invariant[XVID_TYPE_BVOP-1]; /* don't forget to substract header bytes used in quant zones, otherwise we * counting them twice */ total_invariant -= rc->tot_quant_invariant; /* We remove the bytes used by the fixed quantizer zones during first pass * with the same quants, so we know very precisely how much that * represents */ target = rc->target; target -= rc->tot_quant; /* Let's compute a linear scaler in order to perform curve scaling */ scaler = (double)(target - total_invariant) / (double)(rc->tot_weighted);#ifdef SMART_OVERFLOW_SETTING if (scaler > 0.9) { rc->param.max_overflow_degradation *= 5; rc->param.max_overflow_improvement *= 5;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -