deblock.c 34.4 KB
Newer Older
1
/*****************************************************************************
2
 * deblock.c: deblocking
3
 *****************************************************************************
Henrik Gramner's avatar
Henrik Gramner committed
4
 * Copyright (C) 2003-2019 x264 project
5 6 7 8
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Loren Merritt <lorenm@u.washington.edu>
 *          Fiona Glaser <fiona@x264.com>
Henrik Gramner's avatar
Henrik Gramner committed
9
 *          Henrik Gramner <henrik@gramner.com>
10 11 12 13 14 15 16 17 18 19 20 21 22 23
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
24 25 26
 *
 * This program is also available under a commercial proprietary license.
 * For more information, contact us at licensing@x264.com.
27 28 29 30 31
 *****************************************************************************/

#include "common.h"

/* Deblocking filter */
32
static const uint8_t i_alpha_table[52+12*3] =
33
{
34
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
35 36 37 38 39 40 41 42 43
     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,  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,
   255,255,255,255,255,255,255,255,255,255,255,255,
};
44
static const uint8_t i_beta_table[52+12*3] =
45
{
46
     0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
47 48 49 50 51 52 53 54 55
     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,  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,
    18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,
};
56
static const int8_t i_tc0_table[52+12*3][4] =
57 58 59 60 61
{
    {-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, 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 },
62 63
    {-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 },
64 65 66 67 68 69 70 71 72 73
    {-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 },
    {-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 },
};
74 75 76
#define alpha_table(x) i_alpha_table[(x)+24]
#define beta_table(x)  i_beta_table[(x)+24]
#define tc0_table(x)   i_tc0_table[(x)+24]
77 78

/* From ffmpeg */
79
static ALWAYS_INLINE void deblock_edge_luma_c( pixel *pix, intptr_t xstride, int alpha, int beta, int8_t tc0 )
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
{
    int p2 = pix[-3*xstride];
    int p1 = pix[-2*xstride];
    int p0 = pix[-1*xstride];
    int q0 = pix[ 0*xstride];
    int q1 = pix[ 1*xstride];
    int q2 = pix[ 2*xstride];

    if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
    {
        int tc = tc0;
        int delta;
        if( abs( p2 - p0 ) < beta )
        {
            if( tc0 )
                pix[-2*xstride] = p1 + x264_clip3( (( p2 + ((p0 + q0 + 1) >> 1)) >> 1) - p1, -tc0, tc0 );
            tc++;
        }
        if( abs( q2 - q0 ) < beta )
        {
            if( tc0 )
                pix[ 1*xstride] = q1 + x264_clip3( (( q2 + ((p0 + q0 + 1) >> 1)) >> 1) - q1, -tc0, tc0 );
            tc++;
        }

        delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
        pix[-1*xstride] = x264_clip_pixel( p0 + delta );    /* p0' */
        pix[ 0*xstride] = x264_clip_pixel( q0 - delta );    /* q0' */
    }
}
110
static inline void deblock_luma_c( pixel *pix, intptr_t xstride, intptr_t ystride, int alpha, int beta, int8_t *tc0 )
111 112 113 114 115 116 117 118
{
    for( int i = 0; i < 4; i++ )
    {
        if( tc0[i] < 0 )
        {
            pix += 4*ystride;
            continue;
        }
119 120
        for( int d = 0; d < 4; d++, pix += ystride )
            deblock_edge_luma_c( pix, xstride, alpha, beta, tc0[i] );
121 122
    }
}
123
static void deblock_h_luma_mbaff_c( pixel *pix, intptr_t stride, int alpha, int beta, int8_t *tc0 )
124 125 126 127
{
    for( int d = 0; d < 8; d++, pix += stride )
        deblock_edge_luma_c( pix, 1, alpha, beta, tc0[d>>1] );
}
128
static void deblock_v_luma_c( pixel *pix, intptr_t stride, int alpha, int beta, int8_t *tc0 )
129 130 131
{
    deblock_luma_c( pix, stride, 1, alpha, beta, tc0 );
}
132
static void deblock_h_luma_c( pixel *pix, intptr_t stride, int alpha, int beta, int8_t *tc0 )
133 134 135 136
{
    deblock_luma_c( pix, 1, stride, alpha, beta, tc0 );
}

137
static ALWAYS_INLINE void deblock_edge_chroma_c( pixel *pix, intptr_t xstride, int alpha, int beta, int8_t tc )
138 139 140 141 142 143 144 145 146 147 148 149 150
{
    int p1 = pix[-2*xstride];
    int p0 = pix[-1*xstride];
    int q0 = pix[ 0*xstride];
    int q1 = pix[ 1*xstride];

    if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
    {
        int delta = x264_clip3( (((q0 - p0 ) << 2) + (p1 - q1) + 4) >> 3, -tc, tc );
        pix[-1*xstride] = x264_clip_pixel( p0 + delta );    /* p0' */
        pix[ 0*xstride] = x264_clip_pixel( q0 - delta );    /* q0' */
    }
}
151
static ALWAYS_INLINE void deblock_chroma_c( pixel *pix, int height, intptr_t xstride, intptr_t ystride, int alpha, int beta, int8_t *tc0 )
152 153 154 155 156 157
{
    for( int i = 0; i < 4; i++ )
    {
        int tc = tc0[i];
        if( tc <= 0 )
        {
Henrik Gramner's avatar
Henrik Gramner committed
158
            pix += height*ystride;
159 160
            continue;
        }
Henrik Gramner's avatar
Henrik Gramner committed
161 162 163
        for( int d = 0; d < height; d++, pix += ystride-2 )
            for( int e = 0; e < 2; e++, pix++ )
                deblock_edge_chroma_c( pix, xstride, alpha, beta, tc0[i] );
164 165
    }
}
166
static void deblock_h_chroma_mbaff_c( pixel *pix, intptr_t stride, int alpha, int beta, int8_t *tc0 )
167
{
168
    deblock_chroma_c( pix, 1, 2, stride, alpha, beta, tc0 );
169
}
170
static void deblock_v_chroma_c( pixel *pix, intptr_t stride, int alpha, int beta, int8_t *tc0 )
171
{
Henrik Gramner's avatar
Henrik Gramner committed
172
    deblock_chroma_c( pix, 2, stride, 2, alpha, beta, tc0 );
173
}
174
static void deblock_h_chroma_c( pixel *pix, intptr_t stride, int alpha, int beta, int8_t *tc0 )
175
{
Henrik Gramner's avatar
Henrik Gramner committed
176 177
    deblock_chroma_c( pix, 2, 2, stride, alpha, beta, tc0 );
}
178
static void deblock_h_chroma_422_c( pixel *pix, intptr_t stride, int alpha, int beta, int8_t *tc0 )
Henrik Gramner's avatar
Henrik Gramner committed
179 180
{
    deblock_chroma_c( pix, 4, 2, stride, alpha, beta, tc0 );
181 182
}

183
static ALWAYS_INLINE void deblock_edge_luma_intra_c( pixel *pix, intptr_t xstride, int alpha, int beta )
184
{
185 186 187 188 189 190
    int p2 = pix[-3*xstride];
    int p1 = pix[-2*xstride];
    int p0 = pix[-1*xstride];
    int q0 = pix[ 0*xstride];
    int q1 = pix[ 1*xstride];
    int q2 = pix[ 2*xstride];
191

192 193 194
    if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
    {
        if( abs( p0 - q0 ) < ((alpha >> 2) + 2) )
195
        {
196
            if( abs( p2 - p0 ) < beta ) /* p0', p1', p2' */
197
            {
198 199 200 201
                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;
202
            }
203
            else /* p0' */
204
                pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
205 206 207 208 209 210
            if( abs( q2 - q0 ) < beta ) /* q0', q1', q2' */
            {
                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;
211
            }
212 213 214 215 216 217 218
            else /* q0' */
                pix[0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
        }
        else /* p0', q0' */
        {
            pix[-1*xstride] = ( 2*p1 + p0 + q1 + 2 ) >> 2;
            pix[ 0*xstride] = ( 2*q1 + q0 + p1 + 2 ) >> 2;
219 220 221
        }
    }
}
222
static inline void deblock_luma_intra_c( pixel *pix, intptr_t xstride, intptr_t ystride, int alpha, int beta )
223 224 225 226
{
    for( int d = 0; d < 16; d++, pix += ystride )
        deblock_edge_luma_intra_c( pix, xstride, alpha, beta );
}
227
static void deblock_h_luma_intra_mbaff_c( pixel *pix, intptr_t ystride, int alpha, int beta )
228 229 230 231
{
    for( int d = 0; d < 8; d++, pix += ystride )
        deblock_edge_luma_intra_c( pix, 1, alpha, beta );
}
232
static void deblock_v_luma_intra_c( pixel *pix, intptr_t stride, int alpha, int beta )
233 234 235
{
    deblock_luma_intra_c( pix, stride, 1, alpha, beta );
}
236
static void deblock_h_luma_intra_c( pixel *pix, intptr_t stride, int alpha, int beta )
237 238 239 240
{
    deblock_luma_intra_c( pix, 1, stride, alpha, beta );
}

241
static ALWAYS_INLINE void deblock_edge_chroma_intra_c( pixel *pix, intptr_t xstride, int alpha, int beta )
242 243 244 245 246 247 248 249 250 251 252 253
{
    int p1 = pix[-2*xstride];
    int p0 = pix[-1*xstride];
    int q0 = pix[ 0*xstride];
    int q1 = pix[ 1*xstride];

    if( abs( p0 - q0 ) < alpha && abs( p1 - p0 ) < beta && abs( q1 - q0 ) < beta )
    {
        pix[-1*xstride] = (2*p1 + p0 + q1 + 2) >> 2;   /* p0' */
        pix[ 0*xstride] = (2*q1 + q0 + p1 + 2) >> 2;   /* q0' */
    }
}
254
static ALWAYS_INLINE void deblock_chroma_intra_c( pixel *pix, int width, int height, intptr_t xstride, intptr_t ystride, int alpha, int beta )
255
{
Henrik Gramner's avatar
Henrik Gramner committed
256 257 258
    for( int d = 0; d < height; d++, pix += ystride-2 )
        for( int e = 0; e < width; e++, pix++ )
            deblock_edge_chroma_intra_c( pix, xstride, alpha, beta );
259
}
260
static void deblock_h_chroma_intra_mbaff_c( pixel *pix, intptr_t stride, int alpha, int beta )
261
{
262
    deblock_chroma_intra_c( pix, 2, 4, 2, stride, alpha, beta );
263
}
264
static void deblock_v_chroma_intra_c( pixel *pix, intptr_t stride, int alpha, int beta )
265
{
Henrik Gramner's avatar
Henrik Gramner committed
266
    deblock_chroma_intra_c( pix, 1, 16, stride, 2, alpha, beta );
267
}
268
static void deblock_h_chroma_intra_c( pixel *pix, intptr_t stride, int alpha, int beta )
269
{
Henrik Gramner's avatar
Henrik Gramner committed
270 271
    deblock_chroma_intra_c( pix, 2, 8, 2, stride, alpha, beta );
}
272
static void deblock_h_chroma_422_intra_c( pixel *pix, intptr_t stride, int alpha, int beta )
Henrik Gramner's avatar
Henrik Gramner committed
273 274
{
    deblock_chroma_intra_c( pix, 2, 16, 2, stride, alpha, beta );
275 276
}

Fiona Glaser's avatar
Fiona Glaser committed
277
static void deblock_strength_c( uint8_t nnz[X264_SCAN8_SIZE], int8_t ref[2][X264_SCAN8_LUMA_SIZE],
278
                                int16_t mv[2][X264_SCAN8_LUMA_SIZE][2], uint8_t bs[2][8][4], int mvy_limit,
279
                                int bframe )
280 281 282 283 284
{
    for( int dir = 0; dir < 2; dir++ )
    {
        int s1 = dir ? 1 : 8;
        int s2 = dir ? 8 : 1;
Fiona Glaser's avatar
Fiona Glaser committed
285
        for( int edge = 0; edge < 4; edge++ )
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
            for( int i = 0, loc = X264_SCAN8_0+edge*s2; i < 4; i++, loc += s1 )
            {
                int locn = loc - s2;
                if( nnz[loc] || nnz[locn] )
                    bs[dir][edge][i] = 2;
                else if( ref[0][loc] != ref[0][locn] ||
                         abs( mv[0][loc][0] - mv[0][locn][0] ) >= 4 ||
                         abs( mv[0][loc][1] - mv[0][locn][1] ) >= mvy_limit ||
                        (bframe && (ref[1][loc] != ref[1][locn] ||
                         abs( mv[1][loc][0] - mv[1][locn][0] ) >= 4 ||
                         abs( mv[1][loc][1] - mv[1][locn][1] ) >= mvy_limit )))
                {
                    bs[dir][edge][i] = 1;
                }
                else
                    bs[dir][edge][i] = 0;
            }
    }
}
305

306 307
static ALWAYS_INLINE void deblock_edge( x264_t *h, pixel *pix, intptr_t i_stride, uint8_t bS[4], int i_qp,
                                        int a, int b, int b_chroma, x264_deblock_inter_t pf_inter )
308
{
309 310
    int index_a = i_qp + a;
    int index_b = i_qp + b;
311 312
    int alpha = alpha_table(index_a) << (BIT_DEPTH-8);
    int beta  = beta_table(index_b) << (BIT_DEPTH-8);
313 314
    int8_t tc[4];

315
    if( !M32(bS) || !alpha || !beta )
316 317
        return;

318 319 320 321
    tc[0] = (tc0_table(index_a)[bS[0]] << (BIT_DEPTH-8)) + b_chroma;
    tc[1] = (tc0_table(index_a)[bS[1]] << (BIT_DEPTH-8)) + b_chroma;
    tc[2] = (tc0_table(index_a)[bS[2]] << (BIT_DEPTH-8)) + b_chroma;
    tc[3] = (tc0_table(index_a)[bS[3]] << (BIT_DEPTH-8)) + b_chroma;
322

323
    pf_inter( pix, i_stride, alpha, beta, tc );
324 325
}

326 327
static ALWAYS_INLINE void deblock_edge_intra( x264_t *h, pixel *pix, intptr_t i_stride, uint8_t bS[4], int i_qp,
                                              int a, int b, int b_chroma, x264_deblock_intra_t pf_intra )
328
{
329 330
    int index_a = i_qp + a;
    int index_b = i_qp + b;
331 332
    int alpha = alpha_table(index_a) << (BIT_DEPTH-8);
    int beta  = beta_table(index_b) << (BIT_DEPTH-8);
333 334 335 336

    if( !alpha || !beta )
        return;

337
    pf_intra( pix, i_stride, alpha, beta );
338 339
}

340
static ALWAYS_INLINE void macroblock_cache_load_neighbours_deblock( x264_t *h, int mb_x, int mb_y )
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
{
    int deblock_on_slice_edges = h->sh.i_disable_deblocking_filter_idc != 2;

    h->mb.i_neighbour = 0;
    h->mb.i_mb_xy = mb_y * h->mb.i_mb_stride + mb_x;
    h->mb.b_interlaced = PARAM_INTERLACED && h->mb.field[h->mb.i_mb_xy];
    h->mb.i_mb_top_y = mb_y - (1 << MB_INTERLACED);
    h->mb.i_mb_top_xy = mb_x + h->mb.i_mb_stride*h->mb.i_mb_top_y;
    h->mb.i_mb_left_xy[1] =
    h->mb.i_mb_left_xy[0] = h->mb.i_mb_xy - 1;
    if( SLICE_MBAFF )
    {
        if( mb_y&1 )
        {
            if( mb_x && h->mb.field[h->mb.i_mb_xy - 1] != MB_INTERLACED )
                h->mb.i_mb_left_xy[0] -= h->mb.i_mb_stride;
        }
        else
        {
            if( h->mb.i_mb_top_xy >= 0 && MB_INTERLACED && !h->mb.field[h->mb.i_mb_top_xy] )
            {
                h->mb.i_mb_top_xy += h->mb.i_mb_stride;
                h->mb.i_mb_top_y++;
            }
            if( mb_x && h->mb.field[h->mb.i_mb_xy - 1] != MB_INTERLACED )
                h->mb.i_mb_left_xy[1] += h->mb.i_mb_stride;
        }
    }

    if( mb_x > 0 && (deblock_on_slice_edges ||
        h->mb.slice_table[h->mb.i_mb_left_xy[0]] == h->mb.slice_table[h->mb.i_mb_xy]) )
        h->mb.i_neighbour |= MB_LEFT;
    if( mb_y > MB_INTERLACED && (deblock_on_slice_edges
        || h->mb.slice_table[h->mb.i_mb_top_xy] == h->mb.slice_table[h->mb.i_mb_xy]) )
        h->mb.i_neighbour |= MB_TOP;
}

378 379
void x264_frame_deblock_row( x264_t *h, int mb_y )
{
380
    int b_interlaced = SLICE_MBAFF;
381 382 383
    int a = h->sh.i_alpha_c0_offset - QP_BD_OFFSET;
    int b = h->sh.i_beta_offset - QP_BD_OFFSET;
    int qp_thresh = 15 - X264_MIN( a, b ) - X264_MAX( 0, h->pps->i_chroma_qp_index_offset );
384 385
    int stridey   = h->fdec->i_stride[0];
    int strideuv  = h->fdec->i_stride[1];
386
    int chroma_format = CHROMA_FORMAT;
387
    int chroma444 = CHROMA444;
388
    int chroma_height = 16 >> CHROMA_V_SHIFT;
389
    intptr_t uvdiff = chroma444 ? h->fdec->plane[2] - h->fdec->plane[1] : 1;
390

391
    for( int mb_x = 0; mb_x < h->mb.i_mb_width; mb_x += (~b_interlaced | mb_y)&1, mb_y ^= b_interlaced )
392
    {
393
        x264_prefetch_fenc( h, h->fdec, mb_x, mb_y );
394
        macroblock_cache_load_neighbours_deblock( h, mb_x, mb_y );
395 396

        int mb_xy = h->mb.i_mb_xy;
397
        int transform_8x8 = h->mb.mb_transform_size[mb_xy];
398
        int intra_cur = IS_INTRA( h->mb.type[mb_xy] );
399
        uint8_t (*bs)[8][4] = h->deblock_strength[mb_y&1][h->param.b_sliced_threads?mb_xy:mb_x];
400

401
        pixel *pixy = h->fdec->plane[0] + 16*mb_y*stridey  + 16*mb_x;
Henrik Gramner's avatar
Henrik Gramner committed
402
        pixel *pixuv = h->fdec->plane[1] + chroma_height*mb_y*strideuv + 16*mb_x;
403

404
        if( mb_y & MB_INTERLACED )
405 406
        {
            pixy -= 15*stridey;
Henrik Gramner's avatar
Henrik Gramner committed
407
            pixuv -= (chroma_height-1)*strideuv;
408 409
        }

410 411
        int stride2y  = stridey << MB_INTERLACED;
        int stride2uv = strideuv << MB_INTERLACED;
412 413
        int qp = h->mb.qp[mb_xy];
        int qpc = h->chroma_qp_table[qp];
414
        int first_edge_only = (h->mb.partition[mb_xy] == D_16x16 && !h->mb.cbp[mb_xy] && !intra_cur) || qp <= qp_thresh;
415

416 417
        #define FILTER( intra, dir, edge, qp, chroma_qp )\
        do\
418
        {\
Henrik Gramner's avatar
Henrik Gramner committed
419
            if( !(edge & 1) || !transform_8x8 )\
Fiona Glaser's avatar
Fiona Glaser committed
420
            {\
Henrik Gramner's avatar
Henrik Gramner committed
421 422
                deblock_edge##intra( h, pixy + 4*edge*(dir?stride2y:1),\
                                     stride2y, bs[dir][edge], qp, a, b, 0,\
Fiona Glaser's avatar
Fiona Glaser committed
423
                                     h->loopf.deblock_luma##intra[dir] );\
424
                if( chroma_format == CHROMA_444 )\
Henrik Gramner's avatar
Henrik Gramner committed
425 426 427 428 429 430 431 432
                {\
                    deblock_edge##intra( h, pixuv          + 4*edge*(dir?stride2uv:1),\
                                         stride2uv, bs[dir][edge], chroma_qp, a, b, 0,\
                                         h->loopf.deblock_luma##intra[dir] );\
                    deblock_edge##intra( h, pixuv + uvdiff + 4*edge*(dir?stride2uv:1),\
                                         stride2uv, bs[dir][edge], chroma_qp, a, b, 0,\
                                         h->loopf.deblock_luma##intra[dir] );\
                }\
433
                else if( chroma_format == CHROMA_420 && !(edge & 1) )\
Henrik Gramner's avatar
Henrik Gramner committed
434 435 436 437 438
                {\
                    deblock_edge##intra( h, pixuv + edge*(dir?2*stride2uv:4),\
                                         stride2uv, bs[dir][edge], chroma_qp, a, b, 1,\
                                         h->loopf.deblock_chroma##intra[dir] );\
                }\
Fiona Glaser's avatar
Fiona Glaser committed
439
            }\
440
            if( chroma_format == CHROMA_422 && (dir || !(edge & 1)) )\
Henrik Gramner's avatar
Henrik Gramner committed
441 442
            {\
                deblock_edge##intra( h, pixuv + edge*(dir?4*stride2uv:4),\
443
                                     stride2uv, bs[dir][edge], chroma_qp, a, b, 1,\
444
                                     h->loopf.deblock_chroma##intra[dir] );\
Henrik Gramner's avatar
Henrik Gramner committed
445
            }\
Anton Mitrofanov's avatar
Anton Mitrofanov committed
446
        } while( 0 )
447 448 449

        if( h->mb.i_neighbour & MB_LEFT )
        {
450
            if( b_interlaced && h->mb.field[h->mb.i_mb_left_xy[0]] != MB_INTERLACED )
451 452 453 454
            {
                int luma_qp[2];
                int chroma_qp[2];
                int left_qp[2];
455
                x264_deblock_inter_t luma_deblock = h->loopf.deblock_luma_mbaff;
Henrik Gramner's avatar
Henrik Gramner committed
456
                x264_deblock_inter_t chroma_deblock = h->loopf.deblock_chroma_mbaff;
457
                x264_deblock_intra_t luma_intra_deblock = h->loopf.deblock_luma_intra_mbaff;
Henrik Gramner's avatar
Henrik Gramner committed
458
                x264_deblock_intra_t chroma_intra_deblock = h->loopf.deblock_chroma_intra_mbaff;
459
                int c = chroma444 ? 0 : 1;
Fiona Glaser's avatar
Fiona Glaser committed
460

461
                left_qp[0] = h->mb.qp[h->mb.i_mb_left_xy[0]];
462 463
                luma_qp[0] = (qp + left_qp[0] + 1) >> 1;
                chroma_qp[0] = (qpc + h->chroma_qp_table[left_qp[0]] + 1) >> 1;
464
                if( intra_cur || IS_INTRA( h->mb.type[h->mb.i_mb_left_xy[0]] ) )
465
                {
466
                    deblock_edge_intra( h, pixy,           2*stridey,  bs[0][0], luma_qp[0],   a, b, 0, luma_intra_deblock );
467 468 469 470 471 472
                    if( chroma_format )
                    {
                        deblock_edge_intra( h, pixuv,          2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_intra_deblock );
                        if( chroma444 )
                            deblock_edge_intra( h, pixuv + uvdiff, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_intra_deblock );
                    }
473 474 475
                }
                else
                {
476
                    deblock_edge( h, pixy,           2*stridey,  bs[0][0], luma_qp[0],   a, b, 0, luma_deblock );
477 478 479 480 481 482
                    if( chroma_format )
                    {
                        deblock_edge( h, pixuv,          2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_deblock );
                        if( chroma444 )
                            deblock_edge( h, pixuv + uvdiff, 2*strideuv, bs[0][0], chroma_qp[0], a, b, c, chroma_deblock );
                    }
483 484
                }

485
                int offy = MB_INTERLACED ? 4 : 0;
486
                int offuv = MB_INTERLACED ? 4-CHROMA_V_SHIFT : 0;
487
                left_qp[1] = h->mb.qp[h->mb.i_mb_left_xy[1]];
488 489
                luma_qp[1] = (qp + left_qp[1] + 1) >> 1;
                chroma_qp[1] = (qpc + h->chroma_qp_table[left_qp[1]] + 1) >> 1;
490
                if( intra_cur || IS_INTRA( h->mb.type[h->mb.i_mb_left_xy[1]] ) )
491
                {
492
                    deblock_edge_intra( h, pixy           + (stridey<<offy),   2*stridey,  bs[0][4], luma_qp[1],   a, b, 0, luma_intra_deblock );
493 494 495 496 497 498
                    if( chroma_format )
                    {
                        deblock_edge_intra( h, pixuv          + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_intra_deblock );
                        if( chroma444 )
                            deblock_edge_intra( h, pixuv + uvdiff + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_intra_deblock );
                    }
499 500 501
                }
                else
                {
502
                    deblock_edge( h, pixy           + (stridey<<offy),   2*stridey,  bs[0][4], luma_qp[1],   a, b, 0, luma_deblock );
503 504 505 506 507 508
                    if( chroma_format )
                    {
                        deblock_edge( h, pixuv          + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_deblock );
                        if( chroma444 )
                            deblock_edge( h, pixuv + uvdiff + (strideuv<<offuv), 2*strideuv, bs[0][4], chroma_qp[1], a, b, c, chroma_deblock );
                    }
509 510
                }
            }
511
            else
512 513 514
            {
                int qpl = h->mb.qp[h->mb.i_mb_xy-1];
                int qp_left = (qp + qpl + 1) >> 1;
515
                int qpc_left = (qpc + h->chroma_qp_table[qpl] + 1) >> 1;
516
                int intra_left = IS_INTRA( h->mb.type[h->mb.i_mb_xy-1] );
517
                int intra_deblock = intra_cur || intra_left;
518

519 520 521
                /* Any MB that was coded, or that analysis decided to skip, has quality commensurate with its QP.
                 * But if deblocking affects neighboring MBs that were force-skipped, blur might accumulate there.
                 * So reset their effective QP to max, to indicate that lack of guarantee. */
522
                if( h->fdec->mb_info && M32( bs[0][0] ) )
523
                {
524
#define RESET_EFFECTIVE_QP(xy) h->fdec->effective_qp[xy] |= 0xff * !!(h->fdec->mb_info[xy] & X264_MBINFO_CONSTANT);
525 526 527 528 529
                    RESET_EFFECTIVE_QP(mb_xy);
                    RESET_EFFECTIVE_QP(h->mb.i_mb_left_xy[0]);
                }

                if( intra_deblock )
530 531 532 533 534
                    FILTER( _intra, 0, 0, qp_left, qpc_left );
                else
                    FILTER(       , 0, 0, qp_left, qpc_left );
            }
        }
535 536
        if( !first_edge_only )
        {
Henrik Gramner's avatar
Henrik Gramner committed
537 538 539
            FILTER( , 0, 1, qp, qpc );
            FILTER( , 0, 2, qp, qpc );
            FILTER( , 0, 3, qp, qpc );
540 541
        }

542 543
        if( h->mb.i_neighbour & MB_TOP )
        {
544
            if( b_interlaced && !(mb_y&1) && !MB_INTERLACED && h->mb.field[h->mb.i_mb_top_xy] )
545 546 547
            {
                int mbn_xy = mb_xy - 2 * h->mb.i_mb_stride;

548
                for( int j = 0; j < 2; j++, mbn_xy += h->mb.i_mb_stride )
549 550 551
                {
                    int qpt = h->mb.qp[mbn_xy];
                    int qp_top = (qp + qpt + 1) >> 1;
552
                    int qpc_top = (qpc + h->chroma_qp_table[qpt] + 1) >> 1;
553 554 555
                    int intra_top = IS_INTRA( h->mb.type[mbn_xy] );
                    if( intra_cur || intra_top )
                        M32( bs[1][4*j] ) = 0x03030303;
556 557

                    // deblock the first horizontal edge of the even rows, then the first horizontal edge of the odd rows
558
                    deblock_edge( h, pixy      + j*stridey,  2* stridey, bs[1][4*j], qp_top, a, b, 0, h->loopf.deblock_luma[1] );
559
                    if( chroma444 )
Fiona Glaser's avatar
Fiona Glaser committed
560
                    {
561 562
                        deblock_edge( h, pixuv          + j*strideuv, 2*strideuv, bs[1][4*j], qpc_top, a, b, 0, h->loopf.deblock_luma[1] );
                        deblock_edge( h, pixuv + uvdiff + j*strideuv, 2*strideuv, bs[1][4*j], qpc_top, a, b, 0, h->loopf.deblock_luma[1] );
Fiona Glaser's avatar
Fiona Glaser committed
563
                    }
564
                    else if( chroma_format )
565
                        deblock_edge( h, pixuv          + j*strideuv, 2*strideuv, bs[1][4*j], qpc_top, a, b, 1, h->loopf.deblock_chroma[1] );
566 567
                }
            }
568 569
            else
            {
570 571
                int qpt = h->mb.qp[h->mb.i_mb_top_xy];
                int qp_top = (qp + qpt + 1) >> 1;
572
                int qpc_top = (qpc + h->chroma_qp_table[qpt] + 1) >> 1;
573
                int intra_top = IS_INTRA( h->mb.type[h->mb.i_mb_top_xy] );
574
                int intra_deblock = intra_cur || intra_top;
575

576
                /* This edge has been modified, reset effective qp to max. */
577
                if( h->fdec->mb_info && M32( bs[1][0] ) )
578 579 580 581 582 583
                {
                    RESET_EFFECTIVE_QP(mb_xy);
                    RESET_EFFECTIVE_QP(h->mb.i_mb_top_xy);
                }

                if( (!b_interlaced || (!MB_INTERLACED && !h->mb.field[h->mb.i_mb_top_xy])) && intra_deblock )
584 585 586 587 588
                {
                    FILTER( _intra, 1, 0, qp_top, qpc_top );
                }
                else
                {
589
                    if( intra_deblock )
590 591 592
                        M32( bs[1][0] ) = 0x03030303;
                    FILTER(       , 1, 0, qp_top, qpc_top );
                }
593
            }
594 595
        }

596 597
        if( !first_edge_only )
        {
Henrik Gramner's avatar
Henrik Gramner committed
598 599 600
            FILTER( , 1, 1, qp, qpc );
            FILTER( , 1, 2, qp, qpc );
            FILTER( , 1, 3, qp, qpc );
601
        }
Fiona Glaser's avatar
Fiona Glaser committed
602 603

        #undef FILTER
604 605 606
    }
}

Fiona Glaser's avatar
Fiona Glaser committed
607 608 609 610
/* For deblock-aware RD.
 * TODO:
 *  deblock macroblock edges
 *  support analysis partitions smaller than 16x16
Henrik Gramner's avatar
Henrik Gramner committed
611
 *  deblock chroma for 4:2:0/4:2:2
Fiona Glaser's avatar
Fiona Glaser committed
612 613 614 615
 *  handle duplicate refs correctly
 */
void x264_macroblock_deblock( x264_t *h )
{
616 617 618 619
    int a = h->sh.i_alpha_c0_offset - QP_BD_OFFSET;
    int b = h->sh.i_beta_offset - QP_BD_OFFSET;
    int qp_thresh = 15 - X264_MIN( a, b ) - X264_MAX( 0, h->pps->i_chroma_qp_index_offset );
    int intra_cur = IS_INTRA( h->mb.i_type );
Fiona Glaser's avatar
Fiona Glaser committed
620
    int qp = h->mb.i_qp;
Fiona Glaser's avatar
Fiona Glaser committed
621
    int qpc = h->mb.i_chroma_qp;
622
    if( (h->mb.i_partition == D_16x16 && !h->mb.i_cbp_luma && !intra_cur) || qp <= qp_thresh )
Fiona Glaser's avatar
Fiona Glaser committed
623 624
        return;

625
    uint8_t (*bs)[8][4] = h->mb.cache.deblock_strength;
626 627
    if( intra_cur )
    {
628 629 630 631
        M32( bs[0][1] ) = 0x03030303;
        M64( bs[0][2] ) = 0x0303030303030303ULL;
        M32( bs[1][1] ) = 0x03030303;
        M64( bs[1][2] ) = 0x0303030303030303ULL;
632
    }
Fiona Glaser's avatar
Fiona Glaser committed
633 634
    else
        h->loopf.deblock_strength( h->mb.cache.non_zero_count, h->mb.cache.ref, h->mb.cache.mv,
635
                                   bs, 4 >> MB_INTERLACED, h->sh.i_type == SLICE_TYPE_B );
Fiona Glaser's avatar
Fiona Glaser committed
636 637 638 639 640 641

    int transform_8x8 = h->mb.b_transform_8x8;

    #define FILTER( dir, edge )\
    do\
    {\
Fiona Glaser's avatar
Fiona Glaser committed
642
        deblock_edge( h, h->mb.pic.p_fdec[0] + 4*edge*(dir?FDEC_STRIDE:1),\
643
                      FDEC_STRIDE, bs[dir][edge], qp, a, b, 0,\
Fiona Glaser's avatar
Fiona Glaser committed
644
                      h->loopf.deblock_luma[dir] );\
Fiona Glaser's avatar
Fiona Glaser committed
645 646 647
        if( CHROMA444 )\
        {\
            deblock_edge( h, h->mb.pic.p_fdec[1] + 4*edge*(dir?FDEC_STRIDE:1),\
648
                          FDEC_STRIDE, bs[dir][edge], qpc, a, b, 0,\
Fiona Glaser's avatar
Fiona Glaser committed
649 650
                          h->loopf.deblock_luma[dir] );\
            deblock_edge( h, h->mb.pic.p_fdec[2] + 4*edge*(dir?FDEC_STRIDE:1),\
651
                          FDEC_STRIDE, bs[dir][edge], qpc, a, b, 0,\
Fiona Glaser's avatar
Fiona Glaser committed
652 653
                          h->loopf.deblock_luma[dir] );\
        }\
Anton Mitrofanov's avatar
Anton Mitrofanov committed
654
    } while( 0 )
Fiona Glaser's avatar
Fiona Glaser committed
655 656 657 658 659 660 661 662 663 664 665 666

    if( !transform_8x8 ) FILTER( 0, 1 );
                         FILTER( 0, 2 );
    if( !transform_8x8 ) FILTER( 0, 3 );

    if( !transform_8x8 ) FILTER( 1, 1 );
                         FILTER( 1, 2 );
    if( !transform_8x8 ) FILTER( 1, 3 );

    #undef FILTER
}

Steven Walters's avatar
Steven Walters committed
667
#if HAVE_MMX
668
#include "x86/deblock.h"
669
#endif
Steven Walters's avatar
Steven Walters committed
670
#if ARCH_PPC
671
#include "ppc/deblock.h"
672
#endif
673 674
#if HAVE_ARMV6
#include "arm/deblock.h"
675
#endif
676 677 678 679 680
#if ARCH_AARCH64
#include "aarch64/deblock.h"
#endif
#if HAVE_MSA
#include "mips/deblock.h"
681 682
#endif

683
void x264_deblock_init( int cpu, x264_deblock_function_t *pf, int b_mbaff )
684
{
685 686 687
    pf->deblock_luma[1] = deblock_v_luma_c;
    pf->deblock_luma[0] = deblock_h_luma_c;
    pf->deblock_chroma[1] = deblock_v_chroma_c;
Henrik Gramner's avatar
Henrik Gramner committed
688 689
    pf->deblock_h_chroma_420 = deblock_h_chroma_c;
    pf->deblock_h_chroma_422 = deblock_h_chroma_422_c;
690 691 692
    pf->deblock_luma_intra[1] = deblock_v_luma_intra_c;
    pf->deblock_luma_intra[0] = deblock_h_luma_intra_c;
    pf->deblock_chroma_intra[1] = deblock_v_chroma_intra_c;
Henrik Gramner's avatar
Henrik Gramner committed
693 694 695 696 697 698
    pf->deblock_h_chroma_420_intra = deblock_h_chroma_intra_c;
    pf->deblock_h_chroma_422_intra = deblock_h_chroma_422_intra_c;
    pf->deblock_luma_mbaff = deblock_h_luma_mbaff_c;
    pf->deblock_chroma_420_mbaff = deblock_h_chroma_mbaff_c;
    pf->deblock_luma_intra_mbaff = deblock_h_luma_intra_mbaff_c;
    pf->deblock_chroma_420_intra_mbaff = deblock_h_chroma_intra_mbaff_c;
699
    pf->deblock_strength = deblock_strength_c;
700

Steven Walters's avatar
Steven Walters committed
701
#if HAVE_MMX
702
    if( cpu&X264_CPU_MMX2 )
703
    {
Steven Walters's avatar
Steven Walters committed
704
#if ARCH_X86
705 706 707
        pf->deblock_luma[1] = x264_deblock_v_luma_mmx2;
        pf->deblock_luma[0] = x264_deblock_h_luma_mmx2;
        pf->deblock_chroma[1] = x264_deblock_v_chroma_mmx2;
Henrik Gramner's avatar
Henrik Gramner committed
708
        pf->deblock_h_chroma_420 = x264_deblock_h_chroma_mmx2;
709
        pf->deblock_chroma_420_mbaff = x264_deblock_h_chroma_mbaff_mmx2;
Fiona Glaser's avatar
Fiona Glaser committed
710
        pf->deblock_h_chroma_422 = x264_deblock_h_chroma_422_mmx2;
Ilia's avatar
Ilia committed
711
        pf->deblock_h_chroma_422_intra = x264_deblock_h_chroma_422_intra_mmx2;
712 713 714
        pf->deblock_luma_intra[1] = x264_deblock_v_luma_intra_mmx2;
        pf->deblock_luma_intra[0] = x264_deblock_h_luma_intra_mmx2;
        pf->deblock_chroma_intra[1] = x264_deblock_v_chroma_intra_mmx2;
Henrik Gramner's avatar
Henrik Gramner committed
715
        pf->deblock_h_chroma_420_intra = x264_deblock_h_chroma_intra_mmx2;
716 717 718 719
        pf->deblock_chroma_420_intra_mbaff = x264_deblock_h_chroma_intra_mbaff_mmx2;
#endif
#if !HIGH_BIT_DEPTH
        pf->deblock_chroma_420_intra_mbaff = x264_deblock_h_chroma_intra_mbaff_mmx2;
720
#endif
721
        if( cpu&X264_CPU_SSE2 )
722
        {
723
            pf->deblock_strength = x264_deblock_strength_sse2;
Fiona Glaser's avatar
Fiona Glaser committed
724 725
            pf->deblock_h_chroma_420 = x264_deblock_h_chroma_sse2;
            pf->deblock_h_chroma_422 = x264_deblock_h_chroma_422_sse2;
Ilia's avatar
Ilia committed
726
            pf->deblock_h_chroma_422_intra = x264_deblock_h_chroma_422_intra_sse2;
727
            pf->deblock_chroma_420_mbaff = x264_deblock_h_chroma_mbaff_sse2;
728 729 730 731
            pf->deblock_luma[1] = x264_deblock_v_luma_sse2;
            pf->deblock_luma[0] = x264_deblock_h_luma_sse2;
            pf->deblock_luma_intra[1] = x264_deblock_v_luma_intra_sse2;
            pf->deblock_luma_intra[0] = x264_deblock_h_luma_intra_sse2;
732 733
            if( !(cpu&X264_CPU_STACK_MOD4) )
            {
734 735
                pf->deblock_chroma[1] = x264_deblock_v_chroma_sse2;
                pf->deblock_chroma_intra[1] = x264_deblock_v_chroma_intra_sse2;
Henrik Gramner's avatar
Henrik Gramner committed
736
                pf->deblock_h_chroma_420_intra = x264_deblock_h_chroma_intra_sse2;
737 738 739
#if HIGH_BIT_DEPTH
                pf->deblock_chroma_420_intra_mbaff= x264_deblock_h_chroma_intra_mbaff_sse2;
#endif
740
            }
741
        }
742 743
        if( cpu&X264_CPU_SSSE3 )
            pf->deblock_strength = x264_deblock_strength_ssse3;
744 745 746
        if( cpu&X264_CPU_AVX )
        {
            pf->deblock_strength = x264_deblock_strength_avx;
Fiona Glaser's avatar
Fiona Glaser committed
747 748
            pf->deblock_h_chroma_420 = x264_deblock_h_chroma_avx;
            pf->deblock_h_chroma_422 = x264_deblock_h_chroma_422_avx;
749
            pf->deblock_h_chroma_422_intra = x264_deblock_h_chroma_422_intra_avx;
750 751 752 753
            pf->deblock_luma[1] = x264_deblock_v_luma_avx;
            pf->deblock_luma[0] = x264_deblock_h_luma_avx;
            pf->deblock_luma_intra[1] = x264_deblock_v_luma_intra_avx;
            pf->deblock_luma_intra[0] = x264_deblock_h_luma_intra_avx;
754 755 756 757
            if( !(cpu&X264_CPU_STACK_MOD4) )
            {
                pf->deblock_chroma[1] = x264_deblock_v_chroma_avx;
                pf->deblock_chroma_intra[1] = x264_deblock_v_chroma_intra_avx;
Henrik Gramner's avatar
Henrik Gramner committed
758
                pf->deblock_h_chroma_420_intra = x264_deblock_h_chroma_intra_avx;
759 760 761 762
#if HIGH_BIT_DEPTH
                pf->deblock_chroma_420_mbaff = x264_deblock_h_chroma_mbaff_avx;
                pf->deblock_chroma_420_intra_mbaff = x264_deblock_h_chroma_intra_mbaff_avx;
#endif
763 764
            }
        }
765 766 767 768
        if( cpu&X264_CPU_AVX2 )
        {
            pf->deblock_strength = x264_deblock_strength_avx2;
        }
769 770 771 772
        if( cpu&X264_CPU_AVX512 )
        {
            pf->deblock_strength = x264_deblock_strength_avx512;
        }
773 774 775
    }
#endif

776
#if !HIGH_BIT_DEPTH
Steven Walters's avatar
Steven Walters committed
777
#if HAVE_ALTIVEC
778 779
    if( cpu&X264_CPU_ALTIVEC )
    {
780 781
        pf->deblock_luma[1] = x264_deblock_v_luma_altivec;
        pf->deblock_luma[0] = x264_deblock_h_luma_altivec;
782
    }
783 784
#endif // HAVE_ALTIVEC

785
#if HAVE_ARMV6 || ARCH_AARCH64
786 787
    if( cpu&X264_CPU_NEON )
    {
788 789
        pf->deblock_luma[1] = x264_deblock_v_luma_neon;
        pf->deblock_luma[0] = x264_deblock_h_luma_neon;
790 791
        pf->deblock_chroma[1] = x264_deblock_v_chroma_neon;
        pf->deblock_h_chroma_420 = x264_deblock_h_chroma_neon;
792
        pf->deblock_h_chroma_422 = x264_deblock_h_chroma_422_neon;
793
        pf->deblock_chroma_420_mbaff = x264_deblock_h_chroma_mbaff_neon;
794 795 796 797
        pf->deblock_chroma_420_intra_mbaff = x264_deblock_h_chroma_intra_mbaff_neon;
        pf->deblock_h_chroma_420_intra = x264_deblock_h_chroma_intra_neon;
        pf->deblock_h_chroma_422_intra = x264_deblock_h_chroma_422_intra_neon;
        pf->deblock_chroma_intra[1] = x264_deblock_v_chroma_intra_neon;
798 799
        pf->deblock_luma_intra[0] = x264_deblock_h_luma_intra_neon;
        pf->deblock_luma_intra[1] = x264_deblock_v_luma_intra_neon;
800
        pf->deblock_strength     = x264_deblock_strength_neon;
801
    }
802
#endif
803 804 805 806 807 808 809 810 811 812 813 814 815 816 817

#if HAVE_MSA
    if( cpu&X264_CPU_MSA )
    {
        pf->deblock_luma[1] = x264_deblock_v_luma_msa;
        pf->deblock_luma[0] = x264_deblock_h_luma_msa;
        pf->deblock_chroma[1] = x264_deblock_v_chroma_msa;
        pf->deblock_h_chroma_420 = x264_deblock_h_chroma_msa;
        pf->deblock_luma_intra[1] = x264_deblock_v_luma_intra_msa;
        pf->deblock_luma_intra[0] = x264_deblock_h_luma_intra_msa;
        pf->deblock_chroma_intra[1] = x264_deblock_v_chroma_intra_msa;
        pf->deblock_h_chroma_420_intra = x264_deblock_h_chroma_intra_msa;
        pf->deblock_strength = x264_deblock_strength_msa;
    }
#endif
818
#endif // !HIGH_BIT_DEPTH
819 820 821 822

    /* These functions are equivalent, so don't duplicate them. */
    pf->deblock_chroma_422_mbaff = pf->deblock_h_chroma_420;
    pf->deblock_chroma_422_intra_mbaff = pf->deblock_h_chroma_420_intra;
823
}