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

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