[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 1077 - (view) (download)

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

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