frame.c 27.2 KB
Newer Older
Laurent Aimar's avatar
Laurent Aimar committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*****************************************************************************
 * frame.c: h264 encoder library
 *****************************************************************************
 * Copyright (C) 2003 Laurent Aimar
 * $Id: frame.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *
 * 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
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

#include <stdio.h>
#include <string.h>

#include "common.h"

29 30 31
#define PADH 32
#define PADV 32

Laurent Aimar's avatar
Laurent Aimar committed
32 33
x264_frame_t *x264_frame_new( x264_t *h )
{
34
    x264_frame_t *frame = x264_malloc( sizeof(x264_frame_t) );
35
    int i, j;
Laurent Aimar's avatar
Laurent Aimar committed
36

37
    int i_mb_count = h->mb.i_mb_count;
Laurent Aimar's avatar
Laurent Aimar committed
38 39
    int i_stride;
    int i_lines;
40
    int i_padv = PADV << h->param.b_interlaced;
Laurent Aimar's avatar
Laurent Aimar committed
41

42 43
    if( !frame ) return NULL;

44 45
    memset( frame, 0, sizeof(x264_frame_t) );

Laurent Aimar's avatar
Laurent Aimar committed
46
    /* allocate frame data (+64 for extra data for me) */
47 48 49 50
    i_stride = ( ( h->param.i_width  + 15 ) & -16 )+ 2*PADH;
    i_lines  = ( ( h->param.i_height + 15 ) & -16 );
    if( h->param.b_interlaced )
        i_lines = ( i_lines + 31 ) & -32;
Laurent Aimar's avatar
Laurent Aimar committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

    frame->i_plane = 3;
    for( i = 0; i < 3; i++ )
    {
        int i_divh = 1;
        int i_divw = 1;
        if( i > 0 )
        {
            if( h->param.i_csp == X264_CSP_I420 )
                i_divh = i_divw = 2;
            else if( h->param.i_csp == X264_CSP_I422 )
                i_divw = 2;
        }
        frame->i_stride[i] = i_stride / i_divw;
        frame->i_lines[i] = i_lines / i_divh;
66
        CHECKED_MALLOC( frame->buffer[i],
67 68
                        frame->i_stride[i] * ( frame->i_lines[i] + 2*i_padv / i_divh ) );

Laurent Aimar's avatar
Laurent Aimar committed
69
        frame->plane[i] = ((uint8_t*)frame->buffer[i]) +
70
                          frame->i_stride[i] * i_padv / i_divh + PADH / i_divw;
Laurent Aimar's avatar
Laurent Aimar committed
71 72 73 74 75 76
    }
    frame->i_stride[3] = 0;
    frame->i_lines[3] = 0;
    frame->buffer[3] = NULL;
    frame->plane[3] = NULL;

77 78 79
    frame->filtered[0] = frame->plane[0];
    for( i = 0; i < 3; i++ )
    {
80
        CHECKED_MALLOC( frame->buffer[4+i],
81
                        frame->i_stride[0] * ( frame->i_lines[0] + 2*i_padv ) );
82
        frame->filtered[i+1] = ((uint8_t*)frame->buffer[4+i]) +
83
                                frame->i_stride[0] * i_padv + PADH;
84 85
    }

86
    if( h->frames.b_have_lowres )
87
    {
88
        frame->i_stride_lowres = frame->i_stride[0]/2 + PADH;
89 90 91
        frame->i_lines_lowres = frame->i_lines[0]/2;
        for( i = 0; i < 4; i++ )
        {
92 93 94 95
            CHECKED_MALLOC( frame->buffer_lowres[i],
                            frame->i_stride_lowres * ( frame->i_lines[0]/2 + 2*i_padv ) );
            frame->lowres[i] = ((uint8_t*)frame->buffer_lowres[i]) +
                                frame->i_stride_lowres * i_padv + PADH;
96
        }
97
    }
98

99 100
    if( h->param.analyse.i_me_method == X264_ME_ESA )
    {
101 102 103
        CHECKED_MALLOC( frame->buffer[7],
                        2 * frame->i_stride[0] * (frame->i_lines[0] + 2*i_padv) * sizeof(uint16_t) );
        frame->integral = (uint16_t*)frame->buffer[7] + frame->i_stride[0] * i_padv + PADH;
104 105
    }

Laurent Aimar's avatar
Laurent Aimar committed
106 107 108
    frame->i_poc = -1;
    frame->i_type = X264_TYPE_AUTO;
    frame->i_qpplus1 = 0;
109 110
    frame->i_pts = -1;
    frame->i_frame = -1;
111
    frame->i_frame_num = -1;
Laurent Aimar's avatar
Laurent Aimar committed
112

113 114 115
    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) );
116 117
    if( h->param.i_bframe )
    {
118 119
        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) );
120 121 122 123 124 125 126
    }
    else
    {
        frame->mv[1]  = NULL;
        frame->ref[1] = NULL;
    }

127 128
    CHECKED_MALLOC( frame->i_row_bits, i_lines/16 * sizeof(int) );
    CHECKED_MALLOC( frame->i_row_qp, i_lines/16 * sizeof(int) );
129 130
    for( i = 0; i < h->param.i_bframe + 2; i++ )
        for( j = 0; j < h->param.i_bframe + 2; j++ )
131
            CHECKED_MALLOC( frame->i_row_satds[i][j], i_lines/16 * sizeof(int) );
132

Laurent Aimar's avatar
Laurent Aimar committed
133
    return frame;
134 135 136 137

fail:
    x264_frame_delete( frame );
    return NULL;
Laurent Aimar's avatar
Laurent Aimar committed
138 139 140 141
}

void x264_frame_delete( x264_frame_t *frame )
{
142
    int i, j;
143
    for( i = 0; i < 8; i++ )
144
        x264_free( frame->buffer[i] );
145 146
    for( i = 0; i < 4; i++ )
        x264_free( frame->buffer_lowres[i] );
147 148 149 150 151
    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] );
    x264_free( frame->i_row_bits );
    x264_free( frame->i_row_qp );
152
    x264_free( frame->mb_type );
153 154 155 156
    x264_free( frame->mv[0] );
    x264_free( frame->mv[1] );
    x264_free( frame->ref[0] );
    x264_free( frame->ref[1] );
Laurent Aimar's avatar
Laurent Aimar committed
157 158 159 160 161
    x264_free( frame );
}

void x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src )
{
162
    int i_csp = src->img.i_csp & X264_CSP_MASK;
Laurent Aimar's avatar
Laurent Aimar committed
163 164 165 166
    dst->i_type     = src->i_type;
    dst->i_qpplus1  = src->i_qpplus1;
    dst->i_pts      = src->i_pts;

167 168 169 170
    if( i_csp <= X264_CSP_NONE  || i_csp >= X264_CSP_MAX )
        x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" );
    else
        h->csp.convert[i_csp]( &h->mc, dst, &src->img, h->param.i_width, h->param.i_height );
Laurent Aimar's avatar
Laurent Aimar committed
171 172 173 174
}



175
static void plane_expand_border( uint8_t *pix, int i_stride, int i_width, int i_height, int i_padh, int i_padv )
176 177 178 179 180 181
{
#define PPIXEL(x, y) ( pix + (x) + (y)*i_stride )
    int y;
    for( y = 0; y < i_height; y++ )
    {
        /* left band */
182
        memset( PPIXEL(-i_padh, y), PPIXEL(0, y)[0], i_padh );
183
        /* right band */
184
        memset( PPIXEL(i_width, y), PPIXEL(i_width-1, y)[0], i_padh );
185 186
    }
    /* upper band */
187 188
    for( y = 0; y < i_padv; y++ )
        memcpy( PPIXEL(-i_padh, -y-1), PPIXEL(-i_padh, 0), i_width+2*i_padh );
189
    /* lower band */
190 191
    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 );
192 193 194
#undef PPIXEL
}

195
void x264_frame_expand_border( x264_t *h, x264_frame_t *frame )
Laurent Aimar's avatar
Laurent Aimar committed
196
{
197
    int i;
Laurent Aimar's avatar
Laurent Aimar committed
198 199
    for( i = 0; i < frame->i_plane; i++ )
    {
200 201 202 203 204 205 206 207 208 209 210 211 212 213
        int stride = frame->i_stride[i];
        int width = 16*h->sps->i_mb_width >> !!i;
        int height = 16*h->sps->i_mb_height >> !!i;
        int padh = PADH >> !!i;
        int padv = PADV >> !!i;
        if( h->param.b_interlaced )
        {
            plane_expand_border( frame->plane[i], stride*2, width, height>>1, padh, padv );
            plane_expand_border( frame->plane[i]+stride, stride*2, width, height>>1, padh, padv );
        }
        else
        {
            plane_expand_border( frame->plane[i], stride, width, height, padh, padv );
        }
Laurent Aimar's avatar
Laurent Aimar committed
214 215 216
    }
}

217
void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame )
218 219 220
{
    /* during filtering, 8 extra pixels were filtered on each edge. 
       we want to expand border from the last filtered pixel */
221 222 223 224 225
    int stride = frame->i_stride[0];
    int width = 16*h->sps->i_mb_width;
    int height = 16*h->sps->i_mb_height;
    int padh = PADH - 8;
    int padv = PADV - 8;
226
    int i;
227
    for( i = 1; i < 4; i++ )
228 229 230 231 232 233 234 235 236 237 238
    {
        if( h->param.b_interlaced )
        {
            plane_expand_border( frame->filtered[i] - 16*stride - 8, stride*2, width+16, (height>>1)+16, padh, padv );
            plane_expand_border( frame->filtered[i] - 15*stride - 8, stride*2, width+16, (height>>1)+16, padh, padv );
        }
        else
        {
            plane_expand_border( frame->filtered[i] - 8*stride - 8, stride, width+16, height+16, padh, padv );
        }
    }
239 240
}

241
void x264_frame_expand_border_lowres( x264_frame_t *frame )
242
{
243
    int i;
244
    for( i = 0; i < 4; i++ )
245
        plane_expand_border( frame->lowres[i], frame->i_stride_lowres, frame->i_stride_lowres - 2*PADH, frame->i_lines_lowres, PADH, PADV );
246 247
}

Loren Merritt's avatar
Loren Merritt committed
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267
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 )
        {
268
            //FIXME interlace? or just let it pad using the wrong field
Loren Merritt's avatar
Loren Merritt committed
269
            for( y = i_height; y < i_height + i_pady; y++ )
Loren Merritt's avatar
Loren Merritt committed
270 271 272 273 274 275 276
                memcpy( &frame->plane[i][y*frame->i_stride[i]],
                        &frame->plane[i][(i_height-1)*frame->i_stride[i]],
                        i_width + i_padx );
        }
    }
}

277

278
/* Deblocking filter */
Laurent Aimar's avatar
Laurent Aimar committed
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319

static const int i_alpha_table[52] =
{
     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,
    255, 255
};
static const int i_beta_table[52] =
{
     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,
    18, 18
};
static const int i_tc0_table[52][3] =
{
    { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
    { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 },
    { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 1 },
    { 0, 0, 1 }, { 0, 0, 1 }, { 0, 0, 1 }, { 0, 1, 1 }, { 0, 1, 1 }, { 1, 1, 1 },
    { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 1 }, { 1, 1, 2 }, { 1, 1, 2 }, { 1, 1, 2 },
    { 1, 1, 2 }, { 1, 2, 3 }, { 1, 2, 3 }, { 2, 2, 3 }, { 2, 2, 4 }, { 2, 3, 4 },
    { 2, 3, 4 }, { 3, 3, 5 }, { 3, 4, 6 }, { 3, 4, 6 }, { 4, 5, 7 }, { 4, 5, 8 },
    { 4, 6, 9 }, { 5, 7,10 }, { 6, 8,11 }, { 6, 8,13 }, { 7,10,14 }, { 8,11,16 },
    { 9,12,18 }, {10,13,20 }, {11,15,23 }, {13,17,25 }
};

/* From ffmpeg */
static inline int clip_uint8( int a )
{
    if (a&(~255))
        return (-a)>>31;
    else
        return a;
}

Loren Merritt's avatar
Loren Merritt committed
320
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
321 322
{
    int i, d;
Loren Merritt's avatar
Loren Merritt committed
323 324 325
    for( i = 0; i < 4; i++ ) {
        if( tc0[i] < 0 ) {
            pix += 4*ystride;
Laurent Aimar's avatar
Laurent Aimar committed
326 327
            continue;
        }
Loren Merritt's avatar
Loren Merritt committed
328 329 330 331 332 333 334 335
        for( d = 0; d < 4; d++ ) {
            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];
   
Loren Merritt's avatar
Loren Merritt committed
336 337 338
            if( abs( p0 - q0 ) < alpha &&
                abs( p1 - p0 ) < beta &&
                abs( q1 - q0 ) < beta ) {
Loren Merritt's avatar
Loren Merritt committed
339 340 341 342
   
                int tc = tc0[i];
                int delta;
   
Loren Merritt's avatar
Loren Merritt committed
343
                if( abs( p2 - p0 ) < beta ) {
Loren Merritt's avatar
Loren Merritt committed
344 345
                    pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0[i], tc0[i] );
                    tc++; 
Laurent Aimar's avatar
Laurent Aimar committed
346
                }
Loren Merritt's avatar
Loren Merritt committed
347
                if( abs( q2 - q0 ) < beta ) {
Loren Merritt's avatar
Loren Merritt committed
348 349
                    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
350
                }
Loren Merritt's avatar
Loren Merritt committed
351 352 353 354
    
                delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
                pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
                pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
Laurent Aimar's avatar
Laurent Aimar committed
355
            }
Loren Merritt's avatar
Loren Merritt committed
356
            pix += ystride;
Laurent Aimar's avatar
Laurent Aimar committed
357 358 359
        }
    }
}
Loren Merritt's avatar
Loren Merritt committed
360 361 362 363 364 365 366 367
static void deblock_v_luma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
{
    deblock_luma_c( pix, stride, 1, alpha, beta, tc0 ); 
}
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
368

Loren Merritt's avatar
Loren Merritt committed
369
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
370 371
{
    int i, d;
Loren Merritt's avatar
Loren Merritt committed
372 373 374 375
    for( i = 0; i < 4; i++ ) {
        const int tc = tc0[i];
        if( tc <= 0 ) {
            pix += 2*ystride;
Laurent Aimar's avatar
Laurent Aimar committed
376 377
            continue;
        }
Loren Merritt's avatar
Loren Merritt committed
378 379 380 381 382 383
        for( d = 0; d < 2; d++ ) {
            const int p1 = pix[-2*xstride];
            const int p0 = pix[-1*xstride];
            const int q0 = pix[ 0*xstride];
            const int q1 = pix[ 1*xstride];

Loren Merritt's avatar
Loren Merritt committed
384 385 386
            if( abs( p0 - q0 ) < alpha &&
                abs( p1 - p0 ) < beta &&
                abs( q1 - q0 ) < beta ) {
Loren Merritt's avatar
Loren Merritt committed
387 388 389 390

                int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
                pix[-1*xstride] = clip_uint8( p0 + delta );    /* p0' */
                pix[ 0*xstride] = clip_uint8( q0 - delta );    /* q0' */
Laurent Aimar's avatar
Laurent Aimar committed
391
            }
Loren Merritt's avatar
Loren Merritt committed
392
            pix += ystride;
Laurent Aimar's avatar
Laurent Aimar committed
393 394 395
        }
    }
}
Loren Merritt's avatar
Loren Merritt committed
396 397 398 399 400 401 402 403
static void deblock_v_chroma_c( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
{   
    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 )
{   
    deblock_chroma_c( pix, 1, stride, alpha, beta, tc0 );
}
Laurent Aimar's avatar
Laurent Aimar committed
404

Loren Merritt's avatar
Loren Merritt committed
405
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
406
{
Loren Merritt's avatar
Loren Merritt committed
407 408 409 410 411 412 413 414 415
    int d;
    for( d = 0; d < 16; d++ ) {
        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];

Loren Merritt's avatar
Loren Merritt committed
416 417 418
        if( abs( p0 - q0 ) < alpha &&
            abs( p1 - p0 ) < beta &&
            abs( q1 - q0 ) < beta ) {
Loren Merritt's avatar
Loren Merritt committed
419

Loren Merritt's avatar
Loren Merritt committed
420 421
            if(abs( p0 - q0 ) < ((alpha >> 2) + 2) ){
                if( abs( p2 - p0 ) < beta)
Laurent Aimar's avatar
Laurent Aimar committed
422
                {
Loren Merritt's avatar
Loren Merritt committed
423 424 425 426 427 428 429 430
                    const int p3 = pix[-4*xstride];
                    /* p0', p1', p2' */
                    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;
                } else {
                    /* p0' */
                    pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
Laurent Aimar's avatar
Laurent Aimar committed
431
                }
Loren Merritt's avatar
Loren Merritt committed
432
                if( abs( q2 - q0 ) < beta)
Laurent Aimar's avatar
Laurent Aimar committed
433
                {
Loren Merritt's avatar
Loren Merritt committed
434 435 436 437 438 439 440 441
                    const int q3 = pix[3*xstride];
                    /* q0', q1', q2' */
                    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;
                } else {
                    /* q0' */
                    pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
Laurent Aimar's avatar
Laurent Aimar committed
442
                }
Loren Merritt's avatar
Loren Merritt committed
443 444 445 446
            }else{
                /* p0', q0' */
                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
447 448
            }
        }
Loren Merritt's avatar
Loren Merritt committed
449
        pix += ystride;
Laurent Aimar's avatar
Laurent Aimar committed
450 451
    }
}
Loren Merritt's avatar
Loren Merritt committed
452 453 454 455 456 457 458 459
static void deblock_v_luma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
{   
    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 )
{   
    deblock_luma_intra_c( pix, 1, stride, alpha, beta );
}
Laurent Aimar's avatar
Laurent Aimar committed
460

Loren Merritt's avatar
Loren Merritt committed
461 462 463 464 465 466 467 468 469
static inline void deblock_chroma_intra_c( uint8_t *pix, int xstride, int ystride, int alpha, int beta )
{   
    int d; 
    for( d = 0; d < 8; d++ ) {
        const int p1 = pix[-2*xstride];
        const int p0 = pix[-1*xstride];
        const int q0 = pix[ 0*xstride];
        const int q1 = pix[ 1*xstride];

Loren Merritt's avatar
Loren Merritt committed
470 471 472
        if( abs( p0 - q0 ) < alpha &&
            abs( p1 - p0 ) < beta &&
            abs( q1 - q0 ) < beta ) {
Loren Merritt's avatar
Loren Merritt committed
473 474 475

            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
476 477
        }

Loren Merritt's avatar
Loren Merritt committed
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504
        pix += ystride;
    }
}
static void deblock_v_chroma_intra_c( uint8_t *pix, int stride, int alpha, int beta )
{   
    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 )
{   
    deblock_chroma_intra_c( pix, 1, stride, alpha, beta );
}

static inline void deblock_edge( x264_t *h, uint8_t *pix, int i_stride, int bS[4], int i_qp, int b_chroma,
                                 x264_deblock_inter_t pf_inter, x264_deblock_intra_t pf_intra )
{
    int i;
    const int index_a = x264_clip3( i_qp + h->sh.i_alpha_c0_offset, 0, 51 );
    const int alpha = i_alpha_table[index_a];
    const int beta  = i_beta_table[x264_clip3( i_qp + h->sh.i_beta_offset, 0, 51 )];

    if( bS[0] < 4 ) {
        int8_t tc[4]; 
        for(i=0; i<4; i++)
            tc[i] = (bS[i] ? i_tc0_table[index_a][bS[i] - 1] : -1) + b_chroma;
        pf_inter( pix, i_stride, alpha, beta, tc );
    } else {
        pf_intra( pix, i_stride, alpha, beta );
Laurent Aimar's avatar
Laurent Aimar committed
505 506 507 508 509 510 511
    }
}

void x264_frame_deblocking_filter( x264_t *h, int i_slice_type )
{
    const int s8x8 = 2 * h->mb.i_mb_stride;
    const int s4x4 = 4 * h->mb.i_mb_stride;
512 513
    const int b_interlaced = h->param.b_interlaced;
    const int mvy_limit = 4 >> b_interlaced;
Laurent Aimar's avatar
Laurent Aimar committed
514 515
    int mb_y, mb_x;

516 517 518 519
    int i_stride2[3] = { h->fdec->i_stride[0] << b_interlaced,
                         h->fdec->i_stride[1] << b_interlaced,
                         h->fdec->i_stride[2] << b_interlaced };

Laurent Aimar's avatar
Laurent Aimar committed
520 521 522 523 524
    for( mb_y = 0, mb_x = 0; mb_y < h->sps->i_mb_height; )
    {
        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;
525
        const int b_8x8_transform = h->mb.mb_transform_size[mb_xy];
Loren Merritt's avatar
Loren Merritt committed
526 527
        const int i_edge_end = (h->mb.type[mb_xy] == P_SKIP) ? 1 : 4;
        int i_edge, i_dir;
528

529 530 531 532 533 534 535 536 537 538
        int i_pix_y[3] = { 16*mb_y*h->fdec->i_stride[0] + 16*mb_x,
                            8*mb_y*h->fdec->i_stride[1] +  8*mb_x,
                            8*mb_y*h->fdec->i_stride[2] +  8*mb_x };
        if( b_interlaced && (mb_y&1) )
        {
            i_pix_y[0] -= 15*h->fdec->i_stride[0];
            i_pix_y[1] -=  7*h->fdec->i_stride[1];
            i_pix_y[2] -=  7*h->fdec->i_stride[2];
        }

539 540 541 542 543 544 545 546 547 548
        /* cavlc + 8x8 transform stores nnz per 16 coeffs for the purpose of
         * entropy coding, but per 64 coeffs for the purpose of deblocking */
        if( !h->param.b_cabac && b_8x8_transform )
        {
            uint32_t *nnz = (uint32_t*)h->mb.non_zero_count[mb_xy];
            if( nnz[0] ) nnz[0] = 0x01010101;
            if( nnz[1] ) nnz[1] = 0x01010101;
            if( nnz[2] ) nnz[2] = 0x01010101;
            if( nnz[3] ) nnz[3] = 0x01010101;
        }
Laurent Aimar's avatar
Laurent Aimar committed
549 550 551 552 553

        /* i_dir == 0 -> vertical edge
         * i_dir == 1 -> horizontal edge */
        for( i_dir = 0; i_dir < 2; i_dir++ )
        {
554
            int i_start = (i_dir ? (mb_y <= b_interlaced) : (mb_x == 0));
Laurent Aimar's avatar
Laurent Aimar committed
555 556
            int i_qp, i_qpn;

Loren Merritt's avatar
Loren Merritt committed
557
            for( i_edge = i_start; i_edge < i_edge_end; i_edge++ )
Laurent Aimar's avatar
Laurent Aimar committed
558
            {
Loren Merritt's avatar
Loren Merritt committed
559
                int mbn_xy, mbn_8x8, mbn_4x4;
Laurent Aimar's avatar
Laurent Aimar committed
560 561
                int bS[4];  /* filtering strength */

Loren Merritt's avatar
Loren Merritt committed
562 563 564 565 566 567 568
                if( b_8x8_transform && (i_edge&1) )
                    continue;

                mbn_xy  = i_edge > 0 ? mb_xy  : ( i_dir == 0 ? mb_xy  - 1 : mb_xy - h->mb.i_mb_stride );
                mbn_8x8 = i_edge > 0 ? mb_8x8 : ( i_dir == 0 ? mb_8x8 - 2 : mb_8x8 - 2 * s8x8 );
                mbn_4x4 = i_edge > 0 ? mb_4x4 : ( i_dir == 0 ? mb_4x4 - 4 : mb_4x4 - 4 * s4x4 );

569 570 571 572 573 574 575
                if( b_interlaced && i_edge == 0 && i_dir == 1 )
                {
                    mbn_xy -= h->mb.i_mb_stride;
                    mbn_8x8 -= 2 * s8x8;
                    mbn_4x4 -= 4 * s4x4;
                }

Laurent Aimar's avatar
Laurent Aimar committed
576 577 578
                /* *** Get bS for each 4px for the current edge *** */
                if( IS_INTRA( h->mb.type[mb_xy] ) || IS_INTRA( h->mb.type[mbn_xy] ) )
                {
579
                    bS[0] = bS[1] = bS[2] = bS[3] = ( i_edge == 0 && !(b_interlaced && i_dir) ? 4 : 3 );
Laurent Aimar's avatar
Laurent Aimar committed
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
                }
                else
                {
                    int i;
                    for( i = 0; i < 4; i++ )
                    {
                        int x  = i_dir == 0 ? i_edge : i;
                        int y  = i_dir == 0 ? i      : i_edge;
                        int xn = (x - (i_dir == 0 ? 1 : 0 ))&0x03;
                        int yn = (y - (i_dir == 0 ? 0 : 1 ))&0x03;

                        if( h->mb.non_zero_count[mb_xy][block_idx_xy[x][y]] != 0 ||
                            h->mb.non_zero_count[mbn_xy][block_idx_xy[xn][yn]] != 0 )
                        {
                            bS[i] = 2;
                        }
596
                        else
Laurent Aimar's avatar
Laurent Aimar committed
597
                        {
598 599 600 601 602 603 604 605 606 607 608 609 610 611
                            /* 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/2)+(y/2)*s8x8;
                            int i8q= mbn_8x8+(xn/2)+(yn/2)*s8x8;
                            int i4p= mb_4x4+x+y*s4x4;
                            int i4q= mbn_4x4+xn+yn*s4x4;
                            int l;

                            bS[i] = 0;

                            for( l = 0; l < 1 + (i_slice_type == SLICE_TYPE_B); l++ )
Laurent Aimar's avatar
Laurent Aimar committed
612
                            {
613 614
                                if( h->mb.ref[l][i8p] != h->mb.ref[l][i8q] ||
                                    abs( h->mb.mv[l][i4p][0] - h->mb.mv[l][i4q][0] ) >= 4 ||
615
                                    abs( h->mb.mv[l][i4p][1] - h->mb.mv[l][i4q][1] ) >= mvy_limit )
616 617 618 619
                                {
                                    bS[i] = 1;
                                    break;
                                }
Laurent Aimar's avatar
Laurent Aimar committed
620 621 622 623 624 625 626 627 628 629 630 631 632
                            }
                        }
                    }
                }

                /* *** filter *** */
                /* Y plane */
                i_qp = h->mb.qp[mb_xy];
                i_qpn= h->mb.qp[mbn_xy];

                if( i_dir == 0 )
                {
                    /* vertical edge */
633 634
                    deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge],
                                  i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
Loren Merritt's avatar
Loren Merritt committed
635
                                  h->loopf.deblock_h_luma, h->loopf.deblock_h_luma_intra );
636
                    if( !(i_edge & 1) )
Laurent Aimar's avatar
Laurent Aimar committed
637 638 639 640
                    {
                        /* U/V planes */
                        int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
                                      i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
641 642
                        deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge],
                                      i_stride2[1], bS, i_qpc, 1,
Loren Merritt's avatar
Loren Merritt committed
643
                                      h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
644 645
                        deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge],
                                      i_stride2[2], bS, i_qpc, 1,
Loren Merritt's avatar
Loren Merritt committed
646
                                      h->loopf.deblock_h_chroma, h->loopf.deblock_h_chroma_intra );
Laurent Aimar's avatar
Laurent Aimar committed
647 648 649 650 651
                    }
                }
                else
                {
                    /* horizontal edge */
652 653
                    deblock_edge( h, &h->fdec->plane[0][i_pix_y[0] + 4*i_edge*i_stride2[0]],
                                  i_stride2[0], bS, (i_qp+i_qpn+1) >> 1, 0,
Loren Merritt's avatar
Loren Merritt committed
654
                                  h->loopf.deblock_v_luma, h->loopf.deblock_v_luma_intra );
Laurent Aimar's avatar
Laurent Aimar committed
655
                    /* U/V planes */
656
                    if( !(i_edge & 1) )
Laurent Aimar's avatar
Laurent Aimar committed
657 658 659
                    {
                        int i_qpc = ( i_chroma_qp_table[x264_clip3( i_qp + h->pps->i_chroma_qp_index_offset, 0, 51 )] +
                                      i_chroma_qp_table[x264_clip3( i_qpn + h->pps->i_chroma_qp_index_offset, 0, 51 )] + 1 ) >> 1;
660 661
                        deblock_edge( h, &h->fdec->plane[1][i_pix_y[1] + 2*i_edge*i_stride2[1]],
                                      i_stride2[1], bS, i_qpc, 1,
Loren Merritt's avatar
Loren Merritt committed
662
                                      h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
663 664
                        deblock_edge( h, &h->fdec->plane[2][i_pix_y[2] + 2*i_edge*i_stride2[2]],
                                      i_stride2[2], bS, i_qpc, 1,
Loren Merritt's avatar
Loren Merritt committed
665
                                      h->loopf.deblock_v_chroma, h->loopf.deblock_v_chroma_intra );
Laurent Aimar's avatar
Laurent Aimar committed
666 667 668 669 670
                    }
                }
            }
        }

671 672 673
        /* next mb */
        if( !b_interlaced || (mb_y&1) )
            mb_x++;
Laurent Aimar's avatar
Laurent Aimar committed
674 675 676 677 678
        if( mb_x >= h->sps->i_mb_width )
        {
            mb_x = 0;
            mb_y++;
        }
679 680
        else
            mb_y ^= b_interlaced;
Laurent Aimar's avatar
Laurent Aimar committed
681 682 683
    }
}

684
#ifdef HAVE_MMXEXT
Loren Merritt's avatar
Loren Merritt committed
685 686 687 688 689 690 691 692
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 );

#ifdef ARCH_X86_64
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
693
#else
Loren Merritt's avatar
Loren Merritt committed
694 695 696 697 698 699 700 701 702
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 );

void x264_deblock_v_luma_mmxext( uint8_t *pix, int stride, int alpha, int beta, int8_t *tc0 )
{
    x264_deblock_v8_luma_mmxext( pix,   stride, alpha, beta, tc0   );
    x264_deblock_v8_luma_mmxext( pix+8, stride, alpha, beta, tc0+2 );
}
#endif
Loren Merritt's avatar
Loren Merritt committed
703
#endif
Laurent Aimar's avatar
Laurent Aimar committed
704

Loren Merritt's avatar
Loren Merritt committed
705 706 707 708 709 710 711 712 713 714 715
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;

716
#ifdef HAVE_MMXEXT
Loren Merritt's avatar
Loren Merritt committed
717 718 719 720 721 722
    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;
Laurent Aimar's avatar
Laurent Aimar committed
723

Loren Merritt's avatar
Loren Merritt committed
724 725 726 727 728 729 730 731 732 733 734
#ifdef ARCH_X86_64
        if( cpu&X264_CPU_SSE2 )
        {
            pf->deblock_v_luma = x264_deblock_v_luma_sse2;
            pf->deblock_h_luma = x264_deblock_h_luma_sse2;
        }
#else
        pf->deblock_v_luma = x264_deblock_v_luma_mmxext;
        pf->deblock_h_luma = x264_deblock_h_luma_mmxext;
#endif
    }
735
#endif
Loren Merritt's avatar
Loren Merritt committed
736
}
Laurent Aimar's avatar
Laurent Aimar committed
737