Parent Directory
|
Revision Log
Revision 1382 - (view) (download)
1 : | edgomez | 1382 | /***************************************************************************** |
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: plugin_fixed.c,v 1.2 2004-03-22 22:36:24 edgomez 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 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 |