mmx/prefetch implementation of plane_copy
[x262.git] / common / frame.c
1 /*****************************************************************************
2  * frame.c: h264 encoder library
3  *****************************************************************************
4  * Copyright (C) 2003 Laurent Aimar
5  * $Id: frame.c,v 1.1 2004/06/03 19:27:06 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 #include <stdio.h>
25 #include <string.h>
26
27 #include "common.h"
28
29 #define PADH 32
30 #define PADV 32
31
32 x264_frame_t *x264_frame_new( x264_t *h )
33 {
34     x264_frame_t *frame = x264_malloc( sizeof(x264_frame_t) );
35     int i, j;
36
37     int i_mb_count = h->mb.i_mb_count;
38     int i_stride;
39     int i_lines;
40     int i_padv = PADV << h->param.b_interlaced;
41
42     if( !frame ) return NULL;
43
44     memset( frame, 0, sizeof(x264_frame_t) );
45
46     /* allocate frame data (+64 for extra data for me) */
47     i_stride = ( ( h->param.i_width  + 15 ) & -16 )+ 2*PADH;
48     i_lines  = ( ( h->param.i_height + 15 ) & -16 );
49     if( h->param.b_interlaced )
50         i_lines = ( i_lines + 31 ) & -32;
51
52     frame->i_plane = 3;
53     for( i = 0; i < 3; i++ )
54     {
55         int i_divh = 1;
56         int i_divw = 1;
57         if( i > 0 )
58         {
59             if( h->param.i_csp == X264_CSP_I420 )
60                 i_divh = i_divw = 2;
61             else if( h->param.i_csp == X264_CSP_I422 )
62                 i_divw = 2;
63         }
64         frame->i_stride[i] = i_stride / i_divw;
65         frame->i_lines[i] = i_lines / i_divh;
66         CHECKED_MALLOC( frame->buffer[i],
67                         frame->i_stride[i] * ( frame->i_lines[i] + 2*i_padv / i_divh ) );
68
69         frame->plane[i] = ((uint8_t*)frame->buffer[i]) +
70                           frame->i_stride[i] * i_padv / i_divh + PADH / i_divw;
71     }
72     frame->i_stride[3] = 0;
73     frame->i_lines[3] = 0;
74     frame->buffer[3] = NULL;
75     frame->plane[3] = NULL;
76
77     frame->filtered[0] = frame->plane[0];
78     for( i = 0; i < 3; i++ )
79     {
80         CHECKED_MALLOC( frame->buffer[4+i],
81                         frame->i_stride[0] * ( frame->i_lines[0] + 2*i_padv ) );
82         frame->filtered[i+1] = ((uint8_t*)frame->buffer[4+i]) +
83                                 frame->i_stride[0] * i_padv + PADH;
84     }
85
86     if( h->frames.b_have_lowres )
87     {
88         frame->i_stride_lowres = frame->i_stride[0]/2 + PADH;
89         frame->i_lines_lowres = frame->i_lines[0]/2;
90         for( i = 0; i < 4; i++ )
91         {
92             CHECKED_MALLOC( frame->buffer_lowres[i],
93                             frame->i_stride_lowres * ( frame->i_lines[0]/2 + 2*i_padv ) );
94             frame->lowres[i] = ((uint8_t*)frame->buffer_lowres[i]) +
95                                 frame->i_stride_lowres * i_padv + PADH;
96         }
97     }
98
99     if( h->param.analyse.i_me_method == X264_ME_ESA )
100     {
101         CHECKED_MALLOC( frame->buffer[7],
102                         2 * frame->i_stride[0] * (frame->i_lines[0] + 2*i_padv) * sizeof(uint16_t) );
103         frame->integral = (uint16_t*)frame->buffer[7] + frame->i_stride[0] * i_padv + PADH;
104     }
105
106     frame->i_poc = -1;
107     frame->i_type = X264_TYPE_AUTO;
108     frame->i_qpplus1 = 0;
109     frame->i_pts = -1;
110     frame->i_frame = -1;
111     frame->i_frame_num = -1;
112
113     CHECKED_MALLOC( frame->mb_type, i_mb_count * sizeof(int8_t));
114     CHECKED_MALLOC( frame->mv[0], 2*16 * i_mb_count * sizeof(int16_t) );
115     CHECKED_MALLOC( frame->ref[0], 4 * i_mb_count * sizeof(int8_t) );
116     if( h->param.i_bframe )
117     {
118         CHECKED_MALLOC( frame->mv[1], 2*16 * i_mb_count * sizeof(int16_t) );
119         CHECKED_MALLOC( frame->ref[1], 4 * i_mb_count * sizeof(int8_t) );
120     }
121     else
122     {
123         frame->mv[1]  = NULL;
124         frame->ref[1] = NULL;
125     }
126
127     CHECKED_MALLOC( frame->i_row_bits, i_lines/16 * sizeof(int) );
128     CHECKED_MALLOC( frame->i_row_qp, i_lines/16 * sizeof(int) );
129     for( i = 0; i < h->param.i_bframe + 2; i++ )
130         for( j = 0; j < h->param.i_bframe + 2; j++ )
131             CHECKED_MALLOC( frame->i_row_satds[i][j], i_lines/16 * sizeof(int) );
132
133     return frame;
134
135 fail:
136     x264_frame_delete( frame );
137     return NULL;
138 }
139
140 void x264_frame_delete( x264_frame_t *frame )
141 {
142     int i, j;
143     for( i = 0; i < 8; i++ )
144         x264_free( frame->buffer[i] );
145     for( i = 0; i < 4; i++ )
146         x264_free( frame->buffer_lowres[i] );
147     for( i = 0; i < X264_BFRAME_MAX+2; i++ )
148         for( j = 0; j < X264_BFRAME_MAX+2; j++ )
149             x264_free( frame->i_row_satds[i][j] );
150     x264_free( frame->i_row_bits );
151     x264_free( frame->i_row_qp );
152     x264_free( frame->mb_type );
153     x264_free( frame->mv[0] );
154     x264_free( frame->mv[1] );
155     x264_free( frame->ref[0] );
156     x264_free( frame->ref[1] );
157     x264_free( frame );
158 }
159
160 void x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
161 {
162     int i_csp = src->img.i_csp & X264_CSP_MASK;
163     dst->i_type     = src->i_type;
164     dst->i_qpplus1  = src->i_qpplus1;
165     dst->i_pts      = src->i_pts;
166
167     if( i_csp <= X264_CSP_NONE  || i_csp >= X264_CSP_MAX )
168         x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" );
169     else
170         h->csp.convert[i_csp]( &h->mc, dst, &src->img, h->param.i_width, h->param.i_height );
171 }
172
173
174
175 static void plane_expand_border( uint8_t *pix, int i_stride, int i_width, int i_height, int i_padh, int i_padv )
176 {
177 #define PPIXEL(x, y) ( pix + (x) + (y)*i_stride )
178     int y;
179     for( y = 0; y < i_height; y++ )
180     {
181         /* left band */
182         memset( PPIXEL(-i_padh, y), PPIXEL(0, y)[0], i_padh );
183         /* right band */
184         memset( PPIXEL(i_width, y), PPIXEL(i_width-1, y)[0], i_padh );
185     }
186     /* upper band */
187     for( y = 0; y < i_padv; y++ )
188         memcpy( PPIXEL(-i_padh, -y-1), PPIXEL(-i_padh, 0), i_width+2*i_padh );
189     /* lower band */
190     for( y = 0; y < i_padv; y++ )
191         memcpy( PPIXEL(-i_padh, i_height+y), PPIXEL(-i_padh, i_height-1), i_width+2*i_padh );
192 #undef PPIXEL
193 }
194
195 void x264_frame_expand_border( x264_t *h, x264_frame_t *frame )
196 {
197     int i;
198     for( i = 0; i < frame->i_plane; i++ )
199     {
200         int stride = frame->i_stride[i];
201         int width = 16*h->sps->i_mb_width >> !!i;
202         int height = 16*h->sps->i_mb_height >> !!i;
203         int padh = PADH >> !!i;
204         int padv = PADV >> !!i;
205         if( h->param.b_interlaced )
206         {
207             plane_expand_border( frame->plane[i], stride*2, width, height>>1, padh, padv );
208             plane_expand_border( frame->plane[i]+stride, stride*2, width, height>>1, padh, padv );
209         }
210         else
211         {
212             plane_expand_border( frame->plane[i], stride, width, height, padh, padv );
213         }
214     }
215 }
216
217 void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame )
218 {
219     /* during filtering, 8 extra pixels were filtered on each edge. 
220        we want to expand border from the last filtered pixel */
221     int stride = frame->i_stride[0];
222     int width = 16*h->sps->i_mb_width;
223     int height = 16*h->sps->i_mb_height;
224     int padh = PADH - 8;
225     int padv = PADV - 8;
226     int i;
227     for( i = 1; i < 4; i++ )
228     {
229         if( h->param.b_interlaced )
230         {
231             plane_expand_border( frame->filtered[i] - 16*stride - 8, stride*2, width+16, (height>>1)+16, padh, padv );
232             plane_expand_border( frame->filtered[i] - 15*stride - 8, stride*2, width+16, (height>>1)+16, padh, padv );
233         }
234         else
235         {
236             plane_expand_border( frame->filtered[i] - 8*stride - 8, stride, width+16, height+16, padh, padv );
237         }
238     }
239 }
240
241 void x264_frame_expand_border_lowres( x264_frame_t *frame )
242 {
243     int i;
244     for( i = 0; i < 4; i++ )
245         plane_expand_border( frame->lowres[i], frame->i_stride_lowres, frame->i_stride_lowres - 2*PADH, frame->i_lines_lowres, PADH, PADV );
246 }
247
248 void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
249 {
250     int i, y;
251     for( i = 0; i < frame->i_plane; i++ )
252     {
253         int i_subsample = i ? 1 : 0;
254         int i_width = h->param.i_width >> i_subsample;
255         int i_height = h->param.i_height >> i_subsample;
256         int i_padx = ( h->sps->i_mb_width * 16 - h->param.i_width ) >> i_subsample;
257         int i_pady = ( h->sps->i_mb_height * 16 - h->param.i_height ) >> i_subsample;
258
259         if( i_padx )
260         {
261             for( y = 0; y < i_height; y++ )
262                 memset( &frame->plane[i][y*frame->i_stride[i] + i_width],
263                          frame->plane[i][y*frame->i_stride[i] + i_width - 1],
264                          i_padx );
265         }
266         if( i_pady )
267         {
268             //FIXME interlace? or just let it pad using the wrong field
269             for( y = i_height; y < i_height + i_pady; y++ )
270                 memcpy( &frame->plane[i][y*frame->i_stride[i]],
271                         &frame->plane[i][(i_height-1)*frame->i_stride[i]],
272                         i_width + i_padx );
273         }
274     }
275 }
276
277
278 /* Deblocking filter */
279
280 static const int i_alpha_table[52] =
281 {
282      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
283      0,  0,  0,  0,  0,  0,  4,  4,  5,  6,
284      7,  8,  9, 10, 12, 13, 15, 17, 20, 22,
285     25, 28, 32, 36, 40, 45, 50, 56, 63, 71,
286     80, 90,101,113,127,144,162,182,203,226,
287     255, 255
288 };
289 static const int i_beta_table[52] =
290 {
291      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
292      0,  0,  0,  0,  0,  0,  2,  2,  2,  3,
293      3,  3,  3,  4,  4,  4,  6,  6,  7,  7,
294      8,  8,  9,  9, 10, 10, 11, 11, 12, 12,
295     13, 13, 14, 14, 15, 15, 16, 16, 17, 17,
296     18, 18
297 };
298 static const int i_tc0_table[52][3] =
299 {
300     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
301     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
302     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 1 },
303     { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 0, 1, 1 }, { 1, 1, 1 },
304     { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 },
305     { 1, 1, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 2, 2, 3 }, { 2, 2, 4 }, { 2, 3, 4 },
306     { 2, 3, 4 }, { 3, 3, 5 }, { 3, 4, 6 }, { 3, 4, 6 }, { 4, 5, 7 }, { 4, 5, 8 },
307     { 4, 6, 9 }, { 5, 7,10 }, { 6, 8,11 }, { 6, 8,13 }, { 7,10,14 }, { 8,11,16 },
308     { 9,12,18 }, {10,13,20 }, {11,15,23 }, {13,17,25 }
309 };
310
311 /* From ffmpeg */
312 static inline int clip_uint8( int a )
313 {
314     if (a&(~255))
315         return (-a)>>31;
316     else
317         return a;
318 }
319
320 static inline void deblock_luma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
321 {
322     int i, d;
323     for( i = 0; i < 4; i++ ) {
324         if( tc0[i] < 0 ) {
325             pix += 4*ystride;
326             continue;
327         }
328         for( d = 0; d < 4; d++ ) {
329             const int p2 = pix[-3*xstride];
330             const int p1 = pix[-2*xstride];
331             const int p0 = pix[-1*xstride];
332             const int q0 = pix[ 0*xstride];
333             const int q1 = pix[ 1*xstride];
334             const int q2 = pix[ 2*xstride];
335    
336             if( abs( p0 - q0 ) < alpha &&
337                 abs( p1 - p0 ) < beta &&
338                 abs( q1 - q0 ) < beta ) {
339    
340                 int tc = tc0[i];
341                 int delta;
342    
343                 if( abs( p2 - p0 ) < beta ) {
344                     pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0[i], tc0[i] );
345                     tc++; 
346                 }
347                 if( abs( q2 - q0 ) < beta ) {
348                     pix[ 1*xstride] = q1 + x264_clip3( (( q2 + ((p0 + q0 + 1) >> 1)) >> 1) - q1, -tc0[i], tc0[i] );
349                     tc++;
350                 }
351     
352                 delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
353                 pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
354                 pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
355             }
356             pix += ystride;
357         }
358     }
359 }
360 static void deblock_v_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
361 {
362     deblock_luma_c( pix, stride, 1, alpha, beta, tc0 ); 
363 }
364 static void deblock_h_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
365 {
366     deblock_luma_c( pix, 1, stride, alpha, beta, tc0 );
367 }
368
369 static inline void deblock_chroma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
370 {
371     int i, d;
372     for( i = 0; i < 4; i++ ) {
373         const int tc = tc0[i];
374         if( tc <= 0 ) {
375             pix += 2*ystride;
376             continue;
377         }
378         for( d = 0; d < 2; d++ ) {
379             const int p1 = pix[-2*xstride];
380             const int p0 = pix[-1*xstride];
381             const int q0 = pix[ 0*xstride];
382             const int q1 = pix[ 1*xstride];
383
384             if( abs( p0 - q0 ) < alpha &&
385                 abs( p1 - p0 ) < beta &&
386                 abs( q1 - q0 ) < beta ) {
387
388                 int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
389                 pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
390                 pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
391             }
392             pix += ystride;
393         }
394     }
395 }
396 static void deblock_v_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
397 {   
398     deblock_chroma_c( pix, stride, 1, alpha, beta, tc0 );
399 }
400 static void deblock_h_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
401 {   
402     deblock_chroma_c( pix, 1, stride, alpha, beta, tc0 );
403 }
404
405 static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
406 {
407     int d;
408     for( d = 0; d < 16; d++ ) {
409         const int p2 = pix[-3*xstride];
410         const int p1 = pix[-2*xstride];
411         const int p0 = pix[-1*xstride];
412         const int q0 = pix[ 0*xstride];
413         const int q1 = pix[ 1*xstride];
414         const int q2 = pix[ 2*xstride];
415
416         if( abs( p0 - q0 ) < alpha &&
417             abs( p1 - p0 ) < beta &&
418             abs( q1 - q0 ) < beta ) {
419
420             if(abs( p0 - q0 ) < ((alpha >> 2) + 2) ){
421                 if( abs( p2 - p0 ) < beta)
422                 {
423                     const int p3 = pix[-4*xstride];
424                     /* p0', p1', p2' */
425                     pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
426                     pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
427                     pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
428                 } else {
429                     /* p0' */
430                     pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
431                 }
432                 if( abs( q2 - q0 ) < beta)
433                 {
434                     const int q3 = pix[3*xstride];
435                     /* q0', q1', q2' */
436                     pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
437                     pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
438                     pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
439                 } else {
440                     /* q0' */
441                     pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
442                 }
443             }else{
444                 /* p0', q0' */
445                 pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
446                 pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
447             }
448         }
449         pix += ystride;
450     }
451 }
452 static void deblock_v_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
453 {   
454     deblock_luma_intra_c( pix, stride, 1, alpha, beta );
455 }
456 static void deblock_h_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
457 {   
458     deblock_luma_intra_c( pix, 1, stride, alpha, beta );
459 }
460
461 static inline void deblock_chroma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
462 {   
463     int d; 
464     for( d = 0; d < 8; d++ ) {
465         const int p1 = pix[-2*xstride];
466         const int p0 = pix[-1*xstride];
467         const int q0 = pix[ 0*xstride];
468         const int q1 = pix[ 1*xstride];
469
470         if( abs( p0 - q0 ) < alpha &&
471             abs( p1 - p0 ) < beta &&
472             abs( q1 - q0 ) < beta ) {
473
474             pix[-1*xstride] = (2*p1 + p0 + q1 + 2) >> 2;   /* p0' */
475             pix[ 0*xstride] = (2*q1 + q0 + p1 + 2) >> 2;   /* q0' */
476         }
477
478         pix += ystride;
479     }
480 }
481 static void deblock_v_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
482 {   
483     deblock_chroma_intra_c( pix, stride, 1, alpha, beta );
484 }
485 static void deblock_h_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
486 {   
487     deblock_chroma_intra_c( pix, 1, stride, alpha, beta );
488 }
489
490 static inline void deblock_edge( x264_t *h, uint8_t *pix, int i_stride, int bS[4], int i_qp, int b_chroma,
491                                  x264_deblock_inter_t pf_inter, x264_deblock_intra_t pf_intra )
492 {
493     int i;
494     const int index_a = x264_clip3( i_qp + h->sh.i_alpha_c0_offset, 0, 51 );
495     const int alpha = i_alpha_table[index_a];
496     const int beta  = i_beta_table[x264_clip3( i_qp + h->sh.i_beta_offset, 0, 51 )];
497
498     if( bS[0] < 4 ) {
499         int8_t tc[4]; 
500         for(i=0; i<4; i++)
501             tc[i] = (bS[i] ? i_tc0_table[index_a][bS[i] - 1] : -1) + b_chroma;
502         pf_inter( pix, i_stride, alpha, beta, tc );
503     } else {
504         pf_intra( pix, i_stride, alpha, beta );
505     }
506 }
507
508 void x264_frame_deblocking_filter( x264_t *h, int i_slice_type )
509 {
510     const int s8x8 = 2 * h->mb.i_mb_stride;
511     const int s4x4 = 4 * h->mb.i_mb_stride;
512     const int b_interlaced = h->param.b_interlaced;
513     const int mvy_limit = 4 >> b_interlaced;
514     int mb_y, mb_x;
515
516     int i_stride2[3] = { h->fdec->i_stride[0] << b_interlaced,
517                          h->fdec->i_stride[1] << b_interlaced,
518                          h->fdec->i_stride[2] << b_interlaced };
519
520     for( mb_y = 0, mb_x = 0; mb_y < h->sps->i_mb_height; )
521     {
522         const int mb_xy  = mb_y * h->mb.i_mb_stride + mb_x;
523         const int mb_8x8 = 2 * s8x8 * mb_y + 2 * mb_x;
524         const int mb_4x4 = 4 * s4x4 * mb_y + 4 * mb_x;
525         const int b_8x8_transform = h->mb.mb_transform_size[mb_xy];
526         const int i_edge_end = (h->mb.type[mb_xy] == P_SKIP) ? 1 : 4;
527         int i_edge, i_dir;
528
529         int i_pix_y[3] = { 16*mb_y*h->fdec->i_stride[0] + 16*mb_x,
530                             8*mb_y*h->fdec->i_stride[1] +  8*mb_x,
531                             8*mb_y*h->fdec->i_stride[2] +  8*mb_x };
532         if( b_interlaced && (mb_y&1) )
533         {
534             i_pix_y[0] -= 15*h->fdec->i_stride[0];
535             i_pix_y[1] -=  7*h->fdec->i_stride[1];
536             i_pix_y[2] -=  7*h->fdec->i_stride[2];
537         }
538
539         /* cavlc + 8x8 transform stores nnz per 16 coeffs for the purpose of
540          * entropy coding, but per 64 coeffs for the purpose of deblocking */
541         if( !h->param.b_cabac && b_8x8_transform )
542         {
543             uint32_t *nnz = (uint32_t*)h->mb.non_zero_count[mb_xy];
544             if( nnz[0] ) nnz[0] = 0x01010101;
545             if( nnz[1] ) nnz[1] = 0x01010101;
546             if( nnz[2] ) nnz[2] = 0x01010101;
547             if( nnz[3] ) nnz[3] = 0x01010101;
548         }
549
550         /* i_dir == 0 -> vertical edge
551          * i_dir == 1 -> horizontal edge */
552         for( i_dir = 0; i_dir < 2; i_dir++ )
553         {
554             int i_start = (i_dir ? (mb_y <= b_interlaced) : (mb_x == 0));
555             int i_qp, i_qpn;
556
557             for( i_edge = i_start; i_edge < i_edge_end; i_edge++ )
558             {
559                 int mbn_xy, mbn_8x8, mbn_4x4;
560                 int bS[4];  /* filtering strength */
561
562                 if( b_8x8_transform && (i_edge&1) )
563                     continue;
564
565                 mbn_xy  = i_edge > 0 ? mb_xy  : ( i_dir == 0 ? mb_xy  - 1 : mb_xy - h->mb.i_mb_stride );
566                 mbn_8x8 = i_edge > 0 ? mb_8x8 : ( i_dir == 0 ? mb_8x8 - 2 : mb_8x8 - 2 * s8x8 );
567                 mbn_4x4 = i_edge > 0 ? mb_4x4 : ( i_dir == 0 ? mb_4x4 - 4 : mb_4x4 - 4 * s4x4 );
568
569                 if( b_interlaced && i_edge == 0 && i_dir == 1 )
570                 {
571                     mbn_xy -= h->mb.i_mb_stride;
572                     mbn_8x8 -= 2 * s8x8;
573                     mbn_4x4 -= 4 * s4x4;
574                 }
575
576                 /* *** Get bS for each 4px for the current edge *** */
577                 if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy] ) )
578                 {
579                     bS[0] = bS[1] = bS[2] = bS[3] = ( i_edge == 0 && !(b_interlaced && i_dir) ? 4 : 3 );
580                 }
581                 else
582                 {
583                     int i;
584                     for( i = 0; i < 4; i++ )
585                     {
586                         int x  = i_dir == 0 ? i_edge : i;
587                         int y  = i_dir == 0 ? i      : i_edge;
588                         int xn = (x - (i_dir == 0 ? 1 : 0 ))&0x03;
589                         int yn = (y - (i_dir == 0 ? 0 : 1 ))&0x03;
590
591                         if( h->mb.non_zero_count[mb_xy][block_idx_xy[x][y]] != 0 ||
592                             h->mb.non_zero_count[mbn_xy][block_idx_xy[xn][yn]] != 0 )
593                         {
594                             bS[i] = 2;
595                         }
596                         else
597                         {
598                             /* FIXME: A given frame may occupy more than one position in
599                              * the reference list. So we should compare the frame numbers,
600                              * not the indices in the ref list.
601                              * No harm yet, as we don't generate that case.*/
602
603                             int i8p= mb_8x8+(x/2)+(y/2)*s8x8;
604                             int i8q= mbn_8x8+(xn/2)+(yn/2)*s8x8;
605                             int i4p= mb_4x4+x+y*s4x4;
606                             int i4q= mbn_4x4+xn+yn*s4x4;
607                             int l;
608
609                             bS[i] = 0;
610
611                             for( l = 0; l < 1 + (i_slice_type == SLICE_TYPE_B); l++ )
612                             {
613                                 if( h->mb.ref[l][i8p] != h->mb.ref[l][i8q] ||
614                                     abs( h->mb.mv[l][i4p][0] - h->mb.mv[l][i4q][0] ) >= 4 ||
615                                     abs( h->mb.mv[l][i4p][1] - h->mb.mv[l][i4q][1] ) >= mvy_limit )
616                                 {
617                                     bS[i] = 1;
618                                     break;
619                                 }
620                             }
621                         }
622                     }
623                 }
624
625                 /* *** filter *** */
626                 /* Y plane */
627                 i_qp = h->mb.qp[mb_xy];
628                 i_qpn= h->mb.qp[mbn_xy];
629
630                 if( i_dir == 0 )
631                 {
632                     /* vertical edge */
633                     deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge],
634                                   i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
635                                   h->loopf.deblock_h_luma, h->loopf.deblock_h_luma_intra );
636                     if( !(i_edge & 1) )
637                     {
638                         /* U/V planes */
639                         int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
640                                       i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
641                         deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge],
642                                       i_stride2[1], bS, i_qpc, 1,
643                                       h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
644                         deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge],
645                                       i_stride2[2], bS, i_qpc, 1,
646                                       h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
647                     }
648                 }
649                 else
650                 {
651                     /* horizontal edge */
652                     deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge*i_stride2[0]],
653                                   i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
654                                   h->loopf.deblock_v_luma, h->loopf.deblock_v_luma_intra );
655                     /* U/V planes */
656                     if( !(i_edge & 1) )
657                     {
658                         int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
659                                       i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
660                         deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge*i_stride2[1]],
661                                       i_stride2[1], bS, i_qpc, 1,
662                                       h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
663                         deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge*i_stride2[2]],
664                                       i_stride2[2], bS, i_qpc, 1,
665                                       h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
666                     }
667                 }
668             }
669         }
670
671         /* next mb */
672         if( !b_interlaced || (mb_y&1) )
673             mb_x++;
674         if( mb_x >= h->sps->i_mb_width )
675         {
676             mb_x = 0;
677             mb_y++;
678         }
679         else
680             mb_y ^= b_interlaced;
681     }
682 }
683
684 #ifdef HAVE_MMXEXT
685 void x264_deblock_v_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
686 void x264_deblock_h_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
687 void x264_deblock_v_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
688 void x264_deblock_h_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
689
690 #ifdef ARCH_X86_64
691 void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
692 void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
693 #else
694 void x264_deblock_h_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
695 void x264_deblock_v8_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
696
697 void x264_deblock_v_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
698 {
699     x264_deblock_v8_luma_mmxext( pix,   stride, alpha, beta, tc0   );
700     x264_deblock_v8_luma_mmxext( pix+8, stride, alpha, beta, tc0+2 );
701 }
702 #endif
703 #endif
704
705 void x264_deblock_init( int cpu, x264_deblock_function_t *pf )
706 {
707     pf->deblock_v_luma = deblock_v_luma_c;
708     pf->deblock_h_luma = deblock_h_luma_c;
709     pf->deblock_v_chroma = deblock_v_chroma_c;
710     pf->deblock_h_chroma = deblock_h_chroma_c;
711     pf->deblock_v_luma_intra = deblock_v_luma_intra_c;
712     pf->deblock_h_luma_intra = deblock_h_luma_intra_c;
713     pf->deblock_v_chroma_intra = deblock_v_chroma_intra_c;
714     pf->deblock_h_chroma_intra = deblock_h_chroma_intra_c;
715
716 #ifdef HAVE_MMXEXT
717     if( cpu&X264_CPU_MMXEXT )
718     {
719         pf->deblock_v_chroma = x264_deblock_v_chroma_mmxext;
720         pf->deblock_h_chroma = x264_deblock_h_chroma_mmxext;
721         pf->deblock_v_chroma_intra = x264_deblock_v_chroma_intra_mmxext;
722         pf->deblock_h_chroma_intra = x264_deblock_h_chroma_intra_mmxext;
723
724 #ifdef ARCH_X86_64
725         if( cpu&X264_CPU_SSE2 )
726         {
727             pf->deblock_v_luma = x264_deblock_v_luma_sse2;
728             pf->deblock_h_luma = x264_deblock_h_luma_sse2;
729         }
730 #else
731         pf->deblock_v_luma = x264_deblock_v_luma_mmxext;
732         pf->deblock_h_luma = x264_deblock_h_luma_mmxext;
733 #endif
734     }
735 #endif
736 }
737