[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.1.2.1, Sun Mar 23 04:03:01 2003 UTC
# Line 0  Line 1 
1    /*****************************************************************************
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$
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    }

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

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