📄 xvid_vbr.c
字号:
/****************************************************************************** * * XviD VBR Library * * Copyright (C) 2002 Edouard Gomez <ed.gomez@wanadoo.fr> * * The curve treatment algorithm is based on work done by Foxer <email?> and * Dirk Knop <dknop@gwdg.de> for the XviD vfw dynamic library. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * *****************************************************************************//* Standard Headers */#include <stdio.h>#include <string.h>#include <fcntl.h>#include <stdlib.h>#include <math.h>/* Local headers */#include "xvid_vbr.h"/****************************************************************************** * Build time constants *****************************************************************************//* * Portability note * Perhaps the msvc headers define Pi with another constant name */#define DEG2RAD (M_PI / 180.0)/* Defaults settings will be computed with the help of these constants */#define DEFAULT_DESIRED_SIZE 700#define DEFAULT_AUDIO_BITRATE 128#define DEFAULT_MOVIE_LENGTH 2#define DEFAULT_TWOPASS_BOOST 1000#define DEFAULT_FPS 25.0f#define DEFAULT_CREDITS_SIZE 0#define DEFAULT_XVID_DBG_FILE "xvid.dbg"#define DEFAULT_XVID_STATS_FILE "xvid.stats"/****************************************************************************** * Local prototypes *****************************************************************************//* Sub vbrInit cases functions */static vbr_init_function vbr_init_dummy;static vbr_init_function vbr_init_2pass1;static vbr_init_function vbr_init_2pass2;static vbr_init_function vbr_init_fixedquant;/* Sub vbrGetQuant cases functions */static vbr_get_quant_function vbr_getquant_1pass;static vbr_get_quant_function vbr_getquant_2pass1;static vbr_get_quant_function vbr_getquant_2pass2;static vbr_get_quant_function vbr_getquant_fixedquant;/* Sub vbrGetIntra cases functions */static vbr_get_intra_function vbr_getintra_1pass;static vbr_get_intra_function vbr_getintra_2pass1;static vbr_get_intra_function vbr_getintra_2pass2;static vbr_get_intra_function vbr_getintra_fixedquant;/* Sub vbrUpdate prototypes */static vbr_update_function vbr_update_dummy;static vbr_update_function vbr_update_2pass1;static vbr_update_function vbr_update_2pass2;/* Sub vbrFinish cases functions */static vbr_finish_function vbr_finish_dummy;static vbr_finish_function vbr_finish_2pass1;static vbr_finish_function vbr_finish_2pass2;/* Is the encoder in the credits */#define FRAME_TYPE_NORMAL_MOVIE 0x00#define FRAME_TYPE_STARTING_CREDITS 0x01#define FRAME_TYPE_ENDING_CREDITS 0x02/****************************************************************************** * Inline utility functions *****************************************************************************/static __inline int util_frametype(vbr_control_t *state){ if(state->credits_start) { if(state->cur_frame >= state->credits_start_begin && state->cur_frame < state->credits_start_end) return(FRAME_TYPE_STARTING_CREDITS); } if(state->credits_end) { if(state->cur_frame >= state->credits_end_begin && state->cur_frame < state->credits_end_end) return(FRAME_TYPE_ENDING_CREDITS); } return(FRAME_TYPE_NORMAL_MOVIE);}static __inline int util_creditsframes(vbr_control_t *state){ int frames = 0; if(state->credits_start) frames += state->credits_start_end - state->credits_start_begin; if(state->credits_end) frames += state->credits_end_end - state->credits_end_begin; return(frames);}/****************************************************************************** * Functions *****************************************************************************//***************************************************************************** * Function description : * * This function initialiazes the vbr_control_t with safe defaults for all * modes. * * Return Values : * = 0 ****************************************************************************/int vbrSetDefaults(vbr_control_t *state){ /* Set all the structure to zero */ memset(state, 0, sizeof(state)); /* Default mode is CBR */ state->mode = VBR_MODE_1PASS; /* Default statistic filename */ state->filename = DEFAULT_XVID_STATS_FILE; /* * Default is a 2hour movie on 700Mo CD-ROM + 128kbit sound track * This represents a target bitrate of 687kbit/s */ state->desired_size = DEFAULT_DESIRED_SIZE*1024*1024 - DEFAULT_MOVIE_LENGTH*3600*DEFAULT_AUDIO_BITRATE*1000/8; state->desired_bitrate = state->desired_size*8/(DEFAULT_MOVIE_LENGTH*3600); /* Credits */ state->credits_mode = VBR_CREDITS_MODE_RATE; state->credits_start = 0; state->credits_start_begin = 0; state->credits_start_end = 0; state->credits_end = 0; state->credits_end_begin = 0; state->credits_end_end = 0; state->credits_quant_ratio = 20; state->credits_fixed_quant = 20; state->credits_quant_i = 20; state->credits_quant_p = 20; state->credits_start_size = DEFAULT_CREDITS_SIZE*1024*1024; state->credits_end_size = DEFAULT_CREDITS_SIZE*1024*1024; /* Keyframe boost */ state->keyframe_boost = 0; state->kftreshold = 10; state->kfreduction = 30; state->min_key_interval = 1; state->max_key_interval = (int)DEFAULT_FPS*10; /* Normal curve treatment */ state->curve_compression_high = 25; state->curve_compression_low = 10; /* Alt curve */ state->use_alt_curve = 1; state->alt_curve_type = VBR_ALT_CURVE_LINEAR; state->alt_curve_low_dist = 90; state->alt_curve_high_dist = 500; state->alt_curve_min_rel_qual = 50; state->alt_curve_use_auto = 1; state->alt_curve_auto_str = 30; state->alt_curve_use_auto_bonus_bias = 1; state->alt_curve_bonus_bias = 50; state->bitrate_payback_method = VBR_PAYBACK_BIAS; state->bitrate_payback_delay = 250; state->twopass_max_bitrate = DEFAULT_TWOPASS_BOOST*state->desired_bitrate; state->twopass_max_overflow_improvement = 60; state->twopass_max_overflow_degradation = 60; state->max_iquant = 31; state->min_iquant = 2; state->max_pquant = 31; state->min_pquant = 2; state->fixed_quant = 3; state->max_framesize = (1.0/(float)DEFAULT_FPS) * state->twopass_max_bitrate / 8; state->fps = (float)DEFAULT_FPS; return(0);}/***************************************************************************** * Function description : * * This function initialiaze the vbr_control_t state passed in parameter. * * The initialization depends on state->mode, there are 4 modes allowed. * Each mode description is done in the README file shipped with the lib. * * Return values : * * = 0 on success * = -1 on error *****************************************************************************/int vbrInit(vbr_control_t *state){ if(state == NULL) return(-1); /* Function pointers safe initialization */ state->init = NULL; state->getquant = NULL; state->getintra = NULL; state->update = NULL; state->finish = NULL; if(state->debug) { state->debug_file = fopen(DEFAULT_XVID_DBG_FILE, "w+"); if(state->debug_file == NULL) return(-1); fprintf(state->debug_file, "# XviD Debug output\n"); fprintf(state->debug_file, "# quant | intra | header bytes" "| total bytes | kblocks | mblocks | ublocks" "| vbr overflow | vbr kf overflow" "| vbr kf partial overflow\n\n"); } /* Function pointers sub case initialization */ switch(state->mode) { case VBR_MODE_1PASS: state->init = vbr_init_dummy; state->getquant = vbr_getquant_1pass; state->getintra = vbr_getintra_1pass; state->update = vbr_update_dummy; state->finish = vbr_finish_dummy; break; case VBR_MODE_2PASS_1: state->init = vbr_init_2pass1; state->getquant = vbr_getquant_2pass1; state->getintra = vbr_getintra_2pass1; state->update = vbr_update_2pass1; state->finish = vbr_finish_2pass1; break; case VBR_MODE_FIXED_QUANT: state->init = vbr_init_fixedquant; state->getquant = vbr_getquant_fixedquant; state->getintra = vbr_getintra_fixedquant; state->update = vbr_update_dummy; state->finish = vbr_finish_dummy; break; case VBR_MODE_2PASS_2: state->init = vbr_init_2pass2; state->getintra = vbr_getintra_2pass2; state->getquant = vbr_getquant_2pass2; state->update = vbr_update_2pass2; state->finish = vbr_finish_2pass2; break; default: return(-1); } return(state->init(state));}/****************************************************************************** * Function description : * * This function returns an adapted quantizer according to the current vbr * controler state * * Return values : * the quantizer value (0 <= value <= 31) * (0 is a special case, means : let XviD decide) * *****************************************************************************/int vbrGetQuant(vbr_control_t *state){ /* Returns Zero, so XviD decides alone */ if(state == NULL || state->getquant == NULL) return(0); return(state->getquant(state));}/****************************************************************************** * Function description : * * This function returns the type of the frame to be encoded next (I or P/B) * * Return values : * = -1 let the XviD encoder decide wether or not the next frame is I * = 0 no I frame * = 1 force keyframe * *****************************************************************************/int vbrGetIntra(vbr_control_t *state){ /* Returns -1, means let XviD decide */ if(state == NULL || state->getintra == NULL) return(-1); return(state->getintra(state));}/****************************************************************************** * Function description : * * This function updates the vbr control state according to collected statistics * from XviD core * * Return values : * * = 0 on success * = -1 on error *****************************************************************************/int vbrUpdate(vbr_control_t *state, int quant, int intra, int header_bytes, int total_bytes, int kblocks, int mblocks, int ublocks){ if(state == NULL || state->update == NULL) return(-1); if(state->debug && state->debug_file != NULL) { int idx; fprintf(state->debug_file, "%d %d %d %d %d %d %d %d %d %d\n", quant, intra, header_bytes, total_bytes, kblocks, mblocks, ublocks, state->overflow, state->KFoverflow, state->KFoverflow_partial); idx = quant; if(quant < 1) idx = 1; if(quant > 31) idx = 31; idx--; state->debug_quant_count[idx]++; } return(state->update(state, quant, intra, header_bytes, total_bytes, kblocks, mblocks, ublocks));}/****************************************************************************** * Function description : * * This function stops the vbr controller * * Return values : * * = 0 on success * = -1 on error *****************************************************************************/int vbrFinish(vbr_control_t *state){ if(state == NULL || state->finish == NULL) return(-1); if(state->debug && state->debug_file != NULL) { int i; fprintf(state->debug_file, "\n\n"); for(i=0; i<79; i++) fprintf(state->debug_file, "#"); fprintf(state->debug_file, "\n# Quantizer distribution :\n\n"); for(i=0;i<32; i++) { fprintf(state->debug_file, "# quant %d : %d\n", i+1, state->debug_quant_count[i]); } fclose(state->debug_file); } return(state->finish(state));}/****************************************************************************** * Dummy functions - Used when a mode does not need such a function *****************************************************************************/static int vbr_init_dummy(void *sstate){ vbr_control_t *state = sstate; state->cur_frame = 0; return(0);}static int vbr_update_dummy(void *state, int quant, int intra, int header_bytes, int total_bytes, int kblocks, int mblocks, int ublocks){ ((vbr_control_t*)state)->cur_frame++; return(0);}static int vbr_finish_dummy(void *state){ return(0);}/****************************************************************************** * 1 pass mode - XviD will do its job alone. *****************************************************************************/static int vbr_getquant_1pass(void *state){ return(0);}static int vbr_getintra_1pass(void *state){ return(-1);}/****************************************************************************** * 2 pass mode - first pass functions *****************************************************************************/static int vbr_init_2pass1(void *sstate){ FILE *f; vbr_control_t *state = sstate; /* Check the filename */ if(state->filename == NULL || state->filename[0] == '\0') return(-1); /* Initialize safe defaults for 2pass 1 */ state->pass1_file = NULL; state->nb_frames = 0; state->nb_keyframes = 0; state->cur_frame = 0; /* Open the 1st pass file */ if((f = fopen(state->filename, "w+")) == NULL) return(-1); /* * The File Header * * The extra white spaces will be used during the vbrFinish to write * the resulting number of frames and keyframes (10 spaces == maximum * string length of an int on 32bit machines, i don't think anyone is * encoding more than 4 billion frames :-) */ fprintf(f, "# ASCII XviD vbr stat file version %d\n#\n", VBR_VERSION); fprintf(f, "# frames : \n"); fprintf(f, "# keyframes : \n"); fprintf(f, "#\n# quant | intra | header bytes | total bytes | kblocks |" " mblocks | ublocks\n\n"); /* Save file pointer */ state->pass1_file = f; return(0);}static int vbr_getquant_2pass1(void *state){ return(2);}static int vbr_getintra_2pass1(void *state){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -