1 /*
2     libfame - Fast Assembly MPEG Encoder Library
3     Copyright (C) 2002 Yannick Vignon
4 
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9 
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14 
15     You should have received a copy of the GNU Library General Public
16     License along with this library; if not, write to the Free
17     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>	/* strlen() */
23 #include <math.h>
24 #include "fame.h"
25 #include "fame_rate_simple.h"
26 #include "fame_monitor.h"
27 
28 #define power(x,y) (exp(y*log(x)))
29 #define quant_model(coeff, rate, act) (coeff*act/rate)
30 #define coeff_model(quant, rate, act) (quant*rate/act)
31 
32 static void rate_init(fame_rate_t *rate,
33 		      int mb_width,
34 		      int mb_height,
35 		      int bitrate,
36 		      char *coding,
37 		      fame_frame_statistics_t *stats_list,
38 		      fame_global_statistics_t *global_stats,
39 		      unsigned int flags);
40 static void rate_enter(fame_rate_t *rate,
41 		       fame_yuv_t **ref,
42 		       fame_yuv_t *current,
43 		       unsigned char *shape,
44 		       char coding,
45 		       fame_frame_statistics_t *frame_stats);
46 static void rate_leave(fame_rate_t *rate,
47 		       int spent);
48 
FAME_CONSTRUCTOR(fame_rate_simple_t)49 FAME_CONSTRUCTOR(fame_rate_simple_t)
50 {
51   fame_rate_t_constructor(FAME_RATE(this));
52   FAME_OBJECT(this)->name = "simple rate estimation";
53 
54   this->FAME_OVERLOADED(init) = FAME_RATE(this)->init;
55   FAME_RATE(this)->init = rate_init;
56   this->FAME_OVERLOADED(enter) = FAME_RATE(this)->enter;
57   FAME_RATE(this)->enter = rate_enter;
58   this->FAME_OVERLOADED(leave) = FAME_RATE(this)->leave;
59   FAME_RATE(this)->leave = rate_leave;
60 
61   FAME_RATE(this)->flags = 0xffffffff;
62   return(this);
63 }
64 
65 /*  rate_init                                                                */
66 /*                                                                           */
67 /*  Description:                                                             */
68 /*    Initialise rate estimation.                                            */
69 /*                                                                           */
70 /*  Arguments:                                                               */
71 /*    fame_rate_t *rate: the rate estimation                                 */
72 /*    int mb_width: width in macroblocks                                     */
73 /*    int mb_height: height in macroblocks                                   */
74 /*                                                                           */
75 /*  Return value:                                                            */
76 /*    Rate.                                                                  */
77 
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)78 static void rate_init(fame_rate_t *rate,
79 		      int mb_width,
80 		      int mb_height,
81 		      int bitrate,
82 		      char *coding,
83 		      fame_frame_statistics_t *stats_list,
84 		      fame_global_statistics_t *global_stats,
85 		      unsigned int flags)
86 {
87   int ni, np;
88   int ratio;
89   int i;
90 
91 #ifdef HAS_MMX
92   asm("emms");
93 #endif
94 
95   FAME_RATE_SIMPLE(rate)->FAME_OVERLOADED(init)(rate,
96 					       mb_width,
97 					       mb_height,
98 					       bitrate,
99 					       coding,
100 					       stats_list,
101 					       global_stats,
102 					       flags);
103 
104   ni = np = 0;
105   for(i = 0; i < strlen(coding); i++) {
106     switch(coding[i]) {
107     case 'I': ni++; break;
108     case 'P': np++; break;
109     case 'A': np++; break;
110     }
111   }
112 
113   ratio = 1;
114   FAME_RATE_SIMPLE(rate)->P_bits = bitrate * (np + ni) / (np + ratio * ni);
115   FAME_RATE_SIMPLE(rate)->I_bits = ratio * FAME_RATE_SIMPLE(rate)->P_bits;
116 
117   rate->coeff1 = 1/6.0;
118   FAME_RATE_SIMPLE(rate)->I_coeff1 = 1;
119 }
120 
121 
122 /*  rate_enter                                                               */
123 /*                                                                           */
124 /*  Description:                                                             */
125 /*    Prepare for a new frame.                                               */
126 /*                                                                           */
127 /*  Arguments:                                                               */
128 /*    fame_rate_t *rate: the rate estimation                                 */
129 /*    fame_yuv_t **ref: the reference frames (half-pel)                      */
130 /*    fame_yuv_t *current: the current frame                                 */
131 /*    unsigned char *shape: the current shape                                */
132 /*                                                                           */
133 /*  Return value:                                                            */
134 /*    Rate.                                                                  */
135 
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)136 static void rate_enter(struct _fame_rate_t_ *rate,
137 		       fame_yuv_t **ref,
138 		       fame_yuv_t *current,
139 		       unsigned char *shape,
140 		       char coding,
141 		       fame_frame_statistics_t *frame_stats)
142 {
143   int old_scale;
144 
145 #ifdef HAS_MMX
146   asm("emms");
147 #endif
148 
149 
150   /* Update number of available bits */
151     switch(coding) {
152     case 'I': rate->available += FAME_RATE_SIMPLE(rate)->I_bits; break;
153     case 'P': rate->available += FAME_RATE_SIMPLE(rate)->P_bits; break;
154     };
155 
156 
157   /* Common tasks */
158   FAME_RATE_SIMPLE(rate)->FAME_OVERLOADED(enter)(rate,
159 						ref,
160 						current,
161 						shape,
162 						coding,
163 						frame_stats);
164 
165 
166   /* compute frame activity */
167   if (frame_stats)
168     FAME_RATE_SIMPLE(rate)->activity = frame_stats->spatial_activity;
169   else FAME_RATE_SIMPLE(rate)->activity = activity2(rate->ref[0],
170 						    rate->current,
171 						    rate->shape,
172 						    rate->mb_width,
173 						    rate->mb_height);
174 
175 
176   /* Compute quantization scale */
177   old_scale = rate->global_scale;
178   if (rate->available > 0) {
179     switch (coding) {
180     case 'I':
181      rate->global_scale = quant_model(FAME_RATE_SIMPLE(rate)->I_coeff1,
182 				      rate->available,
183 				      FAME_RATE_SIMPLE(rate)->activity);
184      break;
185     case 'P':
186      rate->global_scale = quant_model(rate->coeff1,
187 				      rate->available,
188 				      FAME_RATE_SIMPLE(rate)->activity);
189      break;
190     }
191   }
192   else
193     rate->global_scale = 31;
194 
195 
196   if( rate->global_scale < 2)  rate->global_scale = 2;
197   if( rate->global_scale > 31)  rate->global_scale = 31;
198   rate->global_scale = (rate->global_scale + old_scale)/2;
199 }
200 
201 /*  rate_leave                                                               */
202 /*                                                                           */
203 /*  Description:                                                             */
204 /*    Finish estimating a frame.                                             */
205 /*                                                                           */
206 /*  Arguments:                                                               */
207 /*    fame_rate_t *rate: the rate estimation                                 */
208 /*                                                                           */
209 /*  Return value:                                                            */
210 /*    Rate.                                                                  */
211 
rate_leave(fame_rate_t * rate,int spent)212 static void rate_leave(fame_rate_t *rate, int spent)
213 {
214 #ifdef HAS_MMX
215   asm("emms");
216 #endif
217 
218   FAME_RATE_SIMPLE(rate)->FAME_OVERLOADED(leave)(rate,
219 						 spent);
220 
221   switch(rate->coding) {
222   case 'I' :
223     FAME_RATE_SIMPLE(rate)->I_coeff1 =
224       coeff_model(rate->global_scale,
225 		  spent,
226 		  FAME_RATE_SIMPLE(rate)->activity);
227     break;
228   case 'P':
229     rate->coeff1 =
230       coeff_model(rate->global_scale,
231 		  spent,
232 		  FAME_RATE_SIMPLE(rate)->activity);
233     break;
234   }
235 }
236 
237 
238 
239 
240 
241 
242 
243 
244 
245 
246 
247 
248 
249 
250 
251