]> git.sesse.net Git - x264/blob - common/mc.c
Faster deblock strength asm on conroe/penryn
[x264] / common / mc.c
1 /*****************************************************************************
2  * mc.c: h264 encoder library (Motion Compensation)
3  *****************************************************************************
4  * Copyright (C) 2003-2008 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
24 #include "common.h"
25
26 #ifdef HAVE_MMX
27 #include "x86/mc.h"
28 #endif
29 #ifdef ARCH_PPC
30 #include "ppc/mc.h"
31 #endif
32 #ifdef ARCH_ARM
33 #include "arm/mc.h"
34 #endif
35
36
37 static inline void pixel_avg( uint8_t *dst,  int i_dst_stride,
38                               uint8_t *src1, int i_src1_stride,
39                               uint8_t *src2, int i_src2_stride,
40                               int i_width, int i_height )
41 {
42     for( int y = 0; y < i_height; y++ )
43     {
44         for( int x = 0; x < i_width; x++ )
45             dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;
46         dst  += i_dst_stride;
47         src1 += i_src1_stride;
48         src2 += i_src2_stride;
49     }
50 }
51
52 static inline void pixel_avg_wxh( uint8_t *dst, int i_dst, uint8_t *src1, int i_src1, uint8_t *src2, int i_src2, int width, int height )
53 {
54     for( int y = 0; y < height; y++ )
55     {
56         for( int x = 0; x < width; x++ )
57             dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;
58         src1 += i_src1;
59         src2 += i_src2;
60         dst += i_dst;
61     }
62 }
63
64 /* Implicit weighted bipred only:
65  * assumes log2_denom = 5, offset = 0, weight1 + weight2 = 64 */
66 #define op_scale2(x) dst[x] = x264_clip_uint8( (src1[x]*i_weight1 + src2[x]*i_weight2 + (1<<5)) >> 6 )
67 static inline void pixel_avg_weight_wxh( uint8_t *dst, int i_dst, uint8_t *src1, int i_src1, uint8_t *src2, int i_src2, int width, int height, int i_weight1 )
68 {
69     const int i_weight2 = 64 - i_weight1;
70     for( int y = 0; y<height; y++, dst += i_dst, src1 += i_src1, src2 += i_src2 )
71     {
72         op_scale2(0);
73         op_scale2(1);
74         if(width==2) continue;
75         op_scale2(2);
76         op_scale2(3);
77         if(width==4) continue;
78         op_scale2(4);
79         op_scale2(5);
80         op_scale2(6);
81         op_scale2(7);
82         if(width==8) continue;
83         op_scale2(8);
84         op_scale2(9);
85         op_scale2(10);
86         op_scale2(11);
87         op_scale2(12);
88         op_scale2(13);
89         op_scale2(14);
90         op_scale2(15);
91     }
92 }
93 #undef op_scale2
94
95 #define PIXEL_AVG_C( name, width, height ) \
96 static void name( uint8_t *pix1, int i_stride_pix1, \
97                   uint8_t *pix2, int i_stride_pix2, \
98                   uint8_t *pix3, int i_stride_pix3, int weight ) \
99 { \
100     if( weight == 32 ) \
101         pixel_avg_wxh( pix1, i_stride_pix1, pix2, i_stride_pix2, pix3, i_stride_pix3, width, height ); \
102     else \
103         pixel_avg_weight_wxh( pix1, i_stride_pix1, pix2, i_stride_pix2, pix3, i_stride_pix3, width, height, weight ); \
104 }
105 PIXEL_AVG_C( pixel_avg_16x16, 16, 16 )
106 PIXEL_AVG_C( pixel_avg_16x8,  16, 8 )
107 PIXEL_AVG_C( pixel_avg_8x16,  8, 16 )
108 PIXEL_AVG_C( pixel_avg_8x8,   8, 8 )
109 PIXEL_AVG_C( pixel_avg_8x4,   8, 4 )
110 PIXEL_AVG_C( pixel_avg_4x8,   4, 8 )
111 PIXEL_AVG_C( pixel_avg_4x4,   4, 4 )
112 PIXEL_AVG_C( pixel_avg_4x2,   4, 2 )
113 PIXEL_AVG_C( pixel_avg_2x4,   2, 4 )
114 PIXEL_AVG_C( pixel_avg_2x2,   2, 2 )
115
116 static void x264_weight_cache( x264_t *h, x264_weight_t *w )
117 {
118     w->weightfn = h->mc.weight;
119 }
120 #define opscale(x) dst[x] = x264_clip_uint8( ((src[x] * weight->i_scale + (1<<(weight->i_denom - 1))) >> weight->i_denom) + weight->i_offset )
121 #define opscale_noden(x) dst[x] = x264_clip_uint8( src[x] * weight->i_scale + weight->i_offset )
122 static inline void mc_weight( uint8_t *dst, int i_dst_stride, uint8_t *src, int i_src_stride, const x264_weight_t *weight, int i_width, int i_height )
123 {
124     if( weight->i_denom >= 1 )
125     {
126         for( int y = 0; y < i_height; y++, dst += i_dst_stride, src += i_src_stride )
127             for( int x = 0; x < i_width; x++ )
128                 opscale( x );
129     }
130     else
131     {
132         for( int y = 0; y < i_height; y++, dst += i_dst_stride, src += i_src_stride )
133             for( int x = 0; x < i_width; x++ )
134                 opscale_noden( x );
135     }
136 }
137
138 #define MC_WEIGHT_C( name, lx ) \
139     static void name( uint8_t *dst, int i_dst_stride, uint8_t *src, int i_src_stride, const x264_weight_t *weight, int height ) \
140 { \
141     if( weight->i_denom >= 1 ) \
142     { \
143         for( int y = 0; y < height; y++, dst += i_dst_stride, src += i_src_stride ) \
144             for( int x = 0; x < lx; x++ ) \
145                 opscale( x ); \
146     } \
147     else \
148     { \
149         for( int y = 0; y < height; y++, dst += i_dst_stride, src += i_src_stride ) \
150             for( int x = 0; x < lx; x++ ) \
151                 opscale_noden( x ); \
152     } \
153 }
154
155 MC_WEIGHT_C( mc_weight_w20, 20 )
156 MC_WEIGHT_C( mc_weight_w16, 16 )
157 MC_WEIGHT_C( mc_weight_w12, 12 )
158 MC_WEIGHT_C( mc_weight_w8,   8 )
159 MC_WEIGHT_C( mc_weight_w4,   4 )
160 MC_WEIGHT_C( mc_weight_w2,   2 )
161
162 static weight_fn_t x264_mc_weight_wtab[6] =
163 {
164     mc_weight_w2,
165     mc_weight_w4,
166     mc_weight_w8,
167     mc_weight_w12,
168     mc_weight_w16,
169     mc_weight_w20,
170 };
171 const x264_weight_t weight_none[3] = { {{0}} };
172 static void mc_copy( uint8_t *src, int i_src_stride, uint8_t *dst, int i_dst_stride, int i_width, int i_height )
173 {
174     for( int y = 0; y < i_height; y++ )
175     {
176         memcpy( dst, src, i_width );
177
178         src += i_src_stride;
179         dst += i_dst_stride;
180     }
181 }
182
183 #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]))
184 static void hpel_filter( uint8_t *dsth, uint8_t *dstv, uint8_t *dstc, uint8_t *src,
185                          int stride, int width, int height, int16_t *buf )
186 {
187     for( int y = 0; y < height; y++ )
188     {
189         for( int x = -2; x < width+3; x++ )
190         {
191             int v = TAPFILTER(src,stride);
192             dstv[x] = x264_clip_uint8( (v + 16) >> 5 );
193             buf[x+2] = v;
194         }
195         for( int x = 0; x < width; x++ )
196             dstc[x] = x264_clip_uint8( (TAPFILTER(buf+2,1) + 512) >> 10 );
197         for( int x = 0; x < width; x++ )
198             dsth[x] = x264_clip_uint8( (TAPFILTER(src,1) + 16) >> 5 );
199         dsth += stride;
200         dstv += stride;
201         dstc += stride;
202         src += stride;
203     }
204 }
205
206 static const uint8_t hpel_ref0[16] = {0,1,1,1,0,1,1,1,2,3,3,3,0,1,1,1};
207 static const uint8_t hpel_ref1[16] = {0,0,0,0,2,2,3,2,2,2,3,2,2,2,3,2};
208
209 static void mc_luma( uint8_t *dst,    int i_dst_stride,
210                      uint8_t *src[4], int i_src_stride,
211                      int mvx, int mvy,
212                      int i_width, int i_height, const x264_weight_t *weight )
213 {
214     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
215     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
216     uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
217
218     if( qpel_idx & 5 ) /* qpel interpolation needed */
219     {
220         uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
221         pixel_avg( dst, i_dst_stride, src1, i_src_stride,
222                    src2, i_src_stride, i_width, i_height );
223         if( weight->weightfn )
224             mc_weight( dst, i_dst_stride, dst, i_dst_stride, weight, i_width, i_height );
225     }
226     else if( weight->weightfn )
227         mc_weight( dst, i_dst_stride, src1, i_src_stride, weight, i_width, i_height );
228     else
229         mc_copy( src1, i_src_stride, dst, i_dst_stride, i_width, i_height );
230 }
231
232 static uint8_t *get_ref( uint8_t *dst,   int *i_dst_stride,
233                          uint8_t *src[4], int i_src_stride,
234                          int mvx, int mvy,
235                          int i_width, int i_height, const x264_weight_t *weight )
236 {
237     int qpel_idx = ((mvy&3)<<2) + (mvx&3);
238     int offset = (mvy>>2)*i_src_stride + (mvx>>2);
239     uint8_t *src1 = src[hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
240
241     if( qpel_idx & 5 ) /* qpel interpolation needed */
242     {
243         uint8_t *src2 = src[hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
244         pixel_avg( dst, *i_dst_stride, src1, i_src_stride,
245                    src2, i_src_stride, i_width, i_height );
246         if( weight->weightfn )
247             mc_weight( dst, *i_dst_stride, dst, *i_dst_stride, weight, i_width, i_height );
248         return dst;
249     }
250     else if( weight->weightfn )
251     {
252         mc_weight( dst, *i_dst_stride, src1, i_src_stride, weight, i_width, i_height );
253         return dst;
254     }
255     else
256     {
257         *i_dst_stride = i_src_stride;
258         return src1;
259     }
260 }
261
262 /* full chroma mc (ie until 1/8 pixel)*/
263 static void mc_chroma( uint8_t *dst, int i_dst_stride,
264                        uint8_t *src, int i_src_stride,
265                        int mvx, int mvy,
266                        int i_width, int i_height )
267 {
268     uint8_t *srcp;
269
270     int d8x = mvx&0x07;
271     int d8y = mvy&0x07;
272     int cA = (8-d8x)*(8-d8y);
273     int cB = d8x    *(8-d8y);
274     int cC = (8-d8x)*d8y;
275     int cD = d8x    *d8y;
276
277     src += (mvy >> 3) * i_src_stride + (mvx >> 3);
278     srcp = &src[i_src_stride];
279
280     for( int y = 0; y < i_height; y++ )
281     {
282         for( int x = 0; x < i_width; x++ )
283             dst[x] = ( cA*src[x]  + cB*src[x+1] + cC*srcp[x] + cD*srcp[x+1] + 32 ) >> 6;
284         dst  += i_dst_stride;
285         src   = srcp;
286         srcp += i_src_stride;
287     }
288 }
289
290 #define MC_COPY(W) \
291 static void mc_copy_w##W( uint8_t *dst, int i_dst, uint8_t *src, int i_src, int i_height ) \
292 { \
293     mc_copy( src, i_src, dst, i_dst, W, i_height ); \
294 }
295 MC_COPY( 16 )
296 MC_COPY( 8 )
297 MC_COPY( 4 )
298
299 void x264_plane_copy_c( uint8_t *dst, int i_dst,
300                         uint8_t *src, int i_src, int w, int h)
301 {
302     while( h-- )
303     {
304         memcpy( dst, src, w );
305         dst += i_dst;
306         src += i_src;
307     }
308 }
309
310 static void prefetch_fenc_null( uint8_t *pix_y, int stride_y,
311                                 uint8_t *pix_uv, int stride_uv, int mb_x )
312 {}
313
314 static void prefetch_ref_null( uint8_t *pix, int stride, int parity )
315 {}
316
317 static void memzero_aligned( void * dst, int n )
318 {
319     memset( dst, 0, n );
320 }
321
322 static void integral_init4h( uint16_t *sum, uint8_t *pix, int stride )
323 {
324     int v = pix[0]+pix[1]+pix[2]+pix[3];
325     for( int x = 0; x < stride-4; x++ )
326     {
327         sum[x] = v + sum[x-stride];
328         v += pix[x+4] - pix[x];
329     }
330 }
331
332 static void integral_init8h( uint16_t *sum, uint8_t *pix, int stride )
333 {
334     int v = pix[0]+pix[1]+pix[2]+pix[3]+pix[4]+pix[5]+pix[6]+pix[7];
335     for( int x = 0; x < stride-8; x++ )
336     {
337         sum[x] = v + sum[x-stride];
338         v += pix[x+8] - pix[x];
339     }
340 }
341
342 static void integral_init4v( uint16_t *sum8, uint16_t *sum4, int stride )
343 {
344     for( int x = 0; x < stride-8; x++ )
345         sum4[x] = sum8[x+4*stride] - sum8[x];
346     for( int x = 0; x < stride-8; x++ )
347         sum8[x] = sum8[x+8*stride] + sum8[x+8*stride+4] - sum8[x] - sum8[x+4];
348 }
349
350 static void integral_init8v( uint16_t *sum8, int stride )
351 {
352     for( int x = 0; x < stride-8; x++ )
353         sum8[x] = sum8[x+8*stride] - sum8[x];
354 }
355
356 void x264_frame_init_lowres( x264_t *h, x264_frame_t *frame )
357 {
358     uint8_t *src = frame->plane[0];
359     int i_stride = frame->i_stride[0];
360     int i_height = frame->i_lines[0];
361     int i_width  = frame->i_width[0];
362
363     // duplicate last row and column so that their interpolation doesn't have to be special-cased
364     for( int y = 0; y < i_height; y++ )
365         src[i_width+y*i_stride] = src[i_width-1+y*i_stride];
366     memcpy( src+i_stride*i_height, src+i_stride*(i_height-1), i_width+1 );
367     h->mc.frame_init_lowres_core( src, frame->lowres[0], frame->lowres[1], frame->lowres[2], frame->lowres[3],
368                                   i_stride, frame->i_stride_lowres, frame->i_width_lowres, frame->i_lines_lowres );
369     x264_frame_expand_border_lowres( frame );
370
371     memset( frame->i_cost_est, -1, sizeof(frame->i_cost_est) );
372
373     for( int y = 0; y < h->param.i_bframe + 2; y++ )
374         for( int x = 0; x < h->param.i_bframe + 2; x++ )
375             frame->i_row_satds[y][x][0] = -1;
376
377     for( int y = 0; y <= !!h->param.i_bframe; y++ )
378         for( int x = 0; x <= h->param.i_bframe; x++ )
379             frame->lowres_mvs[y][x][0][0] = 0x7FFF;
380 }
381
382 static void frame_init_lowres_core( uint8_t *src0, uint8_t *dst0, uint8_t *dsth, uint8_t *dstv, uint8_t *dstc,
383                                     int src_stride, int dst_stride, int width, int height )
384 {
385     for( int y = 0; y < height; y++ )
386     {
387         uint8_t *src1 = src0+src_stride;
388         uint8_t *src2 = src1+src_stride;
389         for( int x = 0; x<width; x++ )
390         {
391             // slower than naive bilinear, but matches asm
392 #define FILTER(a,b,c,d) ((((a+b+1)>>1)+((c+d+1)>>1)+1)>>1)
393             dst0[x] = FILTER(src0[2*x  ], src1[2*x  ], src0[2*x+1], src1[2*x+1]);
394             dsth[x] = FILTER(src0[2*x+1], src1[2*x+1], src0[2*x+2], src1[2*x+2]);
395             dstv[x] = FILTER(src1[2*x  ], src2[2*x  ], src1[2*x+1], src2[2*x+1]);
396             dstc[x] = FILTER(src1[2*x+1], src2[2*x+1], src1[2*x+2], src2[2*x+2]);
397 #undef FILTER
398         }
399         src0 += src_stride*2;
400         dst0 += dst_stride;
401         dsth += dst_stride;
402         dstv += dst_stride;
403         dstc += dst_stride;
404     }
405 }
406
407 #if defined(__GNUC__) && (defined(ARCH_X86) || defined(ARCH_X86_64))
408 // gcc isn't smart enough to use the "idiv" instruction
409 static ALWAYS_INLINE int32_t div_64_32(int64_t x, int32_t y)
410 {
411     int32_t quotient, remainder;
412     asm("idiv %4"
413         :"=a"(quotient), "=d"(remainder)
414         :"a"((uint32_t)x), "d"((int32_t)(x>>32)), "r"(y)
415     );
416     return quotient;
417 }
418 #else
419 #define div_64_32(x,y) ((x)/(y))
420 #endif
421
422 /* Estimate the total amount of influence on future quality that could be had if we
423  * were to improve the reference samples used to inter predict any given macroblock. */
424 static void mbtree_propagate_cost( int *dst, uint16_t *propagate_in, uint16_t *intra_costs,
425                                    uint16_t *inter_costs, uint16_t *inv_qscales, int len )
426 {
427     for( int i = 0; i < len; i++ )
428     {
429         int propagate_amount = propagate_in[i] + ((intra_costs[i] * inv_qscales[i] + 128)>>8);
430         dst[i] = div_64_32((int64_t)propagate_amount * (intra_costs[i] - (inter_costs[i] & LOWRES_COST_MASK)), intra_costs[i]);
431     }
432 }
433
434 void x264_mc_init( int cpu, x264_mc_functions_t *pf )
435 {
436     pf->mc_luma   = mc_luma;
437     pf->get_ref   = get_ref;
438     pf->mc_chroma = mc_chroma;
439
440     pf->avg[PIXEL_16x16]= pixel_avg_16x16;
441     pf->avg[PIXEL_16x8] = pixel_avg_16x8;
442     pf->avg[PIXEL_8x16] = pixel_avg_8x16;
443     pf->avg[PIXEL_8x8]  = pixel_avg_8x8;
444     pf->avg[PIXEL_8x4]  = pixel_avg_8x4;
445     pf->avg[PIXEL_4x8]  = pixel_avg_4x8;
446     pf->avg[PIXEL_4x4]  = pixel_avg_4x4;
447     pf->avg[PIXEL_4x2]  = pixel_avg_4x2;
448     pf->avg[PIXEL_2x4]  = pixel_avg_2x4;
449     pf->avg[PIXEL_2x2]  = pixel_avg_2x2;
450
451     pf->weight    = x264_mc_weight_wtab;
452     pf->offsetadd = x264_mc_weight_wtab;
453     pf->offsetsub = x264_mc_weight_wtab;
454     pf->weight_cache = x264_weight_cache;
455
456     pf->copy_16x16_unaligned = mc_copy_w16;
457     pf->copy[PIXEL_16x16] = mc_copy_w16;
458     pf->copy[PIXEL_8x8]   = mc_copy_w8;
459     pf->copy[PIXEL_4x4]   = mc_copy_w4;
460
461     pf->plane_copy = x264_plane_copy_c;
462     pf->hpel_filter = hpel_filter;
463
464     pf->prefetch_fenc = prefetch_fenc_null;
465     pf->prefetch_ref  = prefetch_ref_null;
466     pf->memcpy_aligned = memcpy;
467     pf->memzero_aligned = memzero_aligned;
468     pf->frame_init_lowres_core = frame_init_lowres_core;
469
470     pf->integral_init4h = integral_init4h;
471     pf->integral_init8h = integral_init8h;
472     pf->integral_init4v = integral_init4v;
473     pf->integral_init8v = integral_init8v;
474
475     pf->mbtree_propagate_cost = mbtree_propagate_cost;
476
477 #ifdef HAVE_MMX
478     x264_mc_init_mmx( cpu, pf );
479 #endif
480 #ifdef HAVE_ALTIVEC
481     if( cpu&X264_CPU_ALTIVEC )
482         x264_mc_altivec_init( pf );
483 #endif
484 #ifdef HAVE_ARMV6
485     x264_mc_init_arm( cpu, pf );
486 #endif
487 }
488
489 void x264_frame_filter( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
490 {
491     const int b_interlaced = h->sh.b_mbaff;
492     const int stride = frame->i_stride[0] << b_interlaced;
493     const int width = frame->i_width[0];
494     int start = (mb_y*16 >> b_interlaced) - 8; // buffer = 4 for deblock + 3 for 6tap, rounded to 8
495     int height = ((b_end ? frame->i_lines[0] : mb_y*16) >> b_interlaced) + 8;
496     int offs = start*stride - 8; // buffer = 3 for 6tap, aligned to 8 for simd
497
498     if( mb_y & b_interlaced )
499         return;
500
501     for( int y = 0; y <= b_interlaced; y++, offs += frame->i_stride[0] )
502     {
503         h->mc.hpel_filter(
504             frame->filtered[1] + offs,
505             frame->filtered[2] + offs,
506             frame->filtered[3] + offs,
507             frame->plane[0] + offs,
508             stride, width + 16, height - start,
509             h->scratch_buffer );
510     }
511
512     /* generate integral image:
513      * frame->integral contains 2 planes. in the upper plane, each element is
514      * the sum of an 8x8 pixel region with top-left corner on that point.
515      * in the lower plane, 4x4 sums (needed only with --partitions p4x4). */
516
517     if( frame->integral )
518     {
519         if( start < 0 )
520         {
521             memset( frame->integral - PADV * stride - PADH, 0, stride * sizeof(uint16_t) );
522             start = -PADV;
523         }
524         if( b_end )
525             height += PADV-9;
526         for( int y = start; y < height; y++ )
527         {
528             uint8_t  *pix  = frame->plane[0] + y * stride - PADH;
529             uint16_t *sum8 = frame->integral + (y+1) * stride - PADH;
530             uint16_t *sum4;
531             if( h->frames.b_have_sub8x8_esa )
532             {
533                 h->mc.integral_init4h( sum8, pix, stride );
534                 sum8 -= 8*stride;
535                 sum4 = sum8 + stride * (frame->i_lines[0] + PADV*2);
536                 if( y >= 8-PADV )
537                     h->mc.integral_init4v( sum8, sum4, stride );
538             }
539             else
540             {
541                 h->mc.integral_init8h( sum8, pix, stride );
542                 if( y >= 8-PADV )
543                     h->mc.integral_init8v( sum8-8*stride, stride );
544             }
545         }
546     }
547 }