]> git.sesse.net Git - x264/blob - common/frame.c
merge x86_32 and x86_64 asm, with macros to abstract calling convention and register...
[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 "common.h"
25
26 x264_frame_t *x264_frame_new( x264_t *h )
27 {
28     x264_frame_t *frame = x264_malloc( sizeof(x264_frame_t) );
29     int i, j;
30
31     int i_mb_count = h->mb.i_mb_count;
32     int i_stride, i_width, i_lines;
33     int i_padv = PADV << h->param.b_interlaced;
34
35     if( !frame ) return NULL;
36
37     memset( frame, 0, sizeof(x264_frame_t) );
38
39     /* allocate frame data (+64 for extra data for me) */
40     i_width  = ( ( h->param.i_width  + 15 ) & -16 );
41     i_stride = i_width + 2*PADH;
42     i_lines  = ( ( h->param.i_height + 15 ) & -16 );
43     if( h->param.b_interlaced )
44         i_lines = ( i_lines + 31 ) & -32;
45
46     if( h->param.cpu&X264_CPU_CACHELINE_SPLIT )
47     {
48         int align = h->param.cpu&X264_CPU_CACHELINE_32 ? 32 : 64;
49         i_stride = (i_stride + align-1) & -align;
50     }
51
52     frame->i_plane = 3;
53     for( i = 0; i < 3; i++ )
54     {
55         frame->i_stride[i] = i_stride >> !!i;
56         frame->i_width[i] = i_width >> !!i;
57         frame->i_lines[i] = i_lines >> !!i;
58         CHECKED_MALLOC( frame->buffer[i],
59                         frame->i_stride[i] * (i_lines + 2*i_padv) >> !!i );
60         frame->plane[i] = ((uint8_t*)frame->buffer[i]) +
61                           ((frame->i_stride[i] * i_padv + PADH) >> !!i);
62     }
63
64     frame->filtered[0] = frame->plane[0];
65     for( i = 0; i < 3; i++ )
66     {
67         CHECKED_MALLOC( frame->buffer[4+i],
68                         frame->i_stride[0] * ( frame->i_lines[0] + 2*i_padv ) );
69         frame->filtered[i+1] = ((uint8_t*)frame->buffer[4+i]) +
70                                 frame->i_stride[0] * i_padv + PADH;
71     }
72
73     if( h->frames.b_have_lowres )
74     {
75         frame->i_width_lowres = frame->i_width[0]/2;
76         frame->i_stride_lowres = frame->i_width_lowres + 2*PADH;
77         frame->i_lines_lowres = frame->i_lines[0]/2;
78         for( i = 0; i < 4; i++ )
79         {
80             CHECKED_MALLOC( frame->buffer_lowres[i],
81                             frame->i_stride_lowres * ( frame->i_lines[0]/2 + 2*i_padv ) );
82             frame->lowres[i] = ((uint8_t*)frame->buffer_lowres[i]) +
83                                 frame->i_stride_lowres * i_padv + PADH;
84         }
85     }
86
87     if( h->param.analyse.i_me_method >= X264_ME_ESA )
88     {
89         CHECKED_MALLOC( frame->buffer[7],
90                         2 * frame->i_stride[0] * (frame->i_lines[0] + 2*i_padv) * sizeof(uint16_t) );
91         frame->integral = (uint16_t*)frame->buffer[7] + frame->i_stride[0] * i_padv + PADH;
92     }
93
94     frame->i_poc = -1;
95     frame->i_type = X264_TYPE_AUTO;
96     frame->i_qpplus1 = 0;
97     frame->i_pts = -1;
98     frame->i_frame = -1;
99     frame->i_frame_num = -1;
100     frame->i_lines_completed = -1;
101
102     CHECKED_MALLOC( frame->mb_type, i_mb_count * sizeof(int8_t));
103     CHECKED_MALLOC( frame->mv[0], 2*16 * i_mb_count * sizeof(int16_t) );
104     CHECKED_MALLOC( frame->ref[0], 4 * i_mb_count * sizeof(int8_t) );
105     if( h->param.i_bframe )
106     {
107         CHECKED_MALLOC( frame->mv[1], 2*16 * i_mb_count * sizeof(int16_t) );
108         CHECKED_MALLOC( frame->ref[1], 4 * i_mb_count * sizeof(int8_t) );
109     }
110     else
111     {
112         frame->mv[1]  = NULL;
113         frame->ref[1] = NULL;
114     }
115
116     CHECKED_MALLOC( frame->i_row_bits, i_lines/16 * sizeof(int) );
117     CHECKED_MALLOC( frame->i_row_qp, i_lines/16 * sizeof(int) );
118     for( i = 0; i < h->param.i_bframe + 2; i++ )
119         for( j = 0; j < h->param.i_bframe + 2; j++ )
120             CHECKED_MALLOC( frame->i_row_satds[i][j], i_lines/16 * sizeof(int) );
121
122     x264_pthread_mutex_init( &frame->mutex, NULL );
123     x264_pthread_cond_init( &frame->cv, NULL );
124
125     return frame;
126
127 fail:
128     x264_frame_delete( frame );
129     return NULL;
130 }
131
132 void x264_frame_delete( x264_frame_t *frame )
133 {
134     int i, j;
135     for( i = 0; i < 8; i++ )
136         x264_free( frame->buffer[i] );
137     for( i = 0; i < 4; i++ )
138         x264_free( frame->buffer_lowres[i] );
139     for( i = 0; i < X264_BFRAME_MAX+2; i++ )
140         for( j = 0; j < X264_BFRAME_MAX+2; j++ )
141             x264_free( frame->i_row_satds[i][j] );
142     x264_free( frame->i_row_bits );
143     x264_free( frame->i_row_qp );
144     x264_free( frame->mb_type );
145     x264_free( frame->mv[0] );
146     x264_free( frame->mv[1] );
147     x264_free( frame->ref[0] );
148     x264_free( frame->ref[1] );
149     x264_pthread_mutex_destroy( &frame->mutex );
150     x264_pthread_cond_destroy( &frame->cv );
151     x264_free( frame );
152 }
153
154 int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
155 {
156     int i_csp = src->img.i_csp & X264_CSP_MASK;
157     int i;
158     if( i_csp != X264_CSP_I420 && i_csp != X264_CSP_YV12 )
159     {
160         x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" );
161         return -1;
162     }
163
164     dst->i_type     = src->i_type;
165     dst->i_qpplus1  = src->i_qpplus1;
166     dst->i_pts      = src->i_pts;
167
168     for( i=0; i<3; i++ )
169     {
170         int s = (i_csp == X264_CSP_YV12 && i) ? i^3 : i;
171         uint8_t *plane = src->img.plane[s];
172         int stride = src->img.i_stride[s];
173         int width = h->param.i_width >> !!i;
174         int height = h->param.i_height >> !!i;
175         if( src->img.i_csp & X264_CSP_VFLIP )
176         {
177             plane += (height-1)*stride;
178             stride = -stride;
179         }
180         h->mc.plane_copy( dst->plane[i], dst->i_stride[i], plane, stride, width, height );
181     }
182     return 0;
183 }
184
185
186
187 static void plane_expand_border( uint8_t *pix, int i_stride, int i_width, int i_height, int i_padh, int i_padv, int b_pad_top, int b_pad_bottom )
188 {
189 #define PPIXEL(x, y) ( pix + (x) + (y)*i_stride )
190     int y;
191     for( y = 0; y < i_height; y++ )
192     {
193         /* left band */
194         memset( PPIXEL(-i_padh, y), PPIXEL(0, y)[0], i_padh );
195         /* right band */
196         memset( PPIXEL(i_width, y), PPIXEL(i_width-1, y)[0], i_padh );
197     }
198     /* upper band */
199     if( b_pad_top )
200     for( y = 0; y < i_padv; y++ )
201         memcpy( PPIXEL(-i_padh, -y-1), PPIXEL(-i_padh, 0), i_width+2*i_padh );
202     /* lower band */
203     if( b_pad_bottom )
204     for( y = 0; y < i_padv; y++ )
205         memcpy( PPIXEL(-i_padh, i_height+y), PPIXEL(-i_padh, i_height-1), i_width+2*i_padh );
206 #undef PPIXEL
207 }
208
209 void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
210 {
211     int i;
212     int b_start = !mb_y;
213     if( mb_y & h->sh.b_mbaff )
214         return;
215     for( i = 0; i < frame->i_plane; i++ )
216     {
217         int stride = frame->i_stride[i];
218         int width = 16*h->sps->i_mb_width >> !!i;
219         int height = (b_end ? 16*(h->sps->i_mb_height - mb_y) >> h->sh.b_mbaff : 16) >> !!i;
220         int padh = PADH >> !!i;
221         int padv = PADV >> !!i;
222         // buffer: 2 chroma, 3 luma (rounded to 4) because deblocking goes beyond the top of the mb
223         uint8_t *pix = frame->plane[i] + X264_MAX(0, (16*mb_y-4)*stride >> !!i);
224         if( b_end && !b_start )
225             height += 4 >> (!!i + h->sh.b_mbaff);
226         if( h->sh.b_mbaff )
227         {
228             plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end );
229             plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end );
230         }
231         else
232         {
233             plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end );
234         }
235     }
236 }
237
238 void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
239 {
240     /* during filtering, 8 extra pixels were filtered on each edge. 
241        we want to expand border from the last filtered pixel */
242     int b_start = !mb_y;
243     int stride = frame->i_stride[0];
244     int width = 16*h->sps->i_mb_width + 16;
245     int height = b_end ? (16*(h->sps->i_mb_height - mb_y) >> h->sh.b_mbaff) + 16 : 16;
246     int padh = PADH - 8;
247     int padv = PADV - 8;
248     int i;
249     for( i = 1; i < 4; i++ )
250     {
251         // buffer: 8 luma, to match the hpel filter
252         uint8_t *pix = frame->filtered[i] + (16*mb_y - (8 << h->sh.b_mbaff)) * stride - 8;
253         if( h->sh.b_mbaff )
254         {
255             plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end );
256             plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end );
257         }
258         else
259         {
260             plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end );
261         }
262     }
263 }
264
265 void x264_frame_expand_border_lowres( x264_frame_t *frame )
266 {
267     int i;
268     for( i = 0; i < 4; i++ )
269         plane_expand_border( frame->lowres[i], frame->i_stride_lowres, frame->i_stride_lowres - 2*PADH, frame->i_lines_lowres, PADH, PADV, 1, 1 );
270 }
271
272 void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
273 {
274     int i, y;
275     for( i = 0; i < frame->i_plane; i++ )
276     {
277         int i_subsample = i ? 1 : 0;
278         int i_width = h->param.i_width >> i_subsample;
279         int i_height = h->param.i_height >> i_subsample;
280         int i_padx = ( h->sps->i_mb_width * 16 - h->param.i_width ) >> i_subsample;
281         int i_pady = ( h->sps->i_mb_height * 16 - h->param.i_height ) >> i_subsample;
282
283         if( i_padx )
284         {
285             for( y = 0; y < i_height; y++ )
286                 memset( &frame->plane[i][y*frame->i_stride[i] + i_width],
287                          frame->plane[i][y*frame->i_stride[i] + i_width - 1],
288                          i_padx );
289         }
290         if( i_pady )
291         {
292             //FIXME interlace? or just let it pad using the wrong field
293             for( y = i_height; y < i_height + i_pady; y++ )
294                 memcpy( &frame->plane[i][y*frame->i_stride[i]],
295                         &frame->plane[i][(i_height-1)*frame->i_stride[i]],
296                         i_width + i_padx );
297         }
298     }
299 }
300
301
302 /* cavlc + 8x8 transform stores nnz per 16 coeffs for the purpose of
303  * entropy coding, but per 64 coeffs for the purpose of deblocking */
304 void munge_cavlc_nnz_row( x264_t *h, int mb_y, uint8_t (*buf)[16] )
305 {
306     uint32_t (*src)[6] = (uint32_t(*)[6])h->mb.non_zero_count + mb_y * h->sps->i_mb_width;
307     int8_t *transform = h->mb.mb_transform_size + mb_y * h->sps->i_mb_width;
308     int x;
309     for( x=0; x<h->sps->i_mb_width; x++ )
310     {
311         memcpy( buf+x, src+x, 16 );
312         if( transform[x] )
313         {
314             if( src[x][0] ) src[x][0] = 0x01010101;
315             if( src[x][1] ) src[x][1] = 0x01010101;
316             if( src[x][2] ) src[x][2] = 0x01010101;
317             if( src[x][3] ) src[x][3] = 0x01010101;
318         }
319     }
320 }
321
322 static void restore_cavlc_nnz_row( x264_t *h, int mb_y, uint8_t (*buf)[16] )
323 {
324     uint8_t (*dst)[24] = h->mb.non_zero_count + mb_y * h->sps->i_mb_width;
325     int x;
326     for( x=0; x<h->sps->i_mb_width; x++ )
327         memcpy( dst+x, buf+x, 16 );
328 }
329
330 static void munge_cavlc_nnz( x264_t *h, int mb_y, uint8_t (*buf)[16], void (*func)(x264_t*, int, uint8_t (*)[16]) )
331 {
332     func( h, mb_y, buf );
333     if( mb_y > 0 )
334         func( h, mb_y-1, buf + h->sps->i_mb_width );
335     if( h->sh.b_mbaff )
336     {
337         func( h, mb_y+1, buf + h->sps->i_mb_width * 2 );
338         if( mb_y > 0 )
339             func( h, mb_y-2, buf + h->sps->i_mb_width * 3 );
340     }
341 }
342
343
344 /* Deblocking filter */
345
346 static const int i_alpha_table[52] =
347 {
348      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
349      0,  0,  0,  0,  0,  0,  4,  4,  5,  6,
350      7,  8,  9, 10, 12, 13, 15, 17, 20, 22,
351     25, 28, 32, 36, 40, 45, 50, 56, 63, 71,
352     80, 90,101,113,127,144,162,182,203,226,
353     255, 255
354 };
355 static const int i_beta_table[52] =
356 {
357      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
358      0,  0,  0,  0,  0,  0,  2,  2,  2,  3,
359      3,  3,  3,  4,  4,  4,  6,  6,  7,  7,
360      8,  8,  9,  9, 10, 10, 11, 11, 12, 12,
361     13, 13, 14, 14, 15, 15, 16, 16, 17, 17,
362     18, 18
363 };
364 static const int i_tc0_table[52][3] =
365 {
366     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
367     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
368     { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 1 },
369     { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 0, 1, 1 }, { 1, 1, 1 },
370     { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 },
371     { 1, 1, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 2, 2, 3 }, { 2, 2, 4 }, { 2, 3, 4 },
372     { 2, 3, 4 }, { 3, 3, 5 }, { 3, 4, 6 }, { 3, 4, 6 }, { 4, 5, 7 }, { 4, 5, 8 },
373     { 4, 6, 9 }, { 5, 7,10 }, { 6, 8,11 }, { 6, 8,13 }, { 7,10,14 }, { 8,11,16 },
374     { 9,12,18 }, {10,13,20 }, {11,15,23 }, {13,17,25 }
375 };
376
377 /* From ffmpeg */
378 static inline int clip_uint8( int a )
379 {
380     if (a&(~255))
381         return (-a)>>31;
382     else
383         return a;
384 }
385
386 static inline void deblock_luma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
387 {
388     int i, d;
389     for( i = 0; i < 4; i++ ) {
390         if( tc0[i] < 0 ) {
391             pix += 4*ystride;
392             continue;
393         }
394         for( d = 0; d < 4; d++ ) {
395             const int p2 = pix[-3*xstride];
396             const int p1 = pix[-2*xstride];
397             const int p0 = pix[-1*xstride];
398             const int q0 = pix[ 0*xstride];
399             const int q1 = pix[ 1*xstride];
400             const int q2 = pix[ 2*xstride];
401    
402             if( abs( p0 - q0 ) < alpha &&
403                 abs( p1 - p0 ) < beta &&
404                 abs( q1 - q0 ) < beta ) {
405    
406                 int tc = tc0[i];
407                 int delta;
408    
409                 if( abs( p2 - p0 ) < beta ) {
410                     pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0[i], tc0[i] );
411                     tc++; 
412                 }
413                 if( abs( q2 - q0 ) < beta ) {
414                     pix[ 1*xstride] = q1 + x264_clip3( (( q2 + ((p0 + q0 + 1) >> 1)) >> 1) - q1, -tc0[i], tc0[i] );
415                     tc++;
416                 }
417     
418                 delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
419                 pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
420                 pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
421             }
422             pix += ystride;
423         }
424     }
425 }
426 static void deblock_v_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
427 {
428     deblock_luma_c( pix, stride, 1, alpha, beta, tc0 ); 
429 }
430 static void deblock_h_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
431 {
432     deblock_luma_c( pix, 1, stride, alpha, beta, tc0 );
433 }
434
435 static inline void deblock_chroma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
436 {
437     int i, d;
438     for( i = 0; i < 4; i++ ) {
439         const int tc = tc0[i];
440         if( tc <= 0 ) {
441             pix += 2*ystride;
442             continue;
443         }
444         for( d = 0; d < 2; d++ ) {
445             const int p1 = pix[-2*xstride];
446             const int p0 = pix[-1*xstride];
447             const int q0 = pix[ 0*xstride];
448             const int q1 = pix[ 1*xstride];
449
450             if( abs( p0 - q0 ) < alpha &&
451                 abs( p1 - p0 ) < beta &&
452                 abs( q1 - q0 ) < beta ) {
453
454                 int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
455                 pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
456                 pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
457             }
458             pix += ystride;
459         }
460     }
461 }
462 static void deblock_v_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
463 {   
464     deblock_chroma_c( pix, stride, 1, alpha, beta, tc0 );
465 }
466 static void deblock_h_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
467 {   
468     deblock_chroma_c( pix, 1, stride, alpha, beta, tc0 );
469 }
470
471 static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
472 {
473     int d;
474     for( d = 0; d < 16; d++ ) {
475         const int p2 = pix[-3*xstride];
476         const int p1 = pix[-2*xstride];
477         const int p0 = pix[-1*xstride];
478         const int q0 = pix[ 0*xstride];
479         const int q1 = pix[ 1*xstride];
480         const int q2 = pix[ 2*xstride];
481
482         if( abs( p0 - q0 ) < alpha &&
483             abs( p1 - p0 ) < beta &&
484             abs( q1 - q0 ) < beta ) {
485
486             if(abs( p0 - q0 ) < ((alpha >> 2) + 2) ){
487                 if( abs( p2 - p0 ) < beta)
488                 {
489                     const int p3 = pix[-4*xstride];
490                     /* p0', p1', p2' */
491                     pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
492                     pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
493                     pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
494                 } else {
495                     /* p0' */
496                     pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
497                 }
498                 if( abs( q2 - q0 ) < beta)
499                 {
500                     const int q3 = pix[3*xstride];
501                     /* q0', q1', q2' */
502                     pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
503                     pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
504                     pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
505                 } else {
506                     /* q0' */
507                     pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
508                 }
509             }else{
510                 /* p0', q0' */
511                 pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
512                 pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
513             }
514         }
515         pix += ystride;
516     }
517 }
518 static void deblock_v_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
519 {   
520     deblock_luma_intra_c( pix, stride, 1, alpha, beta );
521 }
522 static void deblock_h_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
523 {   
524     deblock_luma_intra_c( pix, 1, stride, alpha, beta );
525 }
526
527 static inline void deblock_chroma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
528 {   
529     int d; 
530     for( d = 0; d < 8; d++ ) {
531         const int p1 = pix[-2*xstride];
532         const int p0 = pix[-1*xstride];
533         const int q0 = pix[ 0*xstride];
534         const int q1 = pix[ 1*xstride];
535
536         if( abs( p0 - q0 ) < alpha &&
537             abs( p1 - p0 ) < beta &&
538             abs( q1 - q0 ) < beta ) {
539
540             pix[-1*xstride] = (2*p1 + p0 + q1 + 2) >> 2;   /* p0' */
541             pix[ 0*xstride] = (2*q1 + q0 + p1 + 2) >> 2;   /* q0' */
542         }
543
544         pix += ystride;
545     }
546 }
547 static void deblock_v_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
548 {   
549     deblock_chroma_intra_c( pix, stride, 1, alpha, beta );
550 }
551 static void deblock_h_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
552 {   
553     deblock_chroma_intra_c( pix, 1, stride, alpha, beta );
554 }
555
556 static inline void deblock_edge( x264_t *h, uint8_t *pix, int i_stride, int bS[4], int i_qp, int b_chroma,
557                                  x264_deblock_inter_t pf_inter, x264_deblock_intra_t pf_intra )
558 {
559     int i;
560     const int index_a = x264_clip3( i_qp + h->sh.i_alpha_c0_offset, 0, 51 );
561     const int alpha = i_alpha_table[index_a];
562     const int beta  = i_beta_table[x264_clip3( i_qp + h->sh.i_beta_offset, 0, 51 )];
563
564     if( bS[0] < 4 ) {
565         int8_t tc[4]; 
566         for(i=0; i<4; i++)
567             tc[i] = (bS[i] ? i_tc0_table[index_a][bS[i] - 1] : -1) + b_chroma;
568         pf_inter( pix, i_stride, alpha, beta, tc );
569     } else {
570         pf_intra( pix, i_stride, alpha, beta );
571     }
572 }
573
574 void x264_frame_deblock_row( x264_t *h, int mb_y )
575 {
576     const int s8x8 = 2 * h->mb.i_mb_stride;
577     const int s4x4 = 4 * h->mb.i_mb_stride;
578     const int b_interlaced = h->sh.b_mbaff;
579     const int mvy_limit = 4 >> b_interlaced;
580     int mb_x;
581
582     int i_stride2[3] = { h->fdec->i_stride[0] << b_interlaced,
583                          h->fdec->i_stride[1] << b_interlaced,
584                          h->fdec->i_stride[2] << b_interlaced };
585
586     if( !h->pps->b_cabac && h->pps->b_transform_8x8_mode )
587         munge_cavlc_nnz( h, mb_y, h->mb.nnz_backup, munge_cavlc_nnz_row );
588
589     for( mb_x = 0; mb_x < h->sps->i_mb_width; )
590     {
591         const int mb_xy  = mb_y * h->mb.i_mb_stride + mb_x;
592         const int mb_8x8 = 2 * s8x8 * mb_y + 2 * mb_x;
593         const int mb_4x4 = 4 * s4x4 * mb_y + 4 * mb_x;
594         const int b_8x8_transform = h->mb.mb_transform_size[mb_xy];
595         const int i_edge_end = (h->mb.type[mb_xy] == P_SKIP) ? 1 : 4;
596         int i_edge, i_dir;
597
598         int i_pix_y[3] = { 16*mb_y*h->fdec->i_stride[0] + 16*mb_x,
599                             8*mb_y*h->fdec->i_stride[1] +  8*mb_x,
600                             8*mb_y*h->fdec->i_stride[2] +  8*mb_x };
601         if( b_interlaced && (mb_y&1) )
602         {
603             i_pix_y[0] -= 15*h->fdec->i_stride[0];
604             i_pix_y[1] -=  7*h->fdec->i_stride[1];
605             i_pix_y[2] -=  7*h->fdec->i_stride[2];
606         }
607
608         x264_prefetch_fenc( h, h->fdec, mb_x, mb_y );
609
610         /* i_dir == 0 -> vertical edge
611          * i_dir == 1 -> horizontal edge */
612         for( i_dir = 0; i_dir < 2; i_dir++ )
613         {
614             int i_start = (i_dir ? (mb_y <= b_interlaced) : (mb_x == 0));
615             int i_qp, i_qpn;
616
617             for( i_edge = i_start; i_edge < i_edge_end; i_edge++ )
618             {
619                 int mbn_xy, mbn_8x8, mbn_4x4;
620                 int bS[4];  /* filtering strength */
621
622                 if( b_8x8_transform && (i_edge&1) )
623                     continue;
624
625                 mbn_xy  = i_edge > 0 ? mb_xy  : ( i_dir == 0 ? mb_xy  - 1 : mb_xy - h->mb.i_mb_stride );
626                 mbn_8x8 = i_edge > 0 ? mb_8x8 : ( i_dir == 0 ? mb_8x8 - 2 : mb_8x8 - 2 * s8x8 );
627                 mbn_4x4 = i_edge > 0 ? mb_4x4 : ( i_dir == 0 ? mb_4x4 - 4 : mb_4x4 - 4 * s4x4 );
628
629                 if( b_interlaced && i_edge == 0 && i_dir == 1 )
630                 {
631                     mbn_xy -= h->mb.i_mb_stride;
632                     mbn_8x8 -= 2 * s8x8;
633                     mbn_4x4 -= 4 * s4x4;
634                 }
635
636                 /* *** Get bS for each 4px for the current edge *** */
637                 if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy] ) )
638                 {
639                     bS[0] = bS[1] = bS[2] = bS[3] = ( i_edge == 0 && !(b_interlaced && i_dir) ? 4 : 3 );
640                 }
641                 else
642                 {
643                     int i;
644                     for( i = 0; i < 4; i++ )
645                     {
646                         int x  = i_dir == 0 ? i_edge : i;
647                         int y  = i_dir == 0 ? i      : i_edge;
648                         int xn = (x - (i_dir == 0 ? 1 : 0 ))&0x03;
649                         int yn = (y - (i_dir == 0 ? 0 : 1 ))&0x03;
650
651                         if( h->mb.non_zero_count[mb_xy][block_idx_xy[x][y]] != 0 ||
652                             h->mb.non_zero_count[mbn_xy][block_idx_xy[xn][yn]] != 0 )
653                         {
654                             bS[i] = 2;
655                         }
656                         else
657                         {
658                             /* FIXME: A given frame may occupy more than one position in
659                              * the reference list. So we should compare the frame numbers,
660                              * not the indices in the ref list.
661                              * No harm yet, as we don't generate that case.*/
662
663                             int i8p= mb_8x8+(x/2)+(y/2)*s8x8;
664                             int i8q= mbn_8x8+(xn/2)+(yn/2)*s8x8;
665                             int i4p= mb_4x4+x+y*s4x4;
666                             int i4q= mbn_4x4+xn+yn*s4x4;
667                             int l;
668
669                             bS[i] = 0;
670
671                             for( l = 0; l < 1 + (h->sh.i_type == SLICE_TYPE_B); l++ )
672                             {
673                                 if( h->mb.ref[l][i8p] != h->mb.ref[l][i8q] ||
674                                     abs( h->mb.mv[l][i4p][0] - h->mb.mv[l][i4q][0] ) >= 4 ||
675                                     abs( h->mb.mv[l][i4p][1] - h->mb.mv[l][i4q][1] ) >= mvy_limit )
676                                 {
677                                     bS[i] = 1;
678                                     break;
679                                 }
680                             }
681                         }
682                     }
683                 }
684
685                 /* *** filter *** */
686                 /* Y plane */
687                 i_qp = h->mb.qp[mb_xy];
688                 i_qpn= h->mb.qp[mbn_xy];
689
690                 if( i_dir == 0 )
691                 {
692                     /* vertical edge */
693                     deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge],
694                                   i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
695                                   h->loopf.deblock_h_luma, h->loopf.deblock_h_luma_intra );
696                     if( !(i_edge & 1) )
697                     {
698                         /* U/V planes */
699                         int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
700                                       i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
701                         deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge],
702                                       i_stride2[1], bS, i_qpc, 1,
703                                       h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
704                         deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge],
705                                       i_stride2[2], bS, i_qpc, 1,
706                                       h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
707                     }
708                 }
709                 else
710                 {
711                     /* horizontal edge */
712                     deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge*i_stride2[0]],
713                                   i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
714                                   h->loopf.deblock_v_luma, h->loopf.deblock_v_luma_intra );
715                     /* U/V planes */
716                     if( !(i_edge & 1) )
717                     {
718                         int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
719                                       i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
720                         deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge*i_stride2[1]],
721                                       i_stride2[1], bS, i_qpc, 1,
722                                       h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
723                         deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge*i_stride2[2]],
724                                       i_stride2[2], bS, i_qpc, 1,
725                                       h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
726                     }
727                 }
728             }
729         }
730
731         /* next mb */
732         if( !b_interlaced || (mb_y&1) )
733             mb_x++;
734         mb_y ^= b_interlaced;
735     }
736
737     if( !h->pps->b_cabac && h->pps->b_transform_8x8_mode )
738         munge_cavlc_nnz( h, mb_y, h->mb.nnz_backup, restore_cavlc_nnz_row );
739 }
740
741 void x264_frame_deblock( x264_t *h )
742 {
743     int mb_y;
744     for( mb_y = 0; mb_y < h->sps->i_mb_height; mb_y += 1 + h->sh.b_mbaff )
745         x264_frame_deblock_row( h, mb_y );
746 }
747
748 #ifdef HAVE_MMX
749 void x264_deblock_v_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
750 void x264_deblock_h_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
751 void x264_deblock_v_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
752 void x264_deblock_h_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
753
754 void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
755 void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
756 #ifdef ARCH_X86
757 void x264_deblock_h_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
758 void x264_deblock_v8_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
759
760 void x264_deblock_v_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
761 {
762     x264_deblock_v8_luma_mmxext( pix,   stride, alpha, beta, tc0   );
763     x264_deblock_v8_luma_mmxext( pix+8, stride, alpha, beta, tc0+2 );
764 }
765 #endif
766 #endif
767
768 #ifdef ARCH_PPC
769 void x264_deblock_v_luma_altivec( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
770 void x264_deblock_h_luma_altivec( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
771 #endif // ARCH_PPC
772
773 void x264_deblock_init( int cpu, x264_deblock_function_t *pf )
774 {
775     pf->deblock_v_luma = deblock_v_luma_c;
776     pf->deblock_h_luma = deblock_h_luma_c;
777     pf->deblock_v_chroma = deblock_v_chroma_c;
778     pf->deblock_h_chroma = deblock_h_chroma_c;
779     pf->deblock_v_luma_intra = deblock_v_luma_intra_c;
780     pf->deblock_h_luma_intra = deblock_h_luma_intra_c;
781     pf->deblock_v_chroma_intra = deblock_v_chroma_intra_c;
782     pf->deblock_h_chroma_intra = deblock_h_chroma_intra_c;
783
784 #ifdef HAVE_MMX
785     if( cpu&X264_CPU_MMXEXT )
786     {
787         pf->deblock_v_chroma = x264_deblock_v_chroma_mmxext;
788         pf->deblock_h_chroma = x264_deblock_h_chroma_mmxext;
789         pf->deblock_v_chroma_intra = x264_deblock_v_chroma_intra_mmxext;
790         pf->deblock_h_chroma_intra = x264_deblock_h_chroma_intra_mmxext;
791 #ifdef ARCH_X86
792         pf->deblock_v_luma = x264_deblock_v_luma_mmxext;
793         pf->deblock_h_luma = x264_deblock_h_luma_mmxext;
794 #endif
795         if( cpu&X264_CPU_SSE2 )
796         {
797             pf->deblock_v_luma = x264_deblock_v_luma_sse2;
798             pf->deblock_h_luma = x264_deblock_h_luma_sse2;
799         }
800     }
801 #endif
802
803 #ifdef ARCH_PPC
804     if( cpu&X264_CPU_ALTIVEC )
805     {
806         pf->deblock_v_luma = x264_deblock_v_luma_altivec;
807         pf->deblock_h_luma = x264_deblock_h_luma_altivec;
808    }
809 #endif // ARCH_PPC
810 }
811
812
813 /* threading */
814
815 #ifdef HAVE_PTHREAD
816 void x264_frame_cond_broadcast( x264_frame_t *frame, int i_lines_completed )
817 {
818     x264_pthread_mutex_lock( &frame->mutex );
819     frame->i_lines_completed = i_lines_completed;
820     x264_pthread_cond_broadcast( &frame->cv );
821     x264_pthread_mutex_unlock( &frame->mutex );
822 }
823
824 void x264_frame_cond_wait( x264_frame_t *frame, int i_lines_completed )
825 {
826     x264_pthread_mutex_lock( &frame->mutex );
827     while( frame->i_lines_completed < i_lines_completed )
828         x264_pthread_cond_wait( &frame->cv, &frame->mutex );
829     x264_pthread_mutex_unlock( &frame->mutex );
830 }
831
832 #else
833 void x264_frame_cond_broadcast( x264_frame_t *frame, int i_lines_completed )
834 {}
835 void x264_frame_cond_wait( x264_frame_t *frame, int i_lines_completed )
836 {}
837 #endif
838
839
840 /* list operators */
841
842 void x264_frame_push( x264_frame_t **list, x264_frame_t *frame )
843 {
844     int i = 0;
845     while( list[i] ) i++;
846     list[i] = frame;
847 }
848
849 x264_frame_t *x264_frame_pop( x264_frame_t **list )
850 {
851     x264_frame_t *frame;
852     int i = 0;
853     assert( list[0] );
854     while( list[i+1] ) i++;
855     frame = list[i];
856     list[i] = NULL;
857     return frame;
858 }
859
860 void x264_frame_unshift( x264_frame_t **list, x264_frame_t *frame )
861 {
862     int i = 0;
863     while( list[i] ) i++;
864     while( i-- )
865         list[i+1] = list[i];
866     list[0] = frame;
867 }
868
869 x264_frame_t *x264_frame_shift( x264_frame_t **list )
870 {
871     x264_frame_t *frame = list[0];
872     int i;
873     for( i = 0; list[i]; i++ )
874         list[i] = list[i+1];
875     assert(frame);
876     return frame;
877 }
878
879 void x264_frame_push_unused( x264_t *h, x264_frame_t *frame )
880 {
881     assert( frame->i_reference_count > 0 );
882     frame->i_reference_count--;
883     if( frame->i_reference_count == 0 )
884         x264_frame_push( h->frames.unused, frame );
885     assert( h->frames.unused[ sizeof(h->frames.unused) / sizeof(*h->frames.unused) - 1 ] == NULL );
886 }
887
888 x264_frame_t *x264_frame_pop_unused( x264_t *h )
889 {
890     x264_frame_t *frame;
891     if( h->frames.unused[0] )
892         frame = x264_frame_pop( h->frames.unused );
893     else
894         frame = x264_frame_new( h );
895     assert( frame->i_reference_count == 0 );
896     frame->i_reference_count = 1;
897     return frame;
898 }
899
900 void x264_frame_sort( x264_frame_t **list, int b_dts )
901 {
902     int i, b_ok;
903     do {
904         b_ok = 1;
905         for( i = 0; list[i+1]; i++ )
906         {
907             int dtype = list[i]->i_type - list[i+1]->i_type;
908             int dtime = list[i]->i_frame - list[i+1]->i_frame;
909             int swap = b_dts ? dtype > 0 || ( dtype == 0 && dtime > 0 )
910                              : dtime > 0;
911             if( swap )
912             {
913                 XCHG( x264_frame_t*, list[i], list[i+1] );
914                 b_ok = 0;
915             }
916         }
917     } while( !b_ok );
918 }