[svn] / branches / dev-api-4 / xvidcore / src / plugins / plugin_fixed.c Repository:
ViewVC logotype

Annotation of /branches/dev-api-4/xvidcore/src/plugins/plugin_fixed.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 938 - (view) (download)

1 : suxen_drol 938 /*****************************************************************************
2 :     *
3 :     * XviD VBR Library
4 :     * - Fixed quantizer controller implementation -
5 :     *
6 :     * Copyright (C) 2002 Edouard Gomez <ed.gomez@wanadoo.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: plugin_fixed.c,v 1.1.2.1 2003-03-23 04:03:01 suxen_drol Exp $
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 *dist;
68 :    
69 :     /* Low quant */
70 :     low = lquant;
71 :    
72 :     /* High quant is just low quant + 1 */
73 :     high = low + 1;
74 :    
75 :     /* How much low quants we have to distribute */
76 :     nlow = n_lquant;
77 :    
78 :     /* How much high quants we have to distribute */
79 :     nhigh = n_hquant;
80 :    
81 :     /* Simplify the pattern, respecting the current ratio nhigh/nlow */
82 :     _gcd = gcd( nlow, nhigh);
83 :     nlow = nlow / _gcd;
84 :     nhigh = nhigh / _gcd;
85 :    
86 :     /* Allocate the distributuion array */
87 :     if((*quants = (int*)malloc((nhigh + nlow)*sizeof(int))) == NULL)
88 :     return (-1);
89 :    
90 :     /* Validate distribution size */
91 :     n = nlow + nhigh;
92 :    
93 :     /*
94 :     * Our goal now is to find packet length so we distribute the quants
95 :     * the best we can. The solution i chose is quite simple.
96 :     *
97 :     * Let's 'max' be max(nlow, nhigh)
98 :     * Let's 'min' be min(nlow, nhigh)
99 :     *
100 :     * Then if we compute the euclidian division of 'max' by 'min', the
101 :     * quotient 'q' represents the length of 'max type quant' packets
102 :     * length. Let's call 'r' the remaining part of the euclidian division.
103 :     *
104 :     * We could stop there and have something like this:
105 :     * M == quant type of the quantity 'max'
106 :     * m == quant type of the quantity 'min'
107 :     *
108 :     * (MM.........Mm)*(MMMMMM...M)
109 :     * '----------' '--------'
110 :     * '----|------' |-> repeated 'r' times
111 :     * ||
112 :     * ||--> repeated 'min' times
113 :     * |---> repeated 'q' times'
114 :     *
115 :     *
116 :     * Let's look if we have precision quants.
117 :     *
118 :     * We have 'min' packets of (q+1) length
119 :     * We have also a packet of length 'r'
120 :     * So : min*(q+1) + r == (min*q + r) + min == max + min == n
121 :     *
122 :     * Ok this is good :-)
123 :     *
124 :     * Now let's complicate things a bit :-)))
125 :     *
126 :     * We will distribute the last M quantizers all over the distribution
127 :     * array. To achieve that, we build packets of (q+2) quantizers containing
128 :     * qM + 1m as usual plus 1M from the last remaining M quantizer packet and
129 :     * usual packets of (q+1) with qM and 1m.
130 :     *
131 :     * So we will have this kind of distribution:
132 :     *
133 :     * (MM.........Mm)*(MMMM...Mm)
134 :     * '----------' '------'
135 :     * '----|------' '---|---'
136 :     * || ||--> repeated 'min-r' times
137 :     * || |---> repeated 'q' times
138 :     * ||--> repeated 'r' times
139 :     * |---> repeated 'q+1' times
140 :     *
141 :     *
142 :     * Let's check if it's still right:
143 :     *
144 :     * We'll have ((q+1)*r + q*(min-r))M quants == (q*r + r + q*min - q*r)M
145 :     * == (q*min + r)M
146 :     * == (max)M it's good
147 :     * And: (r + min - r)m quantizers == (min)m it's good too)
148 :     *
149 :     * NB: if the fixed quantizer is an integer then we have min == 0, so we
150 :     * must take care of it apart (else the euclidian division leads to
151 :     * an arithmetic signal - division by zero)
152 :     *
153 :     */
154 :    
155 :    
156 :     max = MAX(nlow, nhigh);
157 :     min = MIN(nlow, nhigh);
158 :    
159 :     /* Euclidian division */
160 :     if(min == 0) {
161 :     q = 0;
162 :     r = max;
163 :     } else {
164 :     q = max/min;
165 :     r = max%min;
166 :     }
167 :    
168 :     /* How much packets of (q+1)M quantizers + 1m quantizer */
169 :     a = r;
170 :    
171 :     /* How much packets of (q)M quantizers + 1m quantizer */
172 :     b = min - r;
173 :    
174 :     /*
175 :     * Ok now we know everything we have to know to distribute those funny
176 :     * quantizers. What about just doing it ?
177 :     */
178 :    
179 :     dist = *quants;
180 :    
181 :     /* Distribute big packets */
182 :     for(i=0; i<a; i++) {
183 :    
184 :     int j;
185 :    
186 :     /* Repeat q+1 times the M quantizer */
187 :     for(j=0; j<(q+1); j++) *(dist++) = (max==nhigh)?high:low;
188 :    
189 :     /* Put a m quantizer */
190 :     *(dist++) = (min==nhigh)?high:low;
191 :    
192 :     }
193 :    
194 :     /* Distribute the little packets */
195 :     for(i=0; i<b; i++) {
196 :    
197 :     int j;
198 :    
199 :     /* Repeat q times the M quantizer */
200 :     for(j=0; j<q; j++) *(dist++) = (max==nhigh)?high:low;
201 :    
202 :     /* Put a m quantizer */
203 :     *(dist++) = (min==nhigh)?high:low;
204 :    
205 :     }
206 :    
207 :     return(n);
208 :     }
209 :    
210 :    
211 :    
212 :    
213 :     static int rc_fixed_create(xvid_plg_create_t * create, rc_fixed_t ** handle)
214 :     {
215 :     xvid_plugin_fixed_t * param = (xvid_plugin_fixed_t *)create->param;
216 :     rc_fixed_t * rc;
217 :     int quant_low;
218 :     int nquant_low, nquant_high;
219 :    
220 :     /* allocate context struct */
221 :     if((rc = malloc(sizeof(rc_fixed_t))) == NULL)
222 :     return(XVID_ERR_MEMORY);
223 :    
224 :     /* Copy data to private area */
225 :     rc->quant_increment = param->quant_increment;
226 :     rc->quant_base = param->quant_base;
227 :    
228 :     /* Cut down the precision up to 1/precision */
229 :     quant_low = rc->quant_increment/rc->quant_base;
230 :    
231 :     /* Force [1..31] range */
232 :     if(quant_low < 1) {
233 :     quant_low = 1;
234 :     rc->quant_base = 1;
235 :     rc->quant_increment = quant_low;
236 :     } else if(quant_low > 30) {
237 :     quant_low = 31;
238 :     rc->quant_base = 1;
239 :     rc->quant_increment = quant_low;
240 :     }
241 :    
242 :     /* How much low quants we have to distribute) */
243 :     nquant_low = rc->quant_base*(quant_low+1) - rc->quant_increment;
244 :     nquant_high = rc->quant_base - nquant_low;
245 :    
246 :     /* Distribute the quantizers */
247 :     rc->nquant = distribute_quants(&rc->quant,
248 :     quant_low,
249 :     nquant_low,
250 :     nquant_high);
251 :    
252 :     if(rc->quant == NULL) {
253 :     free(rc);
254 :     return(XVID_ERR_MEMORY);
255 :     }
256 :    
257 :     *handle = rc;
258 :     return(0);
259 :     }
260 :    
261 :    
262 :     static int rc_fixed_destroy(rc_fixed_t * rc, xvid_plg_destroy_t * destroy)
263 :     {
264 :     free(rc);
265 :     return(0);
266 :     }
267 :    
268 :    
269 :     static int rc_fixed_before(rc_fixed_t * rc, xvid_plg_data_t * data)
270 :     {
271 :     data->quant = rc->quant[data->frame_num%rc->nquant];
272 :     data->type = XVID_TYPE_AUTO;
273 :     return 0;
274 :     }
275 :    
276 :    
277 :     int xvid_plugin_fixed(void * handle, int opt, void * param1, void * param2)
278 :     {
279 :     switch(opt)
280 :     {
281 :     case XVID_PLG_INFO :
282 :     return 0;
283 :    
284 :     case XVID_PLG_CREATE :
285 :     return rc_fixed_create((xvid_plg_create_t*)param1, param2);
286 :    
287 :     case XVID_PLG_DESTROY :
288 :     return rc_fixed_destroy((rc_fixed_t*)handle, (xvid_plg_destroy_t*)param1);
289 :    
290 :     case XVID_PLG_BEFORE :
291 :     return rc_fixed_before((rc_fixed_t*)handle, (xvid_plg_data_t*)param1);
292 :    
293 :     case XVID_PLG_AFTER :
294 :     return 0;
295 :     }
296 :    
297 :     return XVID_ERR_FAIL;
298 :     }

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