Add partially accelerated mc_luma
[x262.git] / common / mc.c
1 /*****************************************************************************
2  * mc.c: motion compensation
3  *****************************************************************************
4  * Copyright (C) 2003-2014 x264 project
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *          Loren Merritt <lorenm@u.washington.edu>
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., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
22  *
23  * This program is also available under a commercial proprietary license.
24  * For more information, contact us at licensing@x264.com.
25  *****************************************************************************/
26
27 #include "common.h"
28
29 #if HAVE_MMX
30 #include "x86/mc.h"
31 #endif
32 #if ARCH_PPC
33 #include "ppc/mc.h"
34 #endif
35 #if ARCH_ARM
36 #include "arm/mc.h"
37 #endif
38
39
40 static inline void pixel_avg( pixel *dst,  intptr_t i_dst_stride,
41                               pixel *src1, intptr_t i_src1_stride,
42                               pixel *src2, intptr_t i_src2_stride, int i_width, int i_height )
43 {
44     for( int y = 0; y < i_height; y++ )
45     {
46         for( int x = 0; x < i_width; x++ )
47             dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;
48         dst  += i_dst_stride;
49         src1 += i_src1_stride;
50         src2 += i_src2_stride;
51     }
52 }
53
54 static inline void pixel_avg_wxh( pixel *dst,  intptr_t i_dst,
55                                   pixel *src1, intptr_t i_src1,
56                                   pixel *src2, intptr_t i_src2, int width, int height )
57 {
58     for( int y = 0; y < height; y++ )
59     {
60         for( int x = 0; x < width; x++ )
61             dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;
62         src1 += i_src1;
63         src2 += i_src2;
64         dst += i_dst;
65     }
66 }
67
68 /* Implicit weighted bipred only:
69  * assumes log2_denom = 5, offset = 0, weight1 + weight2 = 64 */
70 static inline void pixel_avg_weight_wxh( pixel *dst,  intptr_t i_dst,
71                                          pixel *src1, intptr_t i_src1,
72                                          pixel *src2, intptr_t i_src2, int width, int height, int i_weight1 )
73 {
74     int i_weight2 = 64 - i_weight1;
75     for( int y = 0; y<height; y++, dst += i_dst, src1 += i_src1, src2 += i_src2 )
76         for( int x = 0; x<width; x++ )
77             dst[x] = x264_clip_pixel( (src1[x]*i_weight1 + src2[x]*i_weight2 + (1<<5)) >> 6 );
78 }
79 #undef op_scale2
80
81 #define PIXEL_AVG_C( name, width, height ) \
82 static void name( pixel *pix1, intptr_t i_stride_pix1, \
83                   pixel *pix2, intptr_t i_stride_pix2, \
84                   pixel *pix3, intptr_t i_stride_pix3, int weight ) \
85 { \
86     if( weight == 32 ) \
87         pixel_avg_wxh( pix1, i_stride_pix1, pix2, i_stride_pix2, pix3, i_stride_pix3, width, height ); \
88     else \
89         pixel_avg_weight_wxh( pix1, i_stride_pix1, pix2, i_stride_pix2, pix3, i_stride_pix3, width, height, weight ); \
90 }
91 PIXEL_AVG_C( pixel_avg_16x16, 16, 16 )
92 PIXEL_AVG_C( pixel_avg_16x8,  16, 8 )
93 PIXEL_AVG_C( pixel_avg_8x16,  8, 16 )
94 PIXEL_AVG_C( pixel_avg_8x8,   8, 8 )
95 PIXEL_AVG_C( pixel_avg_8x4,   8, 4 )
96 PIXEL_AVG_C( pixel_avg_4x16,  4, 16 )
97 PIXEL_AVG_C( pixel_avg_4x8,   4, 8 )
98 PIXEL_AVG_C( pixel_avg_4x4,   4, 4 )
99 PIXEL_AVG_C( pixel_avg_4x2,   4, 2 )
100 PIXEL_AVG_C( pixel_avg_2x8,   2, 8 )
101 PIXEL_AVG_C( pixel_avg_2x4,   2, 4 )
102 PIXEL_AVG_C( pixel_avg_2x2,   2, 2 )
103
104 static void x264_weight_cache( x264_t *h, x264_weight_t *w )
105 {
106     w->weightfn = h->mc.weight;
107 }
108 #define opscale(x) dst[x] = x264_clip_pixel( ((src[x] * scale + (1<<(denom - 1))) >> denom) + offset )
109 #define opscale_noden(x) dst[x] = x264_clip_pixel( src[x] * scale + offset )
110 static void mc_weight( pixel *dst, intptr_t i_dst_stride, pixel *src, intptr_t i_src_stride,
111                        const x264_weight_t *weight, int i_width, int i_height )
112 {
113     int offset = weight->i_offset << (BIT_DEPTH-8);
114     int scale = weight->i_scale;
115     int denom = weight->i_denom;
116     if( denom >= 1 )
117     {
118         for( int y = 0; y < i_height; y++, dst += i_dst_stride, src += i_src_stride )
119             for( int x = 0; x < i_width; x++ )
120                 opscale( x );
121     }
122     else
123     {
124         for( int y = 0; y < i_height; y++, dst += i_dst_stride, src += i_src_stride )
125             for( int x = 0; x < i_width; x++ )
126                 opscale_noden( x );
127     }
128 }
129
130 #define MC_WEIGHT_C( name, width ) \
131     static void name( pixel *dst, intptr_t i_dst_stride, pixel *src, intptr_t i_src_stride, const x264_weight_t *weight, int height ) \
132 { \
133     mc_weight( dst, i_dst_stride, src, i_src_stride, weight, width, height );\
134 }
135
136 MC_WEIGHT_C( mc_weight_w20, 20 )
137 MC_WEIGHT_C( mc_weight_w16, 16 )
138 MC_WEIGHT_C( mc_weight_w12, 12 )
139 MC_WEIGHT_C( mc_weight_w8,   8 )
140 MC_WEIGHT_C( mc_weight_w4,   4 )
141 MC_WEIGHT_C( mc_weight_w2,   2 )
142
143 static weight_fn_t x264_mc_weight_wtab[6] =
144 {
145     mc_weight_w2,
146     mc_weight_w4,
147     mc_weight_w8,
148     mc_weight_w12,
149     mc_weight_w16,
150     mc_weight_w20,
151 };
152 const x264_weight_t x264_weight_none[3] = { {{0}} };
153 static void mc_copy( pixel *src, intptr_t i_src_stride, pixel *dst, intptr_t i_dst_stride, int i_width, int i_height )
154 {
155     for( int y = 0; y < i_height; y++ )
156     {
157         memcpy( dst, src, i_width * sizeof(pixel) );
158
159         src += i_src_stride;
160         dst += i_dst_stride;
161     }
162 }
163
164 #define TAPFILTER(pix, d) ((pix)[x-2*d] + (pix)[x+3*d] - 5*((pix)[x-d] + (pix)[x+2*d]) + 20*((pix)[x] + (pix)[x+d]))
165 static void hpel_filter( pixel *dsth, pixel *dstv, pixel *dstc, pixel *src,
166                          intptr_t stride, int width, int height, int16_t *buf )
167 {
168     const int pad = (BIT_DEPTH > 9) ? (-10 * PIXEL_MAX) : 0;
169     for( int y = 0; y < height; y++ )
170     {
171         for( int x = -2; x < width+3; x++ )
172         {
173             int v = TAPFILTER(src,stride);
174             dstv[x] = x264_clip_pixel( (v + 16) >> 5 );
175             /* transform v for storage in a 16-bit integer */
176             buf[x+2] = v + pad;
177         }
178         for( int x = 0; x < width; x++ )
179             dstc[x] = x264_clip_pixel( (TAPFILTER(buf+2,1) - 32*pad + 512) >> 10 );
180         for( int x = 0; x < width; x++ )
181             dsth[x] = x264_clip_pixel( (TAPFILTER(src,1) + 16) >> 5 );
182         dsth += stride;
183         dstv += stride;
184         dstc += stride;
185         src += stride;
186     }
187 }
188
189 static const uint8_t hpel_ref0[16] = {0,1,1,1,0,1,1,1,2,3,3,3,0,1,1,1};
190 static const uint8_t hpel_ref1[16] = {0,0,0,0,2,2,3,2,2,2,3,2,2,2,3,2};
191
192 static void mc_luma( pixel *dst,    intptr_t i_dst_stride,
193                      pixel *src[4], intptr_t i_src_stride,
194                      int mvx, int mvy,
195                      int i_width, int i_height, const x264_weight_t *weight )
196 {
197     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
198     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
199     pixel *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
200
201     if( qpel_idx & 5 ) /* qpel interpolation needed */
202     {
203         pixel *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
204         pixel_avg( dst, i_dst_stride, src1, i_src_stride,
205                    src2, i_src_stride, i_width, i_height );
206         if( weight->weightfn )
207             mc_weight( dst, i_dst_stride, dst, i_dst_stride, weight, i_width, i_height );
208     }
209     else if( weight->weightfn )
210         mc_weight( dst, i_dst_stride, src1, i_src_stride, weight, i_width, i_height );
211     else
212         mc_copy( src1, i_src_stride, dst, i_dst_stride, i_width, i_height );
213 }
214
215 static pixel *get_ref( pixel *dst,   intptr_t *i_dst_stride,
216                        pixel *src[4], intptr_t i_src_stride,
217                        int mvx, int mvy,
218                        int i_width, int i_height, const x264_weight_t *weight )
219 {
220     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
221     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
222     pixel *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
223
224     if( qpel_idx & 5 ) /* qpel interpolation needed */
225     {
226         pixel *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
227         pixel_avg( dst, *i_dst_stride, src1, i_src_stride,
228                    src2, i_src_stride, i_width, i_height );
229         if( weight->weightfn )
230             mc_weight( dst, *i_dst_stride, dst, *i_dst_stride, weight, i_width, i_height );
231         return dst;
232     }
233     else if( weight->weightfn )
234     {
235         mc_weight( dst, *i_dst_stride, src1, i_src_stride, weight, i_width, i_height );
236         return dst;
237     }
238     else
239     {
240         *i_dst_stride = i_src_stride;
241         return src1;
242     }
243 }
244
245 static void mc_luma_mpeg2( pixel *dst,    intptr_t i_dst_stride,
246                            pixel *src[4], intptr_t i_src_stride,
247                            int mvx, int mvy,
248                            int i_width, int i_height, const x264_weight_t *weight )
249 {
250     mvx >>= 1;
251     mvy >>= 1;
252
253     int offset = (mvy>>1)*i_src_stride + (mvx>>1);
254     pixel *src1 = src[0] + offset;
255     pixel *srcp = src1 + i_src_stride;
256
257     if( !((mvx|mvy)&1) ) // fullpel
258         mc_copy( src1, i_src_stride, dst, i_dst_stride, i_width, i_height );
259     else if( (mvx&mvy)&1 ) // centre hpel positions
260     {
261         for( int y = 0; y < i_height; y++ )
262         {
263             for( int x = 0; x < i_width; x++ )
264                 dst[x] = ( src1[x] + src1[x+1] + srcp[x] + srcp[x+1] + 2 ) >> 2;
265             dst  += i_dst_stride;
266             src1  = srcp;
267             srcp += i_src_stride;
268         }
269     }
270     else if( mvx&1 ) // horizontal hpel positions
271     {
272         pixel *src2 = src1 + 1;
273         pixel_avg( dst, i_dst_stride, src1, i_src_stride,
274                    src2, i_src_stride, i_width, i_height );
275     }
276     else // vertical hpel positions
277     {
278         pixel_avg( dst, i_dst_stride, src1, i_src_stride,
279                    srcp, i_src_stride, i_width, i_height );
280     }
281 }
282
283 static void mc_chroma_mpeg2( pixel *dstu, pixel *dstv, intptr_t i_dst_stride,
284                              pixel *src, intptr_t i_src_stride,
285                              int mvx, int mvy,
286                              int i_width, int i_height )
287 {
288     mvx /= 4;
289     mvy /= 4;
290     src += (mvy >> 1) * i_src_stride + (mvx >> 1)*2;
291     pixel *srcp = &src[i_src_stride];
292
293     if( !((mvx|mvy)&1) ) //fullpell
294     {
295         for( int y = 0; y < i_height; y++ )
296         {
297             for( int x = 0; x < i_width; x++ )
298             {
299                 dstu[x] = src[2*x];
300                 dstv[x] = src[2*x+1];
301             }
302             dstu += i_dst_stride;
303             dstv += i_dst_stride;
304             src += i_src_stride;
305         }
306     }
307     else if( (mvx&mvy)&1 ) // centre hpel positions
308     {
309         for( int y = 0; y < i_height; y++ )
310         {
311             for( int x = 0; x < i_width; x++ )
312             {
313                 dstu[x] = ( src[2*x] + src[2*x+2] + srcp[2*x] + srcp[2*x+2] + 2 ) >> 2;
314                 dstv[x] = ( src[2*x+1] + src[2*x+3] + srcp[2*x+1] + srcp[2*x+3] + 2 ) >> 2;
315             }
316             dstu += i_dst_stride;
317             dstv += i_dst_stride;
318             src   = srcp;
319             srcp += i_src_stride;
320         }
321     }
322     else if( mvx&1 ) // horizontal hpel positions
323     {
324         for( int y = 0; y < i_height; y++ )
325         {
326             for( int x = 0; x < i_width; x++ )
327             {
328                 dstu[x] = ( src[2*x] + src[2*x+2] + 1 ) >> 1;
329                 dstv[x] = ( src[2*x+1] + src[2*x+3] + 1 ) >> 1;
330             }
331             dstu += i_dst_stride;
332             dstv += i_dst_stride;
333             src  += i_src_stride;
334         }
335     }
336     else // vertical hpel positions
337     {
338         for( int y = 0; y < i_height; y++ )
339         {
340             for( int x = 0; x < i_width; x++ )
341             {
342                 dstu[x] = ( src[2*x] + srcp[2*x] + 1 ) >> 1;
343                 dstv[x] = ( src[2*x+1] + srcp[2*x+1] + 1 ) >> 1;
344             }
345             dstu += i_dst_stride;
346             dstv += i_dst_stride;
347             src = srcp;
348             srcp += i_src_stride;
349         }
350     }
351 }
352
353 static pixel *get_ref_mpeg2( pixel *dst,    intptr_t *i_dst_stride,
354                              pixel *src[4], intptr_t i_src_stride,
355                              int mvx, int mvy,
356                              int i_width, int i_height, const x264_weight_t *weight )
357 {
358     mvx >>= 1;
359     mvy >>= 1;
360
361     pixel *src1 = src[0] + (mvy>>1)*i_src_stride + (mvx>>1);
362     pixel *srcp = src1 + i_src_stride;
363     pixel *dst_bak = dst;
364
365     if( !((mvx|mvy)&1) ) // fullpel
366     {
367         *i_dst_stride = i_src_stride;
368         return src1;
369     }
370     else if( (mvx&mvy)&1 ) // centre hpel positions
371     {
372         for( int y = 0; y < i_height; y++ )
373         {
374             for( int x = 0; x < i_width; x++ )
375                 dst[x] = ( src1[x] + src1[x+1] + srcp[x] + srcp[x+1] + 2 ) >> 2;
376             dst  += *i_dst_stride;
377             src1  = srcp;
378             srcp += i_src_stride;
379         }
380     }
381     else if( mvx&1 ) // horizontal hpel positions
382     {
383         pixel *src2 = src1 + 1;
384         pixel_avg( dst, *i_dst_stride, src1, i_src_stride,
385                    src2, i_src_stride, i_width, i_height );
386     }
387     else // vertical hpel positions
388     {
389         pixel_avg( dst, *i_dst_stride, src1, i_src_stride,
390                    srcp, i_src_stride, i_width, i_height );
391     }
392
393     return dst_bak;
394 }
395
396 /* full chroma mc (ie until 1/8 pixel)*/
397 static void mc_chroma( pixel *dstu, pixel *dstv, intptr_t i_dst_stride,
398                        pixel *src, intptr_t i_src_stride,
399                        int mvx, int mvy,
400                        int i_width, int i_height )
401 {
402     pixel *srcp;
403
404     int d8x = mvx&0x07;
405     int d8y = mvy&0x07;
406     int cA = (8-d8x)*(8-d8y);
407     int cB = d8x    *(8-d8y);
408     int cC = (8-d8x)*d8y;
409     int cD = d8x    *d8y;
410
411     src += (mvy >> 3) * i_src_stride + (mvx >> 3)*2;
412     srcp = &src[i_src_stride];
413
414     for( int y = 0; y < i_height; y++ )
415     {
416         for( int x = 0; x < i_width; x++ )
417         {
418             dstu[x] = ( cA*src[2*x]  + cB*src[2*x+2] +
419                         cC*srcp[2*x] + cD*srcp[2*x+2] + 32 ) >> 6;
420             dstv[x] = ( cA*src[2*x+1]  + cB*src[2*x+3] +
421                         cC*srcp[2*x+1] + cD*srcp[2*x+3] + 32 ) >> 6;
422         }
423         dstu += i_dst_stride;
424         dstv += i_dst_stride;
425         src   = srcp;
426         srcp += i_src_stride;
427     }
428 }
429
430 #define MC_COPY(W) \
431 static void mc_copy_w##W( pixel *dst, intptr_t i_dst, pixel *src, intptr_t i_src, int i_height ) \
432 { \
433     mc_copy( src, i_src, dst, i_dst, W, i_height ); \
434 }
435 MC_COPY( 16 )
436 MC_COPY( 8 )
437 MC_COPY( 4 )
438
439 void x264_plane_copy_c( pixel *dst, intptr_t i_dst,
440                         pixel *src, intptr_t i_src, int w, int h )
441 {
442     while( h-- )
443     {
444         memcpy( dst, src, w * sizeof(pixel) );
445         dst += i_dst;
446         src += i_src;
447     }
448 }
449
450 void x264_plane_copy_interleave_c( pixel *dst,  intptr_t i_dst,
451                                    pixel *srcu, intptr_t i_srcu,
452                                    pixel *srcv, intptr_t i_srcv, int w, int h )
453 {
454     for( int y=0; y<h; y++, dst+=i_dst, srcu+=i_srcu, srcv+=i_srcv )
455         for( int x=0; x<w; x++ )
456         {
457             dst[2*x]   = srcu[x];
458             dst[2*x+1] = srcv[x];
459         }
460 }
461
462 static void x264_plane_copy_deinterleave_c( pixel *dstu, intptr_t i_dstu,
463                                             pixel *dstv, intptr_t i_dstv,
464                                             pixel *src,  intptr_t i_src, int w, int h )
465 {
466     for( int y=0; y<h; y++, dstu+=i_dstu, dstv+=i_dstv, src+=i_src )
467         for( int x=0; x<w; x++ )
468         {
469             dstu[x] = src[2*x];
470             dstv[x] = src[2*x+1];
471         }
472 }
473
474 static void x264_plane_copy_deinterleave_rgb_c( pixel *dsta, intptr_t i_dsta,
475                                                 pixel *dstb, intptr_t i_dstb,
476                                                 pixel *dstc, intptr_t i_dstc,
477                                                 pixel *src,  intptr_t i_src, int pw, int w, int h )
478 {
479     for( int y=0; y<h; y++, dsta+=i_dsta, dstb+=i_dstb, dstc+=i_dstc, src+=i_src )
480     {
481         for( int x=0; x<w; x++ )
482         {
483             dsta[x] = src[x*pw];
484             dstb[x] = src[x*pw+1];
485             dstc[x] = src[x*pw+2];
486         }
487     }
488 }
489
490 void x264_plane_copy_deinterleave_v210_c( pixel *dsty, intptr_t i_dsty,
491                                           pixel *dstc, intptr_t i_dstc,
492                                           uint32_t *src, intptr_t i_src, int w, int h )
493 {
494     for( int l = 0; l < h; l++ )
495     {
496         pixel *dsty0 = dsty;
497         pixel *dstc0 = dstc;
498         uint32_t *src0 = src;
499
500         for( int n = 0; n < w; n += 3 )
501         {
502             *(dstc0++) = *src0 & 0x03FF;
503             *(dsty0++) = ( *src0 >> 10 ) & 0x03FF;
504             *(dstc0++) = ( *src0 >> 20 ) & 0x03FF;
505             src0++;
506             *(dsty0++) = *src0 & 0x03FF;
507             *(dstc0++) = ( *src0 >> 10 ) & 0x03FF;
508             *(dsty0++) = ( *src0 >> 20 ) & 0x03FF;
509             src0++;
510         }
511
512         dsty += i_dsty;
513         dstc += i_dstc;
514         src  += i_src;
515     }
516 }
517
518 static void store_interleave_chroma( pixel *dst, intptr_t i_dst, pixel *srcu, pixel *srcv, int height )
519 {
520     for( int y=0; y<height; y++, dst+=i_dst, srcu+=FDEC_STRIDE, srcv+=FDEC_STRIDE )
521         for( int x=0; x<8; x++ )
522         {
523             dst[2*x]   = srcu[x];
524             dst[2*x+1] = srcv[x];
525         }
526 }
527
528 static void load_deinterleave_chroma_fenc( pixel *dst, pixel *src, intptr_t i_src, int height )
529 {
530     x264_plane_copy_deinterleave_c( dst, FENC_STRIDE, dst+FENC_STRIDE/2, FENC_STRIDE, src, i_src, 8, height );
531 }
532
533 static void load_deinterleave_chroma_fdec( pixel *dst, pixel *src, intptr_t i_src, int height )
534 {
535     x264_plane_copy_deinterleave_c( dst, FDEC_STRIDE, dst+FDEC_STRIDE/2, FDEC_STRIDE, src, i_src, 8, height );
536 }
537
538 static void prefetch_fenc_null( pixel *pix_y,  intptr_t stride_y,
539                                 pixel *pix_uv, intptr_t stride_uv, int mb_x )
540 {}
541
542 static void prefetch_ref_null( pixel *pix, intptr_t stride, int parity )
543 {}
544
545 static void memzero_aligned( void * dst, size_t n )
546 {
547     memset( dst, 0, n );
548 }
549
550 static void integral_init4h( uint16_t *sum, pixel *pix, intptr_t stride )
551 {
552     int v = pix[0]+pix[1]+pix[2]+pix[3];
553     for( int x = 0; x < stride-4; x++ )
554     {
555         sum[x] = v + sum[x-stride];
556         v += pix[x+4] - pix[x];
557     }
558 }
559
560 static void integral_init8h( uint16_t *sum, pixel *pix, intptr_t stride )
561 {
562     int v = pix[0]+pix[1]+pix[2]+pix[3]+pix[4]+pix[5]+pix[6]+pix[7];
563     for( int x = 0; x < stride-8; x++ )
564     {
565         sum[x] = v + sum[x-stride];
566         v += pix[x+8] - pix[x];
567     }
568 }
569
570 static void integral_init4v( uint16_t *sum8, uint16_t *sum4, intptr_t stride )
571 {
572     for( int x = 0; x < stride-8; x++ )
573         sum4[x] = sum8[x+4*stride] - sum8[x];
574     for( int x = 0; x < stride-8; x++ )
575         sum8[x] = sum8[x+8*stride] + sum8[x+8*stride+4] - sum8[x] - sum8[x+4];
576 }
577
578 static void integral_init8v( uint16_t *sum8, intptr_t stride )
579 {
580     for( int x = 0; x < stride-8; x++ )
581         sum8[x] = sum8[x+8*stride] - sum8[x];
582 }
583
584 void x264_frame_init_lowres( x264_t *h, x264_frame_t *frame )
585 {
586     pixel *src = frame->plane[0];
587     int i_stride = frame->i_stride[0];
588     int i_height = frame->i_lines[0];
589     int i_width  = frame->i_width[0];
590
591     // duplicate last row and column so that their interpolation doesn't have to be special-cased
592     for( int y = 0; y < i_height; y++ )
593         src[i_width+y*i_stride] = src[i_width-1+y*i_stride];
594     memcpy( src+i_stride*i_height, src+i_stride*(i_height-1), (i_width+1) * sizeof(pixel) );
595     h->mc.frame_init_lowres_core( src, frame->lowres[0], frame->lowres[1], frame->lowres[2], frame->lowres[3],
596                                   i_stride, frame->i_stride_lowres, frame->i_width_lowres, frame->i_lines_lowres );
597     x264_frame_expand_border_lowres( h, frame );
598
599     memset( frame->i_cost_est, -1, sizeof(frame->i_cost_est) );
600
601     for( int y = 0; y < h->param.i_bframe + 2; y++ )
602         for( int x = 0; x < h->param.i_bframe + 2; x++ )
603             frame->i_row_satds[y][x][0] = -1;
604
605     for( int y = 0; y <= !!h->param.i_bframe; y++ )
606         for( int x = 0; x <= h->param.i_bframe; x++ )
607             frame->lowres_mvs[y][x][0][0] = 0x7FFF;
608 }
609
610 static void frame_init_lowres_core( pixel *src0, pixel *dst0, pixel *dsth, pixel *dstv, pixel *dstc,
611                                     intptr_t src_stride, intptr_t dst_stride, int width, int height )
612 {
613     for( int y = 0; y < height; y++ )
614     {
615         pixel *src1 = src0+src_stride;
616         pixel *src2 = src1+src_stride;
617         for( int x = 0; x<width; x++ )
618         {
619             // slower than naive bilinear, but matches asm
620 #define FILTER(a,b,c,d) ((((a+b+1)>>1)+((c+d+1)>>1)+1)>>1)
621             dst0[x] = FILTER(src0[2*x  ], src1[2*x  ], src0[2*x+1], src1[2*x+1]);
622             dsth[x] = FILTER(src0[2*x+1], src1[2*x+1], src0[2*x+2], src1[2*x+2]);
623             dstv[x] = FILTER(src1[2*x  ], src2[2*x  ], src1[2*x+1], src2[2*x+1]);
624             dstc[x] = FILTER(src1[2*x+1], src2[2*x+1], src1[2*x+2], src2[2*x+2]);
625 #undef FILTER
626         }
627         src0 += src_stride*2;
628         dst0 += dst_stride;
629         dsth += dst_stride;
630         dstv += dst_stride;
631         dstc += dst_stride;
632     }
633 }
634
635 static void frame_init_lowres_core_mpeg2( pixel *src0, pixel *dst0, pixel *dsth, pixel *dstv, pixel *dstc,
636                                           intptr_t src_stride, intptr_t dst_stride, int width, int height )
637 {
638     for( int y = 0; y < height; y++ )
639     {
640         pixel *src1 = src0+src_stride;
641         for( int x = 0; x<width; x++ )
642         {
643             // slower than naive bilinear, but matches asm
644 #define FILTER(a,b,c,d) ((((a+b+1)>>1)+((c+d+1)>>1)+1)>>1)
645             dst0[x] = FILTER(src0[2*x  ], src1[2*x  ], src0[2*x+1], src1[2*x+1]);
646 #undef FILTER
647         }
648         src0 += src_stride*2;
649         dst0 += dst_stride;
650     }
651 }
652
653 /* Estimate the total amount of influence on future quality that could be had if we
654  * were to improve the reference samples used to inter predict any given macroblock. */
655 static void mbtree_propagate_cost( int16_t *dst, uint16_t *propagate_in, uint16_t *intra_costs,
656                                    uint16_t *inter_costs, uint16_t *inv_qscales, float *fps_factor, int len )
657 {
658     float fps = *fps_factor;
659     for( int i = 0; i < len; i++ )
660     {
661         int intra_cost = intra_costs[i];
662         int inter_cost = X264_MIN(intra_costs[i], inter_costs[i] & LOWRES_COST_MASK);
663         float propagate_intra  = intra_cost * inv_qscales[i];
664         float propagate_amount = propagate_in[i] + propagate_intra*fps;
665         float propagate_num    = intra_cost - inter_cost;
666         float propagate_denom  = intra_cost;
667         dst[i] = X264_MIN((int)(propagate_amount * propagate_num / propagate_denom + 0.5f), 32767);
668     }
669 }
670
671 static void mbtree_propagate_list( x264_t *h, uint16_t *ref_costs, int16_t (*mvs)[2],
672                                    int16_t *propagate_amount, uint16_t *lowres_costs,
673                                    int bipred_weight, int mb_y, int len, int list )
674 {
675     unsigned stride = h->mb.i_mb_stride;
676     unsigned width = h->mb.i_mb_width;
677     unsigned height = h->mb.i_mb_height;
678
679     for( unsigned i = 0; i < len; i++ )
680     {
681 #define CLIP_ADD(s,x) (s) = X264_MIN((s)+(x),(1<<15)-1)
682         int lists_used = lowres_costs[i]>>LOWRES_COST_SHIFT;
683
684         if( !(lists_used & (1 << list)) )
685             continue;
686
687         int listamount = propagate_amount[i];
688         /* Apply bipred weighting. */
689         if( lists_used == 3 )
690             listamount = (listamount * bipred_weight + 32) >> 6;
691
692         /* Early termination for simple case of mv0. */
693         if( !M32( mvs[i] ) )
694         {
695             CLIP_ADD( ref_costs[mb_y*stride + i], listamount );
696             continue;
697         }
698
699         int x = mvs[i][0];
700         int y = mvs[i][1];
701         unsigned mbx = (x>>5)+i;
702         unsigned mby = (y>>5)+mb_y;
703         unsigned idx0 = mbx + mby * stride;
704         unsigned idx2 = idx0 + stride;
705         x &= 31;
706         y &= 31;
707         int idx0weight = (32-y)*(32-x);
708         int idx1weight = (32-y)*x;
709         int idx2weight = y*(32-x);
710         int idx3weight = y*x;
711         idx0weight = (idx0weight * listamount + 512) >> 10;
712         idx1weight = (idx1weight * listamount + 512) >> 10;
713         idx2weight = (idx2weight * listamount + 512) >> 10;
714         idx3weight = (idx3weight * listamount + 512) >> 10;
715
716         if( mbx < width-1 && mby < height-1 )
717         {
718             CLIP_ADD( ref_costs[idx0+0], idx0weight );
719             CLIP_ADD( ref_costs[idx0+1], idx1weight );
720             CLIP_ADD( ref_costs[idx2+0], idx2weight );
721             CLIP_ADD( ref_costs[idx2+1], idx3weight );
722         }
723         else
724         {
725             /* Note: this takes advantage of unsigned representation to
726              * catch negative mbx/mby. */
727             if( mby < height )
728             {
729                 if( mbx < width )
730                     CLIP_ADD( ref_costs[idx0+0], idx0weight );
731                 if( mbx+1 < width )
732                     CLIP_ADD( ref_costs[idx0+1], idx1weight );
733             }
734             if( mby+1 < height )
735             {
736                 if( mbx < width )
737                     CLIP_ADD( ref_costs[idx2+0], idx2weight );
738                 if( mbx+1 < width )
739                     CLIP_ADD( ref_costs[idx2+1], idx3weight );
740             }
741         }
742     }
743 #undef CLIP_ADD
744 }
745
746 void x264_mc_init( int cpu, x264_mc_functions_t *pf, int cpu_independent, int b_mpeg2 )
747 {
748     pf->mc_luma   = mc_luma;
749     pf->get_ref   = get_ref;
750
751     pf->mc_chroma = mc_chroma;
752
753     pf->avg[PIXEL_16x16]= pixel_avg_16x16;
754     pf->avg[PIXEL_16x8] = pixel_avg_16x8;
755     pf->avg[PIXEL_8x16] = pixel_avg_8x16;
756     pf->avg[PIXEL_8x8]  = pixel_avg_8x8;
757     pf->avg[PIXEL_8x4]  = pixel_avg_8x4;
758     pf->avg[PIXEL_4x16] = pixel_avg_4x16;
759     pf->avg[PIXEL_4x8]  = pixel_avg_4x8;
760     pf->avg[PIXEL_4x4]  = pixel_avg_4x4;
761     pf->avg[PIXEL_4x2]  = pixel_avg_4x2;
762     pf->avg[PIXEL_2x8]  = pixel_avg_2x8;
763     pf->avg[PIXEL_2x4]  = pixel_avg_2x4;
764     pf->avg[PIXEL_2x2]  = pixel_avg_2x2;
765
766     pf->weight    = x264_mc_weight_wtab;
767     pf->offsetadd = x264_mc_weight_wtab;
768     pf->offsetsub = x264_mc_weight_wtab;
769     pf->weight_cache = x264_weight_cache;
770
771     pf->copy_16x16_unaligned = mc_copy_w16;
772     pf->copy[PIXEL_16x16] = mc_copy_w16;
773     pf->copy[PIXEL_8x8]   = mc_copy_w8;
774     pf->copy[PIXEL_4x4]   = mc_copy_w4;
775
776     pf->store_interleave_chroma       = store_interleave_chroma;
777     pf->load_deinterleave_chroma_fenc = load_deinterleave_chroma_fenc;
778     pf->load_deinterleave_chroma_fdec = load_deinterleave_chroma_fdec;
779
780     pf->plane_copy = x264_plane_copy_c;
781     pf->plane_copy_interleave = x264_plane_copy_interleave_c;
782     pf->plane_copy_deinterleave = x264_plane_copy_deinterleave_c;
783     pf->plane_copy_deinterleave_rgb = x264_plane_copy_deinterleave_rgb_c;
784     pf->plane_copy_deinterleave_v210 = x264_plane_copy_deinterleave_v210_c;
785
786     pf->hpel_filter = hpel_filter;
787
788     pf->prefetch_fenc_420 = prefetch_fenc_null;
789     pf->prefetch_fenc_422 = prefetch_fenc_null;
790     pf->prefetch_ref  = prefetch_ref_null;
791     pf->memcpy_aligned = memcpy;
792     pf->memzero_aligned = memzero_aligned;
793     pf->frame_init_lowres_core = frame_init_lowres_core;
794
795     pf->integral_init4h = integral_init4h;
796     pf->integral_init8h = integral_init8h;
797     pf->integral_init4v = integral_init4v;
798     pf->integral_init8v = integral_init8v;
799
800     pf->mbtree_propagate_cost = mbtree_propagate_cost;
801     pf->mbtree_propagate_list = mbtree_propagate_list;
802
803 #if HAVE_MMX
804     x264_mc_init_mmx( cpu, pf );
805 #endif
806 #if HAVE_ALTIVEC
807     if( cpu&X264_CPU_ALTIVEC )
808         x264_mc_altivec_init( pf );
809 #endif
810 #if HAVE_ARMV6
811     x264_mc_init_arm( cpu, pf );
812 #endif
813
814     // override any simd for the time being
815     if( b_mpeg2 )
816     {
817         pf->mc_luma   = mc_luma_mpeg2;
818         pf->mc_chroma = mc_chroma_mpeg2;
819         pf->get_ref   = get_ref_mpeg2;
820         pf->hpel_filter = NULL;
821         pf->frame_init_lowres_core = frame_init_lowres_core_mpeg2;
822
823 #if HAVE_MMX
824             x264_mc_init_mmx_mpeg2( cpu, pf );
825 #endif
826     }
827
828     if( cpu_independent )
829     {
830         pf->mbtree_propagate_cost = mbtree_propagate_cost;
831         pf->mbtree_propagate_list = mbtree_propagate_list;
832     }
833 }
834
835 void x264_frame_filter( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
836 {
837     const int b_interlaced = PARAM_INTERLACED;
838     int start = mb_y*16 - 8; // buffer = 4 for deblock + 3 for 6tap, rounded to 8
839     int height = (b_end ? frame->i_lines[0] + 16*PARAM_INTERLACED : (mb_y+b_interlaced)*16) + 8;
840
841     if( (mb_y & b_interlaced) && !MPEG2 )
842         return;
843
844     for( int p = 0; p < (CHROMA444 ? 3 : 1) && !MPEG2; p++ )
845     {
846         int stride = frame->i_stride[p];
847         const int width = frame->i_width[p];
848         int offs = start*stride - 8; // buffer = 3 for 6tap, aligned to 8 for simd
849
850         if( !b_interlaced || h->mb.b_adaptive_mbaff )
851             h->mc.hpel_filter(
852                 frame->filtered[p][1] + offs,
853                 frame->filtered[p][2] + offs,
854                 frame->filtered[p][3] + offs,
855                 frame->plane[p] + offs,
856                 stride, width + 16, height - start,
857                 h->scratch_buffer );
858
859         if( b_interlaced )
860         {
861             /* MC must happen between pixels in the same field. */
862             stride = frame->i_stride[p] << 1;
863             start = (mb_y*16 >> 1) - 8;
864             int height_fld = ((b_end ? frame->i_lines[p] : mb_y*16) >> 1) + 8;
865             offs = start*stride - 8;
866             for( int i = 0; i < 2; i++, offs += frame->i_stride[p] )
867             {
868                 h->mc.hpel_filter(
869                     frame->filtered_fld[p][1] + offs,
870                     frame->filtered_fld[p][2] + offs,
871                     frame->filtered_fld[p][3] + offs,
872                     frame->plane_fld[p] + offs,
873                     stride, width + 16, height_fld - start,
874                     h->scratch_buffer );
875             }
876         }
877     }
878
879     /* generate integral image:
880      * frame->integral contains 2 planes. in the upper plane, each element is
881      * the sum of an 8x8 pixel region with top-left corner on that point.
882      * in the lower plane, 4x4 sums (needed only with --partitions p4x4). */
883
884     if( frame->integral )
885     {
886         int stride = frame->i_stride[0];
887         if( start < 0 )
888         {
889             memset( frame->integral - PADV * stride - PADH, 0, stride * sizeof(uint16_t) );
890             start = -PADV;
891         }
892         if( b_end )
893             height += PADV-9;
894         for( int y = start; y < height; y++ )
895         {
896             pixel    *pix  = frame->plane[0] + y * stride - PADH;
897             uint16_t *sum8 = frame->integral + (y+1) * stride - PADH;
898             uint16_t *sum4;
899             if( h->frames.b_have_sub8x8_esa )
900             {
901                 h->mc.integral_init4h( sum8, pix, stride );
902                 sum8 -= 8*stride;
903                 sum4 = sum8 + stride * (frame->i_lines[0] + PADV*2);
904                 if( y >= 8-PADV )
905                     h->mc.integral_init4v( sum8, sum4, stride );
906             }
907             else
908             {
909                 h->mc.integral_init8h( sum8, pix, stride );
910                 if( y >= 8-PADV )
911                     h->mc.integral_init8v( sum8-8*stride, stride );
912             }
913         }
914     }
915 }