Coverage Report

Created: 2026-04-01 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/x264/common/mc.c
Line
Count
Source
1
/*****************************************************************************
2
 * mc.c: motion compensation
3
 *****************************************************************************
4
 * Copyright (C) 2003-2025 x264 project
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Loren Merritt <lorenm@u.washington.edu>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
22
 *
23
 * This program is also available under a commercial proprietary license.
24
 * For more information, contact us at licensing@x264.com.
25
 *****************************************************************************/
26
27
#include "common.h"
28
29
#if HAVE_MMX
30
#include "x86/mc.h"
31
#endif
32
#if HAVE_ALTIVEC
33
#include "ppc/mc.h"
34
#endif
35
#if HAVE_ARMV6
36
#include "arm/mc.h"
37
#endif
38
#if HAVE_AARCH64
39
#include "aarch64/mc.h"
40
#endif
41
#if HAVE_MSA
42
#include "mips/mc.h"
43
#endif
44
#if HAVE_LSX
45
#   include "loongarch/mc.h"
46
#endif
47
48
49
static inline void pixel_avg( pixel *dst,  intptr_t i_dst_stride,
50
                              pixel *src1, intptr_t i_src1_stride,
51
                              pixel *src2, intptr_t i_src2_stride, int i_width, int i_height )
52
0
{
53
0
    for( int y = 0; y < i_height; y++ )
54
0
    {
55
0
        for( int x = 0; x < i_width; x++ )
56
0
            dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;
57
0
        dst  += i_dst_stride;
58
0
        src1 += i_src1_stride;
59
0
        src2 += i_src2_stride;
60
0
    }
61
0
}
62
63
static inline void pixel_avg_wxh( pixel *dst,  intptr_t i_dst,
64
                                  pixel *src1, intptr_t i_src1,
65
                                  pixel *src2, intptr_t i_src2, int width, int height )
66
0
{
67
0
    for( int y = 0; y < height; y++ )
68
0
    {
69
0
        for( int x = 0; x < width; x++ )
70
0
            dst[x] = ( src1[x] + src2[x] + 1 ) >> 1;
71
0
        src1 += i_src1;
72
0
        src2 += i_src2;
73
0
        dst += i_dst;
74
0
    }
75
0
}
76
77
/* Implicit weighted bipred only:
78
 * assumes log2_denom = 5, offset = 0, weight1 + weight2 = 64 */
79
static inline void pixel_avg_weight_wxh( pixel *dst,  intptr_t i_dst,
80
                                         pixel *src1, intptr_t i_src1,
81
                                         pixel *src2, intptr_t i_src2, int width, int height, int i_weight1 )
82
0
{
83
0
    int i_weight2 = 64 - i_weight1;
84
0
    for( int y = 0; y<height; y++, dst += i_dst, src1 += i_src1, src2 += i_src2 )
85
0
        for( int x = 0; x<width; x++ )
86
0
            dst[x] = x264_clip_pixel( (src1[x]*i_weight1 + src2[x]*i_weight2 + (1<<5)) >> 6 );
87
0
}
88
#undef op_scale2
89
90
#define PIXEL_AVG_C( name, width, height ) \
91
static void name( pixel *pix1, intptr_t i_stride_pix1, \
92
                  pixel *pix2, intptr_t i_stride_pix2, \
93
0
                  pixel *pix3, intptr_t i_stride_pix3, int weight ) \
94
0
{ \
95
0
    if( weight == 32 ) \
96
0
        pixel_avg_wxh( pix1, i_stride_pix1, pix2, i_stride_pix2, pix3, i_stride_pix3, width, height ); \
97
0
    else \
98
0
        pixel_avg_weight_wxh( pix1, i_stride_pix1, pix2, i_stride_pix2, pix3, i_stride_pix3, width, height, weight ); \
99
0
}
Unexecuted instantiation: mc.c:pixel_avg_16x16
Unexecuted instantiation: mc.c:pixel_avg_16x8
Unexecuted instantiation: mc.c:pixel_avg_8x16
Unexecuted instantiation: mc.c:pixel_avg_8x8
Unexecuted instantiation: mc.c:pixel_avg_8x4
Unexecuted instantiation: mc.c:pixel_avg_4x16
Unexecuted instantiation: mc.c:pixel_avg_4x8
Unexecuted instantiation: mc.c:pixel_avg_4x4
Unexecuted instantiation: mc.c:pixel_avg_4x2
Unexecuted instantiation: mc.c:pixel_avg_2x8
Unexecuted instantiation: mc.c:pixel_avg_2x4
Unexecuted instantiation: mc.c:pixel_avg_2x2
100
PIXEL_AVG_C( pixel_avg_16x16, 16, 16 )
101
PIXEL_AVG_C( pixel_avg_16x8,  16, 8 )
102
PIXEL_AVG_C( pixel_avg_8x16,  8, 16 )
103
PIXEL_AVG_C( pixel_avg_8x8,   8, 8 )
104
PIXEL_AVG_C( pixel_avg_8x4,   8, 4 )
105
PIXEL_AVG_C( pixel_avg_4x16,  4, 16 )
106
PIXEL_AVG_C( pixel_avg_4x8,   4, 8 )
107
PIXEL_AVG_C( pixel_avg_4x4,   4, 4 )
108
PIXEL_AVG_C( pixel_avg_4x2,   4, 2 )
109
PIXEL_AVG_C( pixel_avg_2x8,   2, 8 )
110
PIXEL_AVG_C( pixel_avg_2x4,   2, 4 )
111
PIXEL_AVG_C( pixel_avg_2x2,   2, 2 )
112
113
static void weight_cache( x264_t *h, x264_weight_t *w )
114
0
{
115
0
    w->weightfn = h->mc.weight;
116
0
}
117
0
#define opscale(x) dst[x] = x264_clip_pixel( ((src[x] * scale + (1<<(denom - 1))) >> denom) + offset )
118
0
#define opscale_noden(x) dst[x] = x264_clip_pixel( src[x] * scale + offset )
119
static void mc_weight( pixel *dst, intptr_t i_dst_stride, pixel *src, intptr_t i_src_stride,
120
                       const x264_weight_t *weight, int i_width, int i_height )
121
0
{
122
0
    int offset = weight->i_offset * (1 << (BIT_DEPTH-8));
123
0
    int scale = weight->i_scale;
124
0
    int denom = weight->i_denom;
125
0
    if( denom >= 1 )
126
0
    {
127
0
        for( int y = 0; y < i_height; y++, dst += i_dst_stride, src += i_src_stride )
128
0
            for( int x = 0; x < i_width; x++ )
129
0
                opscale( x );
130
0
    }
131
0
    else
132
0
    {
133
0
        for( int y = 0; y < i_height; y++, dst += i_dst_stride, src += i_src_stride )
134
0
            for( int x = 0; x < i_width; x++ )
135
0
                opscale_noden( x );
136
0
    }
137
0
}
138
139
#define MC_WEIGHT_C( name, width ) \
140
0
static void name( pixel *dst, intptr_t i_dst_stride, pixel *src, intptr_t i_src_stride, const x264_weight_t *weight, int height ) \
141
0
{ \
142
0
    mc_weight( dst, i_dst_stride, src, i_src_stride, weight, width, height );\
143
0
}
Unexecuted instantiation: mc.c:mc_weight_w2
Unexecuted instantiation: mc.c:mc_weight_w4
Unexecuted instantiation: mc.c:mc_weight_w8
Unexecuted instantiation: mc.c:mc_weight_w12
Unexecuted instantiation: mc.c:mc_weight_w16
Unexecuted instantiation: mc.c:mc_weight_w20
144
145
MC_WEIGHT_C( mc_weight_w20, 20 )
146
MC_WEIGHT_C( mc_weight_w16, 16 )
147
MC_WEIGHT_C( mc_weight_w12, 12 )
148
MC_WEIGHT_C( mc_weight_w8,   8 )
149
MC_WEIGHT_C( mc_weight_w4,   4 )
150
MC_WEIGHT_C( mc_weight_w2,   2 )
151
152
static weight_fn_t mc_weight_wtab[6] =
153
{
154
    mc_weight_w2,
155
    mc_weight_w4,
156
    mc_weight_w8,
157
    mc_weight_w12,
158
    mc_weight_w16,
159
    mc_weight_w20,
160
};
161
162
static void mc_copy( pixel *src, intptr_t i_src_stride, pixel *dst, intptr_t i_dst_stride, int i_width, int i_height )
163
0
{
164
0
    for( int y = 0; y < i_height; y++ )
165
0
    {
166
0
        memcpy( dst, src, i_width * SIZEOF_PIXEL );
167
168
0
        src += i_src_stride;
169
0
        dst += i_dst_stride;
170
0
    }
171
0
}
172
173
0
#define TAPFILTER(pix, d) ((pix)[x-2*d] + (pix)[x+3*d] - 5*((pix)[x-d] + (pix)[x+2*d]) + 20*((pix)[x] + (pix)[x+d]))
174
static void hpel_filter( pixel *dsth, pixel *dstv, pixel *dstc, pixel *src,
175
                         intptr_t stride, int width, int height, int16_t *buf )
176
0
{
177
0
    const int pad = (BIT_DEPTH > 9) ? (-10 * PIXEL_MAX) : 0;
178
0
    for( int y = 0; y < height; y++ )
179
0
    {
180
0
        for( int x = -2; x < width+3; x++ )
181
0
        {
182
0
            int v = TAPFILTER(src,stride);
183
0
            dstv[x] = x264_clip_pixel( (v + 16) >> 5 );
184
            /* transform v for storage in a 16-bit integer */
185
0
            buf[x+2] = v + pad;
186
0
        }
187
0
        for( int x = 0; x < width; x++ )
188
0
            dstc[x] = x264_clip_pixel( (TAPFILTER(buf+2,1) - 32*pad + 512) >> 10 );
189
0
        for( int x = 0; x < width; x++ )
190
0
            dsth[x] = x264_clip_pixel( (TAPFILTER(src,1) + 16) >> 5 );
191
0
        dsth += stride;
192
0
        dstv += stride;
193
0
        dstc += stride;
194
0
        src += stride;
195
0
    }
196
0
}
197
198
static void mc_luma( pixel *dst,    intptr_t i_dst_stride,
199
                     pixel *src[4], intptr_t i_src_stride,
200
                     int mvx, int mvy,
201
                     int i_width, int i_height, const x264_weight_t *weight )
202
0
{
203
0
    int qpel_idx = ((mvy&3)<<2) + (mvx&3);
204
0
    int offset = (mvy>>2)*i_src_stride + (mvx>>2);
205
0
    pixel *src1 = src[x264_hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
206
207
0
    if( qpel_idx & 5 ) /* qpel interpolation needed */
208
0
    {
209
0
        pixel *src2 = src[x264_hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
210
0
        pixel_avg( dst, i_dst_stride, src1, i_src_stride,
211
0
                   src2, i_src_stride, i_width, i_height );
212
0
        if( weight->weightfn )
213
0
            mc_weight( dst, i_dst_stride, dst, i_dst_stride, weight, i_width, i_height );
214
0
    }
215
0
    else if( weight->weightfn )
216
0
        mc_weight( dst, i_dst_stride, src1, i_src_stride, weight, i_width, i_height );
217
0
    else
218
0
        mc_copy( src1, i_src_stride, dst, i_dst_stride, i_width, i_height );
219
0
}
220
221
static pixel *get_ref( pixel *dst,   intptr_t *i_dst_stride,
222
                       pixel *src[4], intptr_t i_src_stride,
223
                       int mvx, int mvy,
224
                       int i_width, int i_height, const x264_weight_t *weight )
225
0
{
226
0
    int qpel_idx = ((mvy&3)<<2) + (mvx&3);
227
0
    int offset = (mvy>>2)*i_src_stride + (mvx>>2);
228
0
    pixel *src1 = src[x264_hpel_ref0[qpel_idx]] + offset + ((mvy&3) == 3) * i_src_stride;
229
230
0
    if( qpel_idx & 5 ) /* qpel interpolation needed */
231
0
    {
232
0
        pixel *src2 = src[x264_hpel_ref1[qpel_idx]] + offset + ((mvx&3) == 3);
233
0
        pixel_avg( dst, *i_dst_stride, src1, i_src_stride,
234
0
                   src2, i_src_stride, i_width, i_height );
235
0
        if( weight->weightfn )
236
0
            mc_weight( dst, *i_dst_stride, dst, *i_dst_stride, weight, i_width, i_height );
237
0
        return dst;
238
0
    }
239
0
    else if( weight->weightfn )
240
0
    {
241
0
        mc_weight( dst, *i_dst_stride, src1, i_src_stride, weight, i_width, i_height );
242
0
        return dst;
243
0
    }
244
0
    else
245
0
    {
246
0
        *i_dst_stride = i_src_stride;
247
0
        return src1;
248
0
    }
249
0
}
250
251
/* full chroma mc (ie until 1/8 pixel)*/
252
static void mc_chroma( pixel *dstu, pixel *dstv, intptr_t i_dst_stride,
253
                       pixel *src, intptr_t i_src_stride,
254
                       int mvx, int mvy,
255
                       int i_width, int i_height )
256
0
{
257
0
    pixel *srcp;
258
259
0
    int d8x = mvx&0x07;
260
0
    int d8y = mvy&0x07;
261
0
    int cA = (8-d8x)*(8-d8y);
262
0
    int cB = d8x    *(8-d8y);
263
0
    int cC = (8-d8x)*d8y;
264
0
    int cD = d8x    *d8y;
265
266
0
    src += (mvy >> 3) * i_src_stride + (mvx >> 3)*2;
267
0
    srcp = &src[i_src_stride];
268
269
0
    for( int y = 0; y < i_height; y++ )
270
0
    {
271
0
        for( int x = 0; x < i_width; x++ )
272
0
        {
273
0
            dstu[x] = ( cA*src[2*x]  + cB*src[2*x+2] +
274
0
                        cC*srcp[2*x] + cD*srcp[2*x+2] + 32 ) >> 6;
275
0
            dstv[x] = ( cA*src[2*x+1]  + cB*src[2*x+3] +
276
0
                        cC*srcp[2*x+1] + cD*srcp[2*x+3] + 32 ) >> 6;
277
0
        }
278
0
        dstu += i_dst_stride;
279
0
        dstv += i_dst_stride;
280
0
        src   = srcp;
281
0
        srcp += i_src_stride;
282
0
    }
283
0
}
284
285
#define MC_COPY(W) \
286
0
static void mc_copy_w##W( pixel *dst, intptr_t i_dst, pixel *src, intptr_t i_src, int i_height ) \
287
0
{ \
288
0
    mc_copy( src, i_src, dst, i_dst, W, i_height ); \
289
0
}
Unexecuted instantiation: mc.c:mc_copy_w16
Unexecuted instantiation: mc.c:mc_copy_w8
Unexecuted instantiation: mc.c:mc_copy_w4
290
MC_COPY( 16 )
291
MC_COPY( 8 )
292
MC_COPY( 4 )
293
294
void x264_plane_copy_c( pixel *dst, intptr_t i_dst,
295
                        pixel *src, intptr_t i_src, int w, int h )
296
0
{
297
0
    while( h-- )
298
0
    {
299
0
        memcpy( dst, src, w * SIZEOF_PIXEL );
300
0
        dst += i_dst;
301
0
        src += i_src;
302
0
    }
303
0
}
Unexecuted instantiation: x264_8_plane_copy_c
Unexecuted instantiation: x264_10_plane_copy_c
304
305
void x264_plane_copy_swap_c( pixel *dst, intptr_t i_dst,
306
                             pixel *src, intptr_t i_src, int w, int h )
307
0
{
308
0
    for( int y=0; y<h; y++, dst+=i_dst, src+=i_src )
309
0
        for( int x=0; x<2*w; x+=2 )
310
0
        {
311
0
            dst[x]   = src[x+1];
312
0
            dst[x+1] = src[x];
313
0
        }
314
0
}
Unexecuted instantiation: x264_8_plane_copy_swap_c
Unexecuted instantiation: x264_10_plane_copy_swap_c
315
316
void x264_plane_copy_interleave_c( pixel *dst,  intptr_t i_dst,
317
                                   pixel *srcu, intptr_t i_srcu,
318
                                   pixel *srcv, intptr_t i_srcv, int w, int h )
319
0
{
320
0
    for( int y=0; y<h; y++, dst+=i_dst, srcu+=i_srcu, srcv+=i_srcv )
321
0
        for( int x=0; x<w; x++ )
322
0
        {
323
0
            dst[2*x]   = srcu[x];
324
0
            dst[2*x+1] = srcv[x];
325
0
        }
326
0
}
Unexecuted instantiation: x264_8_plane_copy_interleave_c
Unexecuted instantiation: x264_10_plane_copy_interleave_c
327
328
void x264_plane_copy_deinterleave_c( pixel *dsta, intptr_t i_dsta, pixel *dstb, intptr_t i_dstb,
329
                                     pixel *src,  intptr_t i_src, int w, int h )
330
0
{
331
0
    for( int y=0; y<h; y++, dsta+=i_dsta, dstb+=i_dstb, src+=i_src )
332
0
        for( int x=0; x<w; x++ )
333
0
        {
334
0
            dsta[x] = src[2*x];
335
0
            dstb[x] = src[2*x+1];
336
0
        }
337
0
}
Unexecuted instantiation: x264_8_plane_copy_deinterleave_c
Unexecuted instantiation: x264_10_plane_copy_deinterleave_c
338
339
static void plane_copy_deinterleave_rgb_c( pixel *dsta, intptr_t i_dsta,
340
                                           pixel *dstb, intptr_t i_dstb,
341
                                           pixel *dstc, intptr_t i_dstc,
342
                                           pixel *src,  intptr_t i_src, int pw, int w, int h )
343
0
{
344
0
    for( int y=0; y<h; y++, dsta+=i_dsta, dstb+=i_dstb, dstc+=i_dstc, src+=i_src )
345
0
    {
346
0
        for( int x=0; x<w; x++ )
347
0
        {
348
0
            dsta[x] = src[x*pw];
349
0
            dstb[x] = src[x*pw+1];
350
0
            dstc[x] = src[x*pw+2];
351
0
        }
352
0
    }
353
0
}
354
355
#if WORDS_BIGENDIAN
356
static ALWAYS_INLINE uint32_t v210_endian_fix32( uint32_t x )
357
{
358
    return (x<<24) + ((x<<8)&0xff0000) + ((x>>8)&0xff00) + (x>>24);
359
}
360
#else
361
0
#define v210_endian_fix32(x) (x)
362
#endif
363
364
static void plane_copy_deinterleave_v210_c( pixel *dsty, intptr_t i_dsty,
365
                                            pixel *dstc, intptr_t i_dstc,
366
                                            uint32_t *src, intptr_t i_src, int w, int h )
367
0
{
368
0
    for( int l = 0; l < h; l++ )
369
0
    {
370
0
        pixel *dsty0 = dsty;
371
0
        pixel *dstc0 = dstc;
372
0
        uint32_t *src0 = src;
373
374
0
        for( int n = 0; n < w; n += 3 )
375
0
        {
376
0
            uint32_t s = v210_endian_fix32( *src0++ );
377
0
            *dstc0++ = s & 0x03FF;
378
0
            *dsty0++ = (s >> 10) & 0x03FF;
379
0
            *dstc0++ = (s >> 20) & 0x03FF;
380
0
            s = v210_endian_fix32( *src0++ );
381
0
            *dsty0++ = s & 0x03FF;
382
0
            *dstc0++ = (s >> 10) & 0x03FF;
383
0
            *dsty0++ = (s >> 20) & 0x03FF;
384
0
        }
385
386
0
        dsty += i_dsty;
387
0
        dstc += i_dstc;
388
0
        src  += i_src;
389
0
    }
390
0
}
391
392
static void store_interleave_chroma( pixel *dst, intptr_t i_dst, pixel *srcu, pixel *srcv, int height )
393
0
{
394
0
    for( int y=0; y<height; y++, dst+=i_dst, srcu+=FDEC_STRIDE, srcv+=FDEC_STRIDE )
395
0
        for( int x=0; x<8; x++ )
396
0
        {
397
0
            dst[2*x]   = srcu[x];
398
0
            dst[2*x+1] = srcv[x];
399
0
        }
400
0
}
401
402
static void load_deinterleave_chroma_fenc( pixel *dst, pixel *src, intptr_t i_src, int height )
403
0
{
404
0
    x264_plane_copy_deinterleave_c( dst, FENC_STRIDE, dst+FENC_STRIDE/2, FENC_STRIDE, src, i_src, 8, height );
405
0
}
406
407
static void load_deinterleave_chroma_fdec( pixel *dst, pixel *src, intptr_t i_src, int height )
408
0
{
409
0
    x264_plane_copy_deinterleave_c( dst, FDEC_STRIDE, dst+FDEC_STRIDE/2, FDEC_STRIDE, src, i_src, 8, height );
410
0
}
411
412
static void prefetch_fenc_null( pixel *pix_y,  intptr_t stride_y,
413
                                pixel *pix_uv, intptr_t stride_uv, int mb_x )
414
0
{}
415
416
static void prefetch_ref_null( pixel *pix, intptr_t stride, int parity )
417
0
{}
418
419
static void memzero_aligned( void * dst, size_t n )
420
0
{
421
0
    memset( dst, 0, n );
422
0
}
423
424
static void integral_init4h( uint16_t *sum, pixel *pix, intptr_t stride )
425
0
{
426
0
    int v = pix[0]+pix[1]+pix[2]+pix[3];
427
0
    for( int x = 0; x < stride-4; x++ )
428
0
    {
429
0
        sum[x] = (uint16_t)(v + sum[x-stride]);
430
0
        v += pix[x+4] - pix[x];
431
0
    }
432
0
}
433
434
static void integral_init8h( uint16_t *sum, pixel *pix, intptr_t stride )
435
0
{
436
0
    int v = pix[0]+pix[1]+pix[2]+pix[3]+pix[4]+pix[5]+pix[6]+pix[7];
437
0
    for( int x = 0; x < stride-8; x++ )
438
0
    {
439
0
        sum[x] = (uint16_t)(v + sum[x-stride]);
440
0
        v += pix[x+8] - pix[x];
441
0
    }
442
0
}
443
444
static void integral_init4v( uint16_t *sum8, uint16_t *sum4, intptr_t stride )
445
0
{
446
0
    for( int x = 0; x < stride-8; x++ )
447
0
        sum4[x] = (uint16_t)(sum8[x+4*stride] - sum8[x]);
448
0
    for( int x = 0; x < stride-8; x++ )
449
0
        sum8[x] = (uint16_t)(sum8[x+8*stride] + sum8[x+8*stride+4] - sum8[x] - sum8[x+4]);
450
0
}
451
452
static void integral_init8v( uint16_t *sum8, intptr_t stride )
453
0
{
454
0
    for( int x = 0; x < stride-8; x++ )
455
0
        sum8[x] = (uint16_t)(sum8[x+8*stride] - sum8[x]);
456
0
}
457
458
void x264_frame_init_lowres( x264_t *h, x264_frame_t *frame )
459
0
{
460
0
    pixel *src = frame->plane[0];
461
0
    int i_stride = frame->i_stride[0];
462
0
    int i_height = frame->i_lines[0];
463
0
    int i_width  = frame->i_width[0];
464
465
    // duplicate last row and column so that their interpolation doesn't have to be special-cased
466
0
    for( int y = 0; y < i_height; y++ )
467
0
        src[i_width+y*i_stride] = src[i_width-1+y*i_stride];
468
0
    memcpy( src+i_stride*i_height, src+i_stride*(i_height-1), (i_width+1) * SIZEOF_PIXEL );
469
0
    h->mc.frame_init_lowres_core( src, frame->lowres[0], frame->lowres[1], frame->lowres[2], frame->lowres[3],
470
0
                                  i_stride, frame->i_stride_lowres, frame->i_width_lowres, frame->i_lines_lowres );
471
0
    x264_frame_expand_border_lowres( frame );
472
473
0
    memset( frame->i_cost_est, -1, sizeof(frame->i_cost_est) );
474
475
0
    for( int y = 0; y < h->param.i_bframe + 2; y++ )
476
0
        for( int x = 0; x < h->param.i_bframe + 2; x++ )
477
0
            frame->i_row_satds[y][x][0] = -1;
478
479
0
    for( int y = 0; y <= !!h->param.i_bframe; y++ )
480
0
        for( int x = 0; x <= h->param.i_bframe; x++ )
481
0
            frame->lowres_mvs[y][x][0][0] = 0x7FFF;
482
0
}
Unexecuted instantiation: x264_8_frame_init_lowres
Unexecuted instantiation: x264_10_frame_init_lowres
483
484
static void frame_init_lowres_core( pixel *src0, pixel *dst0, pixel *dsth, pixel *dstv, pixel *dstc,
485
                                    intptr_t src_stride, intptr_t dst_stride, int width, int height )
486
0
{
487
0
    for( int y = 0; y < height; y++ )
488
0
    {
489
0
        pixel *src1 = src0+src_stride;
490
0
        pixel *src2 = src1+src_stride;
491
0
        for( int x = 0; x<width; x++ )
492
0
        {
493
            // slower than naive bilinear, but matches asm
494
0
#define FILTER(a,b,c,d) ((((a+b+1)>>1)+((c+d+1)>>1)+1)>>1)
495
0
            dst0[x] = FILTER(src0[2*x  ], src1[2*x  ], src0[2*x+1], src1[2*x+1]);
496
0
            dsth[x] = FILTER(src0[2*x+1], src1[2*x+1], src0[2*x+2], src1[2*x+2]);
497
0
            dstv[x] = FILTER(src1[2*x  ], src2[2*x  ], src1[2*x+1], src2[2*x+1]);
498
0
            dstc[x] = FILTER(src1[2*x+1], src2[2*x+1], src1[2*x+2], src2[2*x+2]);
499
0
#undef FILTER
500
0
        }
501
0
        src0 += src_stride*2;
502
0
        dst0 += dst_stride;
503
0
        dsth += dst_stride;
504
0
        dstv += dst_stride;
505
0
        dstc += dst_stride;
506
0
    }
507
0
}
508
509
/* Estimate the total amount of influence on future quality that could be had if we
510
 * were to improve the reference samples used to inter predict any given macroblock. */
511
static void mbtree_propagate_cost( int16_t *dst, uint16_t *propagate_in, uint16_t *intra_costs,
512
                                   uint16_t *inter_costs, uint16_t *inv_qscales, float *fps_factor, int len )
513
0
{
514
0
    float fps = *fps_factor;
515
0
    for( int i = 0; i < len; i++ )
516
0
    {
517
0
        int intra_cost = intra_costs[i];
518
0
        int inter_cost = X264_MIN(intra_costs[i], inter_costs[i] & LOWRES_COST_MASK);
519
0
        float propagate_intra  = intra_cost * inv_qscales[i];
520
0
        float propagate_amount = propagate_in[i] + propagate_intra*fps;
521
0
        float propagate_num    = intra_cost - inter_cost;
522
0
        float propagate_denom  = intra_cost;
523
0
        dst[i] = X264_MIN((int)(propagate_amount * propagate_num / propagate_denom + 0.5f), 32767);
524
0
    }
525
0
}
526
527
static void mbtree_propagate_list( x264_t *h, uint16_t *ref_costs, int16_t (*mvs)[2],
528
                                   int16_t *propagate_amount, uint16_t *lowres_costs,
529
                                   int bipred_weight, int mb_y, int len, int list )
530
0
{
531
0
    unsigned stride = h->mb.i_mb_stride;
532
0
    unsigned width = h->mb.i_mb_width;
533
0
    unsigned height = h->mb.i_mb_height;
534
535
0
    for( int i = 0; i < len; i++ )
536
0
    {
537
0
        int lists_used = lowres_costs[i]>>LOWRES_COST_SHIFT;
538
539
0
        if( !(lists_used & (1 << list)) )
540
0
            continue;
541
542
0
        int listamount = propagate_amount[i];
543
        /* Apply bipred weighting. */
544
0
        if( lists_used == 3 )
545
0
            listamount = (listamount * bipred_weight + 32) >> 6;
546
547
        /* Early termination for simple case of mv0. */
548
0
        if( !M32( mvs[i] ) )
549
0
        {
550
0
            MC_CLIP_ADD( ref_costs[mb_y*stride + i], listamount );
551
0
            continue;
552
0
        }
553
554
0
        int x = mvs[i][0];
555
0
        int y = mvs[i][1];
556
0
        unsigned mbx = (unsigned)((x>>5)+i);
557
0
        unsigned mby = (unsigned)((y>>5)+mb_y);
558
0
        unsigned idx0 = mbx + mby * stride;
559
0
        unsigned idx2 = idx0 + stride;
560
0
        x &= 31;
561
0
        y &= 31;
562
0
        int idx0weight = (32-y)*(32-x);
563
0
        int idx1weight = (32-y)*x;
564
0
        int idx2weight = y*(32-x);
565
0
        int idx3weight = y*x;
566
0
        idx0weight = (idx0weight * listamount + 512) >> 10;
567
0
        idx1weight = (idx1weight * listamount + 512) >> 10;
568
0
        idx2weight = (idx2weight * listamount + 512) >> 10;
569
0
        idx3weight = (idx3weight * listamount + 512) >> 10;
570
571
0
        if( mbx < width-1 && mby < height-1 )
572
0
        {
573
0
            MC_CLIP_ADD( ref_costs[idx0+0], idx0weight );
574
0
            MC_CLIP_ADD( ref_costs[idx0+1], idx1weight );
575
0
            MC_CLIP_ADD( ref_costs[idx2+0], idx2weight );
576
0
            MC_CLIP_ADD( ref_costs[idx2+1], idx3weight );
577
0
        }
578
0
        else
579
0
        {
580
            /* Note: this takes advantage of unsigned representation to
581
             * catch negative mbx/mby. */
582
0
            if( mby < height )
583
0
            {
584
0
                if( mbx < width )
585
0
                    MC_CLIP_ADD( ref_costs[idx0+0], idx0weight );
586
0
                if( mbx+1 < width )
587
0
                    MC_CLIP_ADD( ref_costs[idx0+1], idx1weight );
588
0
            }
589
0
            if( mby+1 < height )
590
0
            {
591
0
                if( mbx < width )
592
0
                    MC_CLIP_ADD( ref_costs[idx2+0], idx2weight );
593
0
                if( mbx+1 < width )
594
0
                    MC_CLIP_ADD( ref_costs[idx2+1], idx3weight );
595
0
            }
596
0
        }
597
0
    }
598
0
}
599
600
/* Conversion between float and Q8.8 fixed point (big-endian) for storage */
601
static void mbtree_fix8_pack( uint16_t *dst, float *src, int count )
602
0
{
603
0
    for( int i = 0; i < count; i++ )
604
0
        dst[i] = endian_fix16( (int16_t)(src[i] * 256.0f) );
605
0
}
606
607
static void mbtree_fix8_unpack( float *dst, uint16_t *src, int count )
608
0
{
609
0
    for( int i = 0; i < count; i++ )
610
0
        dst[i] = (int16_t)endian_fix16( src[i] ) * (1.0f/256.0f);
611
0
}
612
613
void x264_mc_init( uint32_t cpu, x264_mc_functions_t *pf, int cpu_independent )
614
0
{
615
0
    pf->mc_luma   = mc_luma;
616
0
    pf->get_ref   = get_ref;
617
618
0
    pf->mc_chroma = mc_chroma;
619
620
0
    pf->avg[PIXEL_16x16]= pixel_avg_16x16;
621
0
    pf->avg[PIXEL_16x8] = pixel_avg_16x8;
622
0
    pf->avg[PIXEL_8x16] = pixel_avg_8x16;
623
0
    pf->avg[PIXEL_8x8]  = pixel_avg_8x8;
624
0
    pf->avg[PIXEL_8x4]  = pixel_avg_8x4;
625
0
    pf->avg[PIXEL_4x16] = pixel_avg_4x16;
626
0
    pf->avg[PIXEL_4x8]  = pixel_avg_4x8;
627
0
    pf->avg[PIXEL_4x4]  = pixel_avg_4x4;
628
0
    pf->avg[PIXEL_4x2]  = pixel_avg_4x2;
629
0
    pf->avg[PIXEL_2x8]  = pixel_avg_2x8;
630
0
    pf->avg[PIXEL_2x4]  = pixel_avg_2x4;
631
0
    pf->avg[PIXEL_2x2]  = pixel_avg_2x2;
632
633
0
    pf->weight    = mc_weight_wtab;
634
0
    pf->offsetadd = mc_weight_wtab;
635
0
    pf->offsetsub = mc_weight_wtab;
636
0
    pf->weight_cache = weight_cache;
637
638
0
    pf->copy_16x16_unaligned = mc_copy_w16;
639
0
    pf->copy[PIXEL_16x16] = mc_copy_w16;
640
0
    pf->copy[PIXEL_8x8]   = mc_copy_w8;
641
0
    pf->copy[PIXEL_4x4]   = mc_copy_w4;
642
643
0
    pf->store_interleave_chroma       = store_interleave_chroma;
644
0
    pf->load_deinterleave_chroma_fenc = load_deinterleave_chroma_fenc;
645
0
    pf->load_deinterleave_chroma_fdec = load_deinterleave_chroma_fdec;
646
647
0
    pf->plane_copy = x264_plane_copy_c;
648
0
    pf->plane_copy_swap = x264_plane_copy_swap_c;
649
0
    pf->plane_copy_interleave = x264_plane_copy_interleave_c;
650
651
0
    pf->plane_copy_deinterleave = x264_plane_copy_deinterleave_c;
652
0
    pf->plane_copy_deinterleave_yuyv = x264_plane_copy_deinterleave_c;
653
0
    pf->plane_copy_deinterleave_rgb = plane_copy_deinterleave_rgb_c;
654
0
    pf->plane_copy_deinterleave_v210 = plane_copy_deinterleave_v210_c;
655
656
0
    pf->hpel_filter = hpel_filter;
657
658
0
    pf->prefetch_fenc_400 = prefetch_fenc_null;
659
0
    pf->prefetch_fenc_420 = prefetch_fenc_null;
660
0
    pf->prefetch_fenc_422 = prefetch_fenc_null;
661
0
    pf->prefetch_ref  = prefetch_ref_null;
662
0
    pf->memcpy_aligned = memcpy;
663
0
    pf->memzero_aligned = memzero_aligned;
664
0
    pf->frame_init_lowres_core = frame_init_lowres_core;
665
666
0
    pf->integral_init4h = integral_init4h;
667
0
    pf->integral_init8h = integral_init8h;
668
0
    pf->integral_init4v = integral_init4v;
669
0
    pf->integral_init8v = integral_init8v;
670
671
0
    pf->mbtree_propagate_cost = mbtree_propagate_cost;
672
0
    pf->mbtree_propagate_list = mbtree_propagate_list;
673
0
    pf->mbtree_fix8_pack      = mbtree_fix8_pack;
674
0
    pf->mbtree_fix8_unpack    = mbtree_fix8_unpack;
675
676
#if HAVE_MMX
677
    x264_mc_init_mmx( cpu, pf );
678
#endif
679
#if HAVE_ALTIVEC
680
    if( cpu&X264_CPU_ALTIVEC )
681
        x264_mc_init_altivec( pf );
682
#endif
683
#if HAVE_ARMV6
684
    x264_mc_init_arm( cpu, pf );
685
#endif
686
#if HAVE_AARCH64
687
    x264_mc_init_aarch64( cpu, pf );
688
#endif
689
#if HAVE_MSA
690
    if( cpu&X264_CPU_MSA )
691
        x264_mc_init_mips( cpu, pf );
692
#endif
693
#if HAVE_LSX
694
    x264_mc_init_loongarch( cpu, pf );
695
#endif
696
697
0
    if( cpu_independent )
698
0
    {
699
0
        pf->mbtree_propagate_cost = mbtree_propagate_cost;
700
0
        pf->mbtree_propagate_list = mbtree_propagate_list;
701
0
    }
702
0
}
Unexecuted instantiation: x264_8_mc_init
Unexecuted instantiation: x264_10_mc_init
703
704
void x264_frame_filter( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
705
0
{
706
0
    const int b_interlaced = PARAM_INTERLACED;
707
0
    int start = mb_y*16 - 8; // buffer = 4 for deblock + 3 for 6tap, rounded to 8
708
0
    int height = (b_end ? frame->i_lines[0] + 16*PARAM_INTERLACED : (mb_y+b_interlaced)*16) + 8;
709
710
0
    if( mb_y & b_interlaced )
711
0
        return;
712
713
0
    for( int p = 0; p < (CHROMA444 ? 3 : 1); p++ )
714
0
    {
715
0
        int stride = frame->i_stride[p];
716
0
        const int width = frame->i_width[p];
717
0
        int offs = start*stride - 8; // buffer = 3 for 6tap, aligned to 8 for simd
718
719
0
        if( !b_interlaced || h->mb.b_adaptive_mbaff )
720
0
            h->mc.hpel_filter(
721
0
                frame->filtered[p][1] + offs,
722
0
                frame->filtered[p][2] + offs,
723
0
                frame->filtered[p][3] + offs,
724
0
                frame->plane[p] + offs,
725
0
                stride, width + 16, height - start,
726
0
                h->scratch_buffer );
727
728
0
        if( b_interlaced )
729
0
        {
730
            /* MC must happen between pixels in the same field. */
731
0
            stride = frame->i_stride[p] << 1;
732
0
            start = (mb_y*16 >> 1) - 8;
733
0
            int height_fld = ((b_end ? frame->i_lines[p] : mb_y*16) >> 1) + 8;
734
0
            offs = start*stride - 8;
735
0
            for( int i = 0; i < 2; i++, offs += frame->i_stride[p] )
736
0
            {
737
0
                h->mc.hpel_filter(
738
0
                    frame->filtered_fld[p][1] + offs,
739
0
                    frame->filtered_fld[p][2] + offs,
740
0
                    frame->filtered_fld[p][3] + offs,
741
0
                    frame->plane_fld[p] + offs,
742
0
                    stride, width + 16, height_fld - start,
743
0
                    h->scratch_buffer );
744
0
            }
745
0
        }
746
0
    }
747
748
    /* generate integral image:
749
     * frame->integral contains 2 planes. in the upper plane, each element is
750
     * the sum of an 8x8 pixel region with top-left corner on that point.
751
     * in the lower plane, 4x4 sums (needed only with --partitions p4x4). */
752
753
0
    if( frame->integral )
754
0
    {
755
0
        int stride = frame->i_stride[0];
756
0
        if( start < 0 )
757
0
        {
758
0
            memset( frame->integral - PADV * stride - PADH_ALIGN, 0, stride * sizeof(uint16_t) );
759
0
            start = -PADV;
760
0
        }
761
0
        if( b_end )
762
0
            height += PADV-9;
763
0
        for( int y = start; y < height; y++ )
764
0
        {
765
0
            pixel    *pix  = frame->plane[0] + y * stride - PADH_ALIGN;
766
0
            uint16_t *sum8 = frame->integral + (y+1) * stride - PADH_ALIGN;
767
0
            uint16_t *sum4;
768
0
            if( h->frames.b_have_sub8x8_esa )
769
0
            {
770
0
                h->mc.integral_init4h( sum8, pix, stride );
771
0
                sum8 -= 8*stride;
772
0
                sum4 = sum8 + stride * (frame->i_lines[0] + PADV*2);
773
0
                if( y >= 8-PADV )
774
0
                    h->mc.integral_init4v( sum8, sum4, stride );
775
0
            }
776
0
            else
777
0
            {
778
0
                h->mc.integral_init8h( sum8, pix, stride );
779
0
                if( y >= 8-PADV )
780
0
                    h->mc.integral_init8v( sum8-8*stride, stride );
781
0
            }
782
0
        }
783
0
    }
784
0
}
Unexecuted instantiation: x264_8_frame_filter
Unexecuted instantiation: x264_10_frame_filter