[cvs] / xvidcore / src / plugins / plugin_fixed.c Repository:
ViewVC logotype

Annotation of /xvidcore/src/plugins/plugin_fixed.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (view) (download)

1 : edgomez 1.2 /*****************************************************************************
2 :     *
3 :     * XviD VBR Library
4 :     * - Fixed quantizer controller implementation / Deprecated code -
5 :     *
6 :     * Copyright (C) 2002-2003 Edouard Gomez <ed.gomez@free.fr>
7 :     *
8 :     * This program is free software; you can redistribute it and/or modify
9 :     * it under the terms of the GNU General Public License as published by
10 :     * the Free Software Foundation; either version 2 of the License, or
11 :     * (at your option) any later version.
12 :     *
13 :     * This program is distributed in the hope that it will be useful,
14 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 :     * GNU General Public License for more details.
17 :     *
18 :     * You should have received a copy of the GNU General Public License
19 :     * along with this program; if not, write to the Free Software
20 :     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 :     *
22 :     * $Id$
23 :     *
24 :     ****************************************************************************/
25 :    
26 :    
27 :     #include "../xvid.h"
28 :     #include "../image/image.h"
29 :    
30 :    
31 :     typedef struct
32 :     {
33 :     int32_t quant_increment;
34 :     int32_t quant_base;
35 :    
36 :     /* Number of quantizers in the *quant distribution */
37 :     int nquant;
38 :    
39 :     /* Quantizer distribution */
40 :     int *quant;
41 :     } rc_fixed_t;
42 :    
43 :    
44 :     static int gcd(int a, int b)
45 :     {
46 :     int r;
47 :    
48 :     while(b) {
49 :     r = a % b;
50 :     a = b;
51 :     b = r;
52 :     }
53 :    
54 :     return(a);
55 :     }
56 :    
57 :    
58 :     static int
59 :     distribute_quants(int **quants, int lquant, int n_lquant, int n_hquant)
60 :     {
61 :    
62 :     int i, n, _gcd;
63 :     int nlow, nhigh;
64 :     int low, high;
65 :     int q, r;
66 :     int a,b,min, max;
67 :     int m, M;
68 :     int *dist;
69 :    
70 :     /* Low quant */
71 :     low = lquant;
72 :    
73 :     /* High quant is just low quant + 1 */
74 :     high = low + 1;
75 :    
76 :     /* How much low quants we have to distribute */
77 :     nlow = n_lquant;
78 :    
79 :     /* How much high quants we have to distribute */
80 :     nhigh = n_hquant;
81 :    
82 :     /* Simplify the pattern, respecting the current ratio nhigh/nlow */
83 :     _gcd = gcd( nlow, nhigh);
84 :     nlow = nlow / _gcd;
85 :     nhigh = nhigh / _gcd;
86 :    
87 :     /* Allocate the distributuion array */
88 :     if((*quants = (int*)malloc((nhigh + nlow)*sizeof(int))) == NULL)
89 :     return (-1);
90 :    
91 :     /* Validate distribution size */
92 :     n = nlow + nhigh;
93 :    
94 :     /*
95 :     * Our goal now is to find packet length so we distribute the quants
96 :     * the best we can. The solution i chose is quite simple.
97 :     *
98 :     * Let's 'max' be max(nlow, nhigh)
99 :     * Let's 'min' be min(nlow, nhigh)
100 :     *
101 :     * Then if we compute the euclidian division of 'max' by 'min', the
102 :     * quotient 'q' represents the length of 'max type quant' packets
103 :     * length. Let's call 'r' the remaining part of the euclidian division.
104 :     *
105 :     * We could stop there and have something like this:
106 :     * M == quant type of the quantity 'max'
107 :     * m == quant type of the quantity 'min'
108 :     *
109 :     * (MM.........Mm)*(MMMMMM...M)
110 :     * '----------' '--------'
111 :     * '----|------' |-> repeated 'r' times
112 :     * ||
113 :     * ||--> repeated 'min' times
114 :     * |---> repeated 'q' times'
115 :     *
116 :     *
117 :     * Let's look if we have precision quants.
118 :     *
119 :     * We have 'min' packets of (q+1) length
120 :     * We have also a packet of length 'r'
121 :     * So : min*(q+1) + r == (min*q + r) + min == max + min == n
122 :     *
123 :     * Ok this is good :-)
124 :     *
125 :     * Now let's complicate things a bit :-)))
126 :     *
127 :     * We will distribute the last M quantizers all over the distribution
128 :     * array. To achieve that, we build packets of (q+2) quantizers containing
129 :     * qM + 1m as usual plus 1M from the last remaining M quantizer packet and
130 :     * usual packets of (q+1) with qM and 1m.
131 :     *
132 :     * So we will have this kind of distribution:
133 :     *
134 :     * (MM.........Mm)*(MMMM...Mm)
135 :     * '----------' '------'
136 :     * '----|------' '---|---'
137 :     * || ||--> repeated 'min-r' times
138 :     * || |---> repeated 'q' times
139 :     * ||--> repeated 'r' times
140 :     * |---> repeated 'q+1' times
141 :     *
142 :     *
143 :     * Let's check if it's still right:
144 :     *
145 :     * We'll have ((q+1)*r + q*(min-r))M quants == (q*r + r + q*min - q*r)M
146 :     * == (q*min + r)M
147 :     * == (max)M it's good
148 :     * And: (r + min - r)m quantizers == (min)m it's good too)
149 :     *
150 :     * NB: if the fixed quantizer is an integer then we have min == 0, so we
151 :     * must take care of it apart (else the euclidian division leads to
152 :     * an arithmetic signal - division by zero)
153 :     *
154 :     */
155 :    
156 :    
157 :     max = MAX(nlow, nhigh);
158 :     min = MIN(nlow, nhigh);
159 :    
160 :     /* Euclidian division */
161 :     if(min == 0) {
162 :     q = 0;
163 :     r = max;
164 :     } else {
165 :     q = max/min;
166 :     r = max%min;
167 :     }
168 :    
169 :     /* How much packets of (q+1)M quantizers + 1m quantizer */
170 :     a = r;
171 :    
172 :     /* How much packets of (q)M quantizers + 1m quantizer */
173 :     b = min - r;
174 :    
175 :     /* First we set M */
176 :     M = (max==nhigh)?high:low;
177 :    
178 :     /*
179 :     * Then as we can't guarantee that max != min, we are forced to set
180 :     * the other one according to the first value. We can't use the first
181 :     * formula with s/max/min/
182 :     */
183 :     m = (M==high)?low:high;
184 :    
185 :     /*
186 :     * Ok now we know everything we have to know to distribute those funny
187 :     * quantizers. What about just doing it ?
188 :     */
189 :    
190 :     dist = *quants;
191 :    
192 :     /* Distribute big packets */
193 :     for(i=0; i<a; i++) {
194 :    
195 :     int j;
196 :    
197 :     /* Repeat q+1 times the M quantizer */
198 :     for(j=0; j<(q+1); j++) *(dist++) = M;
199 :    
200 :     /* Put a m quantizer */
201 :     *(dist++) = m;
202 :    
203 :     }
204 :    
205 :     /* Distribute the little packets */
206 :     for(i=0; i<b; i++) {
207 :    
208 :     int j;
209 :    
210 :     /* Repeat q times the M quantizer */
211 :     for(j=0; j<q; j++) *(dist++) = M;
212 :    
213 :     /* Put a m quantizer */
214 :     *(dist++) = m;
215 :    
216 :     }
217 :    
218 :     return(n);
219 :     }
220 :    
221 :    
222 :    
223 :    
224 :     static int rc_fixed_create(xvid_plg_create_t * create, rc_fixed_t ** handle)
225 :     {
226 :     xvid_plugin_fixed_t * param = (xvid_plugin_fixed_t *)create->param;
227 :     rc_fixed_t * rc;
228 :     int quant_low;
229 :     int nquant_low, nquant_high;
230 :    
231 :     /* allocate context struct */
232 :     if((rc = malloc(sizeof(rc_fixed_t))) == NULL)
233 :     return(XVID_ERR_MEMORY);
234 :    
235 :     /* Copy data to private area */
236 :     rc->quant_increment = param->quant_increment;
237 :     rc->quant_base = param->quant_base;
238 :    
239 :     /* Cut down the precision up to 1/precision */
240 :     quant_low = rc->quant_increment/rc->quant_base;
241 :    
242 :     /* Force [1..31] range */
243 :     if(quant_low < 1) {
244 :     quant_low = 1;
245 :     rc->quant_base = 1;
246 :     rc->quant_increment = quant_low;
247 :     } else if(quant_low > 30) {
248 :     quant_low = 31;
249 :     rc->quant_base = 1;
250 :     rc->quant_increment = quant_low;
251 :     }
252 :    
253 :     /* How much low quants we have to distribute) */
254 :     nquant_low = rc->quant_base*(quant_low+1) - rc->quant_increment;
255 :     nquant_high = rc->quant_base - nquant_low;
256 :    
257 :     /* Distribute the quantizers */
258 :     rc->nquant = distribute_quants(&rc->quant,
259 :     quant_low,
260 :     nquant_low,
261 :     nquant_high);
262 :    
263 :     if(rc->quant == NULL) {
264 :     free(rc);
265 :     return(XVID_ERR_MEMORY);
266 :     }
267 :    
268 :     *handle = rc;
269 :     return(0);
270 :     }
271 :    
272 :    
273 :     static int rc_fixed_destroy(rc_fixed_t * rc, xvid_plg_destroy_t * destroy)
274 :     {
275 :     free(rc);
276 :     return(0);
277 :     }
278 :    
279 :    
280 :     static int rc_fixed_before(rc_fixed_t * rc, xvid_plg_data_t * data)
281 :     {
282 :     data->quant = rc->quant[data->frame_num%rc->nquant];
283 :     data->type = XVID_TYPE_AUTO;
284 :     return 0;
285 :     }
286 :    
287 :    
288 :     int xvid_plugin_fixed(void * handle, int opt, void * param1, void * param2)
289 :     {
290 :     switch(opt)
291 :     {
292 :     case XVID_PLG_INFO :
293 :     return 0;
294 :    
295 :     case XVID_PLG_CREATE :
296 :     return rc_fixed_create((xvid_plg_create_t*)param1, param2);
297 :    
298 :     case XVID_PLG_DESTROY :
299 :     return rc_fixed_destroy((rc_fixed_t*)handle, (xvid_plg_destroy_t*)param1);
300 :    
301 :     case XVID_PLG_BEFORE :
302 :     return rc_fixed_before((rc_fixed_t*)handle, (xvid_plg_data_t*)param1);
303 :    
304 :     case XVID_PLG_AFTER :
305 :     return 0;
306 :     }
307 :    
308 :     return XVID_ERR_FAIL;
309 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4