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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1, Sun Mar 23 04:03:01 2003 UTC revision 1.2, Mon Mar 22 22:36:24 2004 UTC
# Line 0  Line 1 
1    /*****************************************************************************
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    }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

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