Coverage Report

Created: 2026-09-01 06:17

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
19.7k
{
197
19.7k
    WORD32 row, col;
198
19.7k
    UWORD8 au1_mask[MAX_CTB_SIZE];
199
19.7k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE];
200
19.7k
    WORD8 u1_sign_left, u1_sign_right;
201
19.7k
    WORD32 bit_depth;
202
19.7k
    UNUSED(pu1_src_top_right);
203
19.7k
    UNUSED(pu1_src_bot_left);
204
19.7k
    bit_depth = BIT_DEPTH_LUMA;
205
206
    /* Initialize the mask values */
207
19.7k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
208
209
    /* Update top and top-left arrays */
210
19.7k
    *pu1_src_top_left = pu1_src_top[wd - 1];
211
1.08M
    for(row = 0; row < ht; row++)
212
1.06M
    {
213
1.06M
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
214
1.06M
    }
215
1.11M
    for(col = 0; col < wd; col++)
216
1.09M
    {
217
1.09M
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
218
1.09M
    }
219
220
    /* Update masks based on the availability flags */
221
19.7k
    if(0 == pu1_avail[0])
222
8.07k
    {
223
8.07k
        au1_mask[0] = 0;
224
8.07k
    }
225
19.7k
    if(0 == pu1_avail[1])
226
8.88k
    {
227
8.88k
        au1_mask[wd - 1] = 0;
228
8.88k
    }
229
230
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
231
19.7k
    {
232
1.08M
        for(row = 0; row < ht; row++)
233
1.06M
        {
234
1.06M
            u1_sign_left = SIGN(pu1_src[0] - pu1_src_left[row]);
235
61.4M
            for(col = 0; col < wd; col++)
236
60.3M
            {
237
60.3M
                WORD32 edge_idx;
238
239
60.3M
                u1_sign_right = SIGN(pu1_src[col] - pu1_src[col + 1]);
240
60.3M
                edge_idx = 2 + u1_sign_left + u1_sign_right;
241
60.3M
                u1_sign_left = -u1_sign_right;
242
243
60.3M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
244
245
60.3M
                if(0 != edge_idx)
246
17.0M
                {
247
17.0M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
248
17.0M
                }
249
60.3M
            }
250
251
1.06M
            pu1_src += src_strd;
252
1.06M
        }
253
19.7k
    }
254
255
    /* Update left array */
256
1.08M
    for(row = 0; row < ht; row++)
257
1.06M
    {
258
1.06M
        pu1_src_left[row] = au1_src_left_tmp[row];
259
1.06M
    }
260
261
19.7k
}
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
10.8k
{
280
10.8k
    WORD32 row, col;
281
10.8k
    UWORD8 au1_mask[MAX_CTB_SIZE];
282
10.8k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE];
283
10.8k
    WORD8 u1_sign_left_u, u1_sign_right_u;
284
10.8k
    WORD8 u1_sign_left_v, u1_sign_right_v;
285
10.8k
    WORD32 bit_depth;
286
10.8k
    UNUSED(pu1_src_top_right);
287
10.8k
    UNUSED(pu1_src_bot_left);
288
10.8k
    bit_depth = BIT_DEPTH_CHROMA;
289
290
    /* Initialize the mask values */
291
10.8k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
292
293
    /* Update left, top and top-left arrays */
294
10.8k
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
295
10.8k
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
296
305k
    for(row = 0; row < ht; row++)
297
294k
    {
298
294k
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
299
294k
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
300
294k
    }
301
598k
    for(col = 0; col < wd; col++)
302
587k
    {
303
587k
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
304
587k
    }
305
306
    /* Update masks based on the availability flags */
307
10.8k
    if(0 == pu1_avail[0])
308
3.79k
    {
309
3.79k
        au1_mask[0] = 0;
310
3.79k
    }
311
10.8k
    if(0 == pu1_avail[1])
312
4.60k
    {
313
4.60k
        au1_mask[(wd - 1) >> 1] = 0;
314
4.60k
    }
315
316
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
317
10.8k
    {
318
305k
        for(row = 0; row < ht; row++)
319
294k
        {
320
294k
            u1_sign_left_u = SIGN(pu1_src[0] - pu1_src_left[2 * row]);
321
294k
            u1_sign_left_v = SIGN(pu1_src[1] - pu1_src_left[2 * row + 1]);
322
16.5M
            for(col = 0; col < wd; col++)
323
16.2M
            {
324
16.2M
                WORD32 edge_idx;
325
16.2M
                WORD8 *pi1_sao_offset;
326
327
16.2M
                if(0 == col % 2)
328
8.14M
                {
329
8.14M
                    pi1_sao_offset = pi1_sao_offset_u;
330
8.14M
                    u1_sign_right_u = SIGN(pu1_src[col] - pu1_src[col + 2]);
331
8.14M
                    edge_idx = 2 + u1_sign_left_u + u1_sign_right_u;
332
8.14M
                    u1_sign_left_u = -u1_sign_right_u;
333
8.14M
                }
334
8.14M
                else
335
8.14M
                {
336
8.14M
                    pi1_sao_offset = pi1_sao_offset_v;
337
8.14M
                    u1_sign_right_v = SIGN(pu1_src[col] - pu1_src[col + 2]);
338
8.14M
                    edge_idx = 2 + u1_sign_left_v + u1_sign_right_v;
339
8.14M
                    u1_sign_left_v = -u1_sign_right_v;
340
8.14M
                }
341
342
16.2M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
343
344
16.2M
                if(0 != edge_idx)
345
3.68M
                {
346
3.68M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
347
3.68M
                }
348
16.2M
            }
349
350
294k
            pu1_src += src_strd;
351
294k
        }
352
10.8k
    }
353
354
599k
    for(row = 0; row < 2 * ht; row++)
355
588k
    {
356
588k
        pu1_src_left[row] = au1_src_left_tmp[row];
357
588k
    }
358
359
10.8k
}
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
11.9k
{
376
11.9k
    WORD32 row, col;
377
11.9k
    UWORD8 au1_mask[MAX_CTB_SIZE];
378
11.9k
    UWORD8 au1_src_top_tmp[MAX_CTB_SIZE];
379
11.9k
    WORD8 au1_sign_up[MAX_CTB_SIZE];
380
11.9k
    WORD8 u1_sign_down;
381
11.9k
    WORD32 bit_depth;
382
11.9k
    UNUSED(pu1_src_top_right);
383
11.9k
    UNUSED(pu1_src_bot_left);
384
385
11.9k
    bit_depth = BIT_DEPTH_LUMA;
386
387
    /* Initialize the mask values */
388
11.9k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
389
390
    /* Update left, top and top-left arrays */
391
11.9k
    *pu1_src_top_left = pu1_src_top[wd - 1];
392
660k
    for(row = 0; row < ht; row++)
393
648k
    {
394
648k
        pu1_src_left[row] = pu1_src[row * src_strd + wd - 1];
395
648k
    }
396
698k
    for(col = 0; col < wd; col++)
397
686k
    {
398
686k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
399
686k
    }
400
401
    /* Update height and source pointers based on the availability flags */
402
11.9k
    if(0 == pu1_avail[2])
403
4.47k
    {
404
4.47k
        pu1_src += src_strd;
405
4.47k
        ht--;
406
261k
        for(col = 0; col < wd; col++)
407
257k
        {
408
257k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - src_strd]);
409
257k
        }
410
4.47k
    }
411
7.44k
    else
412
7.44k
    {
413
436k
        for(col = 0; col < wd; col++)
414
429k
        {
415
429k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col]);
416
429k
        }
417
7.44k
    }
418
11.9k
    if(0 == pu1_avail[3])
419
4.69k
    {
420
4.69k
        ht--;
421
4.69k
    }
422
423
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
424
11.9k
    {
425
651k
        for(row = 0; row < ht; row++)
426
639k
        {
427
38.2M
            for(col = 0; col < wd; col++)
428
37.6M
            {
429
37.6M
                WORD32 edge_idx;
430
431
37.6M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + src_strd]);
432
37.6M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
433
37.6M
                au1_sign_up[col] = -u1_sign_down;
434
435
37.6M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
436
437
37.6M
                if(0 != edge_idx)
438
9.72M
                {
439
9.72M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
440
9.72M
                }
441
37.6M
            }
442
443
639k
            pu1_src += src_strd;
444
639k
        }
445
11.9k
    }
446
447
698k
    for(col = 0; col < wd; col++)
448
686k
    {
449
686k
        pu1_src_top[col] = au1_src_top_tmp[col];
450
686k
    }
451
452
11.9k
}
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
2.98k
{
470
2.98k
    WORD32 row, col;
471
2.98k
    UWORD8 au1_mask[MAX_CTB_SIZE];
472
2.98k
    UWORD8 au1_src_top_tmp[2 * MAX_CTB_SIZE];
473
2.98k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE];
474
2.98k
    WORD8 u1_sign_down;
475
2.98k
    WORD32 bit_depth;
476
2.98k
    UNUSED(pu1_src_top_right);
477
2.98k
    UNUSED(pu1_src_bot_left);
478
479
2.98k
    bit_depth = BIT_DEPTH_CHROMA;
480
481
    /* Initialize the mask values */
482
2.98k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
483
484
    /* Update left, top and top-left arrays */
485
2.98k
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
486
2.98k
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
487
87.5k
    for(row = 0; row < ht; row++)
488
84.6k
    {
489
84.6k
        pu1_src_left[2 * row] = pu1_src[row * src_strd + wd - 2];
490
84.6k
        pu1_src_left[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
491
84.6k
    }
492
181k
    for(col = 0; col < wd; col++)
493
178k
    {
494
178k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
495
178k
    }
496
497
    /* Update height and source pointers based on the availability flags */
498
2.98k
    if(0 == pu1_avail[2])
499
645
    {
500
645
        pu1_src += src_strd;
501
645
        ht--;
502
38.6k
        for(col = 0; col < wd; col++)
503
38.0k
        {
504
38.0k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - src_strd]);
505
38.0k
        }
506
645
    }
507
2.34k
    else
508
2.34k
    {
509
142k
        for(col = 0; col < wd; col++)
510
140k
        {
511
140k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col]);
512
140k
        }
513
2.34k
    }
514
2.98k
    if(0 == pu1_avail[3])
515
872
    {
516
872
        ht--;
517
872
    }
518
519
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
520
2.98k
    {
521
86.0k
        for(row = 0; row < ht; row++)
522
83.0k
        {
523
5.15M
            for(col = 0; col < wd; col++)
524
5.07M
            {
525
5.07M
                WORD32 edge_idx;
526
5.07M
                WORD8 *pi1_sao_offset;
527
528
5.07M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
529
530
5.07M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + src_strd]);
531
5.07M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
532
5.07M
                au1_sign_up[col] = -u1_sign_down;
533
534
5.07M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
535
536
5.07M
                if(0 != edge_idx)
537
491k
                {
538
491k
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
539
491k
                }
540
5.07M
            }
541
542
83.0k
            pu1_src += src_strd;
543
83.0k
        }
544
2.98k
    }
545
546
181k
    for(col = 0; col < wd; col++)
547
178k
    {
548
178k
        pu1_src_top[col] = au1_src_top_tmp[col];
549
178k
    }
550
551
2.98k
}
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
9.95k
{
568
9.95k
    WORD32 row, col;
569
9.95k
    UWORD8 au1_mask[MAX_CTB_SIZE];
570
9.95k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE], au1_src_top_tmp[MAX_CTB_SIZE];
571
9.95k
    UWORD8 u1_src_top_left_tmp;
572
9.95k
    WORD8 au1_sign_up[MAX_CTB_SIZE + 1], au1_sign_up_tmp[MAX_CTB_SIZE + 1];
573
9.95k
    WORD8 u1_sign_down;
574
9.95k
    WORD8 *pu1_sign_up;
575
9.95k
    WORD8 *pu1_sign_up_tmp;
576
9.95k
    UWORD8 *pu1_src_left_cpy;
577
578
9.95k
    WORD32 bit_depth;
579
9.95k
    UWORD8 u1_pos_0_0_tmp;
580
9.95k
    UWORD8 u1_pos_wd_ht_tmp;
581
9.95k
    UNUSED(pu1_src_top_right);
582
9.95k
    UNUSED(pu1_src_bot_left);
583
584
9.95k
    bit_depth = BIT_DEPTH_LUMA;
585
9.95k
    pu1_sign_up = au1_sign_up;
586
9.95k
    pu1_sign_up_tmp = au1_sign_up_tmp;
587
9.95k
    pu1_src_left_cpy = pu1_src_left;
588
589
    /* Initialize the mask values */
590
9.95k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
591
592
    /* Update left, top and top-left arrays */
593
9.95k
    u1_src_top_left_tmp = pu1_src_top[wd - 1];
594
546k
    for(row = 0; row < ht; row++)
595
536k
    {
596
536k
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
597
536k
    }
598
578k
    for(col = 0; col < wd; col++)
599
568k
    {
600
568k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
601
568k
    }
602
603
604
    /* If top-left is available, process separately */
605
9.95k
    if(0 != pu1_avail[4])
606
3.17k
    {
607
3.17k
        WORD32 edge_idx;
608
609
3.17k
        edge_idx = 2 + SIGN(pu1_src[0] - pu1_src_top_left[0]) +
610
3.17k
                        SIGN(pu1_src[0] - pu1_src[1 + src_strd]);
611
612
3.17k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
613
614
3.17k
        if(0 != edge_idx)
615
1.28k
        {
616
1.28k
            u1_pos_0_0_tmp = CLIP3(pu1_src[0] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
617
1.28k
        }
618
1.89k
        else
619
1.89k
        {
620
1.89k
            u1_pos_0_0_tmp = pu1_src[0];
621
1.89k
        }
622
3.17k
    }
623
6.78k
    else
624
6.78k
    {
625
6.78k
        u1_pos_0_0_tmp = pu1_src[0];
626
6.78k
    }
627
628
    /* If bottom-right is available, process separately */
629
9.95k
    if(0 != pu1_avail[7])
630
3.07k
    {
631
3.07k
        WORD32 edge_idx;
632
633
3.07k
        edge_idx = 2 + SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd - 1 - src_strd]) +
634
3.07k
                        SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd + 1 + src_strd]);
635
636
3.07k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
637
638
3.07k
        if(0 != edge_idx)
639
1.25k
        {
640
1.25k
            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
1.25k
        }
642
1.82k
        else
643
1.82k
        {
644
1.82k
            u1_pos_wd_ht_tmp = pu1_src[wd - 1 + (ht - 1) * src_strd];
645
1.82k
        }
646
3.07k
    }
647
6.88k
    else
648
6.88k
    {
649
6.88k
        u1_pos_wd_ht_tmp = pu1_src[wd - 1 + (ht - 1) * src_strd];
650
6.88k
    }
651
652
    /* If Left is not available */
653
9.95k
    if(0 == pu1_avail[0])
654
4.66k
    {
655
4.66k
        au1_mask[0] = 0;
656
4.66k
    }
657
658
    /* If Top is not available */
659
9.95k
    if(0 == pu1_avail[2])
660
4.25k
    {
661
4.25k
        pu1_src += src_strd;
662
4.25k
        ht--;
663
4.25k
        pu1_src_left_cpy += 1;
664
244k
        for(col = 1; col < wd; col++)
665
240k
        {
666
240k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - 1 - src_strd]);
667
240k
        }
668
4.25k
    }
669
5.70k
    else
670
5.70k
    {
671
323k
        for(col = 1; col < wd; col++)
672
317k
        {
673
317k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col - 1]);
674
317k
        }
675
5.70k
    }
676
677
    /* If Right is not available */
678
9.95k
    if(0 == pu1_avail[1])
679
4.71k
    {
680
4.71k
        au1_mask[wd - 1] = 0;
681
4.71k
    }
682
683
    /* If Bottom is not available */
684
9.95k
    if(0 == pu1_avail[3])
685
4.34k
    {
686
4.34k
        ht--;
687
4.34k
    }
688
689
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
690
9.95k
    {
691
537k
        for(row = 0; row < ht; row++)
692
527k
        {
693
527k
            pu1_sign_up[0] = SIGN(pu1_src[0] - pu1_src_left_cpy[row - 1]);
694
31.2M
            for(col = 0; col < wd; col++)
695
30.7M
            {
696
30.7M
                WORD32 edge_idx;
697
698
30.7M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + 1 + src_strd]);
699
30.7M
                edge_idx = 2 + pu1_sign_up[col] + u1_sign_down;
700
30.7M
                pu1_sign_up_tmp[col + 1] = -u1_sign_down;
701
702
30.7M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
703
704
30.7M
                if(0 != edge_idx)
705
9.41M
                {
706
9.41M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
707
9.41M
                }
708
30.7M
            }
709
710
            /* Swapping pu1_sign_up_tmp and pu1_sign_up */
711
527k
            {
712
527k
                WORD8 *pu1_swap_tmp = pu1_sign_up;
713
527k
                pu1_sign_up = pu1_sign_up_tmp;
714
527k
                pu1_sign_up_tmp = pu1_swap_tmp;
715
527k
            }
716
717
527k
            pu1_src += src_strd;
718
527k
        }
719
720
9.95k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd] = u1_pos_0_0_tmp;
721
9.95k
        pu1_src[(pu1_avail[3] ? wd - 1 - src_strd : wd - 1)] = u1_pos_wd_ht_tmp;
722
9.95k
    }
723
724
9.95k
    if(0 == pu1_avail[2])
725
4.25k
        ht++;
726
9.95k
    if(0 == pu1_avail[3])
727
4.34k
        ht++;
728
9.95k
    *pu1_src_top_left = u1_src_top_left_tmp;
729
546k
    for(row = 0; row < ht; row++)
730
536k
    {
731
536k
        pu1_src_left[row] = au1_src_left_tmp[row];
732
536k
    }
733
578k
    for(col = 0; col < wd; col++)
734
568k
    {
735
568k
        pu1_src_top[col] = au1_src_top_tmp[col];
736
568k
    }
737
738
9.95k
}
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
1.03k
{
757
1.03k
    WORD32 row, col;
758
1.03k
    UWORD8 au1_mask[MAX_CTB_SIZE];
759
1.03k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE], au1_src_top_tmp[2 * MAX_CTB_SIZE];
760
1.03k
    UWORD8 au1_src_top_left_tmp[2];
761
1.03k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE + 2], au1_sign_up_tmp[2 * MAX_CTB_SIZE + 2];
762
1.03k
    WORD8 u1_sign_down;
763
1.03k
    WORD8 *pu1_sign_up;
764
1.03k
    WORD8 *pu1_sign_up_tmp;
765
1.03k
    UWORD8 *pu1_src_left_cpy;
766
767
1.03k
    WORD32 bit_depth;
768
769
1.03k
    UWORD8 u1_pos_0_0_tmp_u;
770
1.03k
    UWORD8 u1_pos_0_0_tmp_v;
771
1.03k
    UWORD8 u1_pos_wd_ht_tmp_u;
772
1.03k
    UWORD8 u1_pos_wd_ht_tmp_v;
773
1.03k
    UNUSED(pu1_src_top_right);
774
1.03k
    UNUSED(pu1_src_bot_left);
775
776
777
1.03k
    bit_depth = BIT_DEPTH_CHROMA;
778
1.03k
    pu1_sign_up = au1_sign_up;
779
1.03k
    pu1_sign_up_tmp = au1_sign_up_tmp;
780
1.03k
    pu1_src_left_cpy = pu1_src_left;
781
782
    /* Initialize the mask values */
783
1.03k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
784
785
    /* Update left, top and top-left arrays */
786
1.03k
    au1_src_top_left_tmp[0] = pu1_src_top[wd - 2];
787
1.03k
    au1_src_top_left_tmp[1] = pu1_src_top[wd - 1];
788
29.3k
    for(row = 0; row < ht; row++)
789
28.3k
    {
790
28.3k
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
791
28.3k
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
792
28.3k
    }
793
61.1k
    for(col = 0; col < wd; col++)
794
60.1k
    {
795
60.1k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
796
60.1k
    }
797
798
799
    /* If top-left is available, process separately */
800
1.03k
    if(0 != pu1_avail[4])
801
431
    {
802
431
        WORD32 edge_idx;
803
804
        /* U */
805
431
        edge_idx = 2 + SIGN(pu1_src[0] - pu1_src_top_left[0]) +
806
431
                        SIGN(pu1_src[0] - pu1_src[2 + src_strd]);
807
808
431
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
809
810
431
        if(0 != edge_idx)
811
211
        {
812
211
            u1_pos_0_0_tmp_u = CLIP3(pu1_src[0] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
813
211
        }
814
220
        else
815
220
        {
816
220
            u1_pos_0_0_tmp_u = pu1_src[0];
817
220
        }
818
819
        /* V */
820
431
        edge_idx = 2 + SIGN(pu1_src[1] - pu1_src_top_left[1]) +
821
431
                        SIGN(pu1_src[1] - pu1_src[1 + 2 + src_strd]);
822
823
431
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
824
825
431
        if(0 != edge_idx)
826
201
        {
827
201
            u1_pos_0_0_tmp_v = CLIP3(pu1_src[1] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
828
201
        }
829
230
        else
830
230
        {
831
230
            u1_pos_0_0_tmp_v = pu1_src[1];
832
230
        }
833
431
    }
834
599
    else
835
599
    {
836
599
        u1_pos_0_0_tmp_u = pu1_src[0];
837
599
        u1_pos_0_0_tmp_v = pu1_src[1];
838
599
    }
839
840
    /* If bottom-right is available, process separately */
841
1.03k
    if(0 != pu1_avail[7])
842
335
    {
843
335
        WORD32 edge_idx;
844
845
        /* U */
846
335
        edge_idx = 2 + SIGN(pu1_src[wd - 2 + (ht - 1) * src_strd] - pu1_src[wd - 2 + (ht - 1) * src_strd - 2 - src_strd]) +
847
335
                        SIGN(pu1_src[wd - 2 + (ht - 1) * src_strd] - pu1_src[wd - 2 + (ht - 1) * src_strd + 2 + src_strd]);
848
849
335
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
850
851
335
        if(0 != edge_idx)
852
189
        {
853
189
            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
189
        }
855
146
        else
856
146
        {
857
146
            u1_pos_wd_ht_tmp_u = pu1_src[wd - 2 + (ht - 1) * src_strd];
858
146
        }
859
860
        /* V */
861
335
        edge_idx = 2 + SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd - 2 - src_strd]) +
862
335
                        SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd + 2 + src_strd]);
863
864
335
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
865
866
335
        if(0 != edge_idx)
867
174
        {
868
174
            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
174
        }
870
161
        else
871
161
        {
872
161
            u1_pos_wd_ht_tmp_v = pu1_src[wd - 1 + (ht - 1) * src_strd];
873
161
        }
874
335
    }
875
695
    else
876
695
    {
877
695
        u1_pos_wd_ht_tmp_u = pu1_src[wd - 2 + (ht - 1) * src_strd];
878
695
        u1_pos_wd_ht_tmp_v = pu1_src[wd - 1 + (ht - 1) * src_strd];
879
695
    }
880
881
    /* If Left is not available */
882
1.03k
    if(0 == pu1_avail[0])
883
380
    {
884
380
        au1_mask[0] = 0;
885
380
    }
886
887
    /* If Top is not available */
888
1.03k
    if(0 == pu1_avail[2])
889
433
    {
890
433
        pu1_src += src_strd;
891
433
        pu1_src_left_cpy += 2;
892
433
        ht--;
893
25.3k
        for(col = 2; col < wd; col++)
894
24.9k
        {
895
24.9k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - 2 - src_strd]);
896
24.9k
        }
897
433
    }
898
597
    else
899
597
    {
900
33.7k
        for(col = 2; col < wd; col++)
901
33.1k
        {
902
33.1k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col - 2]);
903
33.1k
        }
904
597
    }
905
906
    /* If Right is not available */
907
1.03k
    if(0 == pu1_avail[1])
908
435
    {
909
435
        au1_mask[(wd - 1) >> 1] = 0;
910
435
    }
911
912
    /* If Bottom is not available */
913
1.03k
    if(0 == pu1_avail[3])
914
518
    {
915
518
        ht--;
916
518
    }
917
918
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
919
1.03k
    {
920
28.3k
        for(row = 0; row < ht; row++)
921
27.3k
        {
922
27.3k
            pu1_sign_up[0] = SIGN(pu1_src[0] - pu1_src_left_cpy[2 * (row - 1)]);
923
27.3k
            pu1_sign_up[1] = SIGN(pu1_src[1] - pu1_src_left_cpy[2 * (row - 1) + 1]);
924
1.68M
            for(col = 0; col < wd; col++)
925
1.65M
            {
926
1.65M
                WORD32 edge_idx;
927
1.65M
                WORD8 *pi1_sao_offset;
928
929
1.65M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
930
931
1.65M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + 2 + src_strd]);
932
1.65M
                edge_idx = 2 + pu1_sign_up[col] + u1_sign_down;
933
1.65M
                pu1_sign_up_tmp[col + 2] = -u1_sign_down;
934
935
1.65M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
936
937
1.65M
                if(0 != edge_idx)
938
569k
                {
939
569k
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
940
569k
                }
941
1.65M
            }
942
943
            /* Swapping pu1_sign_up_tmp and pu1_sign_up */
944
27.3k
            {
945
27.3k
                WORD8 *pu1_swap_tmp = pu1_sign_up;
946
27.3k
                pu1_sign_up = pu1_sign_up_tmp;
947
27.3k
                pu1_sign_up_tmp = pu1_swap_tmp;
948
27.3k
            }
949
950
27.3k
            pu1_src += src_strd;
951
27.3k
        }
952
953
1.03k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd] = u1_pos_0_0_tmp_u;
954
1.03k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + 1] = u1_pos_0_0_tmp_v;
955
1.03k
        pu1_src[(pu1_avail[3] ? wd - 2 - src_strd : wd - 2)] = u1_pos_wd_ht_tmp_u;
956
1.03k
        pu1_src[(pu1_avail[3] ? wd - 1 - src_strd : wd - 1)] = u1_pos_wd_ht_tmp_v;
957
1.03k
    }
958
959
1.03k
    if(0 == pu1_avail[2])
960
433
        ht++;
961
1.03k
    if(0 == pu1_avail[3])
962
518
        ht++;
963
1.03k
    pu1_src_top_left[0] = au1_src_top_left_tmp[0];
964
1.03k
    pu1_src_top_left[1] = au1_src_top_left_tmp[1];
965
57.6k
    for(row = 0; row < 2 * ht; row++)
966
56.6k
    {
967
56.6k
        pu1_src_left[row] = au1_src_left_tmp[row];
968
56.6k
    }
969
61.1k
    for(col = 0; col < wd; col++)
970
60.1k
    {
971
60.1k
        pu1_src_top[col] = au1_src_top_tmp[col];
972
60.1k
    }
973
974
1.03k
}
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
9.69k
{
992
9.69k
    WORD32 row, col;
993
9.69k
    UWORD8 au1_mask[MAX_CTB_SIZE];
994
9.69k
    UWORD8 au1_src_top_tmp[MAX_CTB_SIZE];
995
9.69k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE];
996
9.69k
    UWORD8 u1_src_top_left_tmp;
997
9.69k
    WORD8 au1_sign_up[MAX_CTB_SIZE];
998
9.69k
    UWORD8 *pu1_src_left_cpy;
999
9.69k
    WORD8 u1_sign_down;
1000
9.69k
    WORD32 bit_depth;
1001
1002
9.69k
    UWORD8 u1_pos_0_ht_tmp;
1003
9.69k
    UWORD8 u1_pos_wd_0_tmp;
1004
1005
9.69k
    bit_depth = BIT_DEPTH_LUMA;
1006
9.69k
    pu1_src_left_cpy = pu1_src_left;
1007
1008
    /* Initialize the mask values */
1009
9.69k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
1010
1011
    /* Update left, top and top-left arrays */
1012
9.69k
    u1_src_top_left_tmp = pu1_src_top[wd - 1];
1013
531k
    for(row = 0; row < ht; row++)
1014
521k
    {
1015
521k
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
1016
521k
    }
1017
561k
    for(col = 0; col < wd; col++)
1018
552k
    {
1019
552k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
1020
552k
    }
1021
1022
    /* If top-right is available, process separately */
1023
9.69k
    if(0 != pu1_avail[5])
1024
2.96k
    {
1025
2.96k
        WORD32 edge_idx;
1026
1027
2.96k
        edge_idx = 2 + SIGN(pu1_src[wd - 1] - pu1_src_top_right[0]) +
1028
2.96k
                        SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 - 1 + src_strd]);
1029
1030
2.96k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1031
1032
2.96k
        if(0 != edge_idx)
1033
1.14k
        {
1034
1.14k
            u1_pos_wd_0_tmp = CLIP3(pu1_src[wd - 1] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1035
1.14k
        }
1036
1.82k
        else
1037
1.82k
        {
1038
1.82k
            u1_pos_wd_0_tmp = pu1_src[wd - 1];
1039
1.82k
        }
1040
2.96k
    }
1041
6.72k
    else
1042
6.72k
    {
1043
6.72k
        u1_pos_wd_0_tmp = pu1_src[wd - 1];
1044
6.72k
    }
1045
1046
    /* If bottom-left is available, process separately */
1047
9.69k
    if(0 != pu1_avail[6])
1048
2.94k
    {
1049
2.94k
        WORD32 edge_idx;
1050
1051
2.94k
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src[(ht - 1) * src_strd + 1 - src_strd]) +
1052
2.94k
                        SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src_bot_left[0]);
1053
1054
2.94k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1055
1056
2.94k
        if(0 != edge_idx)
1057
1.15k
        {
1058
1.15k
            u1_pos_0_ht_tmp = CLIP3(pu1_src[(ht - 1) * src_strd] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1059
1.15k
        }
1060
1.79k
        else
1061
1.79k
        {
1062
1.79k
            u1_pos_0_ht_tmp = pu1_src[(ht - 1) * src_strd];
1063
1.79k
        }
1064
2.94k
    }
1065
6.74k
    else
1066
6.74k
    {
1067
6.74k
        u1_pos_0_ht_tmp = pu1_src[(ht - 1) * src_strd];
1068
6.74k
    }
1069
1070
    /* If Left is not available */
1071
9.69k
    if(0 == pu1_avail[0])
1072
4.59k
    {
1073
4.59k
        au1_mask[0] = 0;
1074
4.59k
    }
1075
1076
    /* If Top is not available */
1077
9.69k
    if(0 == pu1_avail[2])
1078
4.16k
    {
1079
4.16k
        pu1_src += src_strd;
1080
4.16k
        ht--;
1081
4.16k
        pu1_src_left_cpy += 1;
1082
238k
        for(col = 0; col < wd - 1; col++)
1083
234k
        {
1084
234k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col + 1 - src_strd]);
1085
234k
        }
1086
4.16k
    }
1087
5.52k
    else
1088
5.52k
    {
1089
313k
        for(col = 0; col < wd - 1; col++)
1090
307k
        {
1091
307k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col + 1]);
1092
307k
        }
1093
5.52k
    }
1094
1095
    /* If Right is not available */
1096
9.69k
    if(0 == pu1_avail[1])
1097
4.65k
    {
1098
4.65k
        au1_mask[wd - 1] = 0;
1099
4.65k
    }
1100
1101
    /* If Bottom is not available */
1102
9.69k
    if(0 == pu1_avail[3])
1103
4.21k
    {
1104
4.21k
        ht--;
1105
4.21k
    }
1106
1107
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
1108
9.69k
    {
1109
522k
        for(row = 0; row < ht; row++)
1110
512k
        {
1111
512k
            au1_sign_up[wd - 1] = SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 + 1 - src_strd]);
1112
30.3M
            for(col = 0; col < wd; col++)
1113
29.8M
            {
1114
29.8M
                WORD32 edge_idx;
1115
1116
29.8M
                u1_sign_down = SIGN(pu1_src[col] - ((col == 0) ? pu1_src_left_cpy[row + 1] :
1117
29.8M
                                                                 pu1_src[col - 1 + src_strd]));
1118
29.8M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
1119
29.8M
                if(col > 0)
1120
29.3M
                    au1_sign_up[col - 1] = -u1_sign_down;
1121
1122
29.8M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
1123
1124
29.8M
                if(0 != edge_idx)
1125
9.03M
                {
1126
9.03M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1127
9.03M
                }
1128
29.8M
            }
1129
1130
512k
            pu1_src += src_strd;
1131
512k
        }
1132
1133
9.69k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 1] = u1_pos_wd_0_tmp;
1134
9.69k
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0)] = u1_pos_0_ht_tmp;
1135
9.69k
    }
1136
1137
9.69k
    if(0 == pu1_avail[2])
1138
4.16k
        ht++;
1139
9.69k
    if(0 == pu1_avail[3])
1140
4.21k
        ht++;
1141
9.69k
    *pu1_src_top_left = u1_src_top_left_tmp;
1142
531k
    for(row = 0; row < ht; row++)
1143
521k
    {
1144
521k
        pu1_src_left[row] = au1_src_left_tmp[row];
1145
521k
    }
1146
561k
    for(col = 0; col < wd; col++)
1147
552k
    {
1148
552k
        pu1_src_top[col] = au1_src_top_tmp[col];
1149
552k
    }
1150
1151
9.69k
}
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
766
{
1169
766
    WORD32 row, col;
1170
766
    UWORD8 au1_mask[MAX_CTB_SIZE];
1171
766
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE], au1_src_top_tmp[2 * MAX_CTB_SIZE];
1172
766
    UWORD8 au1_src_top_left_tmp[2];
1173
766
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE];
1174
766
    UWORD8 *pu1_src_left_cpy;
1175
766
    WORD8 u1_sign_down;
1176
766
    WORD32 bit_depth;
1177
1178
766
    UWORD8 u1_pos_wd_0_tmp_u;
1179
766
    UWORD8 u1_pos_wd_0_tmp_v;
1180
766
    UWORD8 u1_pos_0_ht_tmp_u;
1181
766
    UWORD8 u1_pos_0_ht_tmp_v;
1182
1183
766
    bit_depth = BIT_DEPTH_CHROMA;
1184
766
    pu1_src_left_cpy = pu1_src_left;
1185
1186
    /* Initialize the mask values */
1187
766
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
1188
1189
    /* Update left, top and top-left arrays */
1190
766
    au1_src_top_left_tmp[0] = pu1_src_top[wd - 2];
1191
766
    au1_src_top_left_tmp[1] = pu1_src_top[wd - 1];
1192
21.6k
    for(row = 0; row < ht; row++)
1193
20.8k
    {
1194
20.8k
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
1195
20.8k
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
1196
20.8k
    }
1197
44.8k
    for(col = 0; col < wd; col++)
1198
44.0k
    {
1199
44.0k
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
1200
44.0k
    }
1201
1202
1203
    /* If top-right is available, process separately */
1204
766
    if(0 != pu1_avail[5])
1205
226
    {
1206
226
        WORD32 edge_idx;
1207
1208
        /* U */
1209
226
        edge_idx = 2 + SIGN(pu1_src[wd - 2] - pu1_src_top_right[0]) +
1210
226
                        SIGN(pu1_src[wd - 2] - pu1_src[wd - 2 - 2 + src_strd]);
1211
1212
226
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1213
1214
226
        if(0 != edge_idx)
1215
83
        {
1216
83
            u1_pos_wd_0_tmp_u = CLIP3(pu1_src[wd - 2] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
1217
83
        }
1218
143
        else
1219
143
        {
1220
143
            u1_pos_wd_0_tmp_u = pu1_src[wd - 2];
1221
143
        }
1222
1223
        /* V */
1224
226
        edge_idx = 2 + SIGN(pu1_src[wd - 1] - pu1_src_top_right[1]) +
1225
226
                        SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 - 2 + src_strd]);
1226
1227
226
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1228
1229
226
        if(0 != edge_idx)
1230
82
        {
1231
82
            u1_pos_wd_0_tmp_v = CLIP3(pu1_src[wd - 1] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
1232
82
        }
1233
144
        else
1234
144
        {
1235
144
            u1_pos_wd_0_tmp_v = pu1_src[wd - 1];
1236
144
        }
1237
226
    }
1238
540
    else
1239
540
    {
1240
540
        u1_pos_wd_0_tmp_u = pu1_src[wd - 2];
1241
540
        u1_pos_wd_0_tmp_v = pu1_src[wd - 1];
1242
540
    }
1243
1244
    /* If bottom-left is available, process separately */
1245
766
    if(0 != pu1_avail[6])
1246
205
    {
1247
205
        WORD32 edge_idx;
1248
1249
        /* U */
1250
205
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src[(ht - 1) * src_strd + 2 - src_strd]) +
1251
205
                        SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src_bot_left[0]);
1252
1253
205
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1254
1255
205
        if(0 != edge_idx)
1256
78
        {
1257
78
            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
78
        }
1259
127
        else
1260
127
        {
1261
127
            u1_pos_0_ht_tmp_u = pu1_src[(ht - 1) * src_strd];
1262
127
        }
1263
1264
        /* V */
1265
205
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd + 1] - pu1_src[(ht - 1) * src_strd + 1 + 2 - src_strd]) +
1266
205
                        SIGN(pu1_src[(ht - 1) * src_strd + 1] - pu1_src_bot_left[1]);
1267
1268
205
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1269
1270
205
        if(0 != edge_idx)
1271
70
        {
1272
70
            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
70
        }
1274
135
        else
1275
135
        {
1276
135
            u1_pos_0_ht_tmp_v = pu1_src[(ht - 1) * src_strd + 1];
1277
135
        }
1278
205
    }
1279
561
    else
1280
561
    {
1281
561
        u1_pos_0_ht_tmp_u = pu1_src[(ht - 1) * src_strd];
1282
561
        u1_pos_0_ht_tmp_v = pu1_src[(ht - 1) * src_strd + 1];
1283
561
    }
1284
1285
    /* If Left is not available */
1286
766
    if(0 == pu1_avail[0])
1287
318
    {
1288
318
        au1_mask[0] = 0;
1289
318
    }
1290
1291
    /* If Top is not available */
1292
766
    if(0 == pu1_avail[2])
1293
341
    {
1294
341
        pu1_src += src_strd;
1295
341
        ht--;
1296
341
        pu1_src_left_cpy += 2;
1297
19.6k
        for(col = 0; col < wd - 2; col++)
1298
19.3k
        {
1299
19.3k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col + 2 - src_strd]);
1300
19.3k
        }
1301
341
    }
1302
425
    else
1303
425
    {
1304
23.6k
        for(col = 0; col < wd - 2; col++)
1305
23.2k
        {
1306
23.2k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col + 2]);
1307
23.2k
        }
1308
425
    }
1309
1310
    /* If Right is not available */
1311
766
    if(0 == pu1_avail[1])
1312
377
    {
1313
377
        au1_mask[(wd - 1) >> 1] = 0;
1314
377
    }
1315
1316
    /* If Bottom is not available */
1317
766
    if(0 == pu1_avail[3])
1318
385
    {
1319
385
        ht--;
1320
385
    }
1321
1322
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
1323
766
    {
1324
20.9k
        for(row = 0; row < ht; row++)
1325
20.1k
        {
1326
20.1k
            au1_sign_up[wd - 2] = SIGN(pu1_src[wd - 2] - pu1_src[wd - 2 + 2 - src_strd]);
1327
20.1k
            au1_sign_up[wd - 1] = SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 + 2 - src_strd]);
1328
1.21M
            for(col = 0; col < wd; col++)
1329
1.19M
            {
1330
1.19M
                WORD32 edge_idx;
1331
1.19M
                WORD8 *pi1_sao_offset;
1332
1333
1.19M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
1334
1335
1.19M
                u1_sign_down = SIGN(pu1_src[col] - ((col < 2) ? pu1_src_left_cpy[2 * (row + 1) + col] :
1336
1.19M
                                                                pu1_src[col - 2 + src_strd]));
1337
1.19M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
1338
1.19M
                if(col > 1)
1339
1.15M
                    au1_sign_up[col - 2] = -u1_sign_down;
1340
1341
1.19M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
1342
1343
1.19M
                if(0 != edge_idx)
1344
321k
                {
1345
321k
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1346
321k
                }
1347
1.19M
            }
1348
1349
20.1k
            pu1_src += src_strd;
1350
20.1k
        }
1351
1352
766
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 2] = u1_pos_wd_0_tmp_u;
1353
766
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 1] = u1_pos_wd_0_tmp_v;
1354
766
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0)] = u1_pos_0_ht_tmp_u;
1355
766
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0) + 1] = u1_pos_0_ht_tmp_v;
1356
766
    }
1357
1358
766
    if(0 == pu1_avail[2])
1359
341
        ht++;
1360
766
    if(0 == pu1_avail[3])
1361
385
        ht++;
1362
766
    pu1_src_top_left[0] = au1_src_top_left_tmp[0];
1363
766
    pu1_src_top_left[1] = au1_src_top_left_tmp[1];
1364
42.5k
    for(row = 0; row < 2 * ht; row++)
1365
41.7k
    {
1366
41.7k
        pu1_src_left[row] = au1_src_left_tmp[row];
1367
41.7k
    }
1368
44.8k
    for(col = 0; col < wd; col++)
1369
44.0k
    {
1370
44.0k
        pu1_src_top[col] = au1_src_top_tmp[col];
1371
44.0k
    }
1372
1373
766
}