📄 xvid_vbr.c
字号:
return(-1);}static int vbr_update_2pass1(void *sstate, int quant, int intra, int header_bytes, int total_bytes, int kblocks, int mblocks, int ublocks) { vbr_control_t *state = sstate; if(state->pass1_file == NULL) return(-1); /* Writes the resulting statistics */ fprintf(state->pass1_file, "%d %d %d %d %d %d %d\n", quant, intra, header_bytes, total_bytes, kblocks, mblocks, ublocks); /* Update vbr control state */ if(intra) state->nb_keyframes++; state->nb_frames++; state->cur_frame++; return(0); }static int vbr_finish_2pass1(void *sstate){ int c, i; vbr_control_t *state = sstate; if(state->pass1_file == NULL) return(-1); /* Goto to the file beginning */ fseek(state->pass1_file, 0, SEEK_SET); /* Skip the version line and the empty line */ c = i = 0; do { c = fgetc(state->pass1_file); if(c == EOF) return(-1); if(c == '\n') i++; }while(i < 2); /* Prepare to write to the stream */ fseek( state->pass1_file, 0L, SEEK_CUR ); /* Overwrite the frame field - safe as we have written extra spaces */ fprintf(state->pass1_file, "# frames : %.10d\n", state->nb_frames); /* Overwrite the keyframe field */ fprintf(state->pass1_file, "# keyframes : %.10d\n", state->nb_keyframes); /* Close the file */ if(fclose(state->pass1_file) != 0) return(-1); return(0);}/****************************************************************************** * 2 pass mode - 2nd pass functions (Need to be finished) *****************************************************************************/static int vbr_init_2pass2(void *sstate){ FILE *f; int c, n, pos_firstframe, credits_frames; long long credits1_bytes; long long credits2_bytes; long long desired; long long total_bytes; long long itotal_bytes; long long start_curved; long long end_curved; double total1; double total2; vbr_control_t *state = sstate; /* Check the filename */ if(state->filename == NULL || state->filename[0] == '\0') return(-1); /* Initialize safe defaults for 2pass 2 */ state->pass1_file = NULL; state->nb_frames = 0; state->nb_keyframes = 0; /* Open the 1st pass file */ if((f = fopen(state->filename, "r")) == NULL) return(-1); state->pass1_file = f; /* Get the file version and check against current version */ fscanf(state->pass1_file, "# ASCII XviD vbr stat file version %d\n", &n); if(n != VBR_VERSION) { fclose(state->pass1_file); state->pass1_file = NULL; return(-1); } /* Skip the blank commented line */ c = n = 0; do { c = fgetc(state->pass1_file); if(c == EOF) { fclose(state->pass1_file); state->pass1_file = NULL; return(-1); } if(c == '\n') n++; }while(n < 1); /* Get the number of frames */ fscanf(state->pass1_file, "# frames : %d\n", &state->nb_frames); /* Compute the desired size */ state->desired_size = (long long) (((long long)state->nb_frames * (long long)state->desired_bitrate) / (state->fps * 8.0)); /* Get the number of keyframes */ fscanf(state->pass1_file, "# keyframes : %d\n", &state->nb_keyframes); /* Allocate memory space for the keyframe_location array */ if((state->keyframe_locations = (int*)malloc((state->nb_keyframes+1)*sizeof(int))) == NULL) { fclose(state->pass1_file); state->pass1_file = NULL; return(-1); } /* Skip the blank commented line and the colum description */ c = n = 0; do { c = fgetc(state->pass1_file); if(c == EOF) { fclose(state->pass1_file); state->pass1_file = NULL; return(-1); } if(c == '\n') n++; }while(n < 2); /* Save position for future use */ pos_firstframe = ftell(state->pass1_file); /* Read and initialize some variables */ credits1_bytes = credits2_bytes = 0; total_bytes = itotal_bytes = 0; start_curved = end_curved = 0; credits_frames = 0; for(state->cur_frame = c = 0; state->cur_frame<state->nb_frames; state->cur_frame++) { int quant, keyframe, frame_hbytes, frame_bytes; int kblocks, mblocks, ublocks; fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", &quant, &keyframe, &frame_hbytes, &frame_bytes, &kblocks, &mblocks, &ublocks); /* Is the frame in the beginning credits */ if(util_frametype(state) == FRAME_TYPE_STARTING_CREDITS) { credits1_bytes += frame_bytes; credits_frames++; continue; } /* Is the frame in the eding credits */ if(util_frametype(state) == FRAME_TYPE_ENDING_CREDITS) { credits2_bytes += frame_bytes; credits_frames++; continue; } /* We only care about Keyframes when not in credits */ if(keyframe) { itotal_bytes += frame_bytes + frame_bytes * state->keyframe_boost / 100; total_bytes += frame_bytes * state->keyframe_boost / 100; state->keyframe_locations[c++] = state->cur_frame; } total_bytes += frame_bytes; } /* * Last frame is treated like an I Frame so we can dispatch overflow * all other the last film segment */ state->keyframe_locations[c] = state->cur_frame; desired = state->desired_size; switch(state->credits_mode) { case VBR_CREDITS_MODE_QUANT : state->movie_curve = (double) (total_bytes - credits1_bytes - credits2_bytes) / (desired - credits1_bytes - credits2_bytes); start_curved = credits1_bytes; end_curved = credits2_bytes; break; case VBR_CREDITS_MODE_SIZE: /* start curve = (start / start desired size) */ state->credits_start_curve = (double) (credits1_bytes / state->credits_start_size); /* end curve = (end / end desired size) */ state->credits_end_curve = (double) (credits2_bytes / state->credits_end_size); start_curved = (long long) (credits1_bytes / state->credits_start_curve); end_curved = (long long) (credits2_bytes / state->credits_end_curve); /* movie curve=(total-credits)/(desired_size-curved credits) */ state->movie_curve = (double) (total_bytes - credits1_bytes - credits2_bytes) / (desired - start_curved - end_curved); break; case VBR_CREDITS_MODE_RATE: default: /* credits curve = (total/desired_size)*(100/credits_rate) */ state->credits_start_curve = state->credits_end_curve = ((double)total_bytes / desired) * ((double)100 / state->credits_quant_ratio); start_curved = (long long)(credits1_bytes/state->credits_start_curve); end_curved = (long long)(credits2_bytes/state->credits_end_curve); state->movie_curve = (double) (total_bytes - credits1_bytes - credits2_bytes) / (desired - start_curved - end_curved); break; } /* * average frame size = (desired - curved credits - curved keyframes) / * (frames - credits frames - keyframes) */ state->average_frame = (double) (desired - start_curved - end_curved - (itotal_bytes / state->movie_curve)) / (state->nb_frames - util_creditsframes(state) - state->nb_keyframes); /* Initialize alt curve parameters */ if (state->use_alt_curve) { state->alt_curve_low = state->average_frame - state->average_frame * (double)(state->alt_curve_low_dist / 100.0); state->alt_curve_low_diff = state->average_frame - state->alt_curve_low; state->alt_curve_high = state->average_frame + state->average_frame * (double)(state->alt_curve_high_dist / 100.0); state->alt_curve_high_diff = state->alt_curve_high - state->average_frame; if (state->alt_curve_use_auto) { if (state->movie_curve > 1.0) { state->alt_curve_min_rel_qual = (int)(100.0 - (100.0 - 100.0 / state->movie_curve) * (double)state->alt_curve_auto_str / 100.0); if (state->alt_curve_min_rel_qual < 20) state->alt_curve_min_rel_qual = 20; } else { state->alt_curve_min_rel_qual = 100; } } state->alt_curve_mid_qual = (1.0 + (double)state->alt_curve_min_rel_qual / 100.0) / 2.0; state->alt_curve_qual_dev = 1.0 - state->alt_curve_mid_qual; if (state->alt_curve_low_dist > 100) { switch(state->alt_curve_type) { case VBR_ALT_CURVE_AGGRESIVE: /* Sine Curve (high aggressiveness) */ state->alt_curve_qual_dev *= 2.0 / (1.0 + sin(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff))); state->alt_curve_mid_qual = 1.0 - state->alt_curve_qual_dev * sin(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff)); break; default: case VBR_ALT_CURVE_LINEAR: /* Linear (medium aggressiveness) */ state->alt_curve_qual_dev *= 2.0 / (1.0 + state->average_frame / state->alt_curve_low_diff); state->alt_curve_mid_qual = 1.0 - state->alt_curve_qual_dev * state->average_frame / state->alt_curve_low_diff; break; case VBR_ALT_CURVE_SOFT: /* Cosine Curve (low aggressiveness) */ state->alt_curve_qual_dev *= 2.0 / (1.0 + (1.0 - cos(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff)))); state->alt_curve_mid_qual = 1.0 - state->alt_curve_qual_dev * (1.0 - cos(DEG2RAD * (state->average_frame * 90.0 / state->alt_curve_low_diff))); break; } } } /* Go to the first non credits frame stats line into file */ fseek(state->pass1_file, pos_firstframe, SEEK_SET); /* Perform prepass to compensate for over/undersizing */ total1 = total2 = 0.0; for(state->cur_frame=0; state->cur_frame<state->nb_frames; state->cur_frame++) { int quant, keyframe, frame_hbytes, frame_bytes; int kblocks, mblocks, ublocks; fscanf(state->pass1_file, "%d %d %d %d %d %d %d\n", &quant, &keyframe, &frame_hbytes, &frame_bytes, &kblocks, &mblocks, &ublocks); if(util_frametype(state) != FRAME_TYPE_NORMAL_MOVIE) continue; if(!keyframe) { double dbytes = frame_bytes / state->movie_curve; total1 += dbytes; if (state->use_alt_curve) { if (dbytes > state->average_frame) { if (dbytes >= state->alt_curve_high) { total2 += dbytes * (state->alt_curve_mid_qual - state->alt_curve_qual_dev); } else { switch(state->alt_curve_type) { case VBR_ALT_CURVE_AGGRESIVE: total2 += 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: total2 += 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: total2 += 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) { total2 += dbytes; } else { switch(state->alt_curve_type) { case VBR_ALT_CURVE_AGGRESIVE: total2 += 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: total2 += 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: total2 += 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)))); } } } } else { if (dbytes > state->average_frame) { total2 += ((double)dbytes + (state->average_frame - dbytes) * state->curve_compression_high / 100.0); } else { total2 += ((double)dbytes + (state->average_frame - dbytes) * state->curve_compression_low / 100.0); } } } } state->curve_comp_scale = total1 / total2; if (state->use_alt_curve) { double curve_temp, dbytes; int newquant, percent; int oldquant = 1; if (state->alt_curve_use_auto_bonus_bias) state->alt_curve_bonus_bias = state->alt_curve_min_rel_qual; state->curve_bias_bonus = (total1 - total2) * (double)state->alt_curve_bonus_bias / (100.0 * (double)(state->nb_frames - util_creditsframes(state) - state->nb_keyframes)); state->curve_comp_scale = ((total1 - total2) * (1.0 - (double)state->alt_curve_bonus_bias / 100.0) + total2) / total2; for (n=1; n <= (int)(state->alt_curve_high*2) + 1; n++) { dbytes = n; 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)))); } } } if (state->movie_curve > 1.0) dbytes *= state->movie_curve; newquant = (int)(dbytes * 2.0 / (curve_temp * state->curve_comp_scale + state->curve_bias_bonus)); if (newquant > 1) { if (newquant != oldquant)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -