Coverage Report

Created: 2026-10-17 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libhevc/common/ihevc_sao.c
Line
Count
Source
1
/******************************************************************************
2
*
3
* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
4
*
5
* Licensed under the Apache License, Version 2.0 (the "License");
6
* you may not use this file except in compliance with the License.
7
* You may obtain a copy of the License at:
8
*
9
* http://www.apache.org/licenses/LICENSE-2.0
10
*
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
16
*
17
******************************************************************************/
18
/**
19
*******************************************************************************
20
* @file
21
*  ihevc_sao.c
22
*
23
* @brief
24
*  Contains leaf level function definitions for sample adaptive offset process
25
*
26
* @author
27
*  Srinivas T
28
*
29
* @par List of Functions:
30
*   - ihevc_sao_band_offset_luma()
31
*   - ihevc_sao_band_offset_chroma()
32
*   - ihevc_sao_edge_offset_class0()
33
*   - ihevc_sao_edge_offset_class0_chroma()
34
*   - ihevc_sao_edge_offset_class1()
35
*   - ihevc_sao_edge_offset_class1_chroma()
36
*   - ihevc_sao_edge_offset_class2()
37
*   - ihevc_sao_edge_offset_class2_chroma()
38
*   - ihevc_sao_edge_offset_class3()
39
*   - ihevc_sao_edge_offset_class3_chroma()
40
* @remarks
41
*  None
42
*
43
*******************************************************************************
44
*/
45
#include <stdlib.h>
46
#include <assert.h>
47
#include <string.h>
48
#include "ihevc_typedefs.h"
49
#include "ihevc_macros.h"
50
#include "ihevc_platform_macros.h"
51
#include "ihevc_defs.h"
52
#include "ihevc_structs.h"
53
#include "ihevc_sao.h"
54
55
0
#define NUM_BAND_TABLE  32
56
57
const WORD32 gi4_ihevc_table_edge_idx[5] = { 1, 2, 0, 3, 4 };
58
/**
59
 * au4_avail is an array of flags - one for each neighboring block specifying if the block is available
60
 * au4_avail[0] - left
61
 * au4_avail[1] - right
62
 * au4_avail[2] - top
63
 * au4_avail[3] - bottom
64
 * au4_avail[4] - top-left
65
 * au4_avail[5] - top-right
66
 * au4_avail[6] - bottom-left
67
 * au4_avail[7] - bottom-right
68
 */
69
70
71
void ihevc_sao_band_offset_luma(UWORD8 *pu1_src,
72
                                WORD32 src_strd,
73
                                UWORD8 *pu1_src_left,
74
                                UWORD8 *pu1_src_top,
75
                                UWORD8 *pu1_src_top_left,
76
                                WORD32 sao_band_pos,
77
                                WORD8 *pi1_sao_offset,
78
                                WORD32 wd,
79
                                WORD32 ht)
80
0
{
81
0
    WORD32 band_shift;
82
0
    WORD32 band_table[NUM_BAND_TABLE];
83
0
    WORD32 i;
84
0
    WORD32 row, col;
85
86
    /* Updating left and top and top-left */
87
0
    for(row = 0; row < ht; row++)
88
0
    {
89
0
        pu1_src_left[row] = pu1_src[row * src_strd + (wd - 1)];
90
0
    }
91
0
    pu1_src_top_left[0] = pu1_src_top[wd - 1];
92
0
    for(col = 0; col < wd; col++)
93
0
    {
94
0
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
95
0
    }
96
97
0
    band_shift = BIT_DEPTH_LUMA - 5;
98
0
    for(i = 0; i < NUM_BAND_TABLE; i++)
99
0
    {
100
0
        band_table[i] = 0;
101
0
    }
102
0
    for(i = 0; i < 4; i++)
103
0
    {
104
0
        band_table[(i + sao_band_pos) & 31] = i + 1;
105
0
    }
106
107
0
    for(row = 0; row < ht; row++)
108
0
    {
109
0
        for(col = 0; col < wd; col++)
110
0
        {
111
0
            WORD32 band_idx;
112
113
0
            band_idx = band_table[pu1_src[col] >> band_shift];
114
0
            pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[band_idx], 0, (1 << (band_shift + 5)) - 1);
115
0
        }
116
0
        pu1_src += src_strd;
117
0
    }
118
0
}
119
120
121
122
/* input 'wd' has to be for the interleaved block and not for each color component */
123
void ihevc_sao_band_offset_chroma(UWORD8 *pu1_src,
124
                                  WORD32 src_strd,
125
                                  UWORD8 *pu1_src_left,
126
                                  UWORD8 *pu1_src_top,
127
                                  UWORD8 *pu1_src_top_left,
128
                                  WORD32 sao_band_pos_u,
129
                                  WORD32 sao_band_pos_v,
130
                                  WORD8 *pi1_sao_offset_u,
131
                                  WORD8 *pi1_sao_offset_v,
132
                                  WORD32 wd,
133
                                  WORD32 ht)
134
0
{
135
0
    WORD32 band_shift;
136
0
    WORD32 band_table_u[NUM_BAND_TABLE];
137
0
    WORD32 band_table_v[NUM_BAND_TABLE];
138
0
    WORD32 i;
139
0
    WORD32 row, col;
140
141
    /* Updating left and top and top-left */
142
0
    for(row = 0; row < ht; row++)
143
0
    {
144
0
        pu1_src_left[2 * row] = pu1_src[row * src_strd + (wd - 2)];
145
0
        pu1_src_left[2 * row + 1] = pu1_src[row * src_strd + (wd - 1)];
146
0
    }
147
0
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
148
0
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
149
0
    for(col = 0; col < wd; col++)
150
0
    {
151
0
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
152
0
    }
153
154
155
0
    band_shift = BIT_DEPTH_CHROMA - 5;
156
0
    for(i = 0; i < NUM_BAND_TABLE; i++)
157
0
    {
158
0
        band_table_u[i] = 0;
159
0
        band_table_v[i] = 0;
160
0
    }
161
0
    for(i = 0; i < 4; i++)
162
0
    {
163
0
        band_table_u[(i + sao_band_pos_u) & 31] = i + 1;
164
0
        band_table_v[(i + sao_band_pos_v) & 31] = i + 1;
165
0
    }
166
167
0
    for(row = 0; row < ht; row++)
168
0
    {
169
0
        for(col = 0; col < wd; col++)
170
0
        {
171
0
            WORD32 band_idx;
172
0
            WORD8 *pi1_sao_offset;
173
174
0
            pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
175
0
            band_idx = (0 == col % 2) ? band_table_u[pu1_src[col] >> band_shift] : band_table_v[pu1_src[col] >> band_shift];
176
0
            pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[band_idx], 0, (1 << (band_shift + 5)) - 1);
177
0
        }
178
0
        pu1_src += src_strd;
179
0
    }
180
0
}
181
182
183
184
/* Horizontal filtering */
185
void ihevc_sao_edge_offset_class0(UWORD8 *pu1_src,
186
                                  WORD32 src_strd,
187
                                  UWORD8 *pu1_src_left,
188
                                  UWORD8 *pu1_src_top,
189
                                  UWORD8 *pu1_src_top_left,
190
                                  UWORD8 *pu1_src_top_right,
191
                                  UWORD8 *pu1_src_bot_left,
192
                                  UWORD8 *pu1_avail,
193
                                  WORD8 *pi1_sao_offset,
194
                                  WORD32 wd,
195
                                  WORD32 ht)
196
220k
{
197
220k
    WORD32 row, col;
198
220k
    UWORD8 au1_mask[MAX_CTB_SIZE];
199
220k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE];
200
220k
    WORD8 u1_sign_left, u1_sign_right;
201
220k
    WORD32 bit_depth;
202
220k
    UNUSED(pu1_src_top_right);
203
220k
    UNUSED(pu1_src_bot_left);
204
220k
    bit_depth = BIT_DEPTH_LUMA;
205
206
    /* Initialize the mask values */
207
220k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
208
209
    /* Update top and top-left arrays */
210
220k
    *pu1_src_top_left = pu1_src_top[wd - 1];
211
13.6M
    for(row = 0; row < ht; row++)
212
13.4M
    {
213
13.4M
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
214
13.4M
    }
215
13.7M
    for(col = 0; col < wd; col++)
216
13.4M
    {
217
13.4M
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
218
13.4M
    }
219
220
    /* Update masks based on the availability flags */
221
220k
    if(0 == pu1_avail[0])
222
111k
    {
223
111k
        au1_mask[0] = 0;
224
111k
    }
225
220k
    if(0 == pu1_avail[1])
226
114k
    {
227
114k
        au1_mask[wd - 1] = 0;
228
114k
    }
229
230
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
231
220k
    {
232
13.6M
        for(row = 0; row < ht; row++)
233
13.4M
        {
234
13.4M
            u1_sign_left = SIGN(pu1_src[0] - pu1_src_left[row]);
235
837M
            for(col = 0; col < wd; col++)
236
824M
            {
237
824M
                WORD32 edge_idx;
238
239
824M
                u1_sign_right = SIGN(pu1_src[col] - pu1_src[col + 1]);
240
824M
                edge_idx = 2 + u1_sign_left + u1_sign_right;
241
824M
                u1_sign_left = -u1_sign_right;
242
243
824M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
244
245
824M
                if(0 != edge_idx)
246
40.7M
                {
247
40.7M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
248
40.7M
                }
249
824M
            }
250
251
13.4M
            pu1_src += src_strd;
252
13.4M
        }
253
220k
    }
254
255
    /* Update left array */
256
13.6M
    for(row = 0; row < ht; row++)
257
13.4M
    {
258
13.4M
        pu1_src_left[row] = au1_src_left_tmp[row];
259
13.4M
    }
260
261
220k
}
262
263
264
265
266
/* input 'wd' has to be for the interleaved block and not for each color component */
267
void ihevc_sao_edge_offset_class0_chroma(UWORD8 *pu1_src,
268
                                         WORD32 src_strd,
269
                                         UWORD8 *pu1_src_left,
270
                                         UWORD8 *pu1_src_top,
271
                                         UWORD8 *pu1_src_top_left,
272
                                         UWORD8 *pu1_src_top_right,
273
                                         UWORD8 *pu1_src_bot_left,
274
                                         UWORD8 *pu1_avail,
275
                                         WORD8 *pi1_sao_offset_u,
276
                                         WORD8 *pi1_sao_offset_v,
277
                                         WORD32 wd,
278
                                         WORD32 ht)
279
95.3k
{
280
95.3k
    WORD32 row, col;
281
95.3k
    UWORD8 au1_mask[MAX_CTB_SIZE];
282
95.3k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE];
283
95.3k
    WORD8 u1_sign_left_u, u1_sign_right_u;
284
95.3k
    WORD8 u1_sign_left_v, u1_sign_right_v;
285
95.3k
    WORD32 bit_depth;
286
95.3k
    UNUSED(pu1_src_top_right);
287
95.3k
    UNUSED(pu1_src_bot_left);
288
95.3k
    bit_depth = BIT_DEPTH_CHROMA;
289
290
    /* Initialize the mask values */
291
95.3k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
292
293
    /* Update left, top and top-left arrays */
294
95.3k
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
295
95.3k
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
296
2.97M
    for(row = 0; row < ht; row++)
297
2.87M
    {
298
2.87M
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
299
2.87M
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
300
2.87M
    }
301
5.86M
    for(col = 0; col < wd; col++)
302
5.77M
    {
303
5.77M
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
304
5.77M
    }
305
306
    /* Update masks based on the availability flags */
307
95.3k
    if(0 == pu1_avail[0])
308
40.2k
    {
309
40.2k
        au1_mask[0] = 0;
310
40.2k
    }
311
95.3k
    if(0 == pu1_avail[1])
312
43.1k
    {
313
43.1k
        au1_mask[(wd - 1) >> 1] = 0;
314
43.1k
    }
315
316
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
317
95.3k
    {
318
2.97M
        for(row = 0; row < ht; row++)
319
2.87M
        {
320
2.87M
            u1_sign_left_u = SIGN(pu1_src[0] - pu1_src_left[2 * row]);
321
2.87M
            u1_sign_left_v = SIGN(pu1_src[1] - pu1_src_left[2 * row + 1]);
322
178M
            for(col = 0; col < wd; col++)
323
175M
            {
324
175M
                WORD32 edge_idx;
325
175M
                WORD8 *pi1_sao_offset;
326
327
175M
                if(0 == col % 2)
328
87.5M
                {
329
87.5M
                    pi1_sao_offset = pi1_sao_offset_u;
330
87.5M
                    u1_sign_right_u = SIGN(pu1_src[col] - pu1_src[col + 2]);
331
87.5M
                    edge_idx = 2 + u1_sign_left_u + u1_sign_right_u;
332
87.5M
                    u1_sign_left_u = -u1_sign_right_u;
333
87.5M
                }
334
87.5M
                else
335
87.5M
                {
336
87.5M
                    pi1_sao_offset = pi1_sao_offset_v;
337
87.5M
                    u1_sign_right_v = SIGN(pu1_src[col] - pu1_src[col + 2]);
338
87.5M
                    edge_idx = 2 + u1_sign_left_v + u1_sign_right_v;
339
87.5M
                    u1_sign_left_v = -u1_sign_right_v;
340
87.5M
                }
341
342
175M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
343
344
175M
                if(0 != edge_idx)
345
9.53M
                {
346
9.53M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
347
9.53M
                }
348
175M
            }
349
350
2.87M
            pu1_src += src_strd;
351
2.87M
        }
352
95.3k
    }
353
354
5.84M
    for(row = 0; row < 2 * ht; row++)
355
5.75M
    {
356
5.75M
        pu1_src_left[row] = au1_src_left_tmp[row];
357
5.75M
    }
358
359
95.3k
}
360
361
362
363
/* Vertical filtering */
364
void ihevc_sao_edge_offset_class1(UWORD8 *pu1_src,
365
                                  WORD32 src_strd,
366
                                  UWORD8 *pu1_src_left,
367
                                  UWORD8 *pu1_src_top,
368
                                  UWORD8 *pu1_src_top_left,
369
                                  UWORD8 *pu1_src_top_right,
370
                                  UWORD8 *pu1_src_bot_left,
371
                                  UWORD8 *pu1_avail,
372
                                  WORD8 *pi1_sao_offset,
373
                                  WORD32 wd,
374
                                  WORD32 ht)
375
150k
{
376
150k
    WORD32 row, col;
377
150k
    UWORD8 au1_mask[MAX_CTB_SIZE];
378
150k
    UWORD8 au1_src_top_tmp[MAX_CTB_SIZE];
379
150k
    WORD8 au1_sign_up[MAX_CTB_SIZE];
380
150k
    WORD8 u1_sign_down;
381
150k
    WORD32 bit_depth;
382
150k
    UNUSED(pu1_src_top_right);
383
150k
    UNUSED(pu1_src_bot_left);
384
385
150k
    bit_depth = BIT_DEPTH_LUMA;
386
387
    /* Initialize the mask values */
388
150k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
389
390
    /* Update left, top and top-left arrays */
391
150k
    *pu1_src_top_left = pu1_src_top[wd - 1];
392
9.35M
    for(row = 0; row < ht; row++)
393
9.20M
    {
394
9.20M
        pu1_src_left[row] = pu1_src[row * src_strd + wd - 1];
395
9.20M
    }
396
9.36M
    for(col = 0; col < wd; col++)
397
9.21M
    {
398
9.21M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
399
9.21M
    }
400
401
    /* Update height and source pointers based on the availability flags */
402
150k
    if(0 == pu1_avail[2])
403
95.8k
    {
404
95.8k
        pu1_src += src_strd;
405
95.8k
        ht--;
406
5.98M
        for(col = 0; col < wd; col++)
407
5.88M
        {
408
5.88M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - src_strd]);
409
5.88M
        }
410
95.8k
    }
411
54.3k
    else
412
54.3k
    {
413
3.37M
        for(col = 0; col < wd; col++)
414
3.32M
        {
415
3.32M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col]);
416
3.32M
        }
417
54.3k
    }
418
150k
    if(0 == pu1_avail[3])
419
95.9k
    {
420
95.9k
        ht--;
421
95.9k
    }
422
423
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
424
150k
    {
425
9.16M
        for(row = 0; row < ht; row++)
426
9.01M
        {
427
563M
            for(col = 0; col < wd; col++)
428
554M
            {
429
554M
                WORD32 edge_idx;
430
431
554M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + src_strd]);
432
554M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
433
554M
                au1_sign_up[col] = -u1_sign_down;
434
435
554M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
436
437
554M
                if(0 != edge_idx)
438
25.9M
                {
439
25.9M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
440
25.9M
                }
441
554M
            }
442
443
9.01M
            pu1_src += src_strd;
444
9.01M
        }
445
150k
    }
446
447
9.36M
    for(col = 0; col < wd; col++)
448
9.21M
    {
449
9.21M
        pu1_src_top[col] = au1_src_top_tmp[col];
450
9.21M
    }
451
452
150k
}
453
454
455
456
/* input 'wd' has to be for the interleaved block and not for each color component */
457
void ihevc_sao_edge_offset_class1_chroma(UWORD8 *pu1_src,
458
                                         WORD32 src_strd,
459
                                         UWORD8 *pu1_src_left,
460
                                         UWORD8 *pu1_src_top,
461
                                         UWORD8 *pu1_src_top_left,
462
                                         UWORD8 *pu1_src_top_right,
463
                                         UWORD8 *pu1_src_bot_left,
464
                                         UWORD8 *pu1_avail,
465
                                         WORD8 *pi1_sao_offset_u,
466
                                         WORD8 *pi1_sao_offset_v,
467
                                         WORD32 wd,
468
                                         WORD32 ht)
469
24.6k
{
470
24.6k
    WORD32 row, col;
471
24.6k
    UWORD8 au1_mask[MAX_CTB_SIZE];
472
24.6k
    UWORD8 au1_src_top_tmp[2 * MAX_CTB_SIZE];
473
24.6k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE];
474
24.6k
    WORD8 u1_sign_down;
475
24.6k
    WORD32 bit_depth;
476
24.6k
    UNUSED(pu1_src_top_right);
477
24.6k
    UNUSED(pu1_src_bot_left);
478
479
24.6k
    bit_depth = BIT_DEPTH_CHROMA;
480
481
    /* Initialize the mask values */
482
24.6k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
483
484
    /* Update left, top and top-left arrays */
485
24.6k
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
486
24.6k
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
487
779k
    for(row = 0; row < ht; row++)
488
754k
    {
489
754k
        pu1_src_left[2 * row] = pu1_src[row * src_strd + wd - 2];
490
754k
        pu1_src_left[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
491
754k
    }
492
1.52M
    for(col = 0; col < wd; col++)
493
1.50M
    {
494
1.50M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
495
1.50M
    }
496
497
    /* Update height and source pointers based on the availability flags */
498
24.6k
    if(0 == pu1_avail[2])
499
17.2k
    {
500
17.2k
        pu1_src += src_strd;
501
17.2k
        ht--;
502
1.06M
        for(col = 0; col < wd; col++)
503
1.04M
        {
504
1.04M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - src_strd]);
505
1.04M
        }
506
17.2k
    }
507
7.43k
    else
508
7.43k
    {
509
463k
        for(col = 0; col < wd; col++)
510
456k
        {
511
456k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col]);
512
456k
        }
513
7.43k
    }
514
24.6k
    if(0 == pu1_avail[3])
515
17.3k
    {
516
17.3k
        ht--;
517
17.3k
    }
518
519
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
520
24.6k
    {
521
744k
        for(row = 0; row < ht; row++)
522
720k
        {
523
44.7M
            for(col = 0; col < wd; col++)
524
44.0M
            {
525
44.0M
                WORD32 edge_idx;
526
44.0M
                WORD8 *pi1_sao_offset;
527
528
44.0M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
529
530
44.0M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + src_strd]);
531
44.0M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
532
44.0M
                au1_sign_up[col] = -u1_sign_down;
533
534
44.0M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
535
536
44.0M
                if(0 != edge_idx)
537
2.54M
                {
538
2.54M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
539
2.54M
                }
540
44.0M
            }
541
542
720k
            pu1_src += src_strd;
543
720k
        }
544
24.6k
    }
545
546
1.52M
    for(col = 0; col < wd; col++)
547
1.50M
    {
548
1.50M
        pu1_src_top[col] = au1_src_top_tmp[col];
549
1.50M
    }
550
551
24.6k
}
552
553
554
555
/* 135 degree filtering */
556
void ihevc_sao_edge_offset_class2(UWORD8 *pu1_src,
557
                                  WORD32 src_strd,
558
                                  UWORD8 *pu1_src_left,
559
                                  UWORD8 *pu1_src_top,
560
                                  UWORD8 *pu1_src_top_left,
561
                                  UWORD8 *pu1_src_top_right,
562
                                  UWORD8 *pu1_src_bot_left,
563
                                  UWORD8 *pu1_avail,
564
                                  WORD8 *pi1_sao_offset,
565
                                  WORD32 wd,
566
                                  WORD32 ht)
567
141k
{
568
141k
    WORD32 row, col;
569
141k
    UWORD8 au1_mask[MAX_CTB_SIZE];
570
141k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE], au1_src_top_tmp[MAX_CTB_SIZE];
571
141k
    UWORD8 u1_src_top_left_tmp;
572
141k
    WORD8 au1_sign_up[MAX_CTB_SIZE + 1], au1_sign_up_tmp[MAX_CTB_SIZE + 1];
573
141k
    WORD8 u1_sign_down;
574
141k
    WORD8 *pu1_sign_up;
575
141k
    WORD8 *pu1_sign_up_tmp;
576
141k
    UWORD8 *pu1_src_left_cpy;
577
578
141k
    WORD32 bit_depth;
579
141k
    UWORD8 u1_pos_0_0_tmp;
580
141k
    UWORD8 u1_pos_wd_ht_tmp;
581
141k
    UNUSED(pu1_src_top_right);
582
141k
    UNUSED(pu1_src_bot_left);
583
584
141k
    bit_depth = BIT_DEPTH_LUMA;
585
141k
    pu1_sign_up = au1_sign_up;
586
141k
    pu1_sign_up_tmp = au1_sign_up_tmp;
587
141k
    pu1_src_left_cpy = pu1_src_left;
588
589
    /* Initialize the mask values */
590
141k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
591
592
    /* Update left, top and top-left arrays */
593
141k
    u1_src_top_left_tmp = pu1_src_top[wd - 1];
594
8.79M
    for(row = 0; row < ht; row++)
595
8.65M
    {
596
8.65M
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
597
8.65M
    }
598
8.82M
    for(col = 0; col < wd; col++)
599
8.68M
    {
600
8.68M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
601
8.68M
    }
602
603
604
    /* If top-left is available, process separately */
605
141k
    if(0 != pu1_avail[4])
606
38.0k
    {
607
38.0k
        WORD32 edge_idx;
608
609
38.0k
        edge_idx = 2 + SIGN(pu1_src[0] - pu1_src_top_left[0]) +
610
38.0k
                        SIGN(pu1_src[0] - pu1_src[1 + src_strd]);
611
612
38.0k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
613
614
38.0k
        if(0 != edge_idx)
615
3.14k
        {
616
3.14k
            u1_pos_0_0_tmp = CLIP3(pu1_src[0] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
617
3.14k
        }
618
34.8k
        else
619
34.8k
        {
620
34.8k
            u1_pos_0_0_tmp = pu1_src[0];
621
34.8k
        }
622
38.0k
    }
623
103k
    else
624
103k
    {
625
103k
        u1_pos_0_0_tmp = pu1_src[0];
626
103k
    }
627
628
    /* If bottom-right is available, process separately */
629
141k
    if(0 != pu1_avail[7])
630
37.6k
    {
631
37.6k
        WORD32 edge_idx;
632
633
37.6k
        edge_idx = 2 + SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd - 1 - src_strd]) +
634
37.6k
                        SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd + 1 + src_strd]);
635
636
37.6k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
637
638
37.6k
        if(0 != edge_idx)
639
3.13k
        {
640
3.13k
            u1_pos_wd_ht_tmp = CLIP3(pu1_src[wd - 1 + (ht - 1) * src_strd] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
641
3.13k
        }
642
34.5k
        else
643
34.5k
        {
644
34.5k
            u1_pos_wd_ht_tmp = pu1_src[wd - 1 + (ht - 1) * src_strd];
645
34.5k
        }
646
37.6k
    }
647
103k
    else
648
103k
    {
649
103k
        u1_pos_wd_ht_tmp = pu1_src[wd - 1 + (ht - 1) * src_strd];
650
103k
    }
651
652
    /* If Left is not available */
653
141k
    if(0 == pu1_avail[0])
654
81.9k
    {
655
81.9k
        au1_mask[0] = 0;
656
81.9k
    }
657
658
    /* If Top is not available */
659
141k
    if(0 == pu1_avail[2])
660
89.5k
    {
661
89.5k
        pu1_src += src_strd;
662
89.5k
        ht--;
663
89.5k
        pu1_src_left_cpy += 1;
664
5.51M
        for(col = 1; col < wd; col++)
665
5.42M
        {
666
5.42M
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - 1 - src_strd]);
667
5.42M
        }
668
89.5k
    }
669
51.8k
    else
670
51.8k
    {
671
3.17M
        for(col = 1; col < wd; col++)
672
3.11M
        {
673
3.11M
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col - 1]);
674
3.11M
        }
675
51.8k
    }
676
677
    /* If Right is not available */
678
141k
    if(0 == pu1_avail[1])
679
82.0k
    {
680
82.0k
        au1_mask[wd - 1] = 0;
681
82.0k
    }
682
683
    /* If Bottom is not available */
684
141k
    if(0 == pu1_avail[3])
685
89.8k
    {
686
89.8k
        ht--;
687
89.8k
    }
688
689
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
690
141k
    {
691
8.61M
        for(row = 0; row < ht; row++)
692
8.47M
        {
693
8.47M
            pu1_sign_up[0] = SIGN(pu1_src[0] - pu1_src_left_cpy[row - 1]);
694
530M
            for(col = 0; col < wd; col++)
695
522M
            {
696
522M
                WORD32 edge_idx;
697
698
522M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + 1 + src_strd]);
699
522M
                edge_idx = 2 + pu1_sign_up[col] + u1_sign_down;
700
522M
                pu1_sign_up_tmp[col + 1] = -u1_sign_down;
701
702
522M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
703
704
522M
                if(0 != edge_idx)
705
28.9M
                {
706
28.9M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
707
28.9M
                }
708
522M
            }
709
710
            /* Swapping pu1_sign_up_tmp and pu1_sign_up */
711
8.47M
            {
712
8.47M
                WORD8 *pu1_swap_tmp = pu1_sign_up;
713
8.47M
                pu1_sign_up = pu1_sign_up_tmp;
714
8.47M
                pu1_sign_up_tmp = pu1_swap_tmp;
715
8.47M
            }
716
717
8.47M
            pu1_src += src_strd;
718
8.47M
        }
719
720
141k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd] = u1_pos_0_0_tmp;
721
141k
        pu1_src[(pu1_avail[3] ? wd - 1 - src_strd : wd - 1)] = u1_pos_wd_ht_tmp;
722
141k
    }
723
724
141k
    if(0 == pu1_avail[2])
725
89.5k
        ht++;
726
141k
    if(0 == pu1_avail[3])
727
89.8k
        ht++;
728
141k
    *pu1_src_top_left = u1_src_top_left_tmp;
729
8.79M
    for(row = 0; row < ht; row++)
730
8.65M
    {
731
8.65M
        pu1_src_left[row] = au1_src_left_tmp[row];
732
8.65M
    }
733
8.82M
    for(col = 0; col < wd; col++)
734
8.68M
    {
735
8.68M
        pu1_src_top[col] = au1_src_top_tmp[col];
736
8.68M
    }
737
738
141k
}
739
740
741
742
743
/* 135 degree filtering */
744
void ihevc_sao_edge_offset_class2_chroma(UWORD8 *pu1_src,
745
                                         WORD32 src_strd,
746
                                         UWORD8 *pu1_src_left,
747
                                         UWORD8 *pu1_src_top,
748
                                         UWORD8 *pu1_src_top_left,
749
                                         UWORD8 *pu1_src_top_right,
750
                                         UWORD8 *pu1_src_bot_left,
751
                                         UWORD8 *pu1_avail,
752
                                         WORD8 *pi1_sao_offset_u,
753
                                         WORD8 *pi1_sao_offset_v,
754
                                         WORD32 wd,
755
                                         WORD32 ht)
756
15.8k
{
757
15.8k
    WORD32 row, col;
758
15.8k
    UWORD8 au1_mask[MAX_CTB_SIZE];
759
15.8k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE], au1_src_top_tmp[2 * MAX_CTB_SIZE];
760
15.8k
    UWORD8 au1_src_top_left_tmp[2];
761
15.8k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE + 2], au1_sign_up_tmp[2 * MAX_CTB_SIZE + 2];
762
15.8k
    WORD8 u1_sign_down;
763
15.8k
    WORD8 *pu1_sign_up;
764
15.8k
    WORD8 *pu1_sign_up_tmp;
765
15.8k
    UWORD8 *pu1_src_left_cpy;
766
767
15.8k
    WORD32 bit_depth;
768
769
15.8k
    UWORD8 u1_pos_0_0_tmp_u;
770
15.8k
    UWORD8 u1_pos_0_0_tmp_v;
771
15.8k
    UWORD8 u1_pos_wd_ht_tmp_u;
772
15.8k
    UWORD8 u1_pos_wd_ht_tmp_v;
773
15.8k
    UNUSED(pu1_src_top_right);
774
15.8k
    UNUSED(pu1_src_bot_left);
775
776
777
15.8k
    bit_depth = BIT_DEPTH_CHROMA;
778
15.8k
    pu1_sign_up = au1_sign_up;
779
15.8k
    pu1_sign_up_tmp = au1_sign_up_tmp;
780
15.8k
    pu1_src_left_cpy = pu1_src_left;
781
782
    /* Initialize the mask values */
783
15.8k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
784
785
    /* Update left, top and top-left arrays */
786
15.8k
    au1_src_top_left_tmp[0] = pu1_src_top[wd - 2];
787
15.8k
    au1_src_top_left_tmp[1] = pu1_src_top[wd - 1];
788
494k
    for(row = 0; row < ht; row++)
789
479k
    {
790
479k
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
791
479k
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
792
479k
    }
793
989k
    for(col = 0; col < wd; col++)
794
973k
    {
795
973k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
796
973k
    }
797
798
799
    /* If top-left is available, process separately */
800
15.8k
    if(0 != pu1_avail[4])
801
3.30k
    {
802
3.30k
        WORD32 edge_idx;
803
804
        /* U */
805
3.30k
        edge_idx = 2 + SIGN(pu1_src[0] - pu1_src_top_left[0]) +
806
3.30k
                        SIGN(pu1_src[0] - pu1_src[2 + src_strd]);
807
808
3.30k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
809
810
3.30k
        if(0 != edge_idx)
811
428
        {
812
428
            u1_pos_0_0_tmp_u = CLIP3(pu1_src[0] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
813
428
        }
814
2.87k
        else
815
2.87k
        {
816
2.87k
            u1_pos_0_0_tmp_u = pu1_src[0];
817
2.87k
        }
818
819
        /* V */
820
3.30k
        edge_idx = 2 + SIGN(pu1_src[1] - pu1_src_top_left[1]) +
821
3.30k
                        SIGN(pu1_src[1] - pu1_src[1 + 2 + src_strd]);
822
823
3.30k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
824
825
3.30k
        if(0 != edge_idx)
826
386
        {
827
386
            u1_pos_0_0_tmp_v = CLIP3(pu1_src[1] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
828
386
        }
829
2.91k
        else
830
2.91k
        {
831
2.91k
            u1_pos_0_0_tmp_v = pu1_src[1];
832
2.91k
        }
833
3.30k
    }
834
12.5k
    else
835
12.5k
    {
836
12.5k
        u1_pos_0_0_tmp_u = pu1_src[0];
837
12.5k
        u1_pos_0_0_tmp_v = pu1_src[1];
838
12.5k
    }
839
840
    /* If bottom-right is available, process separately */
841
15.8k
    if(0 != pu1_avail[7])
842
2.90k
    {
843
2.90k
        WORD32 edge_idx;
844
845
        /* U */
846
2.90k
        edge_idx = 2 + SIGN(pu1_src[wd - 2 + (ht - 1) * src_strd] - pu1_src[wd - 2 + (ht - 1) * src_strd - 2 - src_strd]) +
847
2.90k
                        SIGN(pu1_src[wd - 2 + (ht - 1) * src_strd] - pu1_src[wd - 2 + (ht - 1) * src_strd + 2 + src_strd]);
848
849
2.90k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
850
851
2.90k
        if(0 != edge_idx)
852
433
        {
853
433
            u1_pos_wd_ht_tmp_u = CLIP3(pu1_src[wd - 2 + (ht - 1) * src_strd] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
854
433
        }
855
2.47k
        else
856
2.47k
        {
857
2.47k
            u1_pos_wd_ht_tmp_u = pu1_src[wd - 2 + (ht - 1) * src_strd];
858
2.47k
        }
859
860
        /* V */
861
2.90k
        edge_idx = 2 + SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd - 2 - src_strd]) +
862
2.90k
                        SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd + 2 + src_strd]);
863
864
2.90k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
865
866
2.90k
        if(0 != edge_idx)
867
405
        {
868
405
            u1_pos_wd_ht_tmp_v = CLIP3(pu1_src[wd - 1 + (ht - 1) * src_strd] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
869
405
        }
870
2.50k
        else
871
2.50k
        {
872
2.50k
            u1_pos_wd_ht_tmp_v = pu1_src[wd - 1 + (ht - 1) * src_strd];
873
2.50k
        }
874
2.90k
    }
875
12.9k
    else
876
12.9k
    {
877
12.9k
        u1_pos_wd_ht_tmp_u = pu1_src[wd - 2 + (ht - 1) * src_strd];
878
12.9k
        u1_pos_wd_ht_tmp_v = pu1_src[wd - 1 + (ht - 1) * src_strd];
879
12.9k
    }
880
881
    /* If Left is not available */
882
15.8k
    if(0 == pu1_avail[0])
883
10.3k
    {
884
10.3k
        au1_mask[0] = 0;
885
10.3k
    }
886
887
    /* If Top is not available */
888
15.8k
    if(0 == pu1_avail[2])
889
10.9k
    {
890
10.9k
        pu1_src += src_strd;
891
10.9k
        pu1_src_left_cpy += 2;
892
10.9k
        ht--;
893
660k
        for(col = 2; col < wd; col++)
894
649k
        {
895
649k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - 2 - src_strd]);
896
649k
        }
897
10.9k
    }
898
4.93k
    else
899
4.93k
    {
900
297k
        for(col = 2; col < wd; col++)
901
292k
        {
902
292k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col - 2]);
903
292k
        }
904
4.93k
    }
905
906
    /* If Right is not available */
907
15.8k
    if(0 == pu1_avail[1])
908
10.3k
    {
909
10.3k
        au1_mask[(wd - 1) >> 1] = 0;
910
10.3k
    }
911
912
    /* If Bottom is not available */
913
15.8k
    if(0 == pu1_avail[3])
914
11.1k
    {
915
11.1k
        ht--;
916
11.1k
    }
917
918
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
919
15.8k
    {
920
472k
        for(row = 0; row < ht; row++)
921
456k
        {
922
456k
            pu1_sign_up[0] = SIGN(pu1_src[0] - pu1_src_left_cpy[2 * (row - 1)]);
923
456k
            pu1_sign_up[1] = SIGN(pu1_src[1] - pu1_src_left_cpy[2 * (row - 1) + 1]);
924
28.6M
            for(col = 0; col < wd; col++)
925
28.2M
            {
926
28.2M
                WORD32 edge_idx;
927
28.2M
                WORD8 *pi1_sao_offset;
928
929
28.2M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
930
931
28.2M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + 2 + src_strd]);
932
28.2M
                edge_idx = 2 + pu1_sign_up[col] + u1_sign_down;
933
28.2M
                pu1_sign_up_tmp[col + 2] = -u1_sign_down;
934
935
28.2M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
936
937
28.2M
                if(0 != edge_idx)
938
2.54M
                {
939
2.54M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
940
2.54M
                }
941
28.2M
            }
942
943
            /* Swapping pu1_sign_up_tmp and pu1_sign_up */
944
456k
            {
945
456k
                WORD8 *pu1_swap_tmp = pu1_sign_up;
946
456k
                pu1_sign_up = pu1_sign_up_tmp;
947
456k
                pu1_sign_up_tmp = pu1_swap_tmp;
948
456k
            }
949
950
456k
            pu1_src += src_strd;
951
456k
        }
952
953
15.8k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd] = u1_pos_0_0_tmp_u;
954
15.8k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + 1] = u1_pos_0_0_tmp_v;
955
15.8k
        pu1_src[(pu1_avail[3] ? wd - 2 - src_strd : wd - 2)] = u1_pos_wd_ht_tmp_u;
956
15.8k
        pu1_src[(pu1_avail[3] ? wd - 1 - src_strd : wd - 1)] = u1_pos_wd_ht_tmp_v;
957
15.8k
    }
958
959
15.8k
    if(0 == pu1_avail[2])
960
10.9k
        ht++;
961
15.8k
    if(0 == pu1_avail[3])
962
11.1k
        ht++;
963
15.8k
    pu1_src_top_left[0] = au1_src_top_left_tmp[0];
964
15.8k
    pu1_src_top_left[1] = au1_src_top_left_tmp[1];
965
973k
    for(row = 0; row < 2 * ht; row++)
966
958k
    {
967
958k
        pu1_src_left[row] = au1_src_left_tmp[row];
968
958k
    }
969
989k
    for(col = 0; col < wd; col++)
970
973k
    {
971
973k
        pu1_src_top[col] = au1_src_top_tmp[col];
972
973k
    }
973
974
15.8k
}
975
976
977
978
979
/* 45 degree filtering */
980
void ihevc_sao_edge_offset_class3(UWORD8 *pu1_src,
981
                                  WORD32 src_strd,
982
                                  UWORD8 *pu1_src_left,
983
                                  UWORD8 *pu1_src_top,
984
                                  UWORD8 *pu1_src_top_left,
985
                                  UWORD8 *pu1_src_top_right,
986
                                  UWORD8 *pu1_src_bot_left,
987
                                  UWORD8 *pu1_avail,
988
                                  WORD8 *pi1_sao_offset,
989
                                  WORD32 wd,
990
                                  WORD32 ht)
991
140k
{
992
140k
    WORD32 row, col;
993
140k
    UWORD8 au1_mask[MAX_CTB_SIZE];
994
140k
    UWORD8 au1_src_top_tmp[MAX_CTB_SIZE];
995
140k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE];
996
140k
    UWORD8 u1_src_top_left_tmp;
997
140k
    WORD8 au1_sign_up[MAX_CTB_SIZE];
998
140k
    UWORD8 *pu1_src_left_cpy;
999
140k
    WORD8 u1_sign_down;
1000
140k
    WORD32 bit_depth;
1001
1002
140k
    UWORD8 u1_pos_0_ht_tmp;
1003
140k
    UWORD8 u1_pos_wd_0_tmp;
1004
1005
140k
    bit_depth = BIT_DEPTH_LUMA;
1006
140k
    pu1_src_left_cpy = pu1_src_left;
1007
1008
    /* Initialize the mask values */
1009
140k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
1010
1011
    /* Update left, top and top-left arrays */
1012
140k
    u1_src_top_left_tmp = pu1_src_top[wd - 1];
1013
8.72M
    for(row = 0; row < ht; row++)
1014
8.58M
    {
1015
8.58M
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
1016
8.58M
    }
1017
8.73M
    for(col = 0; col < wd; col++)
1018
8.59M
    {
1019
8.59M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
1020
8.59M
    }
1021
1022
    /* If top-right is available, process separately */
1023
140k
    if(0 != pu1_avail[5])
1024
37.6k
    {
1025
37.6k
        WORD32 edge_idx;
1026
1027
37.6k
        edge_idx = 2 + SIGN(pu1_src[wd - 1] - pu1_src_top_right[0]) +
1028
37.6k
                        SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 - 1 + src_strd]);
1029
1030
37.6k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1031
1032
37.6k
        if(0 != edge_idx)
1033
3.14k
        {
1034
3.14k
            u1_pos_wd_0_tmp = CLIP3(pu1_src[wd - 1] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1035
3.14k
        }
1036
34.5k
        else
1037
34.5k
        {
1038
34.5k
            u1_pos_wd_0_tmp = pu1_src[wd - 1];
1039
34.5k
        }
1040
37.6k
    }
1041
102k
    else
1042
102k
    {
1043
102k
        u1_pos_wd_0_tmp = pu1_src[wd - 1];
1044
102k
    }
1045
1046
    /* If bottom-left is available, process separately */
1047
140k
    if(0 != pu1_avail[6])
1048
37.9k
    {
1049
37.9k
        WORD32 edge_idx;
1050
1051
37.9k
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src[(ht - 1) * src_strd + 1 - src_strd]) +
1052
37.9k
                        SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src_bot_left[0]);
1053
1054
37.9k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1055
1056
37.9k
        if(0 != edge_idx)
1057
3.16k
        {
1058
3.16k
            u1_pos_0_ht_tmp = CLIP3(pu1_src[(ht - 1) * src_strd] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1059
3.16k
        }
1060
34.7k
        else
1061
34.7k
        {
1062
34.7k
            u1_pos_0_ht_tmp = pu1_src[(ht - 1) * src_strd];
1063
34.7k
        }
1064
37.9k
    }
1065
102k
    else
1066
102k
    {
1067
102k
        u1_pos_0_ht_tmp = pu1_src[(ht - 1) * src_strd];
1068
102k
    }
1069
1070
    /* If Left is not available */
1071
140k
    if(0 == pu1_avail[0])
1072
81.1k
    {
1073
81.1k
        au1_mask[0] = 0;
1074
81.1k
    }
1075
1076
    /* If Top is not available */
1077
140k
    if(0 == pu1_avail[2])
1078
88.4k
    {
1079
88.4k
        pu1_src += src_strd;
1080
88.4k
        ht--;
1081
88.4k
        pu1_src_left_cpy += 1;
1082
5.44M
        for(col = 0; col < wd - 1; col++)
1083
5.35M
        {
1084
5.35M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col + 1 - src_strd]);
1085
5.35M
        }
1086
88.4k
    }
1087
51.6k
    else
1088
51.6k
    {
1089
3.15M
        for(col = 0; col < wd - 1; col++)
1090
3.09M
        {
1091
3.09M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col + 1]);
1092
3.09M
        }
1093
51.6k
    }
1094
1095
    /* If Right is not available */
1096
140k
    if(0 == pu1_avail[1])
1097
81.3k
    {
1098
81.3k
        au1_mask[wd - 1] = 0;
1099
81.3k
    }
1100
1101
    /* If Bottom is not available */
1102
140k
    if(0 == pu1_avail[3])
1103
88.5k
    {
1104
88.5k
        ht--;
1105
88.5k
    }
1106
1107
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
1108
140k
    {
1109
8.54M
        for(row = 0; row < ht; row++)
1110
8.40M
        {
1111
8.40M
            au1_sign_up[wd - 1] = SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 + 1 - src_strd]);
1112
526M
            for(col = 0; col < wd; col++)
1113
517M
            {
1114
517M
                WORD32 edge_idx;
1115
1116
517M
                u1_sign_down = SIGN(pu1_src[col] - ((col == 0) ? pu1_src_left_cpy[row + 1] :
1117
517M
                                                                 pu1_src[col - 1 + src_strd]));
1118
517M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
1119
517M
                if(col > 0)
1120
509M
                    au1_sign_up[col - 1] = -u1_sign_down;
1121
1122
517M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
1123
1124
517M
                if(0 != edge_idx)
1125
29.0M
                {
1126
29.0M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1127
29.0M
                }
1128
517M
            }
1129
1130
8.40M
            pu1_src += src_strd;
1131
8.40M
        }
1132
1133
140k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 1] = u1_pos_wd_0_tmp;
1134
140k
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0)] = u1_pos_0_ht_tmp;
1135
140k
    }
1136
1137
140k
    if(0 == pu1_avail[2])
1138
88.4k
        ht++;
1139
140k
    if(0 == pu1_avail[3])
1140
88.5k
        ht++;
1141
140k
    *pu1_src_top_left = u1_src_top_left_tmp;
1142
8.72M
    for(row = 0; row < ht; row++)
1143
8.58M
    {
1144
8.58M
        pu1_src_left[row] = au1_src_left_tmp[row];
1145
8.58M
    }
1146
8.73M
    for(col = 0; col < wd; col++)
1147
8.59M
    {
1148
8.59M
        pu1_src_top[col] = au1_src_top_tmp[col];
1149
8.59M
    }
1150
1151
140k
}
1152
1153
1154
1155
1156
void ihevc_sao_edge_offset_class3_chroma(UWORD8 *pu1_src,
1157
                                         WORD32 src_strd,
1158
                                         UWORD8 *pu1_src_left,
1159
                                         UWORD8 *pu1_src_top,
1160
                                         UWORD8 *pu1_src_top_left,
1161
                                         UWORD8 *pu1_src_top_right,
1162
                                         UWORD8 *pu1_src_bot_left,
1163
                                         UWORD8 *pu1_avail,
1164
                                         WORD8 *pi1_sao_offset_u,
1165
                                         WORD8 *pi1_sao_offset_v,
1166
                                         WORD32 wd,
1167
                                         WORD32 ht)
1168
14.5k
{
1169
14.5k
    WORD32 row, col;
1170
14.5k
    UWORD8 au1_mask[MAX_CTB_SIZE];
1171
14.5k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE], au1_src_top_tmp[2 * MAX_CTB_SIZE];
1172
14.5k
    UWORD8 au1_src_top_left_tmp[2];
1173
14.5k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE];
1174
14.5k
    UWORD8 *pu1_src_left_cpy;
1175
14.5k
    WORD8 u1_sign_down;
1176
14.5k
    WORD32 bit_depth;
1177
1178
14.5k
    UWORD8 u1_pos_wd_0_tmp_u;
1179
14.5k
    UWORD8 u1_pos_wd_0_tmp_v;
1180
14.5k
    UWORD8 u1_pos_0_ht_tmp_u;
1181
14.5k
    UWORD8 u1_pos_0_ht_tmp_v;
1182
1183
14.5k
    bit_depth = BIT_DEPTH_CHROMA;
1184
14.5k
    pu1_src_left_cpy = pu1_src_left;
1185
1186
    /* Initialize the mask values */
1187
14.5k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
1188
1189
    /* Update left, top and top-left arrays */
1190
14.5k
    au1_src_top_left_tmp[0] = pu1_src_top[wd - 2];
1191
14.5k
    au1_src_top_left_tmp[1] = pu1_src_top[wd - 1];
1192
459k
    for(row = 0; row < ht; row++)
1193
445k
    {
1194
445k
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
1195
445k
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
1196
445k
    }
1197
898k
    for(col = 0; col < wd; col++)
1198
883k
    {
1199
883k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
1200
883k
    }
1201
1202
1203
    /* If top-right is available, process separately */
1204
14.5k
    if(0 != pu1_avail[5])
1205
2.93k
    {
1206
2.93k
        WORD32 edge_idx;
1207
1208
        /* U */
1209
2.93k
        edge_idx = 2 + SIGN(pu1_src[wd - 2] - pu1_src_top_right[0]) +
1210
2.93k
                        SIGN(pu1_src[wd - 2] - pu1_src[wd - 2 - 2 + src_strd]);
1211
1212
2.93k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1213
1214
2.93k
        if(0 != edge_idx)
1215
502
        {
1216
502
            u1_pos_wd_0_tmp_u = CLIP3(pu1_src[wd - 2] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
1217
502
        }
1218
2.43k
        else
1219
2.43k
        {
1220
2.43k
            u1_pos_wd_0_tmp_u = pu1_src[wd - 2];
1221
2.43k
        }
1222
1223
        /* V */
1224
2.93k
        edge_idx = 2 + SIGN(pu1_src[wd - 1] - pu1_src_top_right[1]) +
1225
2.93k
                        SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 - 2 + src_strd]);
1226
1227
2.93k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1228
1229
2.93k
        if(0 != edge_idx)
1230
407
        {
1231
407
            u1_pos_wd_0_tmp_v = CLIP3(pu1_src[wd - 1] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
1232
407
        }
1233
2.53k
        else
1234
2.53k
        {
1235
2.53k
            u1_pos_wd_0_tmp_v = pu1_src[wd - 1];
1236
2.53k
        }
1237
2.93k
    }
1238
11.5k
    else
1239
11.5k
    {
1240
11.5k
        u1_pos_wd_0_tmp_u = pu1_src[wd - 2];
1241
11.5k
        u1_pos_wd_0_tmp_v = pu1_src[wd - 1];
1242
11.5k
    }
1243
1244
    /* If bottom-left is available, process separately */
1245
14.5k
    if(0 != pu1_avail[6])
1246
3.17k
    {
1247
3.17k
        WORD32 edge_idx;
1248
1249
        /* U */
1250
3.17k
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src[(ht - 1) * src_strd + 2 - src_strd]) +
1251
3.17k
                        SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src_bot_left[0]);
1252
1253
3.17k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1254
1255
3.17k
        if(0 != edge_idx)
1256
449
        {
1257
449
            u1_pos_0_ht_tmp_u = CLIP3(pu1_src[(ht - 1) * src_strd] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
1258
449
        }
1259
2.72k
        else
1260
2.72k
        {
1261
2.72k
            u1_pos_0_ht_tmp_u = pu1_src[(ht - 1) * src_strd];
1262
2.72k
        }
1263
1264
        /* V */
1265
3.17k
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd + 1] - pu1_src[(ht - 1) * src_strd + 1 + 2 - src_strd]) +
1266
3.17k
                        SIGN(pu1_src[(ht - 1) * src_strd + 1] - pu1_src_bot_left[1]);
1267
1268
3.17k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1269
1270
3.17k
        if(0 != edge_idx)
1271
379
        {
1272
379
            u1_pos_0_ht_tmp_v = CLIP3(pu1_src[(ht - 1) * src_strd + 1] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
1273
379
        }
1274
2.79k
        else
1275
2.79k
        {
1276
2.79k
            u1_pos_0_ht_tmp_v = pu1_src[(ht - 1) * src_strd + 1];
1277
2.79k
        }
1278
3.17k
    }
1279
11.3k
    else
1280
11.3k
    {
1281
11.3k
        u1_pos_0_ht_tmp_u = pu1_src[(ht - 1) * src_strd];
1282
11.3k
        u1_pos_0_ht_tmp_v = pu1_src[(ht - 1) * src_strd + 1];
1283
11.3k
    }
1284
1285
    /* If Left is not available */
1286
14.5k
    if(0 == pu1_avail[0])
1287
9.51k
    {
1288
9.51k
        au1_mask[0] = 0;
1289
9.51k
    }
1290
1291
    /* If Top is not available */
1292
14.5k
    if(0 == pu1_avail[2])
1293
9.85k
    {
1294
9.85k
        pu1_src += src_strd;
1295
9.85k
        ht--;
1296
9.85k
        pu1_src_left_cpy += 2;
1297
591k
        for(col = 0; col < wd - 2; col++)
1298
581k
        {
1299
581k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col + 2 - src_strd]);
1300
581k
        }
1301
9.85k
    }
1302
4.67k
    else
1303
4.67k
    {
1304
277k
        for(col = 0; col < wd - 2; col++)
1305
272k
        {
1306
272k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col + 2]);
1307
272k
        }
1308
4.67k
    }
1309
1310
    /* If Right is not available */
1311
14.5k
    if(0 == pu1_avail[1])
1312
9.73k
    {
1313
9.73k
        au1_mask[(wd - 1) >> 1] = 0;
1314
9.73k
    }
1315
1316
    /* If Bottom is not available */
1317
14.5k
    if(0 == pu1_avail[3])
1318
9.87k
    {
1319
9.87k
        ht--;
1320
9.87k
    }
1321
1322
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
1323
14.5k
    {
1324
440k
        for(row = 0; row < ht; row++)
1325
425k
        {
1326
425k
            au1_sign_up[wd - 2] = SIGN(pu1_src[wd - 2] - pu1_src[wd - 2 + 2 - src_strd]);
1327
425k
            au1_sign_up[wd - 1] = SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 + 2 - src_strd]);
1328
26.4M
            for(col = 0; col < wd; col++)
1329
26.0M
            {
1330
26.0M
                WORD32 edge_idx;
1331
26.0M
                WORD8 *pi1_sao_offset;
1332
1333
26.0M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
1334
1335
26.0M
                u1_sign_down = SIGN(pu1_src[col] - ((col < 2) ? pu1_src_left_cpy[2 * (row + 1) + col] :
1336
26.0M
                                                                pu1_src[col - 2 + src_strd]));
1337
26.0M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
1338
26.0M
                if(col > 1)
1339
25.1M
                    au1_sign_up[col - 2] = -u1_sign_down;
1340
1341
26.0M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
1342
1343
26.0M
                if(0 != edge_idx)
1344
2.33M
                {
1345
2.33M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1346
2.33M
                }
1347
26.0M
            }
1348
1349
425k
            pu1_src += src_strd;
1350
425k
        }
1351
1352
14.5k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 2] = u1_pos_wd_0_tmp_u;
1353
14.5k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 1] = u1_pos_wd_0_tmp_v;
1354
14.5k
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0)] = u1_pos_0_ht_tmp_u;
1355
14.5k
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0) + 1] = u1_pos_0_ht_tmp_v;
1356
14.5k
    }
1357
1358
14.5k
    if(0 == pu1_avail[2])
1359
9.85k
        ht++;
1360
14.5k
    if(0 == pu1_avail[3])
1361
9.87k
        ht++;
1362
14.5k
    pu1_src_top_left[0] = au1_src_top_left_tmp[0];
1363
14.5k
    pu1_src_top_left[1] = au1_src_top_left_tmp[1];
1364
905k
    for(row = 0; row < 2 * ht; row++)
1365
890k
    {
1366
890k
        pu1_src_left[row] = au1_src_left_tmp[row];
1367
890k
    }
1368
898k
    for(col = 0; col < wd; col++)
1369
883k
    {
1370
883k
        pu1_src_top[col] = au1_src_top_tmp[col];
1371
883k
    }
1372
1373
14.5k
}