Cache half-pixel interpolated reference frames, to avoid duplicate motion compensation.
[x262.git] / common / mc.c
1 /*****************************************************************************
2  * mc.c: h264 encoder library (Motion Compensation)
3  *****************************************************************************
4  * Copyright (C) 2003 Laurent Aimar
5  * $Id: mc.c,v 1.1 2004/06/03 19:27:07 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #ifdef HAVE_STDINT_H
25 #include <stdint.h>
26 #else
27 #include <inttypes.h>
28 #endif
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdarg.h>
33
34 #include "x264.h"
35
36 #include "mc.h"
37 #include "clip1.h"
38 #include "frame.h"
39
40 #ifdef _MSC_VER
41 #undef HAVE_MMXEXT  /* not finished now */
42 #endif
43 #ifdef HAVE_MMXEXT
44 #   include "i386/mc.h"
45 #endif
46 #ifdef ARCH_PPC
47 #   include "ppc/mc.h"
48 #endif
49
50
51 static inline int x264_tapfilter( uint8_t *pix, int i_pix_next )
52 {
53     return pix[-2*i_pix_next] - 5*pix[-1*i_pix_next] + 20*(pix[0] + pix[1*i_pix_next]) - 5*pix[ 2*i_pix_next] + pix[ 3*i_pix_next];
54 }
55 static inline int x264_tapfilter1( uint8_t *pix )
56 {
57     return pix[-2] - 5*pix[-1] + 20*(pix[0] + pix[1]) - 5*pix[ 2] + pix[ 3];
58 }
59
60 static inline void pixel_avg( uint8_t *dst,  int i_dst_stride,
61                               uint8_t *src1, int i_src1_stride,
62                               uint8_t *src2, int i_src2_stride,
63                               int i_width, int i_height )
64 {
65     int x, y;
66     for( y = 0; y < i_height; y++ )
67     {
68         for( x = 0; x < i_width; x++ )
69         {
70             dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;
71         }
72         dst  += i_dst_stride;
73         src1 += i_src1_stride;
74         src2 += i_src2_stride;
75     }
76 }
77
78 typedef void (*pf_mc_t)(uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height );
79
80 static void mc_copy( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
81 {
82     int y;
83
84     for( y = 0; y < i_height; y++ )
85     {
86         memcpy( dst, src, i_width );
87
88         src += i_src_stride;
89         dst += i_dst_stride;
90     }
91 }
92 static inline void mc_hh( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
93 {
94     int x, y;
95
96     for( y = 0; y < i_height; y++ )
97     {
98         for( x = 0; x < i_width; x++ )
99         {
100             dst[x] = x264_mc_clip1( ( x264_tapfilter1( &src[x] ) + 16 ) >> 5 );
101         }
102         src += i_src_stride;
103         dst += i_dst_stride;
104     }
105 }
106 static inline void mc_hv( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
107 {
108     int x, y;
109
110     for( y = 0; y < i_height; y++ )
111     {
112         for( x = 0; x < i_width; x++ )
113         {
114             dst[x] = x264_mc_clip1( ( x264_tapfilter( &src[x], i_src_stride ) + 16 ) >> 5 );
115         }
116         src += i_src_stride;
117         dst += i_dst_stride;
118     }
119 }
120 static inline void mc_hc( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
121 {
122     uint8_t *out;
123     uint8_t *pix;
124     int x, y;
125
126     for( x = 0; x < i_width; x++ )
127     {
128         int tap[6];
129
130         pix = &src[x];
131         out = &dst[x];
132
133         tap[0] = x264_tapfilter1( &pix[-2*i_src_stride] );
134         tap[1] = x264_tapfilter1( &pix[-1*i_src_stride] );
135         tap[2] = x264_tapfilter1( &pix[ 0*i_src_stride] );
136         tap[3] = x264_tapfilter1( &pix[ 1*i_src_stride] );
137         tap[4] = x264_tapfilter1( &pix[ 2*i_src_stride] );
138
139         for( y = 0; y < i_height; y++ )
140         {
141             tap[5] = x264_tapfilter1( &pix[ 3*i_src_stride] );
142
143             *out = x264_mc_clip1( ( tap[0] - 5*tap[1] + 20 * tap[2] + 20 * tap[3] -5*tap[4] + tap[5] + 512 ) >> 10 );
144
145             /* Next line */
146             pix += i_src_stride;
147             out += i_dst_stride;
148             tap[0] = tap[1];
149             tap[1] = tap[2];
150             tap[2] = tap[3];
151             tap[3] = tap[4];
152             tap[4] = tap[5];
153         }
154     }
155 }
156
157 /* mc I+H */
158 static void mc_xy10( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
159 {
160     uint8_t tmp[16*16];
161     mc_hh( src, i_src_stride, tmp, i_width, i_width, i_height );
162     pixel_avg( dst, i_dst_stride, src, i_src_stride, tmp, i_width, i_width, i_height );
163 }
164 static void mc_xy30( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
165 {
166     uint8_t tmp[16*16];
167     mc_hh( src, i_src_stride, tmp, i_width, i_width, i_height );
168     pixel_avg( dst, i_dst_stride, src+1, i_src_stride, tmp, i_width, i_width, i_height );
169 }
170 /* mc I+V */
171 static void mc_xy01( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
172 {
173     uint8_t tmp[16*16];
174     mc_hv( src, i_src_stride, tmp, i_width, i_width, i_height );
175     pixel_avg( dst, i_dst_stride, src, i_src_stride, tmp, i_width, i_width, i_height );
176 }
177 static void mc_xy03( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
178 {
179     uint8_t tmp[16*16];
180     mc_hv( src, i_src_stride, tmp, i_width, i_width, i_height );
181     pixel_avg( dst, i_dst_stride, src+i_src_stride, i_src_stride, tmp, i_width, i_width, i_height );
182 }
183 /* H+V */
184 static void mc_xy11( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
185 {
186     uint8_t tmp1[16*16];
187     uint8_t tmp2[16*16];
188
189     mc_hv( src, i_src_stride, tmp1, i_width, i_width, i_height );
190     mc_hh( src, i_src_stride, tmp2, i_width, i_width, i_height );
191     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
192 }
193 static void mc_xy31( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
194 {
195     uint8_t tmp1[16*16];
196     uint8_t tmp2[16*16];
197
198     mc_hv( src+1, i_src_stride, tmp1, i_width, i_width, i_height );
199     mc_hh( src,   i_src_stride, tmp2, i_width, i_width, i_height );
200     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
201 }
202 static void mc_xy13( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
203 {
204     uint8_t tmp1[16*16];
205     uint8_t tmp2[16*16];
206
207     mc_hv( src,              i_src_stride, tmp1, i_width, i_width, i_height );
208     mc_hh( src+i_src_stride, i_src_stride, tmp2, i_width, i_width, i_height );
209     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
210 }
211 static void mc_xy33( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
212 {
213     uint8_t tmp1[16*16];
214     uint8_t tmp2[16*16];
215
216     mc_hv( src+1,            i_src_stride, tmp1, i_width, i_width, i_height );
217     mc_hh( src+i_src_stride, i_src_stride, tmp2, i_width, i_width, i_height );
218     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
219 }
220 static void mc_xy21( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
221 {
222     uint8_t tmp1[16*16];
223     uint8_t tmp2[16*16];
224
225     mc_hc( src, i_src_stride, tmp1, i_width, i_width, i_height );
226     mc_hh( src, i_src_stride, tmp2, i_width, i_width, i_height );
227     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
228 }
229 static void mc_xy12( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
230 {
231     uint8_t tmp1[16*16];
232     uint8_t tmp2[16*16];
233
234     mc_hc( src, i_src_stride, tmp1, i_width, i_width, i_height );
235     mc_hv( src, i_src_stride, tmp2, i_width, i_width, i_height );
236     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
237 }
238 static void mc_xy32( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
239 {
240     uint8_t tmp1[16*16];
241     uint8_t tmp2[16*16];
242
243     mc_hc( src,   i_src_stride, tmp1, i_width, i_width, i_height );
244     mc_hv( src+1, i_src_stride, tmp2, i_width, i_width, i_height );
245     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
246 }
247 static void mc_xy23( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
248 {
249     uint8_t tmp1[16*16];
250     uint8_t tmp2[16*16];
251
252     mc_hc( src,              i_src_stride, tmp1, i_width, i_width, i_height );
253     mc_hh( src+i_src_stride, i_src_stride, tmp2, i_width, i_width, i_height );
254     pixel_avg( dst, i_dst_stride, tmp1, i_width, tmp2, i_width, i_width, i_height );
255 }
256
257 static void motion_compensation_luma( uint8_t *src, int i_src_stride,
258                                       uint8_t *dst, int i_dst_stride,
259                                       int mvx,int mvy,
260                                       int i_width, int i_height )
261 {
262     static pf_mc_t pf_mc[4][4] =    /*XXX [dqy][dqx] */
263     {
264         { mc_copy,  mc_xy10,    mc_hh,      mc_xy30 },
265         { mc_xy01,  mc_xy11,    mc_xy21,    mc_xy31 },
266         { mc_hv,    mc_xy12,    mc_hc,      mc_xy32 },
267         { mc_xy03,  mc_xy13,    mc_xy23,    mc_xy33 },
268     };
269
270     src += (mvy >> 2) * i_src_stride + (mvx >> 2);
271     pf_mc[mvy&0x03][mvx&0x03]( src, i_src_stride, dst, i_dst_stride, i_width, i_height );
272 }
273
274 void mc_luma( uint8_t *src[4], int i_src_stride,
275               uint8_t *dst,    int i_dst_stride,
276               int mvx,int mvy,
277               int i_width, int i_height )
278 {
279     uint8_t *src1, *src2;
280
281     /* todo : fixme... */
282     int correction = ((mvx&3) == 3 && (mvy&3) == 1 || (mvx&3) == 1 && (mvy&3) == 3) ? 1:0;
283
284     int hpel1x = mvx>>1;
285     int hpel1y = (mvy+1-correction)>>1;
286     int filter1 = (hpel1x & 1) + ( (hpel1y & 1) << 1 );
287
288
289     src1 = src[filter1] + (hpel1y >> 1) * i_src_stride + (hpel1x >> 1);
290
291     if ( (mvx|mvy) & 1 ) /* qpel interpolation needed */
292     {
293         int hpel2x = (mvx+1)>>1;
294         int hpel2y = (mvy+correction)>>1;
295         int filter2 = (hpel2x & 1) + ( (hpel2y & 1) <<1 );
296
297         src2 = src[filter2] + (hpel2y >> 1) * i_src_stride + (hpel2x >> 1);
298     
299         pixel_avg( dst, i_dst_stride, src1, i_src_stride,
300                    src2, i_src_stride, i_width, i_height );
301
302     }
303     else
304     {
305         mc_copy( src1, i_src_stride, dst, i_dst_stride, i_width, i_height );
306
307     }
308 }
309
310 uint8_t *get_ref( uint8_t *src[4], int i_src_stride,
311                   uint8_t *dst,    int * i_dst_stride,
312                   int mvx,int mvy,
313                   int i_width, int i_height )
314 {
315     uint8_t *src1, *src2;
316
317     /* todo : fixme... */
318     int correction = ((mvx&3) == 3 && (mvy&3) == 1 || (mvx&3) == 1 && (mvy&3) == 3) ? 1:0;
319
320     int hpel1x = mvx>>1;
321     int hpel1y = (mvy+1-correction)>>1;
322     int filter1 = (hpel1x & 1) + ( (hpel1y & 1) << 1 );
323
324
325     src1 = src[filter1] + (hpel1y >> 1) * i_src_stride + (hpel1x >> 1);
326
327     if ( (mvx|mvy) & 1 ) /* qpel interpolation needed */
328     {
329         int hpel2x = (mvx+1)>>1;
330         int hpel2y = (mvy+correction)>>1;
331         int filter2 = (hpel2x & 1) + ( (hpel2y & 1) <<1 );
332
333         src2 = src[filter2] + (hpel2y >> 1) * i_src_stride + (hpel2x >> 1);
334     
335         pixel_avg( dst, *i_dst_stride, src1, i_src_stride,
336                    src2, i_src_stride, i_width, i_height );
337
338         return dst;
339
340     }
341     else
342     {
343         *i_dst_stride = i_src_stride;
344         return src1;
345     }
346 }
347
348 /* full chroma mc (ie until 1/8 pixel)*/
349 static void motion_compensation_chroma( uint8_t *src, int i_src_stride,
350                                         uint8_t *dst, int i_dst_stride,
351                                         int mvx, int mvy,
352                                         int i_width, int i_height )
353 {
354     uint8_t *srcp;
355     int x, y;
356
357     const int d8x = mvx&0x07;
358     const int d8y = mvy&0x07;
359
360     const int cA = (8-d8x)*(8-d8y);
361     const int cB = d8x    *(8-d8y);
362     const int cC = (8-d8x)*d8y;
363     const int cD = d8x    *d8y;
364
365     src  += (mvy >> 3) * i_src_stride + (mvx >> 3);
366     srcp = &src[i_src_stride];
367
368     for( y = 0; y < i_height; y++ )
369     {
370         for( x = 0; x < i_width; x++ )
371         {
372             dst[x] = ( cA*src[x]  + cB*src[x+1] +
373                        cC*srcp[x] + cD*srcp[x+1] + 32 ) >> 6;
374         }
375         dst  += i_dst_stride;
376
377         src   = srcp;
378         srcp += i_src_stride;
379     }
380 }
381
382 void x264_mc_init( int cpu, x264_mc_functions_t *pf )
383 {
384     pf->mc_luma   = mc_luma;
385     pf->get_ref   = get_ref;
386     pf->mc_chroma = motion_compensation_chroma;
387
388 #ifdef HAVE_MMXEXT
389     if( cpu&X264_CPU_MMXEXT )
390         x264_mc_mmxext_init( pf );
391 #endif
392 #ifdef HAVE_SSE2
393     if( cpu&X264_CPU_SSE2 )
394         x264_mc_sse2_init( pf );
395 #endif
396 /*
397 #ifdef ARCH_PPC
398     if( cpu&X264_CPU_ALTIVEC )
399         x264_mc_altivec_init( pf );
400 #endif
401 */
402 }
403
404 void get_funcs_mmx(pf_mc_t*, pf_mc_t*, pf_mc_t*);
405 void get_funcs_sse2(pf_mc_t*, pf_mc_t*, pf_mc_t*);
406
407 void x264_frame_filter( int cpu, x264_frame_t *frame )
408 {
409     const int x_inc = 16, y_inc = 16;
410     const int stride = frame->i_stride[0];
411     int x, y;
412
413     pf_mc_t int_h = mc_hh;
414     pf_mc_t int_v = mc_hv;
415     pf_mc_t int_hv = mc_hc;
416
417 #ifdef HAVE_MMXEXT
418     if( cpu&X264_CPU_MMXEXT )
419         get_funcs_mmx(&int_h, &int_v, &int_hv);
420 #endif
421
422 #ifdef HAVE_SSE2
423     if( cpu&X264_CPU_SSE2 )
424         get_funcs_sse2(&int_h, &int_v, &int_hv);
425 #endif
426
427     for( y = -8; y < frame->i_lines[0]+8; y += y_inc ) {
428         
429         uint8_t *p_in = frame->plane[0] + y * stride - 8;
430         uint8_t *p_h  = frame->filtered[1] + y * stride - 8;
431         uint8_t *p_v  = frame->filtered[2] + y * stride - 8;
432         uint8_t *p_hv = frame->filtered[3] + y * stride - 8;
433
434         for( x = -8; x < stride - 64 + 8; x += x_inc )
435         {
436             int_h(  p_in, stride, p_h,  stride, x_inc, y_inc );
437             int_v(  p_in, stride, p_v,  stride, x_inc, y_inc );
438             int_hv( p_in, stride, p_hv, stride, x_inc, y_inc );
439
440             p_h += x_inc;
441             p_v += x_inc;
442             p_hv += x_inc;
443             p_in += x_inc;
444         }
445     }
446 }