📄 fame_rate_1param.c
字号:
/* libfame - Fast Assembly MPEG Encoder Library Copyright (C) 2002 Yannick Vignon This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.*/#include <stdio.h>#include <stdlib.h>#include <math.h>#include "fame.h"#include "fame_rate_1param.h"#include "fame_monitor.h"#define model_power 1.7#define power(x,y) (exp(y*log(x)))#define quant_model(coeff, rate, act) (exp(1.0/model_power*log(coeff*act/rate)))#define coeff_model(quant, rate, act) (exp(model_power*log(quant))*rate/act)static void rate_init(fame_rate_t *rate, int mb_width, int mb_height, int bitrate, char *coding, fame_frame_statistics_t *stats_list, fame_global_statistics_t *global_stats, unsigned int flags);static void rate_enter(fame_rate_t *rate, fame_yuv_t **ref, fame_yuv_t *current, unsigned char *shape, char coding, fame_frame_statistics_t *frame_stats);static void rate_leave(fame_rate_t *rate, int spent);FAME_CONSTRUCTOR(fame_rate_1param_t){ fame_rate_t_constructor(FAME_RATE(this)); FAME_OBJECT(this)->name = "one parameter rate estimation"; this->FAME_OVERLOADED(init) = FAME_RATE(this)->init; FAME_RATE(this)->init = rate_init; this->FAME_OVERLOADED(enter) = FAME_RATE(this)->enter; FAME_RATE(this)->enter = rate_enter; this->FAME_OVERLOADED(leave) = FAME_RATE(this)->leave; FAME_RATE(this)->leave = rate_leave; FAME_RATE(this)->flags = 0xffffffff; return(this);}/* rate_init *//* *//* Description: *//* Initialise rate estimation. *//* *//* Arguments: *//* fame_rate_t *rate: the rate estimation *//* int mb_width: width in macroblocks *//* int mb_height: height in macroblocks *//* *//* Return value: *//* Rate. */static void rate_init(fame_rate_t *rate, int mb_width, int mb_height, int bitrate, char *coding, fame_frame_statistics_t *stats_list, fame_global_statistics_t *global_stats, unsigned int flags){ int ni, np; float ratio; int i; float factor;#ifdef HAS_MMX asm("emms");#endif FAME_RATE_1PARAM(rate)->FAME_OVERLOADED(init)(rate, mb_width, mb_height, bitrate, coding, stats_list, global_stats, flags); if (rate->flags & FAME_RATE_SECOND_PASS) { rate->stats_list = stats_list; factor = 0; ni = np = 0; rate->total_frames= global_stats->total_frames; for (i=0; i < global_stats->total_frames; i++) { if(stats_list[i].spatial_activity) factor += exp(FAME_RATE_2PASS_POWER*log(stats_list[i].spatial_activity)); if(stats_list[i].coding == 'I') ni++; if(stats_list[i].coding == 'P') np++; } ratio = 1; /* change to allocate more bits for scene changes */ FAME_RATE_1PARAM(rate)->global_factor_P = (factor/(bitrate*global_stats->total_frames)) * (np + ratio*ni) / (float)(ni + np); FAME_RATE_1PARAM(rate)->global_factor_I = FAME_RATE_1PARAM(rate)->global_factor_P / ratio; } else { ni = np = 0; for(i = 0; i < strlen(coding); i++) { switch(coding[i]) { case 'I': ni++; break; case 'P': np++; break; case 'A': np++; break; } } ratio = 1; FAME_RATE_1PARAM(rate)->P_bits = bitrate * (np + ni) / (np + ratio * ni); FAME_RATE_1PARAM(rate)->I_bits = ratio * FAME_RATE_1PARAM(rate)->P_bits; } rate->coeff1 = 1.5; rate->coeff2 = 2.75; FAME_RATE_1PARAM(rate)->coeff_index = 0; FAME_RATE_1PARAM(rate)->coeff_I_index = 0; FAME_RATE_1PARAM(rate)->I_number = 0; FAME_RATE_1PARAM(rate)->P_number = 0;}/* rate_enter *//* *//* Description: *//* Prepare for a new frame. *//* *//* Arguments: *//* fame_rate_t *rate: the rate estimation *//* fame_yuv_t **ref: the reference frames (half-pel) *//* fame_yuv_t *current: the current frame *//* unsigned char *shape: the current shape *//* *//* Return value: *//* Rate. */static void rate_enter(struct _fame_rate_t_ *rate, fame_yuv_t **ref, fame_yuv_t *current, unsigned char *shape, char coding, fame_frame_statistics_t *frame_stats){ int avail, old_scale, old_coding; int i, window; float coeff1;#ifdef HAS_MMX asm("emms");#endif /* Update number of available bits */ if (rate->flags & FAME_RATE_SECOND_PASS) { if (rate->available > 0) avail = rate->available/4; else avail = 5*rate->available/6; switch(coding) { case 'I': rate->available += exp(FAME_RATE_2PASS_POWER*log(frame_stats->spatial_activity))/FAME_RATE_1PARAM(rate)->global_factor_I; case 'P': rate->available += exp(FAME_RATE_2PASS_POWER*log(frame_stats->spatial_activity))/FAME_RATE_1PARAM(rate)->global_factor_P; } } else { avail = rate->available/2; switch(coding) { case 'I': rate->available += FAME_RATE_1PARAM(rate)->I_bits; break; case 'P': rate->available += FAME_RATE_1PARAM(rate)->P_bits; break; }; } rate->available -= avail; old_coding = rate->coding; /* Common tasks */ FAME_RATE_1PARAM(rate)->FAME_OVERLOADED(enter)(rate, ref, current, shape, coding, frame_stats); /* compute frame activity */ switch (rate->coding) { case 'I': FAME_RATE_1PARAM(rate)->activity = activity(rate->current, rate->shape, rate->mb_width, rate->mb_height);#ifdef HAS_MMX asm("emms");#endif break; case 'P': if (frame_stats) FAME_RATE_1PARAM(rate)->activity = frame_stats->spatial_activity; else FAME_RATE_1PARAM(rate)->activity = activity2(rate->ref[0], rate->current, rate->shape, rate->mb_width, rate->mb_height); break; } /* Update model parameter */ /* TODO: update window size based on activity change */ coeff1 = 0; window = 0; switch (rate->coding) { case 'I' : window = fame_min(FAME_RATE_WINDOW_SIZE, FAME_RATE_1PARAM(rate)->I_number); for(i=0; i<window; i++) coeff1 += FAME_RATE_1PARAM(rate)->old_I_coeff1[i]; if (window == 0) coeff1 = rate->coeff2; rate->coeff2 = coeff1; FAME_RATE_1PARAM(rate)->P_number = 0; break; case 'P' : window = fame_min(FAME_RATE_WINDOW_SIZE, FAME_RATE_1PARAM(rate)->P_number); for(i=0; i<window; i++) coeff1 += FAME_RATE_1PARAM(rate)->old_coeff1[i]; if (window == 0) coeff1 = rate->coeff1; rate->coeff1 = coeff1; break; } if (window != 0) coeff1 = coeff1/window; /* Compute quantization scale */ old_scale = rate->global_scale; if (rate->available > 0) { rate->global_scale =quant_model(coeff1, rate->available, FAME_RATE_1PARAM(rate)->activity); } else rate->global_scale = 31; if(rate->coding == old_coding) { /* adaptive quant scale variation */ if(rate->global_scale > old_scale+FAME_RATE_WINDOW_SIZE-window+2) rate->global_scale = old_scale+FAME_RATE_WINDOW_SIZE-window+2; if(rate->global_scale < old_scale-FAME_RATE_WINDOW_SIZE+window-2) rate->global_scale = old_scale-FAME_RATE_WINDOW_SIZE+window-2; } //rate->global_scale = (rate->global_scale + old_scale)/2; if( rate->global_scale < 2) rate->global_scale = 2; if( rate->global_scale > 31) rate->global_scale = 31; rate->available += avail; }/* rate_leave *//* *//* Description: *//* Finish estimating a frame. *//* *//* Arguments: *//* fame_rate_t *rate: the rate estimation *//* *//* Return value: *//* Rate. */static void rate_leave(fame_rate_t *rate, int spent){ #ifdef HAS_MMX asm("emms");#endif FAME_RATE_1PARAM(rate)->FAME_OVERLOADED(leave)(rate, spent); switch(rate->coding) { case 'I' : FAME_RATE_1PARAM(rate)->old_I_coeff1[FAME_RATE_1PARAM(rate)->coeff_I_index] = coeff_model(rate->global_scale, spent, FAME_RATE_1PARAM(rate)->activity); FAME_RATE_1PARAM(rate)->coeff_I_index++; if (FAME_RATE_1PARAM(rate)->coeff_I_index >= FAME_RATE_WINDOW_SIZE) FAME_RATE_1PARAM(rate)->coeff_I_index = 0; FAME_RATE_1PARAM(rate)->I_number++; break; case 'P': FAME_RATE_1PARAM(rate)->old_coeff1[FAME_RATE_1PARAM(rate)->coeff_index] = coeff_model(rate->global_scale, spent, FAME_RATE_1PARAM(rate)->activity); FAME_RATE_1PARAM(rate)->coeff_index++; if (FAME_RATE_1PARAM(rate)->coeff_index >= FAME_RATE_WINDOW_SIZE) FAME_RATE_1PARAM(rate)->coeff_index = 0; FAME_RATE_1PARAM(rate)->P_number++; break; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -