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