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

Annotation of /branches/dev-api-4/xvidcore/src/motion/gmc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1142 - (view) (download)

1 : edgomez 1142 /*****************************************************************************
2 : chl 1077 *
3 : edgomez 1142 * XVID MPEG-4 VIDEO CODEC
4 :     * - GMC interpolation module -
5 : chl 1077 *
6 : edgomez 1142 * Copyright(C) 2002-2003 Pascal Massimino <skal@planet-d.net>
7 : chl 1077 *
8 : edgomez 1142 * 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 : chl 1077 *
13 : edgomez 1142 * 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 : chl 1077 *
18 : edgomez 1142 * 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: gmc.c,v 1.1.2.4 2003-09-10 22:18:59 edgomez Exp $
23 :     *
24 :     ****************************************************************************/
25 : chl 1077
26 :     #include "../portab.h"
27 :     #include "../global.h"
28 :     #include "../encoder.h"
29 :     #include "gmc.h"
30 :    
31 :     #include <stdio.h>
32 :    
33 :     /* These are mainly the new GMC routines by -Skal- (C) 2003 */
34 :    
35 :     //////////////////////////////////////////////////////////
36 : syskin 1085 // Pts = 2 or 3
37 : chl 1077
38 : syskin 1085 // Warning! *src is the global frame pointer (that is: adress
39 :     // of pixel 0,0), not the macroblock one.
40 :     // Conversely, *dst is the macroblock top-left adress.
41 : chl 1077
42 :     void Predict_16x16_C(const NEW_GMC_DATA * const This,
43 : syskin 1085 uint8_t *dst, const uint8_t *src,
44 :     int dststride, int srcstride, int x, int y, int rounding)
45 : chl 1077 {
46 : syskin 1085 const int W = This->sW;
47 :     const int H = This->sH;
48 :     const int rho = 3 - This->accuracy;
49 :     const int Rounder = ( (1<<7) - (rounding<<(2*rho)) ) << 16;
50 : chl 1077
51 : syskin 1085 const int dUx = This->dU[0];
52 :     const int dVx = This->dV[0];
53 :     const int dUy = This->dU[1];
54 :     const int dVy = This->dV[1];
55 : chl 1077
56 : syskin 1085 int Uo = This->Uo + 16*(dUy*y + dUx*x);
57 :     int Vo = This->Vo + 16*(dVy*y + dVx*x);
58 : chl 1077
59 : syskin 1085 int i, j;
60 : chl 1077
61 : syskin 1085 dst += 16;
62 : syskin 1117 for (j=16; j>0; --j) {
63 :     int U = Uo, V = Vo;
64 :     Uo += dUy; Vo += dVy;
65 :     for (i=-16; i<0; ++i) {
66 :     unsigned int f0, f1, ri = 16, rj = 16;
67 :     int Offset;
68 :     int u = ( U >> 16 ) << rho;
69 :     int v = ( V >> 16 ) << rho;
70 : chl 1077
71 : syskin 1117 U += dUx; V += dVx;
72 : chl 1077
73 : syskin 1117 if (u > 0 && u <= W) { ri = MTab[u&15]; Offset = u>>4; }
74 :     else if (u > W) Offset = W>>4;
75 :     else Offset = -1;
76 :    
77 :     if (v > 0 && v <= H) { rj = MTab[v&15]; Offset += (v>>4)*srcstride; }
78 :     else if (v > H) Offset += (H>>4)*srcstride;
79 :     else Offset -= srcstride;
80 : chl 1077
81 : syskin 1117 f0 = src[Offset + 0];
82 :     f0 |= src[Offset + 1] << 16;
83 :     f1 = src[Offset + srcstride + 0];
84 :     f1 |= src[Offset + srcstride + 1] << 16;
85 :     f0 = (ri*f0)>>16;
86 :     f1 = (ri*f1) & 0x0fff0000;
87 :     f0 |= f1;
88 :     f0 = (rj*f0 + Rounder) >> 24;
89 : chl 1077
90 : syskin 1117 dst[i] = (uint8_t)f0;
91 :     }
92 :     dst += dststride;
93 : syskin 1085 }
94 : chl 1077 }
95 :    
96 :     void Predict_8x8_C(const NEW_GMC_DATA * const This,
97 : syskin 1085 uint8_t *uDst, const uint8_t *uSrc,
98 :     uint8_t *vDst, const uint8_t *vSrc,
99 :     int dststride, int srcstride, int x, int y, int rounding)
100 : chl 1077 {
101 : syskin 1085 const int W = This->sW >> 1;
102 :     const int H = This->sH >> 1;
103 :     const int rho = 3-This->accuracy;
104 :     const int32_t Rounder = ( 128 - (rounding<<(2*rho)) ) << 16;
105 : chl 1077
106 : syskin 1085 const int32_t dUx = This->dU[0];
107 :     const int32_t dVx = This->dV[0];
108 :     const int32_t dUy = This->dU[1];
109 :     const int32_t dVy = This->dV[1];
110 : chl 1077
111 : syskin 1085 int32_t Uo = This->Uco + 8*(dUy*y + dUx*x);
112 :     int32_t Vo = This->Vco + 8*(dVy*y + dVx*x);
113 : chl 1077
114 : syskin 1085 int i, j;
115 : chl 1077
116 : syskin 1085 uDst += 8;
117 :     vDst += 8;
118 : syskin 1117 for (j=8; j>0; --j) {
119 :     int32_t U = Uo, V = Vo;
120 :     Uo += dUy; Vo += dVy;
121 : chl 1077
122 : syskin 1117 for (i=-8; i<0; ++i) {
123 :     int Offset;
124 :     uint32_t f0, f1, ri, rj;
125 :     int32_t u, v;
126 : chl 1077
127 : syskin 1117 u = ( U >> 16 ) << rho;
128 :     v = ( V >> 16 ) << rho;
129 :     U += dUx; V += dVx;
130 : chl 1077
131 : syskin 1117 if (u > 0 && u <= W) {
132 :     ri = MTab[u&15];
133 :     Offset = u>>4;
134 :     } else {
135 :     ri = 16;
136 :     if (u>W) Offset = W>>4;
137 :     else Offset = -1;
138 :     }
139 :    
140 :     if (v > 0 && v <= H) {
141 :     rj = MTab[v&15];
142 :     Offset += (v>>4)*srcstride;
143 :     } else {
144 :     rj = 16;
145 :     if (v>H) Offset += (H>>4)*srcstride;
146 :     else Offset -= srcstride;
147 :     }
148 : chl 1077
149 : syskin 1117 f0 = uSrc[Offset + 0];
150 :     f0 |= uSrc[Offset + 1] << 16;
151 :     f1 = uSrc[Offset + srcstride + 0];
152 :     f1 |= uSrc[Offset + srcstride + 1] << 16;
153 :     f0 = (ri*f0)>>16;
154 :     f1 = (ri*f1) & 0x0fff0000;
155 :     f0 |= f1;
156 :     f0 = (rj*f0 + Rounder) >> 24;
157 : chl 1077
158 : syskin 1117 uDst[i] = (uint8_t)f0;
159 : chl 1077
160 : syskin 1117 f0 = vSrc[Offset + 0];
161 :     f0 |= vSrc[Offset + 1] << 16;
162 :     f1 = vSrc[Offset + srcstride + 0];
163 :     f1 |= vSrc[Offset + srcstride + 1] << 16;
164 :     f0 = (ri*f0)>>16;
165 :     f1 = (ri*f1) & 0x0fff0000;
166 :     f0 |= f1;
167 :     f0 = (rj*f0 + Rounder) >> 24;
168 : chl 1077
169 : syskin 1117 vDst[i] = (uint8_t)f0;
170 :     }
171 :     uDst += dststride;
172 :     vDst += dststride;
173 : syskin 1085 }
174 : chl 1077 }
175 :    
176 : syskin 1085 void get_average_mv_C(const NEW_GMC_DATA * const Dsp, VECTOR * const mv,
177 :     int x, int y, int qpel)
178 : chl 1077 {
179 : syskin 1085 int i, j;
180 :     int vx = 0, vy = 0;
181 :     int32_t uo = Dsp->Uo + 16*(Dsp->dU[1]*y + Dsp->dU[0]*x);
182 :     int32_t vo = Dsp->Vo + 16*(Dsp->dV[1]*y + Dsp->dV[0]*x);
183 :     for (j=16; j>0; --j)
184 :     {
185 :     int32_t U, V;
186 :     U = uo; uo += Dsp->dU[1];
187 :     V = vo; vo += Dsp->dV[1];
188 :     for (i=16; i>0; --i)
189 :     {
190 :     int32_t u,v;
191 :     u = U >> 16; U += Dsp->dU[0]; vx += u;
192 :     v = V >> 16; V += Dsp->dV[0]; vy += v;
193 :     }
194 :     }
195 :     vx -= (256*x+120) << (5+Dsp->accuracy); // 120 = 15*16/2
196 :     vy -= (256*y+120) << (5+Dsp->accuracy);
197 : chl 1077
198 : syskin 1085 mv->x = RSHIFT( vx, 8+Dsp->accuracy - qpel );
199 :     mv->y = RSHIFT( vy, 8+Dsp->accuracy - qpel );
200 : chl 1077 }
201 :    
202 :     //////////////////////////////////////////////////////////
203 :     // simplified version for 1 warp point
204 :    
205 :     void Predict_1pt_16x16_C(const NEW_GMC_DATA * const This,
206 : syskin 1085 uint8_t *Dst, const uint8_t *Src,
207 :     int dststride, int srcstride, int x, int y, int rounding)
208 : chl 1077 {
209 : syskin 1085 const int W = This->sW;
210 :     const int H = This->sH;
211 :     const int rho = 3-This->accuracy;
212 :     const int32_t Rounder = ( 128 - (rounding<<(2*rho)) ) << 16;
213 : chl 1077
214 :    
215 : syskin 1085 int32_t uo = This->Uo + (x<<8); // ((16*x)<<4)
216 :     int32_t vo = This->Vo + (y<<8);
217 :     const uint32_t ri = MTab[uo & 15];
218 :     const uint32_t rj = MTab[vo & 15];
219 :     int i, j;
220 : chl 1077
221 : syskin 1085 int32_t Offset;
222 :     if ((uint32_t)vo<=(uint32_t)H) Offset = (vo>>4)*srcstride;
223 :     else if (vo>H) Offset = ( H>>4)*srcstride;
224 :     else Offset =-16*srcstride;
225 :     if ((uint32_t)uo<=(uint32_t)W) Offset += (uo>>4);
226 :     else if (uo>W) Offset += ( W>>4);
227 :     else Offset -= 16;
228 : chl 1077
229 : syskin 1085 Dst += 16;
230 : chl 1077
231 : syskin 1085 for(j=16; j>0; --j, Offset+=srcstride-16)
232 :     {
233 :     for(i=-16; i<0; ++i, ++Offset)
234 :     {
235 :     uint32_t f0, f1;
236 :     f0 = Src[ Offset +0 ];
237 :     f0 |= Src[ Offset +1 ] << 16;
238 :     f1 = Src[ Offset+srcstride +0 ];
239 :     f1 |= Src[ Offset+srcstride +1 ] << 16;
240 :     f0 = (ri*f0)>>16;
241 :     f1 = (ri*f1) & 0x0fff0000;
242 :     f0 |= f1;
243 :     f0 = ( rj*f0 + Rounder ) >> 24;
244 :     Dst[i] = (uint8_t)f0;
245 :     }
246 :     Dst += dststride;
247 :     }
248 :     }
249 : chl 1077
250 :     void Predict_1pt_8x8_C(const NEW_GMC_DATA * const This,
251 : syskin 1085 uint8_t *uDst, const uint8_t *uSrc,
252 :     uint8_t *vDst, const uint8_t *vSrc,
253 :     int dststride, int srcstride, int x, int y, int rounding)
254 : chl 1077 {
255 : syskin 1085 const int W = This->sW >> 1;
256 :     const int H = This->sH >> 1;
257 :     const int rho = 3-This->accuracy;
258 :     const int32_t Rounder = ( 128 - (rounding<<(2*rho)) ) << 16;
259 : chl 1077
260 : syskin 1085 int32_t uo = This->Uco + (x<<7);
261 :     int32_t vo = This->Vco + (y<<7);
262 :     const uint32_t rri = MTab[uo & 15];
263 :     const uint32_t rrj = MTab[vo & 15];
264 :     int i, j;
265 : chl 1077
266 : syskin 1085 int32_t Offset;
267 :     if ((uint32_t)vo<=(uint32_t)H) Offset = (vo>>4)*srcstride;
268 :     else if (vo>H) Offset = ( H>>4)*srcstride;
269 :     else Offset =-8*srcstride;
270 :     if ((uint32_t)uo<=(uint32_t)W) Offset += (uo>>4);
271 :     else if (uo>W) Offset += (W>>4);
272 :     else Offset -= 8;
273 : chl 1077
274 : syskin 1085 uDst += 8;
275 :     vDst += 8;
276 :     for(j=8; j>0; --j, Offset+=srcstride-8)
277 :     {
278 :     for(i=-8; i<0; ++i, Offset++)
279 :     {
280 :     uint32_t f0, f1;
281 :     f0 = uSrc[ Offset + 0 ];
282 :     f0 |= uSrc[ Offset + 1 ] << 16;
283 :     f1 = uSrc[ Offset + srcstride + 0 ];
284 :     f1 |= uSrc[ Offset + srcstride + 1 ] << 16;
285 :     f0 = (rri*f0)>>16;
286 :     f1 = (rri*f1) & 0x0fff0000;
287 :     f0 |= f1;
288 :     f0 = ( rrj*f0 + Rounder ) >> 24;
289 :     uDst[i] = (uint8_t)f0;
290 : chl 1077
291 : syskin 1085 f0 = vSrc[ Offset + 0 ];
292 :     f0 |= vSrc[ Offset + 1 ] << 16;
293 :     f1 = vSrc[ Offset + srcstride + 0 ];
294 :     f1 |= vSrc[ Offset + srcstride + 1 ] << 16;
295 :     f0 = (rri*f0)>>16;
296 :     f1 = (rri*f1) & 0x0fff0000;
297 :     f0 |= f1;
298 :     f0 = ( rrj*f0 + Rounder ) >> 24;
299 :     vDst[i] = (uint8_t)f0;
300 :     }
301 :     uDst += dststride;
302 :     vDst += dststride;
303 :     }
304 : chl 1077 }
305 :    
306 : syskin 1085 void get_average_mv_1pt_C(const NEW_GMC_DATA * const Dsp, VECTOR * const mv,
307 :     int x, int y, int qpel)
308 : chl 1077 {
309 : syskin 1085 mv->x = RSHIFT(Dsp->Uo<<qpel, 3);
310 :     mv->y = RSHIFT(Dsp->Vo<<qpel, 3);
311 : chl 1077 }
312 :    
313 :     //////////////////////////////////////////////////////////
314 :    
315 :    
316 : syskin 1085 // Warning! It's Accuracy being passed, not 'resolution'!
317 : chl 1077
318 :     void generate_GMCparameters( int nb_pts, const int accuracy,
319 : syskin 1085 const WARPPOINTS *const pts,
320 :     const int width, const int height,
321 :     NEW_GMC_DATA *const gmc)
322 : chl 1077 {
323 : syskin 1085 gmc->sW = width << 4;
324 :     gmc->sH = height << 4;
325 :     gmc->accuracy = accuracy;
326 :     gmc->num_wp = nb_pts;
327 : chl 1077
328 : syskin 1085 // reduce the number of points, if possible
329 :     if (nb_pts<3 || (pts->duv[2].x==-pts->duv[1].y && pts->duv[2].y==pts->duv[1].x)) {
330 :     if (nb_pts<2 || (pts->duv[1].x==0 && pts->duv[1].y==0)) {
331 :     if (nb_pts<1 || (pts->duv[0].x==0 && pts->duv[0].y==0)) {
332 :     nb_pts = 0;
333 :     }
334 :     else nb_pts = 1;
335 :     }
336 :     else nb_pts = 2;
337 :     }
338 :     else nb_pts = 3;
339 :    
340 :     // now, nb_pts stores the actual number of points required for interpolation
341 : chl 1077
342 : syskin 1085 if (nb_pts<=1)
343 :     {
344 :     if (nb_pts==1) {
345 :     // store as 4b fixed point
346 :     gmc->Uo = pts->duv[0].x << accuracy;
347 :     gmc->Vo = pts->duv[0].y << accuracy;
348 :     gmc->Uco = ((pts->duv[0].x>>1) | (pts->duv[0].x&1)) << accuracy; // DIV2RND()
349 :     gmc->Vco = ((pts->duv[0].y>>1) | (pts->duv[0].y&1)) << accuracy; // DIV2RND()
350 :     }
351 :     else { // zero points?!
352 :     gmc->Uo = gmc->Vo = 0;
353 :     gmc->Uco = gmc->Vco = 0;
354 :     }
355 : chl 1077
356 : syskin 1085 gmc->predict_16x16 = Predict_1pt_16x16_C;
357 :     gmc->predict_8x8 = Predict_1pt_8x8_C;
358 :     gmc->get_average_mv = get_average_mv_1pt_C;
359 :     }
360 :     else { // 2 or 3 points
361 :     const int rho = 3 - accuracy; // = {3,2,1,0} for Acc={0,1,2,3}
362 :     int Alpha = log2bin(width-1);
363 :     int Ws = 1 << Alpha;
364 : chl 1077
365 : syskin 1085 gmc->dU[0] = 16*Ws + RDIV( 8*Ws*pts->duv[1].x, width ); // dU/dx
366 :     gmc->dV[0] = RDIV( 8*Ws*pts->duv[1].y, width ); // dV/dx
367 : chl 1077
368 : syskin 1085 /* disabled, because possibly buggy? */
369 : chl 1077
370 :     /* if (nb_pts==2) {
371 : syskin 1085 gmc->dU[1] = -gmc->dV[0]; // -Sin
372 :     gmc->dV[1] = gmc->dU[0] ; // Cos
373 :     }
374 :     else */
375 : chl 1077 {
376 : syskin 1085 const int Beta = log2bin(height-1);
377 :     const int Hs = 1<<Beta;
378 :     gmc->dU[1] = RDIV( 8*Hs*pts->duv[2].x, height ); // dU/dy
379 :     gmc->dV[1] = 16*Hs + RDIV( 8*Hs*pts->duv[2].y, height ); // dV/dy
380 :     if (Beta>Alpha) {
381 :     gmc->dU[0] <<= (Beta-Alpha);
382 :     gmc->dV[0] <<= (Beta-Alpha);
383 :     Alpha = Beta;
384 :     Ws = Hs;
385 :     }
386 :     else {
387 :     gmc->dU[1] <<= Alpha - Beta;
388 :     gmc->dV[1] <<= Alpha - Beta;
389 :     }
390 :     }
391 :     // upscale to 16b fixed-point
392 :     gmc->dU[0] <<= (16-Alpha - rho);
393 :     gmc->dU[1] <<= (16-Alpha - rho);
394 :     gmc->dV[0] <<= (16-Alpha - rho);
395 :     gmc->dV[1] <<= (16-Alpha - rho);
396 : chl 1077
397 : syskin 1085 gmc->Uo = ( pts->duv[0].x <<(16+ accuracy)) + (1<<15);
398 :     gmc->Vo = ( pts->duv[0].y <<(16+ accuracy)) + (1<<15);
399 :     gmc->Uco = ((pts->duv[0].x-1)<<(17+ accuracy)) + (1<<17);
400 :     gmc->Vco = ((pts->duv[0].y-1)<<(17+ accuracy)) + (1<<17);
401 :     gmc->Uco = (gmc->Uco + gmc->dU[0] + gmc->dU[1])>>2;
402 :     gmc->Vco = (gmc->Vco + gmc->dV[0] + gmc->dV[1])>>2;
403 : chl 1077
404 : syskin 1085 gmc->predict_16x16 = Predict_16x16_C;
405 :     gmc->predict_8x8 = Predict_8x8_C;
406 :     gmc->get_average_mv = get_average_mv_C;
407 :     }
408 : chl 1077 }
409 :    
410 :     //////////////////////////////////////////////////////////
411 :    
412 :     /* quick and dirty routine to generate the full warped image (pGMC != NULL)
413 :     or just all average Motion Vectors (pGMC == NULL) */
414 :    
415 :     void
416 :     generate_GMCimage( const NEW_GMC_DATA *const gmc_data, // [input] precalculated data
417 :     const IMAGE *const pRef, // [input]
418 :     const int mb_width,
419 :     const int mb_height,
420 :     const int stride,
421 :     const int stride2,
422 :     const int fcode, // [input] some parameters...
423 : syskin 1085 const int32_t quarterpel, // [input] for rounding avgMV
424 : chl 1077 const int reduced_resolution, // [input] ignored
425 :     const int32_t rounding, // [input] for rounding image data
426 :     MACROBLOCK *const pMBs, // [output] average motion vectors
427 :     IMAGE *const pGMC) // [output] full warped image
428 :     {
429 :    
430 :     unsigned int mj,mi;
431 :     VECTOR avgMV;
432 :    
433 :     for (mj = 0; mj < (unsigned int)mb_height; mj++)
434 :     for (mi = 0; mi < (unsigned int)mb_width; mi++) {
435 :     const int mbnum = mj*mb_width+mi;
436 :     if (pGMC)
437 :     {
438 :     gmc_data->predict_16x16(gmc_data,
439 :     pGMC->y + mj*16*stride + mi*16, pRef->y,
440 :     stride, stride, mi, mj, rounding);
441 :    
442 :     gmc_data->predict_8x8(gmc_data,
443 :     pGMC->u + mj*8*stride2 + mi*8, pRef->u,
444 :     pGMC->v + mj*8*stride2 + mi*8, pRef->v,
445 :     stride2, stride2, mi, mj, rounding);
446 :     }
447 :     gmc_data->get_average_mv(gmc_data, &avgMV, mi, mj, quarterpel);
448 :    
449 :     pMBs[mbnum].amv.x = gmc_sanitize(avgMV.x, quarterpel, fcode);
450 :     pMBs[mbnum].amv.y = gmc_sanitize(avgMV.y, quarterpel, fcode);
451 :    
452 :     pMBs[mbnum].mcsel = 0; /* until mode decision */
453 :     }
454 :     }

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