]> git.sesse.net Git - x264/blob - common/frame.c
support interlace. uses MBAFF syntax, but is not adaptive yet.
[x264] / 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     dst->i_type     = src->i_type;
163     dst->i_qpplus1  = src->i_qpplus1;
164     dst->i_pts      = src->i_pts;
165
166     switch( src->img.i_csp & X264_CSP_MASK )
167     {
168         case X264_CSP_I420:
169             h->csp.i420( dst, &src->img, h->param.i_width, h->param.i_height );
170             break;
171         case X264_CSP_YV12:
172             h->csp.yv12( dst, &src->img, h->param.i_width, h->param.i_height );
173             break;
174         case X264_CSP_I422:
175             h->csp.i422( dst, &src->img, h->param.i_width, h->param.i_height );
176             break;
177         case X264_CSP_I444:
178             h->csp.i444( dst, &src->img, h->param.i_width, h->param.i_height );
179             break;
180         case X264_CSP_YUYV:
181             h->csp.yuyv( dst, &src->img, h->param.i_width, h->param.i_height );
182             break;
183         case X264_CSP_RGB:
184             h->csp.rgb( dst, &src->img, h->param.i_width, h->param.i_height );
185             break;
186         case X264_CSP_BGR:
187             h->csp.bgr( dst, &src->img, h->param.i_width, h->param.i_height );
188             break;
189         case X264_CSP_BGRA:
190             h->csp.bgra( dst, &src->img, h->param.i_width, h->param.i_height );
191             break;
192
193         default:
194             x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" );
195             break;
196     }
197 }
198
199
200
201 static void plane_expand_border( uint8_t *pix, int i_stride, int i_width, int i_height, int i_padh, int i_padv )
202 {
203 #define PPIXEL(x, y) ( pix + (x) + (y)*i_stride )
204     int y;
205     for( y = 0; y < i_height; y++ )
206     {
207         /* left band */
208         memset( PPIXEL(-i_padh, y), PPIXEL(0, y)[0], i_padh );
209         /* right band */
210         memset( PPIXEL(i_width, y), PPIXEL(i_width-1, y)[0], i_padh );
211     }
212     /* upper band */
213     for( y = 0; y < i_padv; y++ )
214         memcpy( PPIXEL(-i_padh, -y-1), PPIXEL(-i_padh, 0), i_width+2*i_padh );
215     /* lower band */
216     for( y = 0; y < i_padv; y++ )
217         memcpy( PPIXEL(-i_padh, i_height+y), PPIXEL(-i_padh, i_height-1), i_width+2*i_padh );
218 #undef PPIXEL
219 }
220
221 void x264_frame_expand_border( x264_t *h, x264_frame_t *frame )
222 {
223     int i;
224     for( i = 0; i < frame->i_plane; i++ )
225     {
226         int stride = frame->i_stride[i];
227         int width = 16*h->sps->i_mb_width >> !!i;
228         int height = 16*h->sps->i_mb_height >> !!i;
229         int padh = PADH >> !!i;
230         int padv = PADV >> !!i;
231         if( h->param.b_interlaced )
232         {
233             plane_expand_border( frame->plane[i], stride*2, width, height>>1, padh, padv );
234             plane_expand_border( frame->plane[i]+stride, stride*2, width, height>>1, padh, padv );
235         }
236         else
237         {
238             plane_expand_border( frame->plane[i], stride, width, height, padh, padv );
239         }
240     }
241 }
242
243 void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame )
244 {
245     /* during filtering, 8 extra pixels were filtered on each edge. 
246        we want to expand border from the last filtered pixel */
247     int stride = frame->i_stride[0];
248     int width = 16*h->sps->i_mb_width;
249     int height = 16*h->sps->i_mb_height;
250     int padh = PADH - 8;
251     int padv = PADV - 8;
252     int i;
253     for( i = 1; i < 4; i++ )
254     {
255         if( h->param.b_interlaced )
256         {
257             plane_expand_border( frame->filtered[i] - 16*stride - 8, stride*2, width+16, (height>>1)+16, padh, padv );
258             plane_expand_border( frame->filtered[i] - 15*stride - 8, stride*2, width+16, (height>>1)+16, padh, padv );
259         }
260         else
261         {
262             plane_expand_border( frame->filtered[i] - 8*stride - 8, stride, width+16, height+16, padh, padv );
263         }
264     }
265 }
266
267 void x264_frame_expand_border_lowres( x264_frame_t *frame )
268 {
269     int i;
270     for( i = 0; i < 4; i++ )
271         plane_expand_border( frame->lowres[i], frame->i_stride_lowres, frame->i_stride_lowres - 2*PADH, frame->i_lines_lowres, PADH, PADV );
272 }
273
274 void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
275 {
276     int i, y;
277     for( i = 0; i < frame->i_plane; i++ )
278     {
279         int i_subsample = i ? 1 : 0;
280         int i_width = h->param.i_width >> i_subsample;
281         int i_height = h->param.i_height >> i_subsample;
282         int i_padx = ( h->sps->i_mb_width * 16 - h->param.i_width ) >> i_subsample;
283         int i_pady = ( h->sps->i_mb_height * 16 - h->param.i_height ) >> i_subsample;
284
285         if( i_padx )
286         {
287             for( y = 0; y < i_height; y++ )
288                 memset( &frame->plane[i][y*frame->i_stride[i] + i_width],
289                          frame->plane[i][y*frame->i_stride[i] + i_width - 1],
290                          i_padx );
291         }
292         if( i_pady )
293         {
294             //FIXME interlace? or just let it pad using the wrong field
295             for( y = i_height; y < i_height + i_pady; y++ )
296                 memcpy( &frame->plane[i][y*frame->i_stride[i]],
297                         &frame->plane[i][(i_height-1)*frame->i_stride[i]],
298                         i_width + i_padx );
299         }
300     }
301 }
302
303
304 /* Deblocking filter */
305
306 static const int i_alpha_table[52] =
307 {
308      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
309      0,  0,  0,  0,  0,  0,  4,  4,  5,  6,
310      7,  8,  9, 10, 12, 13, 15, 17, 20, 22,
311     25, 28, 32, 36, 40, 45, 50, 56, 63, 71,
312     80, 90,101,113,127,144,162,182,203,226,
313     255, 255
314 };
315 static const int i_beta_table[52] =
316 {
317      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
318      0,  0,  0,  0,  0,  0,  2,  2,  2,  3,
319      3,  3,  3,  4,  4,  4,  6,  6,  7,  7,
320      8,  8,  9,  9, 10, 10, 11, 11, 12, 12,
321     13, 13, 14, 14, 15, 15, 16, 16, 17, 17,
322     18, 18
323 };
324 static const int i_tc0_table[52][3] =
325 {
326     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
327     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
328     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 1 },
329     { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 0, 1, 1 }, { 1, 1, 1 },
330     { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 },
331     { 1, 1, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 2, 2, 3 }, { 2, 2, 4 }, { 2, 3, 4 },
332     { 2, 3, 4 }, { 3, 3, 5 }, { 3, 4, 6 }, { 3, 4, 6 }, { 4, 5, 7 }, { 4, 5, 8 },
333     { 4, 6, 9 }, { 5, 7,10 }, { 6, 8,11 }, { 6, 8,13 }, { 7,10,14 }, { 8,11,16 },
334     { 9,12,18 }, {10,13,20 }, {11,15,23 }, {13,17,25 }
335 };
336
337 /* From ffmpeg */
338 static inline int clip_uint8( int a )
339 {
340     if (a&(~255))
341         return (-a)>>31;
342     else
343         return a;
344 }
345
346 static inline void deblock_luma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
347 {
348     int i, d;
349     for( i = 0; i < 4; i++ ) {
350         if( tc0[i] < 0 ) {
351             pix += 4*ystride;
352             continue;
353         }
354         for( d = 0; d < 4; d++ ) {
355             const int p2 = pix[-3*xstride];
356             const int p1 = pix[-2*xstride];
357             const int p0 = pix[-1*xstride];
358             const int q0 = pix[ 0*xstride];
359             const int q1 = pix[ 1*xstride];
360             const int q2 = pix[ 2*xstride];
361    
362             if( abs( p0 - q0 ) < alpha &&
363                 abs( p1 - p0 ) < beta &&
364                 abs( q1 - q0 ) < beta ) {
365    
366                 int tc = tc0[i];
367                 int delta;
368    
369                 if( abs( p2 - p0 ) < beta ) {
370                     pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0[i], tc0[i] );
371                     tc++; 
372                 }
373                 if( abs( q2 - q0 ) < beta ) {
374                     pix[ 1*xstride] = q1 + x264_clip3( (( q2 + ((p0 + q0 + 1) >> 1)) >> 1) - q1, -tc0[i], tc0[i] );
375                     tc++;
376                 }
377     
378                 delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
379                 pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
380                 pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
381             }
382             pix += ystride;
383         }
384     }
385 }
386 static void deblock_v_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
387 {
388     deblock_luma_c( pix, stride, 1, alpha, beta, tc0 ); 
389 }
390 static void deblock_h_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
391 {
392     deblock_luma_c( pix, 1, stride, alpha, beta, tc0 );
393 }
394
395 static inline void deblock_chroma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
396 {
397     int i, d;
398     for( i = 0; i < 4; i++ ) {
399         const int tc = tc0[i];
400         if( tc <= 0 ) {
401             pix += 2*ystride;
402             continue;
403         }
404         for( d = 0; d < 2; d++ ) {
405             const int p1 = pix[-2*xstride];
406             const int p0 = pix[-1*xstride];
407             const int q0 = pix[ 0*xstride];
408             const int q1 = pix[ 1*xstride];
409
410             if( abs( p0 - q0 ) < alpha &&
411                 abs( p1 - p0 ) < beta &&
412                 abs( q1 - q0 ) < beta ) {
413
414                 int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
415                 pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
416                 pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
417             }
418             pix += ystride;
419         }
420     }
421 }
422 static void deblock_v_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
423 {   
424     deblock_chroma_c( pix, stride, 1, alpha, beta, tc0 );
425 }
426 static void deblock_h_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
427 {   
428     deblock_chroma_c( pix, 1, stride, alpha, beta, tc0 );
429 }
430
431 static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
432 {
433     int d;
434     for( d = 0; d < 16; d++ ) {
435         const int p2 = pix[-3*xstride];
436         const int p1 = pix[-2*xstride];
437         const int p0 = pix[-1*xstride];
438         const int q0 = pix[ 0*xstride];
439         const int q1 = pix[ 1*xstride];
440         const int q2 = pix[ 2*xstride];
441
442         if( abs( p0 - q0 ) < alpha &&
443             abs( p1 - p0 ) < beta &&
444             abs( q1 - q0 ) < beta ) {
445
446             if(abs( p0 - q0 ) < ((alpha >> 2) + 2) ){
447                 if( abs( p2 - p0 ) < beta)
448                 {
449                     const int p3 = pix[-4*xstride];
450                     /* p0', p1', p2' */
451                     pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
452                     pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
453                     pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
454                 } else {
455                     /* p0' */
456                     pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
457                 }
458                 if( abs( q2 - q0 ) < beta)
459                 {
460                     const int q3 = pix[3*xstride];
461                     /* q0', q1', q2' */
462                     pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
463                     pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
464                     pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
465                 } else {
466                     /* q0' */
467                     pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
468                 }
469             }else{
470                 /* p0', q0' */
471                 pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
472                 pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
473             }
474         }
475         pix += ystride;
476     }
477 }
478 static void deblock_v_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
479 {   
480     deblock_luma_intra_c( pix, stride, 1, alpha, beta );
481 }
482 static void deblock_h_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
483 {   
484     deblock_luma_intra_c( pix, 1, stride, alpha, beta );
485 }
486
487 static inline void deblock_chroma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
488 {   
489     int d; 
490     for( d = 0; d < 8; d++ ) {
491         const int p1 = pix[-2*xstride];
492         const int p0 = pix[-1*xstride];
493         const int q0 = pix[ 0*xstride];
494         const int q1 = pix[ 1*xstride];
495
496         if( abs( p0 - q0 ) < alpha &&
497             abs( p1 - p0 ) < beta &&
498             abs( q1 - q0 ) < beta ) {
499
500             pix[-1*xstride] = (2*p1 + p0 + q1 + 2) >> 2;   /* p0' */
501             pix[ 0*xstride] = (2*q1 + q0 + p1 + 2) >> 2;   /* q0' */
502         }
503
504         pix += ystride;
505     }
506 }
507 static void deblock_v_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
508 {   
509     deblock_chroma_intra_c( pix, stride, 1, alpha, beta );
510 }
511 static void deblock_h_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
512 {   
513     deblock_chroma_intra_c( pix, 1, stride, alpha, beta );
514 }
515
516 static inline void deblock_edge( x264_t *h, uint8_t *pix, int i_stride, int bS[4], int i_qp, int b_chroma,
517                                  x264_deblock_inter_t pf_inter, x264_deblock_intra_t pf_intra )
518 {
519     int i;
520     const int index_a = x264_clip3( i_qp + h->sh.i_alpha_c0_offset, 0, 51 );
521     const int alpha = i_alpha_table[index_a];
522     const int beta  = i_beta_table[x264_clip3( i_qp + h->sh.i_beta_offset, 0, 51 )];
523
524     if( bS[0] < 4 ) {
525         int8_t tc[4]; 
526         for(i=0; i<4; i++)
527             tc[i] = (bS[i] ? i_tc0_table[index_a][bS[i] - 1] : -1) + b_chroma;
528         pf_inter( pix, i_stride, alpha, beta, tc );
529     } else {
530         pf_intra( pix, i_stride, alpha, beta );
531     }
532 }
533
534 void x264_frame_deblocking_filter( x264_t *h, int i_slice_type )
535 {
536     const int s8x8 = 2 * h->mb.i_mb_stride;
537     const int s4x4 = 4 * h->mb.i_mb_stride;
538     const int b_interlaced = h->param.b_interlaced;
539     const int mvy_limit = 4 >> b_interlaced;
540     int mb_y, mb_x;
541
542     int i_stride2[3] = { h->fdec->i_stride[0] << b_interlaced,
543                          h->fdec->i_stride[1] << b_interlaced,
544                          h->fdec->i_stride[2] << b_interlaced };
545
546     for( mb_y = 0, mb_x = 0; mb_y < h->sps->i_mb_height; )
547     {
548         const int mb_xy  = mb_y * h->mb.i_mb_stride + mb_x;
549         const int mb_8x8 = 2 * s8x8 * mb_y + 2 * mb_x;
550         const int mb_4x4 = 4 * s4x4 * mb_y + 4 * mb_x;
551         const int b_8x8_transform = h->mb.mb_transform_size[mb_xy];
552         const int i_edge_end = (h->mb.type[mb_xy] == P_SKIP) ? 1 : 4;
553         int i_edge, i_dir;
554
555         int i_pix_y[3] = { 16*mb_y*h->fdec->i_stride[0] + 16*mb_x,
556                             8*mb_y*h->fdec->i_stride[1] +  8*mb_x,
557                             8*mb_y*h->fdec->i_stride[2] +  8*mb_x };
558         if( b_interlaced && (mb_y&1) )
559         {
560             i_pix_y[0] -= 15*h->fdec->i_stride[0];
561             i_pix_y[1] -=  7*h->fdec->i_stride[1];
562             i_pix_y[2] -=  7*h->fdec->i_stride[2];
563         }
564
565         /* cavlc + 8x8 transform stores nnz per 16 coeffs for the purpose of
566          * entropy coding, but per 64 coeffs for the purpose of deblocking */
567         if( !h->param.b_cabac && b_8x8_transform )
568         {
569             uint32_t *nnz = (uint32_t*)h->mb.non_zero_count[mb_xy];
570             if( nnz[0] ) nnz[0] = 0x01010101;
571             if( nnz[1] ) nnz[1] = 0x01010101;
572             if( nnz[2] ) nnz[2] = 0x01010101;
573             if( nnz[3] ) nnz[3] = 0x01010101;
574         }
575
576         /* i_dir == 0 -> vertical edge
577          * i_dir == 1 -> horizontal edge */
578         for( i_dir = 0; i_dir < 2; i_dir++ )
579         {
580             int i_start = (i_dir ? (mb_y <= b_interlaced) : (mb_x == 0));
581             int i_qp, i_qpn;
582
583             for( i_edge = i_start; i_edge < i_edge_end; i_edge++ )
584             {
585                 int mbn_xy, mbn_8x8, mbn_4x4;
586                 int bS[4];  /* filtering strength */
587
588                 if( b_8x8_transform && (i_edge&1) )
589                     continue;
590
591                 mbn_xy  = i_edge > 0 ? mb_xy  : ( i_dir == 0 ? mb_xy  - 1 : mb_xy - h->mb.i_mb_stride );
592                 mbn_8x8 = i_edge > 0 ? mb_8x8 : ( i_dir == 0 ? mb_8x8 - 2 : mb_8x8 - 2 * s8x8 );
593                 mbn_4x4 = i_edge > 0 ? mb_4x4 : ( i_dir == 0 ? mb_4x4 - 4 : mb_4x4 - 4 * s4x4 );
594
595                 if( b_interlaced && i_edge == 0 && i_dir == 1 )
596                 {
597                     mbn_xy -= h->mb.i_mb_stride;
598                     mbn_8x8 -= 2 * s8x8;
599                     mbn_4x4 -= 4 * s4x4;
600                 }
601
602                 /* *** Get bS for each 4px for the current edge *** */
603                 if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy] ) )
604                 {
605                     bS[0] = bS[1] = bS[2] = bS[3] = ( i_edge == 0 && !(b_interlaced && i_dir) ? 4 : 3 );
606                 }
607                 else
608                 {
609                     int i;
610                     for( i = 0; i < 4; i++ )
611                     {
612                         int x  = i_dir == 0 ? i_edge : i;
613                         int y  = i_dir == 0 ? i      : i_edge;
614                         int xn = (x - (i_dir == 0 ? 1 : 0 ))&0x03;
615                         int yn = (y - (i_dir == 0 ? 0 : 1 ))&0x03;
616
617                         if( h->mb.non_zero_count[mb_xy][block_idx_xy[x][y]] != 0 ||
618                             h->mb.non_zero_count[mbn_xy][block_idx_xy[xn][yn]] != 0 )
619                         {
620                             bS[i] = 2;
621                         }
622                         else
623                         {
624                             /* FIXME: A given frame may occupy more than one position in
625                              * the reference list. So we should compare the frame numbers,
626                              * not the indices in the ref list.
627                              * No harm yet, as we don't generate that case.*/
628
629                             int i8p= mb_8x8+(x/2)+(y/2)*s8x8;
630                             int i8q= mbn_8x8+(xn/2)+(yn/2)*s8x8;
631                             int i4p= mb_4x4+x+y*s4x4;
632                             int i4q= mbn_4x4+xn+yn*s4x4;
633                             int l;
634
635                             bS[i] = 0;
636
637                             for( l = 0; l < 1 + (i_slice_type == SLICE_TYPE_B); l++ )
638                             {
639                                 if( h->mb.ref[l][i8p] != h->mb.ref[l][i8q] ||
640                                     abs( h->mb.mv[l][i4p][0] - h->mb.mv[l][i4q][0] ) >= 4 ||
641                                     abs( h->mb.mv[l][i4p][1] - h->mb.mv[l][i4q][1] ) >= mvy_limit )
642                                 {
643                                     bS[i] = 1;
644                                     break;
645                                 }
646                             }
647                         }
648                     }
649                 }
650
651                 /* *** filter *** */
652                 /* Y plane */
653                 i_qp = h->mb.qp[mb_xy];
654                 i_qpn= h->mb.qp[mbn_xy];
655
656                 if( i_dir == 0 )
657                 {
658                     /* vertical edge */
659                     deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge],
660                                   i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
661                                   h->loopf.deblock_h_luma, h->loopf.deblock_h_luma_intra );
662                     if( !(i_edge & 1) )
663                     {
664                         /* U/V planes */
665                         int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
666                                       i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
667                         deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge],
668                                       i_stride2[1], bS, i_qpc, 1,
669                                       h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
670                         deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge],
671                                       i_stride2[2], bS, i_qpc, 1,
672                                       h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
673                     }
674                 }
675                 else
676                 {
677                     /* horizontal edge */
678                     deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge*i_stride2[0]],
679                                   i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
680                                   h->loopf.deblock_v_luma, h->loopf.deblock_v_luma_intra );
681                     /* U/V planes */
682                     if( !(i_edge & 1) )
683                     {
684                         int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
685                                       i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
686                         deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge*i_stride2[1]],
687                                       i_stride2[1], bS, i_qpc, 1,
688                                       h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
689                         deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge*i_stride2[2]],
690                                       i_stride2[2], bS, i_qpc, 1,
691                                       h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
692                     }
693                 }
694             }
695         }
696
697         /* next mb */
698         if( !b_interlaced || (mb_y&1) )
699             mb_x++;
700         if( mb_x >= h->sps->i_mb_width )
701         {
702             mb_x = 0;
703             mb_y++;
704         }
705         else
706             mb_y ^= b_interlaced;
707     }
708 }
709
710 #ifdef HAVE_MMXEXT
711 void x264_deblock_v_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
712 void x264_deblock_h_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
713 void x264_deblock_v_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
714 void x264_deblock_h_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
715
716 #ifdef ARCH_X86_64
717 void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
718 void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
719 #else
720 void x264_deblock_h_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
721 void x264_deblock_v8_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
722
723 void x264_deblock_v_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
724 {
725     x264_deblock_v8_luma_mmxext( pix,   stride, alpha, beta, tc0   );
726     x264_deblock_v8_luma_mmxext( pix+8, stride, alpha, beta, tc0+2 );
727 }
728 #endif
729 #endif
730
731 void x264_deblock_init( int cpu, x264_deblock_function_t *pf )
732 {
733     pf->deblock_v_luma = deblock_v_luma_c;
734     pf->deblock_h_luma = deblock_h_luma_c;
735     pf->deblock_v_chroma = deblock_v_chroma_c;
736     pf->deblock_h_chroma = deblock_h_chroma_c;
737     pf->deblock_v_luma_intra = deblock_v_luma_intra_c;
738     pf->deblock_h_luma_intra = deblock_h_luma_intra_c;
739     pf->deblock_v_chroma_intra = deblock_v_chroma_intra_c;
740     pf->deblock_h_chroma_intra = deblock_h_chroma_intra_c;
741
742 #ifdef HAVE_MMXEXT
743     if( cpu&X264_CPU_MMXEXT )
744     {
745         pf->deblock_v_chroma = x264_deblock_v_chroma_mmxext;
746         pf->deblock_h_chroma = x264_deblock_h_chroma_mmxext;
747         pf->deblock_v_chroma_intra = x264_deblock_v_chroma_intra_mmxext;
748         pf->deblock_h_chroma_intra = x264_deblock_h_chroma_intra_mmxext;
749
750 #ifdef ARCH_X86_64
751         if( cpu&X264_CPU_SSE2 )
752         {
753             pf->deblock_v_luma = x264_deblock_v_luma_sse2;
754             pf->deblock_h_luma = x264_deblock_h_luma_sse2;
755         }
756 #else
757         pf->deblock_v_luma = x264_deblock_v_luma_mmxext;
758         pf->deblock_h_luma = x264_deblock_h_luma_mmxext;
759 #endif
760     }
761 #endif
762 }
763