frame.c 35.4 KB
Newer Older
Laurent Aimar's avatar
Laurent Aimar committed
1 2 3
/*****************************************************************************
 * frame.c: h264 encoder library
 *****************************************************************************
4
 * Copyright (C) 2003-2008 x264 project
Laurent Aimar's avatar
Laurent Aimar committed
5 6
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Loren Merritt <lorenm@u.washington.edu>
Laurent Aimar's avatar
Laurent Aimar committed
8 9 10 11 12 13 14 15 16 17 18 19 20
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
Laurent Aimar's avatar
Laurent Aimar committed
22 23 24 25
 *****************************************************************************/

#include "common.h"

26 27
#define ALIGN(x,a) (((x)+((a)-1))&~((a)-1))

Laurent Aimar's avatar
Laurent Aimar committed
28 29
x264_frame_t *x264_frame_new( x264_t *h )
{
30
    x264_frame_t *frame = x264_malloc( sizeof(x264_frame_t) );
31
    int i, j;
Laurent Aimar's avatar
Laurent Aimar committed
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;
Laurent Aimar's avatar
Laurent Aimar committed
38

39 40
    if( !frame ) return NULL;

41 42
    memset( frame, 0, sizeof(x264_frame_t) );

Laurent Aimar's avatar
Laurent Aimar committed
43
    /* allocate frame data (+64 for extra data for me) */
44 45 46
    i_width  = ALIGN( h->param.i_width, 16 );
    i_stride = ALIGN( i_width + 2*PADH, align );
    i_lines  = ALIGN( h->param.i_height, 16<<h->param.b_interlaced );
47

Laurent Aimar's avatar
Laurent Aimar committed
48 49 50
    frame->i_plane = 3;
    for( i = 0; i < 3; i++ )
    {
51 52 53
        frame->i_stride[i] = i_stride >> !!i;
        frame->i_width[i] = i_width >> !!i;
        frame->i_lines[i] = i_lines >> !!i;
Laurent Aimar's avatar
Laurent Aimar committed
54 55
    }

56 57
    luma_plane_size = (frame->i_stride[0] * ( frame->i_lines[0] + 2*i_padv ));
    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 63 64 65
    /* all 4 luma planes allocated together, since the cacheline split code
     * requires them to be in-phase wrt cacheline alignment. */
    CHECKED_MALLOC( frame->buffer[0], 4*luma_plane_size);
    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 76 77

        luma_plane_size = frame->i_stride_lowres * ( frame->i_lines[0]/2 + 2*i_padv );

        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 83 84 85 86 87

        for( j = 0; j <= !!h->param.i_bframe; j++ )
            for( i = 0; i <= h->param.i_bframe; i++ )
            {
                CHECKED_MALLOC( frame->lowres_mvs[j][i], 2*h->mb.i_mb_count*sizeof(int16_t) );
                memset( frame->lowres_mvs[j][i], 0, 2*h->mb.i_mb_count*sizeof(int16_t) );
                CHECKED_MALLOC( frame->lowres_mv_costs[j][i], h->mb.i_mb_count*sizeof(int) );
            }
88
    }
89

90
    if( h->param.analyse.i_me_method >= X264_ME_ESA )
91
    {
92
        CHECKED_MALLOC( frame->buffer[3],
93
                        2 * frame->i_stride[0] * (frame->i_lines[0] + 2*i_padv) * sizeof(uint16_t) );
94
        frame->integral = (uint16_t*)frame->buffer[3] + frame->i_stride[0] * i_padv + PADH;
95 96
    }

Laurent Aimar's avatar
Laurent Aimar committed
97 98 99
    frame->i_poc = -1;
    frame->i_type = X264_TYPE_AUTO;
    frame->i_qpplus1 = 0;
100 101
    frame->i_pts = -1;
    frame->i_frame = -1;
102
    frame->i_frame_num = -1;
Loren Merritt's avatar
Loren Merritt committed
103
    frame->i_lines_completed = -1;
Laurent Aimar's avatar
Laurent Aimar committed
104

105 106 107
    CHECKED_MALLOC( frame->mb_type, i_mb_count * sizeof(int8_t));
    CHECKED_MALLOC( frame->mv[0], 2*16 * i_mb_count * sizeof(int16_t) );
    CHECKED_MALLOC( frame->ref[0], 4 * i_mb_count * sizeof(int8_t) );
108
    CHECKED_MALLOC( frame->i_intra_cost, i_mb_count * sizeof(uint16_t) );
109 110
    if( h->param.i_bframe )
    {
111 112
        CHECKED_MALLOC( frame->mv[1], 2*16 * i_mb_count * sizeof(int16_t) );
        CHECKED_MALLOC( frame->ref[1], 4 * i_mb_count * sizeof(int8_t) );
113 114 115 116 117 118 119
    }
    else
    {
        frame->mv[1]  = NULL;
        frame->ref[1] = NULL;
    }

120 121
    CHECKED_MALLOC( frame->i_row_bits, i_lines/16 * sizeof(int) );
    CHECKED_MALLOC( frame->i_row_qp, i_lines/16 * sizeof(int) );
122 123
    for( i = 0; i < h->param.i_bframe + 2; i++ )
        for( j = 0; j < h->param.i_bframe + 2; j++ )
124
            CHECKED_MALLOC( frame->i_row_satds[i][j], i_lines/16 * sizeof(int) );
125

126
    if( h->param.rc.i_aq_mode )
127
    {
128
        CHECKED_MALLOC( frame->f_qp_offset, h->mb.i_mb_count * sizeof(float) );
129 130 131
        if( h->frames.b_have_lowres )
            CHECKED_MALLOC( frame->i_inv_qscale_factor, h->mb.i_mb_count * sizeof(uint16_t) );
    }
132

133 134
    x264_pthread_mutex_init( &frame->mutex, NULL );
    x264_pthread_cond_init( &frame->cv, NULL );
135

Laurent Aimar's avatar
Laurent Aimar committed
136
    return frame;
137 138 139 140

fail:
    x264_frame_delete( frame );
    return NULL;
Laurent Aimar's avatar
Laurent Aimar committed
141 142 143 144
}

void x264_frame_delete( x264_frame_t *frame )
{
145
    int i, j;
146
    for( i = 0; i < 4; i++ )
147
        x264_free( frame->buffer[i] );
148 149
    for( i = 0; i < 4; i++ )
        x264_free( frame->buffer_lowres[i] );
150 151 152
    for( i = 0; i < X264_BFRAME_MAX+2; i++ )
        for( j = 0; j < X264_BFRAME_MAX+2; j++ )
            x264_free( frame->i_row_satds[i][j] );
153 154 155 156 157 158
    for( j = 0; j < 2; j++ )
        for( i = 0; i <= X264_BFRAME_MAX; i++ )
        {
            x264_free( frame->lowres_mvs[j][i] );
            x264_free( frame->lowres_mv_costs[j][i] );
        }
159
    x264_free( frame->f_qp_offset );
160
    x264_free( frame->i_intra_cost );
161 162
    x264_free( frame->i_row_bits );
    x264_free( frame->i_row_qp );
163
    x264_free( frame->mb_type );
164 165 166 167
    x264_free( frame->mv[0] );
    x264_free( frame->mv[1] );
    x264_free( frame->ref[0] );
    x264_free( frame->ref[1] );
168 169
    x264_pthread_mutex_destroy( &frame->mutex );
    x264_pthread_cond_destroy( &frame->cv );
Laurent Aimar's avatar
Laurent Aimar committed
170 171 172
    x264_free( frame );
}

173
int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
Laurent Aimar's avatar
Laurent Aimar committed
174
{
175
    int i_csp = src->img.i_csp & X264_CSP_MASK;
176 177 178 179 180 181 182
    int i;
    if( i_csp != X264_CSP_I420 && i_csp != X264_CSP_YV12 )
    {
        x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" );
        return -1;
    }

Laurent Aimar's avatar
Laurent Aimar committed
183 184 185 186
    dst->i_type     = src->i_type;
    dst->i_qpplus1  = src->i_qpplus1;
    dst->i_pts      = src->i_pts;

187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
    for( i=0; i<3; i++ )
    {
        int s = (i_csp == X264_CSP_YV12 && i) ? i^3 : i;
        uint8_t *plane = src->img.plane[s];
        int stride = src->img.i_stride[s];
        int width = h->param.i_width >> !!i;
        int height = h->param.i_height >> !!i;
        if( src->img.i_csp & X264_CSP_VFLIP )
        {
            plane += (height-1)*stride;
            stride = -stride;
        }
        h->mc.plane_copy( dst->plane[i], dst->i_stride[i], plane, stride, width, height );
    }
    return 0;
Laurent Aimar's avatar
Laurent Aimar committed
202 203 204 205
}



Loren Merritt's avatar
Loren Merritt committed
206
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 )
207 208 209 210 211 212
{
#define PPIXEL(x, y) ( pix + (x) + (y)*i_stride )
    int y;
    for( y = 0; y < i_height; y++ )
    {
        /* left band */
213
        memset( PPIXEL(-i_padh, y), PPIXEL(0, y)[0], i_padh );
214
        /* right band */
215
        memset( PPIXEL(i_width, y), PPIXEL(i_width-1, y)[0], i_padh );
216 217
    }
    /* upper band */
Loren Merritt's avatar
Loren Merritt committed
218
    if( b_pad_top )
219 220
    for( y = 0; y < i_padv; y++ )
        memcpy( PPIXEL(-i_padh, -y-1), PPIXEL(-i_padh, 0), i_width+2*i_padh );
221
    /* lower band */
Loren Merritt's avatar
Loren Merritt committed
222
    if( b_pad_bottom )
223 224
    for( y = 0; y < i_padv; y++ )
        memcpy( PPIXEL(-i_padh, i_height+y), PPIXEL(-i_padh, i_height-1), i_width+2*i_padh );
225 226 227
#undef PPIXEL
}

Loren Merritt's avatar
Loren Merritt committed
228
void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
Laurent Aimar's avatar
Laurent Aimar committed
229
{
230
    int i;
Loren Merritt's avatar
Loren Merritt committed
231 232 233
    int b_start = !mb_y;
    if( mb_y & h->sh.b_mbaff )
        return;
Laurent Aimar's avatar
Laurent Aimar committed
234 235
    for( i = 0; i < frame->i_plane; i++ )
    {
236 237
        int stride = frame->i_stride[i];
        int width = 16*h->sps->i_mb_width >> !!i;
Loren Merritt's avatar
Loren Merritt committed
238
        int height = (b_end ? 16*(h->sps->i_mb_height - mb_y) >> h->sh.b_mbaff : 16) >> !!i;
239 240
        int padh = PADH >> !!i;
        int padv = PADV >> !!i;
Loren Merritt's avatar
Loren Merritt committed
241 242 243 244 245
        // buffer: 2 chroma, 3 luma (rounded to 4) because deblocking goes beyond the top of the mb
        uint8_t *pix = frame->plane[i] + X264_MAX(0, (16*mb_y-4)*stride >> !!i);
        if( b_end && !b_start )
            height += 4 >> (!!i + h->sh.b_mbaff);
        if( h->sh.b_mbaff )
246
        {
Loren Merritt's avatar
Loren Merritt committed
247 248
            plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end );
            plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end );
249 250 251
        }
        else
        {
Loren Merritt's avatar
Loren Merritt committed
252
            plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end );
253
        }
Laurent Aimar's avatar
Laurent Aimar committed
254 255 256
    }
}

Loren Merritt's avatar
Loren Merritt committed
257
void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
258
{
Loren Merritt's avatar
Loren Merritt committed
259
    /* during filtering, 8 extra pixels were filtered on each edge,
Loren Merritt's avatar
Loren Merritt committed
260
     * but up to 3 of the horizontal ones may be wrong.
261
       we want to expand border from the last filtered pixel */
Loren Merritt's avatar
Loren Merritt committed
262
    int b_start = !mb_y;
263
    int stride = frame->i_stride[0];
Loren Merritt's avatar
Loren Merritt committed
264
    int width = 16*h->sps->i_mb_width + 8;
Loren Merritt's avatar
Loren Merritt committed
265
    int height = b_end ? (16*(h->sps->i_mb_height - mb_y) >> h->sh.b_mbaff) + 16 : 16;
Loren Merritt's avatar
Loren Merritt committed
266
    int padh = PADH - 4;
267
    int padv = PADV - 8;
268
    int i;
269
    for( i = 1; i < 4; i++ )
270
    {
Loren Merritt's avatar
Loren Merritt committed
271
        // buffer: 8 luma, to match the hpel filter
Loren Merritt's avatar
Loren Merritt committed
272
        uint8_t *pix = frame->filtered[i] + (16*mb_y - (8 << h->sh.b_mbaff)) * stride - 4;
Loren Merritt's avatar
Loren Merritt committed
273
        if( h->sh.b_mbaff )
274
        {
Loren Merritt's avatar
Loren Merritt committed
275 276
            plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end );
            plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end );
277 278 279
        }
        else
        {
Loren Merritt's avatar
Loren Merritt committed
280
            plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end );
281 282
        }
    }
283 284
}

285
void x264_frame_expand_border_lowres( x264_frame_t *frame )
286
{
287
    int i;
288
    for( i = 0; i < 4; i++ )
Loren Merritt's avatar
Loren Merritt committed
289
        plane_expand_border( frame->lowres[i], frame->i_stride_lowres, frame->i_stride_lowres - 2*PADH, frame->i_lines_lowres, PADH, PADV, 1, 1 );
290 291
}

Loren Merritt's avatar
Loren Merritt committed
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
{
    int i, y;
    for( i = 0; i < frame->i_plane; i++ )
    {
        int i_subsample = i ? 1 : 0;
        int i_width = h->param.i_width >> i_subsample;
        int i_height = h->param.i_height >> i_subsample;
        int i_padx = ( h->sps->i_mb_width * 16 - h->param.i_width ) >> i_subsample;
        int i_pady = ( h->sps->i_mb_height * 16 - h->param.i_height ) >> i_subsample;

        if( i_padx )
        {
            for( y = 0; y < i_height; y++ )
                memset( &frame->plane[i][y*frame->i_stride[i] + i_width],
                         frame->plane[i][y*frame->i_stride[i] + i_width - 1],
                         i_padx );
        }
        if( i_pady )
        {
312
            //FIXME interlace? or just let it pad using the wrong field
Loren Merritt's avatar
Loren Merritt committed
313
            for( y = i_height; y < i_height + i_pady; y++ )
Loren Merritt's avatar
Loren Merritt committed
314 315 316 317 318 319 320
                memcpy( &frame->plane[i][y*frame->i_stride[i]],
                        &frame->plane[i][(i_height-1)*frame->i_stride[i]],
                        i_width + i_padx );
        }
    }
}

321

322 323
/* cavlc + 8x8 transform stores nnz per 16 coeffs for the purpose of
 * entropy coding, but per 64 coeffs for the purpose of deblocking */
Loic Le Loarer's avatar
Loic Le Loarer committed
324
static void munge_cavlc_nnz_row( x264_t *h, int mb_y, uint8_t (*buf)[16] )
325 326 327
{
    uint32_t (*src)[6] = (uint32_t(*)[6])h->mb.non_zero_count + mb_y * h->sps->i_mb_width;
    int8_t *transform = h->mb.mb_transform_size + mb_y * h->sps->i_mb_width;
328
    int x, nnz;
329 330 331 332 333
    for( x=0; x<h->sps->i_mb_width; x++ )
    {
        memcpy( buf+x, src+x, 16 );
        if( transform[x] )
        {
334 335 336 337
            nnz = src[x][0] | src[x][1];
            src[x][0] = src[x][1] = ((uint16_t)nnz ? 0x0101 : 0) + (nnz>>16 ? 0x01010000 : 0);
            nnz = src[x][2] | src[x][3];
            src[x][2] = src[x][3] = ((uint16_t)nnz ? 0x0101 : 0) + (nnz>>16 ? 0x01010000 : 0);
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363
        }
    }
}

static void restore_cavlc_nnz_row( x264_t *h, int mb_y, uint8_t (*buf)[16] )
{
    uint8_t (*dst)[24] = h->mb.non_zero_count + mb_y * h->sps->i_mb_width;
    int x;
    for( x=0; x<h->sps->i_mb_width; x++ )
        memcpy( dst+x, buf+x, 16 );
}

static void munge_cavlc_nnz( x264_t *h, int mb_y, uint8_t (*buf)[16], void (*func)(x264_t*, int, uint8_t (*)[16]) )
{
    func( h, mb_y, buf );
    if( mb_y > 0 )
        func( h, mb_y-1, buf + h->sps->i_mb_width );
    if( h->sh.b_mbaff )
    {
        func( h, mb_y+1, buf + h->sps->i_mb_width * 2 );
        if( mb_y > 0 )
            func( h, mb_y-2, buf + h->sps->i_mb_width * 3 );
    }
}


364
/* Deblocking filter */
365
static const uint8_t i_alpha_table[52+12*2] =
Laurent Aimar's avatar
Laurent Aimar committed
366
{
367
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
Laurent Aimar's avatar
Laurent Aimar committed
368 369 370 371 372
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  4,  4,  5,  6,
     7,  8,  9, 10, 12, 13, 15, 17, 20, 22,
    25, 28, 32, 36, 40, 45, 50, 56, 63, 71,
    80, 90,101,113,127,144,162,182,203,226,
373 374
   255,255,
   255,255,255,255,255,255,255,255,255,255,255,255,
Laurent Aimar's avatar
Laurent Aimar committed
375
};
376
static const uint8_t i_beta_table[52+12*2] =
Laurent Aimar's avatar
Laurent Aimar committed
377
{
378
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
Laurent Aimar's avatar
Laurent Aimar committed
379 380 381 382 383
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
     0,  0,  0,  0,  0,  0,  2,  2,  2,  3,
     3,  3,  3,  4,  4,  4,  6,  6,  7,  7,
     8,  8,  9,  9, 10, 10, 11, 11, 12, 12,
    13, 13, 14, 14, 15, 15, 16, 16, 17, 17,
384 385
    18, 18,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
Laurent Aimar's avatar
Laurent Aimar committed
386
};
387
static const int8_t i_tc0_table[52+12*2][4] =
Laurent Aimar's avatar
Laurent Aimar committed
388
{
389 390
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
Fiona Glaser's avatar
Fiona Glaser committed
391 392 393 394 395 396 397 398
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 },
    {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 0 }, {-1, 0, 0, 1 },
    {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 0, 1 }, {-1, 0, 1, 1 }, {-1, 0, 1, 1 }, {-1, 1, 1, 1 },
    {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 1 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 }, {-1, 1, 1, 2 },
    {-1, 1, 1, 2 }, {-1, 1, 2, 3 }, {-1, 1, 2, 3 }, {-1, 2, 2, 3 }, {-1, 2, 2, 4 }, {-1, 2, 3, 4 },
    {-1, 2, 3, 4 }, {-1, 3, 3, 5 }, {-1, 3, 4, 6 }, {-1, 3, 4, 6 }, {-1, 4, 5, 7 }, {-1, 4, 5, 8 },
    {-1, 4, 6, 9 }, {-1, 5, 7,10 }, {-1, 6, 8,11 }, {-1, 6, 8,13 }, {-1, 7,10,14 }, {-1, 8,11,16 },
399 400 401
    {-1, 9,12,18 }, {-1,10,13,20 }, {-1,11,15,23 }, {-1,13,17,25 },
    {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
    {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 }, {-1,13,17,25 },
Laurent Aimar's avatar
Laurent Aimar committed
402
};
403 404 405
#define alpha_table(x) i_alpha_table[(x)+12]
#define beta_table(x)  i_beta_table[(x)+12]
#define tc0_table(x)   i_tc0_table[(x)+12]
Laurent Aimar's avatar
Laurent Aimar committed
406 407

/* From ffmpeg */
Loren Merritt's avatar
Loren Merritt committed
408
static inline void deblock_luma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
Laurent Aimar's avatar
Laurent Aimar committed
409 410
{
    int i, d;
411 412 413 414
    for( i = 0; i < 4; i++ )
    {
        if( tc0[i] < 0 )
        {
Loren Merritt's avatar
Loren Merritt committed
415
            pix += 4*ystride;
Laurent Aimar's avatar
Laurent Aimar committed
416 417
            continue;
        }
418 419
        for( d = 0; d < 4; d++ )
        {
Loren Merritt's avatar
Loren Merritt committed
420 421 422 423 424 425
            const int p2 = pix[-3*xstride];
            const int p1 = pix[-2*xstride];
            const int p0 = pix[-1*xstride];
            const int q0 = pix[ 0*xstride];
            const int q1 = pix[ 1*xstride];
            const int q2 = pix[ 2*xstride];
426 427 428

            if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
            {
Loren Merritt's avatar
Loren Merritt committed
429 430
                int tc = tc0[i];
                int delta;
431 432
                if( abs( p2 - p0 ) < beta )
                {
Loren Merritt's avatar
Loren Merritt committed
433
                    pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0[i], tc0[i] );
Fiona Glaser's avatar
Fiona Glaser committed
434
                    tc++;
Laurent Aimar's avatar
Laurent Aimar committed
435
                }
436 437
                if( abs( q2 - q0 ) < beta )
                {
Loren Merritt's avatar
Loren Merritt committed
438 439
                    pix[ 1*xstride] = q1 + x264_clip3( (( q2 + ((p0 + q0 + 1) >> 1)) >> 1) - q1, -tc0[i], tc0[i] );
                    tc++;
Laurent Aimar's avatar
Laurent Aimar committed
440
                }
441

Loren Merritt's avatar
Loren Merritt committed
442
                delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
443 444
                pix[-1*xstride] = x264_clip_uint8( p0 + delta );    /* p0' */
                pix[ 0*xstride] = x264_clip_uint8( q0 - delta );    /* q0' */
Laurent Aimar's avatar
Laurent Aimar committed
445
            }
Loren Merritt's avatar
Loren Merritt committed
446
            pix += ystride;
Laurent Aimar's avatar
Laurent Aimar committed
447 448 449
        }
    }
}
Loren Merritt's avatar
Loren Merritt committed
450 451
static void deblock_v_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
{
Loren Merritt's avatar
Loren Merritt committed
452
    deblock_luma_c( pix, stride, 1, alpha, beta, tc0 );
Loren Merritt's avatar
Loren Merritt committed
453 454 455 456 457
}
static void deblock_h_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
{
    deblock_luma_c( pix, 1, stride, alpha, beta, tc0 );
}
Laurent Aimar's avatar
Laurent Aimar committed
458

Loren Merritt's avatar
Loren Merritt committed
459
static inline void deblock_chroma_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta, int8_t *tc0 )
Laurent Aimar's avatar
Laurent Aimar committed
460 461
{
    int i, d;
462 463
    for( i = 0; i < 4; i++ )
    {
Loren Merritt's avatar
Loren Merritt committed
464
        const int tc = tc0[i];
465 466
        if( tc <= 0 )
        {
Loren Merritt's avatar
Loren Merritt committed
467
            pix += 2*ystride;
Laurent Aimar's avatar
Laurent Aimar committed
468 469
            continue;
        }
470 471
        for( d = 0; d < 2; d++ )
        {
Loren Merritt's avatar
Loren Merritt committed
472 473 474 475 476
            const int p1 = pix[-2*xstride];
            const int p0 = pix[-1*xstride];
            const int q0 = pix[ 0*xstride];
            const int q1 = pix[ 1*xstride];

477 478
            if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
            {
Loren Merritt's avatar
Loren Merritt committed
479
                int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
480 481
                pix[-1*xstride] = x264_clip_uint8( p0 + delta );    /* p0' */
                pix[ 0*xstride] = x264_clip_uint8( q0 - delta );    /* q0' */
Laurent Aimar's avatar
Laurent Aimar committed
482
            }
Loren Merritt's avatar
Loren Merritt committed
483
            pix += ystride;
Laurent Aimar's avatar
Laurent Aimar committed
484 485 486
        }
    }
}
Loren Merritt's avatar
Loren Merritt committed
487
static void deblock_v_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
488
{
Loren Merritt's avatar
Loren Merritt committed
489 490 491
    deblock_chroma_c( pix, stride, 1, alpha, beta, tc0 );
}
static void deblock_h_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
492
{
Loren Merritt's avatar
Loren Merritt committed
493 494
    deblock_chroma_c( pix, 1, stride, alpha, beta, tc0 );
}
Laurent Aimar's avatar
Laurent Aimar committed
495

Loren Merritt's avatar
Loren Merritt committed
496
static inline void deblock_luma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
Laurent Aimar's avatar
Laurent Aimar committed
497
{
Loren Merritt's avatar
Loren Merritt committed
498
    int d;
499 500
    for( d = 0; d < 16; d++ )
    {
Loren Merritt's avatar
Loren Merritt committed
501 502 503 504 505 506 507
        const int p2 = pix[-3*xstride];
        const int p1 = pix[-2*xstride];
        const int p0 = pix[-1*xstride];
        const int q0 = pix[ 0*xstride];
        const int q1 = pix[ 1*xstride];
        const int q2 = pix[ 2*xstride];

508 509 510 511 512
        if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
        {
            if(abs( p0 - q0 ) < ((alpha >> 2) + 2) )
            {
                if( abs( p2 - p0 ) < beta ) /* p0', p1', p2' */
Laurent Aimar's avatar
Laurent Aimar committed
513
                {
Loren Merritt's avatar
Loren Merritt committed
514 515 516 517
                    const int p3 = pix[-4*xstride];
                    pix[-1*xstride] = ( p2 + 2*p1 + 2*p0 + 2*q0 + q1 + 4 ) >> 3;
                    pix[-2*xstride] = ( p2 + p1 + p0 + q0 + 2 ) >> 2;
                    pix[-3*xstride] = ( 2*p3 + 3*p2 + p1 + p0 + q0 + 4 ) >> 3;
Laurent Aimar's avatar
Laurent Aimar committed
518
                }
519 520 521
                else /* p0' */
                    pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
                if( abs( q2 - q0 ) < beta ) /* q0', q1', q2' */
Laurent Aimar's avatar
Laurent Aimar committed
522
                {
Loren Merritt's avatar
Loren Merritt committed
523 524 525 526
                    const int q3 = pix[3*xstride];
                    pix[0*xstride] = ( p1 + 2*p0 + 2*q0 + 2*q1 + q2 + 4 ) >> 3;
                    pix[1*xstride] = ( p0 + q0 + q1 + q2 + 2 ) >> 2;
                    pix[2*xstride] = ( 2*q3 + 3*q2 + q1 + q0 + p0 + 4 ) >> 3;
Laurent Aimar's avatar
Laurent Aimar committed
527
                }
528 529 530 531 532
                else /* q0' */
                    pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
            }
            else /* p0', q0' */
            {
Loren Merritt's avatar
Loren Merritt committed
533 534
                pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
                pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
Laurent Aimar's avatar
Laurent Aimar committed
535 536
            }
        }
Loren Merritt's avatar
Loren Merritt committed
537
        pix += ystride;
Laurent Aimar's avatar
Laurent Aimar committed
538 539
    }
}
Loren Merritt's avatar
Loren Merritt committed
540
static void deblock_v_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
541
{
Loren Merritt's avatar
Loren Merritt committed
542 543 544
    deblock_luma_intra_c( pix, stride, 1, alpha, beta );
}
static void deblock_h_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
545
{
Loren Merritt's avatar
Loren Merritt committed
546 547
    deblock_luma_intra_c( pix, 1, stride, alpha, beta );
}
Laurent Aimar's avatar
Laurent Aimar committed
548

Loren Merritt's avatar
Loren Merritt committed
549
static inline void deblock_chroma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
550
{
Loren Merritt's avatar
Loren Merritt committed
551
    int d;
552 553
    for( d = 0; d < 8; d++ )
    {
Loren Merritt's avatar
Loren Merritt committed
554 555 556 557 558
        const int p1 = pix[-2*xstride];
        const int p0 = pix[-1*xstride];
        const int q0 = pix[ 0*xstride];
        const int q1 = pix[ 1*xstride];

559 560
        if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
        {
Loren Merritt's avatar
Loren Merritt committed
561 562
            pix[-1*xstride] = (2*p1 + p0 + q1 + 2) >> 2;   /* p0' */
            pix[ 0*xstride] = (2*q1 + q0 + p1 + 2) >> 2;   /* q0' */
Laurent Aimar's avatar
Laurent Aimar committed
563
        }
Loren Merritt's avatar
Loren Merritt committed
564 565 566 567
        pix += ystride;
    }
}
static void deblock_v_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
568
{
Loren Merritt's avatar
Loren Merritt committed
569 570 571
    deblock_chroma_intra_c( pix, stride, 1, alpha, beta );
}
static void deblock_h_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
572
{
Loren Merritt's avatar
Loren Merritt committed
573 574 575
    deblock_chroma_intra_c( pix, 1, stride, alpha, beta );
}

Fiona Glaser's avatar
Fiona Glaser committed
576 577
static inline void deblock_edge( x264_t *h, uint8_t *pix1, uint8_t *pix2, int i_stride, uint8_t bS[4], int i_qp, int b_chroma, x264_deblock_inter_t pf_inter )
{
578 579 580
    const int index_a = i_qp + h->sh.i_alpha_c0_offset;
    const int alpha = alpha_table(index_a);
    const int beta  = beta_table(i_qp + h->sh.i_beta_offset);
Fiona Glaser's avatar
Fiona Glaser committed
581 582 583 584 585
    int8_t tc[4];

    if( !alpha || !beta )
        return;

586 587 588 589
    tc[0] = tc0_table(index_a)[bS[0]] + b_chroma;
    tc[1] = tc0_table(index_a)[bS[1]] + b_chroma;
    tc[2] = tc0_table(index_a)[bS[2]] + b_chroma;
    tc[3] = tc0_table(index_a)[bS[3]] + b_chroma;
Fiona Glaser's avatar
Fiona Glaser committed
590

591
    pf_inter( pix1, i_stride, alpha, beta, tc );
592
    if( b_chroma )
Fiona Glaser's avatar
Fiona Glaser committed
593 594 595 596
        pf_inter( pix2, i_stride, alpha, beta, tc );
}

static inline void deblock_edge_intra( x264_t *h, uint8_t *pix1, uint8_t *pix2, int i_stride, uint8_t bS[4], int i_qp, int b_chroma, x264_deblock_intra_t pf_intra )
Loren Merritt's avatar
Loren Merritt committed
597
{
598 599
    const int alpha = alpha_table(i_qp + h->sh.i_alpha_c0_offset);
    const int beta  = beta_table(i_qp + h->sh.i_beta_offset);
Loren Merritt's avatar
Loren Merritt committed
600

Fiona Glaser's avatar
Fiona Glaser committed
601 602 603
    if( !alpha || !beta )
        return;

604
    pf_intra( pix1, i_stride, alpha, beta );
605
    if( b_chroma )
Fiona Glaser's avatar
Fiona Glaser committed
606
        pf_intra( pix2, i_stride, alpha, beta );
Laurent Aimar's avatar
Laurent Aimar committed
607 608
}

Loren Merritt's avatar
Loren Merritt committed
609
void x264_frame_deblock_row( x264_t *h, int mb_y )
Laurent Aimar's avatar
Laurent Aimar committed
610 611 612
{
    const int s8x8 = 2 * h->mb.i_mb_stride;
    const int s4x4 = 4 * h->mb.i_mb_stride;
Loren Merritt's avatar
Loren Merritt committed
613
    const int b_interlaced = h->sh.b_mbaff;
614
    const int mvy_limit = 4 >> b_interlaced;
615
    const int qp_thresh = 15 - X264_MIN(h->sh.i_alpha_c0_offset, h->sh.i_beta_offset) - X264_MAX(0, h->param.analyse.i_chroma_qp_offset);
616
    const int no_sub8x8 = !(h->param.analyse.inter & X264_ANALYSE_PSUB8x8);
Loren Merritt's avatar
Loren Merritt committed
617
    int mb_x;
618 619 620 621
    int stridey   = h->fdec->i_stride[0];
    int stride2y  = stridey << b_interlaced;
    int strideuv  = h->fdec->i_stride[1];
    int stride2uv = strideuv << b_interlaced;
622

623 624 625
    if( !h->pps->b_cabac && h->pps->b_transform_8x8_mode )
        munge_cavlc_nnz( h, mb_y, h->mb.nnz_backup, munge_cavlc_nnz_row );

626
    for( mb_x = 0; mb_x < h->sps->i_mb_width; mb_x += (~b_interlaced | mb_y)&1, mb_y ^= b_interlaced )
Laurent Aimar's avatar
Laurent Aimar committed
627 628 629 630
    {
        const int mb_xy  = mb_y * h->mb.i_mb_stride + mb_x;
        const int mb_8x8 = 2 * s8x8 * mb_y + 2 * mb_x;
        const int mb_4x4 = 4 * s4x4 * mb_y + 4 * mb_x;
631
        const int b_8x8_transform = h->mb.mb_transform_size[mb_xy];
632 633 634 635 636
        const int i_qp = h->mb.qp[mb_xy];
        int i_edge_end = (h->mb.type[mb_xy] == P_SKIP) ? 1 : 4;
        uint8_t *pixy = h->fdec->plane[0] + 16*mb_y*stridey  + 16*mb_x;
        uint8_t *pixu = h->fdec->plane[1] +  8*mb_y*strideuv +  8*mb_x;
        uint8_t *pixv = h->fdec->plane[2] +  8*mb_y*strideuv +  8*mb_x;
637 638
        if( b_interlaced && (mb_y&1) )
        {
639 640 641
            pixy -= 15*stridey;
            pixu -=  7*strideuv;
            pixv -=  7*strideuv;
642 643
        }

644 645
        x264_prefetch_fenc( h, h->fdec, mb_x, mb_y );

646 647 648
        if( i_qp <= qp_thresh )
            i_edge_end = 1;

Fiona Glaser's avatar
Fiona Glaser committed
649 650 651 652 653 654 655
        #define FILTER_DIR(intra, i_dir)\
        {\
            /* Y plane */\
            i_qpn= h->mb.qp[mbn_xy];\
            if( i_dir == 0 )\
            {\
                /* vertical edge */\
656 657
                deblock_edge##intra( h, pixy + 4*i_edge, NULL,\
                              stride2y, bS, (i_qp+i_qpn+1) >> 1, 0,\
Fiona Glaser's avatar
Fiona Glaser committed
658 659 660 661
                              h->loopf.deblock_h_luma##intra );\
                if( !(i_edge & 1) )\
                {\
                    /* U/V planes */\
662 663 664
                    int i_qpc = (h->chroma_qp_table[i_qp] + h->chroma_qp_table[i_qpn] + 1) >> 1;\
                    deblock_edge##intra( h, pixu + 2*i_edge, pixv + 2*i_edge,\
                                  stride2uv, bS, i_qpc, 1,\
Fiona Glaser's avatar
Fiona Glaser committed
665 666 667 668 669 670
                                  h->loopf.deblock_h_chroma##intra );\
                }\
            }\
            else\
            {\
                /* horizontal edge */\
671 672
                deblock_edge##intra( h, pixy + 4*i_edge*stride2y, NULL,\
                              stride2y, bS, (i_qp+i_qpn+1) >> 1, 0,\
Fiona Glaser's avatar
Fiona Glaser committed
673 674 675 676
                              h->loopf.deblock_v_luma##intra );\
                /* U/V planes */\
                if( !(i_edge & 1) )\
                {\
677 678 679
                    int i_qpc = (h->chroma_qp_table[i_qp] + h->chroma_qp_table[i_qpn] + 1) >> 1;\
                    deblock_edge##intra( h, pixu + 2*i_edge*stride2uv, pixv + 2*i_edge*stride2uv,\
                                  stride2uv, bS, i_qpc, 1,\
Fiona Glaser's avatar
Fiona Glaser committed
680 681 682 683 684
                                  h->loopf.deblock_v_chroma##intra );\
                }\
            }\
        }

685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
        #define DEBLOCK_STRENGTH(i_dir)\
        {\
            /* *** Get bS for each 4px for the current edge *** */\
            if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy]) )\
                *(uint32_t*)bS = 0x03030303;\
            else\
            {\
                *(uint32_t*)bS = 0x00000000;\
                for( i = 0; i < 4; i++ )\
                {\
                    int x  = i_dir == 0 ? i_edge : i;\
                    int y  = i_dir == 0 ? i      : i_edge;\
                    int xn = i_dir == 0 ? (x - 1)&0x03 : x;\
                    int yn = i_dir == 0 ? y : (y - 1)&0x03;\
                    if( h->mb.non_zero_count[mb_xy][x+y*4] != 0 ||\
                        h->mb.non_zero_count[mbn_xy][xn+yn*4] != 0 )\
                        bS[i] = 2;\
702
                    else if(!(i_edge&no_sub8x8))\
703
                    {\
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
                        if((i&no_sub8x8) && bS[i-1] != 2)\
                            bS[i] = bS[i-1];\
                        else\
                        {\
                            /* FIXME: A given frame may occupy more than one position in\
                             * the reference list. So we should compare the frame numbers,\
                             * not the indices in the ref list.\
                             * No harm yet, as we don't generate that case.*/\
                            int i8p= mb_8x8+(x>>1)+(y>>1)*s8x8;\
                            int i8q= mbn_8x8+(xn>>1)+(yn>>1)*s8x8;\
                            int i4p= mb_4x4+x+y*s4x4;\
                            int i4q= mbn_4x4+xn+yn*s4x4;\
                            if((h->mb.ref[0][i8p] != h->mb.ref[0][i8q] ||\
                                abs( h->mb.mv[0][i4p][0] - h->mb.mv[0][i4q][0] ) >= 4 ||\
                                abs( h->mb.mv[0][i4p][1] - h->mb.mv[0][i4q][1] ) >= mvy_limit ) ||\
                               (h->sh.i_type == SLICE_TYPE_B &&\
                               (h->mb.ref[1][i8p] != h->mb.ref[1][i8q] ||\
                                abs( h->mb.mv[1][i4p][0] - h->mb.mv[1][i4q][0] ) >= 4 ||\
                                abs( h->mb.mv[1][i4p][1] - h->mb.mv[1][i4q][1] ) >= mvy_limit )))\
723 724 725
                            {\
                                bS[i] = 1;\
                            }\
726
                        }\
727 728 729 730 731
                    }\
                }\
            }\
        }

Laurent Aimar's avatar
Laurent Aimar committed
732 733
        /* i_dir == 0 -> vertical edge
         * i_dir == 1 -> horizontal edge */
734
        #define DEBLOCK_DIR(i_dir)\
Fiona Glaser's avatar
Fiona Glaser committed
735
        {\
Fiona Glaser's avatar
Fiona Glaser committed
736
            int i_edge = (i_dir ? (mb_y <= b_interlaced) : (mb_x == 0));\
737
            int i_qpn, i, mbn_xy, mbn_8x8, mbn_4x4;\
Fiona Glaser's avatar
Fiona Glaser committed
738 739 740 741 742 743 744 745 746
            DECLARE_ALIGNED_4( uint8_t bS[4] );  /* filtering strength */\
            if( i_edge )\
                i_edge+= b_8x8_transform;\
            else\
            {\
                mbn_xy  = i_dir == 0 ? mb_xy  - 1 : mb_xy - h->mb.i_mb_stride;\
                mbn_8x8 = i_dir == 0 ? mb_8x8 - 2 : mb_8x8 - 2 * s8x8;\
                mbn_4x4 = i_dir == 0 ? mb_4x4 - 4 : mb_4x4 - 4 * s4x4;\
                if( b_interlaced && i_dir == 1 )\
Fiona Glaser's avatar
Fiona Glaser committed
747 748 749 750 751
                {\
                    mbn_xy -= h->mb.i_mb_stride;\
                    mbn_8x8 -= 2 * s8x8;\
                    mbn_4x4 -= 4 * s4x4;\
                }\
Fiona Glaser's avatar
Fiona Glaser committed
752 753 754
                else if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy]) )\
                {\
                    FILTER_DIR( _intra, i_dir );\
755
                    goto end##i_dir;\
Fiona Glaser's avatar
Fiona Glaser committed
756
                }\
757 758 759 760 761
                DEBLOCK_STRENGTH(i_dir);\
                if( *(uint32_t*)bS )\
                    FILTER_DIR( , i_dir);\
                end##i_dir:\
                i_edge += b_8x8_transform+1;\
Fiona Glaser's avatar
Fiona Glaser committed
762
            }\
763 764 765
            mbn_xy  = mb_xy;\
            mbn_8x8 = mb_8x8;\
            mbn_4x4 = mb_4x4;\
Fiona Glaser's avatar
Fiona Glaser committed
766 767
            for( ; i_edge < i_edge_end; i_edge+=b_8x8_transform+1 )\
            {\
768
                DEBLOCK_STRENGTH(i_dir);\
Fiona Glaser's avatar
Fiona Glaser committed
769 770
                if( *(uint32_t*)bS )\
                    FILTER_DIR( , i_dir);\
Fiona Glaser's avatar
Fiona Glaser committed
771
            }\
Laurent Aimar's avatar
Laurent Aimar committed
772 773
        }

774 775
        DEBLOCK_DIR(0);
        DEBLOCK_DIR(1);
Laurent Aimar's avatar
Laurent Aimar committed
776
    }
777 778 779

    if( !h->pps->b_cabac && h->pps->b_transform_8x8_mode )
        munge_cavlc_nnz( h, mb_y, h->mb.nnz_backup, restore_cavlc_nnz_row );
Laurent Aimar's avatar
Laurent Aimar committed
780 781
}

Loren Merritt's avatar
Loren Merritt committed
782 783 784 785 786 787 788
void x264_frame_deblock( x264_t *h )
{
    int mb_y;
    for( mb_y = 0; mb_y < h->sps->i_mb_height; mb_y += 1 + h->sh.b_mbaff )
        x264_frame_deblock_row( h, mb_y );
}

789
#ifdef HAVE_MMX
Loren Merritt's avatar
Loren Merritt committed
790 791 792 793 794 795 796
void x264_deblock_v_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
void x264_deblock_h_chroma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
void x264_deblock_v_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
void x264_deblock_h_chroma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );

void x264_deblock_v_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
void x264_deblock_h_luma_sse2( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
Loren Merritt's avatar
Loren Merritt committed
797 798
void x264_deblock_v_luma_intra_sse2( uint8_t *pix, int stride, int alpha, int beta );
void x264_deblock_h_luma_intra_sse2( uint8_t *pix, int stride, int alpha, int beta );
799
#ifdef ARCH_X86
Loren Merritt's avatar
Loren Merritt committed
800 801
void x264_deblock_h_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
void x264_deblock_v8_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
Loren Merritt's avatar
Loren Merritt committed
802 803
void x264_deblock_h_luma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
void x264_deblock_v8_luma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta );
Loren Merritt's avatar
Loren Merritt committed
804

Loic Le Loarer's avatar
Loic Le Loarer committed
805
static void x264_deblock_v_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
Loren Merritt's avatar
Loren Merritt committed
806 807 808 809
{
    x264_deblock_v8_luma_mmxext( pix,   stride, alpha, beta, tc0   );
    x264_deblock_v8_luma_mmxext( pix+8, stride, alpha, beta, tc0+2 );
}
Loic Le Loarer's avatar
Loic Le Loarer committed
810
static void x264_deblock_v_luma_intra_mmxext( uint8_t *pix, int stride, int alpha, int beta )
Loren Merritt's avatar
Loren Merritt committed
811 812 813 814
{
    x264_deblock_v8_luma_intra_mmxext( pix,   stride, alpha, beta );
    x264_deblock_v8_luma_intra_mmxext( pix+8, stride, alpha, beta );
}
Loren Merritt's avatar
Loren Merritt committed
815
#endif
Loren Merritt's avatar
Loren Merritt committed
816
#endif
Laurent Aimar's avatar
Laurent Aimar committed
817

818 819 820 821 822
#ifdef ARCH_PPC
void x264_deblock_v_luma_altivec( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
void x264_deblock_h_luma_altivec( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 );
#endif // ARCH_PPC

Loren Merritt's avatar
Loren Merritt committed
823 824 825 826 827 828 829 830 831 832 833
void x264_deblock_init( int cpu, x264_deblock_function_t *pf )
{
    pf->deblock_v_luma = deblock_v_luma_c;
    pf->deblock_h_luma = deblock_h_luma_c;
    pf->deblock_v_chroma = deblock_v_chroma_c;
    pf->deblock_h_chroma = deblock_h_chroma_c;
    pf->deblock_v_luma_intra = deblock_v_luma_intra_c;
    pf->deblock_h_luma_intra = deblock_h_luma_intra_c;
    pf->deblock_v_chroma_intra = deblock_v_chroma_intra_c;
    pf->deblock_h_chroma_intra = deblock_h_chroma_intra_c;

834
#ifdef HAVE_MMX
Loren Merritt's avatar
Loren Merritt committed
835 836 837 838 839 840
    if( cpu&X264_CPU_MMXEXT )
    {
        pf->deblock_v_chroma = x264_deblock_v_chroma_mmxext;
        pf->deblock_h_chroma = x264_deblock_h_chroma_mmxext;
        pf->deblock_v_chroma_intra = x264_deblock_v_chroma_intra_mmxext;
        pf->deblock_h_chroma_intra = x264_deblock_h_chroma_intra_mmxext;
841 842 843
#ifdef ARCH_X86
        pf->deblock_v_luma = x264_deblock_v_luma_mmxext;
        pf->deblock_h_luma = x264_deblock_h_luma_mmxext;
Loren Merritt's avatar
Loren Merritt committed
844 845
        pf->deblock_v_luma_intra = x264_deblock_v_luma_intra_mmxext;
        pf->deblock_h_luma_intra = x264_deblock_h_luma_intra_mmxext;
846
#endif