1 |
/***************************************************************************** |
2 |
* |
3 |
* XVID MPEG-4 VIDEO CODEC |
4 |
* - QPel interpolation - |
5 |
* |
6 |
* Copyright(C) 2003 Pascal Massimino <skal@planet-d.net> |
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: qpel.h,v 1.2 2004-03-22 22:36:23 edgomez Exp $ |
23 |
* |
24 |
****************************************************************************/ |
25 |
|
26 |
#ifndef _XVID_QPEL_H_ |
27 |
#define _XVID_QPEL_H_ |
28 |
|
29 |
#include "../utils/mem_transfer.h" |
30 |
|
31 |
/***************************************************************************** |
32 |
* Signatures |
33 |
****************************************************************************/ |
34 |
|
35 |
#define XVID_QP_PASS_SIGNATURE(NAME) \ |
36 |
void (NAME)(uint8_t *dst, const uint8_t *src, int32_t length, int32_t BpS, int32_t rounding) |
37 |
|
38 |
typedef XVID_QP_PASS_SIGNATURE(XVID_QP_PASS); |
39 |
|
40 |
/* We put everything in a single struct so it can easily be passed |
41 |
* to prediction functions as a whole... */ |
42 |
|
43 |
typedef struct _XVID_QP_FUNCS { |
44 |
|
45 |
/* filter for QPel 16x? prediction */ |
46 |
|
47 |
XVID_QP_PASS *H_Pass; |
48 |
XVID_QP_PASS *H_Pass_Avrg; |
49 |
XVID_QP_PASS *H_Pass_Avrg_Up; |
50 |
XVID_QP_PASS *V_Pass; |
51 |
XVID_QP_PASS *V_Pass_Avrg; |
52 |
XVID_QP_PASS *V_Pass_Avrg_Up; |
53 |
|
54 |
/* filter for QPel 8x? prediction */ |
55 |
|
56 |
XVID_QP_PASS *H_Pass_8; |
57 |
XVID_QP_PASS *H_Pass_Avrg_8; |
58 |
XVID_QP_PASS *H_Pass_Avrg_Up_8; |
59 |
XVID_QP_PASS *V_Pass_8; |
60 |
XVID_QP_PASS *V_Pass_Avrg_8; |
61 |
XVID_QP_PASS *V_Pass_Avrg_Up_8; |
62 |
} XVID_QP_FUNCS; |
63 |
|
64 |
/***************************************************************************** |
65 |
* fwd dcl |
66 |
****************************************************************************/ |
67 |
extern void xvid_Init_QP(); |
68 |
|
69 |
extern XVID_QP_FUNCS xvid_QP_Funcs_C; /* for P-frames */ |
70 |
extern XVID_QP_FUNCS xvid_QP_Add_Funcs_C; /* for B-frames */ |
71 |
|
72 |
#ifdef ARCH_IS_IA32 |
73 |
extern XVID_QP_FUNCS xvid_QP_Funcs_mmx; |
74 |
extern XVID_QP_FUNCS xvid_QP_Add_Funcs_mmx; |
75 |
#endif |
76 |
|
77 |
extern XVID_QP_FUNCS *xvid_QP_Funcs; /* <- main pointer for enc/dec structure */ |
78 |
extern XVID_QP_FUNCS *xvid_QP_Add_Funcs; /* <- main pointer for enc/dec structure */ |
79 |
|
80 |
/***************************************************************************** |
81 |
* macros |
82 |
****************************************************************************/ |
83 |
|
84 |
/***************************************************************************** |
85 |
|
86 |
Passes to be performed |
87 |
|
88 |
case 0: copy |
89 |
case 2: h-pass |
90 |
case 1/3: h-pass + h-avrg |
91 |
case 8: v-pass |
92 |
case 10: h-pass + v-pass |
93 |
case 9/11: h-pass + h-avrg + v-pass |
94 |
case 4/12: v-pass + v-avrg |
95 |
case 6/14: h-pass + v-pass + v-avrg |
96 |
case 5/13/7/15: h-pass + h-avrg + v-pass + v-avrg |
97 |
|
98 |
****************************************************************************/ |
99 |
|
100 |
static void __inline |
101 |
new_interpolate16x16_quarterpel(uint8_t * const cur, |
102 |
uint8_t * const refn, |
103 |
uint8_t * const refh, |
104 |
uint8_t * const refv, |
105 |
uint8_t * const refhv, |
106 |
const uint32_t x, const uint32_t y, |
107 |
const int32_t dx, const int dy, |
108 |
const uint32_t stride, |
109 |
const uint32_t rounding) |
110 |
{ |
111 |
const uint8_t *src; |
112 |
uint8_t *dst; |
113 |
uint8_t *tmp; |
114 |
int32_t quads; |
115 |
const XVID_QP_FUNCS *Ops; |
116 |
|
117 |
int32_t x_int, y_int; |
118 |
|
119 |
const int32_t xRef = x*4 + dx; |
120 |
const int32_t yRef = y*4 + dy; |
121 |
|
122 |
Ops = xvid_QP_Funcs; /* TODO: pass as argument */ |
123 |
quads = (dx&3) | ((dy&3)<<2); |
124 |
|
125 |
x_int = xRef/4; |
126 |
if (xRef < 0 && xRef % 4) |
127 |
x_int--; |
128 |
|
129 |
y_int = yRef/4; |
130 |
if (yRef < 0 && yRef % 4) |
131 |
y_int--; |
132 |
|
133 |
dst = cur + y * stride + x; |
134 |
src = refn + y_int * stride + x_int; |
135 |
|
136 |
tmp = refh; /* we need at least a 16 x stride scratch block */ |
137 |
|
138 |
switch(quads) { |
139 |
case 0: |
140 |
transfer8x8_copy( dst, src, stride); |
141 |
transfer8x8_copy( dst+8, src+8, stride); |
142 |
transfer8x8_copy( dst+8*stride, src+8*stride, stride); |
143 |
transfer8x8_copy( dst+8*stride+8, src+8*stride+8, stride); |
144 |
break; |
145 |
case 1: |
146 |
Ops->H_Pass_Avrg(dst, src, 16, stride, rounding); |
147 |
break; |
148 |
case 2: |
149 |
Ops->H_Pass(dst, src, 16, stride, rounding); |
150 |
break; |
151 |
case 3: |
152 |
Ops->H_Pass_Avrg_Up(dst, src, 16, stride, rounding); |
153 |
break; |
154 |
case 4: |
155 |
Ops->V_Pass_Avrg(dst, src, 16, stride, rounding); |
156 |
break; |
157 |
case 5: |
158 |
Ops->H_Pass_Avrg(tmp, src, 17, stride, rounding); |
159 |
Ops->V_Pass_Avrg(dst, tmp, 16, stride, rounding); |
160 |
break; |
161 |
case 6: |
162 |
Ops->H_Pass(tmp, src, 17, stride, rounding); |
163 |
Ops->V_Pass_Avrg(dst, tmp, 16, stride, rounding); |
164 |
break; |
165 |
case 7: |
166 |
Ops->H_Pass_Avrg_Up(tmp, src, 17, stride, rounding); |
167 |
Ops->V_Pass_Avrg(dst, tmp, 16, stride, rounding); |
168 |
break; |
169 |
case 8: |
170 |
Ops->V_Pass(dst, src, 16, stride, rounding); |
171 |
break; |
172 |
case 9: |
173 |
Ops->H_Pass_Avrg(tmp, src, 17, stride, rounding); |
174 |
Ops->V_Pass(dst, tmp, 16, stride, rounding); |
175 |
break; |
176 |
case 10: |
177 |
Ops->H_Pass(tmp, src, 17, stride, rounding); |
178 |
Ops->V_Pass(dst, tmp, 16, stride, rounding); |
179 |
break; |
180 |
case 11: |
181 |
Ops->H_Pass_Avrg_Up(tmp, src, 17, stride, rounding); |
182 |
Ops->V_Pass(dst, tmp, 16, stride, rounding); |
183 |
break; |
184 |
case 12: |
185 |
Ops->V_Pass_Avrg_Up(dst, src, 16, stride, rounding); |
186 |
break; |
187 |
case 13: |
188 |
Ops->H_Pass_Avrg(tmp, src, 17, stride, rounding); |
189 |
Ops->V_Pass_Avrg_Up(dst, tmp, 16, stride, rounding); |
190 |
break; |
191 |
case 14: |
192 |
Ops->H_Pass(tmp, src, 17, stride, rounding); |
193 |
Ops->V_Pass_Avrg_Up( dst, tmp, 16, stride, rounding); |
194 |
break; |
195 |
case 15: |
196 |
Ops->H_Pass_Avrg_Up(tmp, src, 17, stride, rounding); |
197 |
Ops->V_Pass_Avrg_Up(dst, tmp, 16, stride, rounding); |
198 |
break; |
199 |
} |
200 |
} |
201 |
|
202 |
static void __inline |
203 |
new_interpolate16x8_quarterpel(uint8_t * const cur, |
204 |
uint8_t * const refn, |
205 |
uint8_t * const refh, |
206 |
uint8_t * const refv, |
207 |
uint8_t * const refhv, |
208 |
const uint32_t x, const uint32_t y, |
209 |
const int32_t dx, const int dy, |
210 |
const uint32_t stride, |
211 |
const uint32_t rounding) |
212 |
{ |
213 |
const uint8_t *src; |
214 |
uint8_t *dst; |
215 |
uint8_t *tmp; |
216 |
int32_t quads; |
217 |
const XVID_QP_FUNCS *Ops; |
218 |
|
219 |
int32_t x_int, y_int; |
220 |
|
221 |
const int32_t xRef = x*4 + dx; |
222 |
const int32_t yRef = y*4 + dy; |
223 |
|
224 |
Ops = xvid_QP_Funcs; /* TODO: pass as argument */ |
225 |
quads = (dx&3) | ((dy&3)<<2); |
226 |
|
227 |
x_int = xRef/4; |
228 |
if (xRef < 0 && xRef % 4) |
229 |
x_int--; |
230 |
|
231 |
y_int = yRef/4; |
232 |
if (yRef < 0 && yRef % 4) |
233 |
y_int--; |
234 |
|
235 |
dst = cur + y * stride + x; |
236 |
src = refn + y_int * stride + x_int; |
237 |
|
238 |
tmp = refh; /* we need at least a 16 x stride scratch block */ |
239 |
|
240 |
switch(quads) { |
241 |
case 0: |
242 |
transfer8x8_copy( dst, src, stride); |
243 |
transfer8x8_copy( dst+8, src+8, stride); |
244 |
break; |
245 |
case 1: |
246 |
Ops->H_Pass_Avrg(dst, src, 8, stride, rounding); |
247 |
break; |
248 |
case 2: |
249 |
Ops->H_Pass(dst, src, 8, stride, rounding); |
250 |
break; |
251 |
case 3: |
252 |
Ops->H_Pass_Avrg_Up(dst, src, 8, stride, rounding); |
253 |
break; |
254 |
case 4: |
255 |
Ops->V_Pass_Avrg_8(dst, src, 16, stride, rounding); |
256 |
break; |
257 |
case 5: |
258 |
Ops->H_Pass_Avrg(tmp, src, 9, stride, rounding); |
259 |
Ops->V_Pass_Avrg_8(dst, tmp, 16, stride, rounding); |
260 |
break; |
261 |
case 6: |
262 |
Ops->H_Pass(tmp, src, 9, stride, rounding); |
263 |
Ops->V_Pass_Avrg_8(dst, tmp, 16, stride, rounding); |
264 |
break; |
265 |
case 7: |
266 |
Ops->H_Pass_Avrg_Up(tmp, src, 9, stride, rounding); |
267 |
Ops->V_Pass_Avrg_8(dst, tmp, 16, stride, rounding); |
268 |
break; |
269 |
case 8: |
270 |
Ops->V_Pass_8(dst, src, 16, stride, rounding); |
271 |
break; |
272 |
case 9: |
273 |
Ops->H_Pass_Avrg(tmp, src, 9, stride, rounding); |
274 |
Ops->V_Pass_8(dst, tmp, 16, stride, rounding); |
275 |
break; |
276 |
case 10: |
277 |
Ops->H_Pass(tmp, src, 9, stride, rounding); |
278 |
Ops->V_Pass_8(dst, tmp, 16, stride, rounding); |
279 |
break; |
280 |
case 11: |
281 |
Ops->H_Pass_Avrg_Up(tmp, src, 9, stride, rounding); |
282 |
Ops->V_Pass_8(dst, tmp, 16, stride, rounding); |
283 |
break; |
284 |
case 12: |
285 |
Ops->V_Pass_Avrg_Up_8(dst, src, 16, stride, rounding); |
286 |
break; |
287 |
case 13: |
288 |
Ops->H_Pass_Avrg(tmp, src, 9, stride, rounding); |
289 |
Ops->V_Pass_Avrg_Up_8(dst, tmp, 16, stride, rounding); |
290 |
break; |
291 |
case 14: |
292 |
Ops->H_Pass(tmp, src, 9, stride, rounding); |
293 |
Ops->V_Pass_Avrg_Up_8( dst, tmp, 16, stride, rounding); |
294 |
break; |
295 |
case 15: |
296 |
Ops->H_Pass_Avrg_Up(tmp, src, 9, stride, rounding); |
297 |
Ops->V_Pass_Avrg_Up_8(dst, tmp, 16, stride, rounding); |
298 |
break; |
299 |
} |
300 |
} |
301 |
|
302 |
static void __inline |
303 |
new_interpolate8x8_quarterpel(uint8_t * const cur, |
304 |
uint8_t * const refn, |
305 |
uint8_t * const refh, |
306 |
uint8_t * const refv, |
307 |
uint8_t * const refhv, |
308 |
const uint32_t x, const uint32_t y, |
309 |
const int32_t dx, const int dy, |
310 |
const uint32_t stride, |
311 |
const uint32_t rounding) |
312 |
{ |
313 |
const uint8_t *src; |
314 |
uint8_t *dst; |
315 |
uint8_t *tmp; |
316 |
int32_t quads; |
317 |
const XVID_QP_FUNCS *Ops; |
318 |
|
319 |
int32_t x_int, y_int; |
320 |
|
321 |
const int32_t xRef = x*4 + dx; |
322 |
const int32_t yRef = y*4 + dy; |
323 |
|
324 |
Ops = xvid_QP_Funcs; /* TODO: pass as argument */ |
325 |
quads = (dx&3) | ((dy&3)<<2); |
326 |
|
327 |
x_int = xRef/4; |
328 |
if (xRef < 0 && xRef % 4) |
329 |
x_int--; |
330 |
|
331 |
y_int = yRef/4; |
332 |
if (yRef < 0 && yRef % 4) |
333 |
y_int--; |
334 |
|
335 |
dst = cur + y * stride + x; |
336 |
src = refn + y_int * stride + x_int; |
337 |
|
338 |
tmp = refh; /* we need at least a 16 x stride scratch block */ |
339 |
|
340 |
switch(quads) { |
341 |
case 0: |
342 |
transfer8x8_copy( dst, src, stride); |
343 |
break; |
344 |
case 1: |
345 |
Ops->H_Pass_Avrg_8(dst, src, 8, stride, rounding); |
346 |
break; |
347 |
case 2: |
348 |
Ops->H_Pass_8(dst, src, 8, stride, rounding); |
349 |
break; |
350 |
case 3: |
351 |
Ops->H_Pass_Avrg_Up_8(dst, src, 8, stride, rounding); |
352 |
break; |
353 |
case 4: |
354 |
Ops->V_Pass_Avrg_8(dst, src, 8, stride, rounding); |
355 |
break; |
356 |
case 5: |
357 |
Ops->H_Pass_Avrg_8(tmp, src, 9, stride, rounding); |
358 |
Ops->V_Pass_Avrg_8(dst, tmp, 8, stride, rounding); |
359 |
break; |
360 |
case 6: |
361 |
Ops->H_Pass_8(tmp, src, 9, stride, rounding); |
362 |
Ops->V_Pass_Avrg_8(dst, tmp, 8, stride, rounding); |
363 |
break; |
364 |
case 7: |
365 |
Ops->H_Pass_Avrg_Up_8(tmp, src, 9, stride, rounding); |
366 |
Ops->V_Pass_Avrg_8(dst, tmp, 8, stride, rounding); |
367 |
break; |
368 |
case 8: |
369 |
Ops->V_Pass_8(dst, src, 8, stride, rounding); |
370 |
break; |
371 |
case 9: |
372 |
Ops->H_Pass_Avrg_8(tmp, src, 9, stride, rounding); |
373 |
Ops->V_Pass_8(dst, tmp, 8, stride, rounding); |
374 |
break; |
375 |
case 10: |
376 |
Ops->H_Pass_8(tmp, src, 9, stride, rounding); |
377 |
Ops->V_Pass_8(dst, tmp, 8, stride, rounding); |
378 |
break; |
379 |
case 11: |
380 |
Ops->H_Pass_Avrg_Up_8(tmp, src, 9, stride, rounding); |
381 |
Ops->V_Pass_8(dst, tmp, 8, stride, rounding); |
382 |
break; |
383 |
case 12: |
384 |
Ops->V_Pass_Avrg_Up_8(dst, src, 8, stride, rounding); |
385 |
break; |
386 |
case 13: |
387 |
Ops->H_Pass_Avrg_8(tmp, src, 9, stride, rounding); |
388 |
Ops->V_Pass_Avrg_Up_8(dst, tmp, 8, stride, rounding); |
389 |
break; |
390 |
case 14: |
391 |
Ops->H_Pass_8(tmp, src, 9, stride, rounding); |
392 |
Ops->V_Pass_Avrg_Up_8( dst, tmp, 8, stride, rounding); |
393 |
break; |
394 |
case 15: |
395 |
Ops->H_Pass_Avrg_Up_8(tmp, src, 9, stride, rounding); |
396 |
Ops->V_Pass_Avrg_Up_8(dst, tmp, 8, stride, rounding); |
397 |
break; |
398 |
} |
399 |
} |
400 |
|
401 |
#endif /* _XVID_QPEL_H_ */ |