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
6.20M
#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
105k
{
81
105k
    WORD32 band_shift;
82
105k
    WORD32 band_table[NUM_BAND_TABLE];
83
105k
    WORD32 i;
84
105k
    WORD32 row, col;
85
86
    /* Updating left and top and top-left */
87
2.98M
    for(row = 0; row < ht; row++)
88
2.87M
    {
89
2.87M
        pu1_src_left[row] = pu1_src[row * src_strd + (wd - 1)];
90
2.87M
    }
91
105k
    pu1_src_top_left[0] = pu1_src_top[wd - 1];
92
3.03M
    for(col = 0; col < wd; col++)
93
2.93M
    {
94
2.93M
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
95
2.93M
    }
96
97
105k
    band_shift = BIT_DEPTH_LUMA - 5;
98
3.47M
    for(i = 0; i < NUM_BAND_TABLE; i++)
99
3.36M
    {
100
3.36M
        band_table[i] = 0;
101
3.36M
    }
102
525k
    for(i = 0; i < 4; i++)
103
420k
    {
104
420k
        band_table[(i + sao_band_pos) & 31] = i + 1;
105
420k
    }
106
107
2.93M
    for(row = 0; row < ht; row++)
108
2.83M
    {
109
88.0M
        for(col = 0; col < wd; col++)
110
85.2M
        {
111
85.2M
            WORD32 band_idx;
112
113
85.2M
            band_idx = band_table[pu1_src[col] >> band_shift];
114
85.2M
            pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[band_idx], 0, (1 << (band_shift + 5)) - 1);
115
85.2M
        }
116
2.83M
        pu1_src += src_strd;
117
2.83M
    }
118
105k
}
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
82.9k
{
135
82.9k
    WORD32 band_shift;
136
82.9k
    WORD32 band_table_u[NUM_BAND_TABLE];
137
82.9k
    WORD32 band_table_v[NUM_BAND_TABLE];
138
82.9k
    WORD32 i;
139
82.9k
    WORD32 row, col;
140
141
    /* Updating left and top and top-left */
142
1.24M
    for(row = 0; row < ht; row++)
143
1.16M
    {
144
1.16M
        pu1_src_left[2 * row] = pu1_src[row * src_strd + (wd - 2)];
145
1.16M
        pu1_src_left[2 * row + 1] = pu1_src[row * src_strd + (wd - 1)];
146
1.16M
    }
147
82.9k
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
148
82.9k
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
149
2.45M
    for(col = 0; col < wd; col++)
150
2.37M
    {
151
2.37M
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
152
2.37M
    }
153
154
155
82.9k
    band_shift = BIT_DEPTH_CHROMA - 5;
156
2.73M
    for(i = 0; i < NUM_BAND_TABLE; i++)
157
2.65M
    {
158
2.65M
        band_table_u[i] = 0;
159
2.65M
        band_table_v[i] = 0;
160
2.65M
    }
161
414k
    for(i = 0; i < 4; i++)
162
331k
    {
163
331k
        band_table_u[(i + sao_band_pos_u) & 31] = i + 1;
164
331k
        band_table_v[(i + sao_band_pos_v) & 31] = i + 1;
165
331k
    }
166
167
1.24M
    for(row = 0; row < ht; row++)
168
1.15M
    {
169
36.3M
        for(col = 0; col < wd; col++)
170
35.1M
        {
171
35.1M
            WORD32 band_idx;
172
35.1M
            WORD8 *pi1_sao_offset;
173
174
35.1M
            pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
175
35.1M
            band_idx = (0 == col % 2) ? band_table_u[pu1_src[col] >> band_shift] : band_table_v[pu1_src[col] >> band_shift];
176
35.1M
            pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[band_idx], 0, (1 << (band_shift + 5)) - 1);
177
35.1M
        }
178
1.15M
        pu1_src += src_strd;
179
1.15M
    }
180
82.9k
}
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
247k
{
197
247k
    WORD32 row, col;
198
247k
    UWORD8 au1_mask[MAX_CTB_SIZE];
199
247k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE];
200
247k
    WORD8 u1_sign_left, u1_sign_right;
201
247k
    WORD32 bit_depth;
202
247k
    UNUSED(pu1_src_top_right);
203
247k
    UNUSED(pu1_src_bot_left);
204
247k
    bit_depth = BIT_DEPTH_LUMA;
205
206
    /* Initialize the mask values */
207
247k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
208
209
    /* Update top and top-left arrays */
210
247k
    *pu1_src_top_left = pu1_src_top[wd - 1];
211
14.3M
    for(row = 0; row < ht; row++)
212
14.1M
    {
213
14.1M
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
214
14.1M
    }
215
14.4M
    for(col = 0; col < wd; col++)
216
14.1M
    {
217
14.1M
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
218
14.1M
    }
219
220
    /* Update masks based on the availability flags */
221
247k
    if(0 == pu1_avail[0])
222
114k
    {
223
114k
        au1_mask[0] = 0;
224
114k
    }
225
247k
    if(0 == pu1_avail[1])
226
117k
    {
227
117k
        au1_mask[wd - 1] = 0;
228
117k
    }
229
230
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
231
247k
    {
232
14.3M
        for(row = 0; row < ht; row++)
233
14.1M
        {
234
14.1M
            u1_sign_left = SIGN(pu1_src[0] - pu1_src_left[row]);
235
857M
            for(col = 0; col < wd; col++)
236
843M
            {
237
843M
                WORD32 edge_idx;
238
239
843M
                u1_sign_right = SIGN(pu1_src[col] - pu1_src[col + 1]);
240
843M
                edge_idx = 2 + u1_sign_left + u1_sign_right;
241
843M
                u1_sign_left = -u1_sign_right;
242
243
843M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
244
245
843M
                if(0 != edge_idx)
246
45.0M
                {
247
45.0M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
248
45.0M
                }
249
843M
            }
250
251
14.1M
            pu1_src += src_strd;
252
14.1M
        }
253
247k
    }
254
255
    /* Update left array */
256
14.3M
    for(row = 0; row < ht; row++)
257
14.1M
    {
258
14.1M
        pu1_src_left[row] = au1_src_left_tmp[row];
259
14.1M
    }
260
261
247k
}
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
115k
{
280
115k
    WORD32 row, col;
281
115k
    UWORD8 au1_mask[MAX_CTB_SIZE];
282
115k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE];
283
115k
    WORD8 u1_sign_left_u, u1_sign_right_u;
284
115k
    WORD8 u1_sign_left_v, u1_sign_right_v;
285
115k
    WORD32 bit_depth;
286
115k
    UNUSED(pu1_src_top_right);
287
115k
    UNUSED(pu1_src_bot_left);
288
115k
    bit_depth = BIT_DEPTH_CHROMA;
289
290
    /* Initialize the mask values */
291
115k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
292
293
    /* Update left, top and top-left arrays */
294
115k
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
295
115k
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
296
3.27M
    for(row = 0; row < ht; row++)
297
3.16M
    {
298
3.16M
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
299
3.16M
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
300
3.16M
    }
301
6.47M
    for(col = 0; col < wd; col++)
302
6.35M
    {
303
6.35M
        pu1_src_top[col] = pu1_src[(ht - 1) * src_strd + col];
304
6.35M
    }
305
306
    /* Update masks based on the availability flags */
307
115k
    if(0 == pu1_avail[0])
308
42.1k
    {
309
42.1k
        au1_mask[0] = 0;
310
42.1k
    }
311
115k
    if(0 == pu1_avail[1])
312
44.8k
    {
313
44.8k
        au1_mask[(wd - 1) >> 1] = 0;
314
44.8k
    }
315
316
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
317
115k
    {
318
3.27M
        for(row = 0; row < ht; row++)
319
3.15M
        {
320
3.15M
            u1_sign_left_u = SIGN(pu1_src[0] - pu1_src_left[2 * row]);
321
3.15M
            u1_sign_left_v = SIGN(pu1_src[1] - pu1_src_left[2 * row + 1]);
322
186M
            for(col = 0; col < wd; col++)
323
183M
            {
324
183M
                WORD32 edge_idx;
325
183M
                WORD8 *pi1_sao_offset;
326
327
183M
                if(0 == col % 2)
328
91.8M
                {
329
91.8M
                    pi1_sao_offset = pi1_sao_offset_u;
330
91.8M
                    u1_sign_right_u = SIGN(pu1_src[col] - pu1_src[col + 2]);
331
91.8M
                    edge_idx = 2 + u1_sign_left_u + u1_sign_right_u;
332
91.8M
                    u1_sign_left_u = -u1_sign_right_u;
333
91.8M
                }
334
91.8M
                else
335
91.8M
                {
336
91.8M
                    pi1_sao_offset = pi1_sao_offset_v;
337
91.8M
                    u1_sign_right_v = SIGN(pu1_src[col] - pu1_src[col + 2]);
338
91.8M
                    edge_idx = 2 + u1_sign_left_v + u1_sign_right_v;
339
91.8M
                    u1_sign_left_v = -u1_sign_right_v;
340
91.8M
                }
341
342
183M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
343
344
183M
                if(0 != edge_idx)
345
10.7M
                {
346
10.7M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
347
10.7M
                }
348
183M
            }
349
350
3.15M
            pu1_src += src_strd;
351
3.15M
        }
352
115k
    }
353
354
6.43M
    for(row = 0; row < 2 * ht; row++)
355
6.32M
    {
356
6.32M
        pu1_src_left[row] = au1_src_left_tmp[row];
357
6.32M
    }
358
359
115k
}
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
171k
{
376
171k
    WORD32 row, col;
377
171k
    UWORD8 au1_mask[MAX_CTB_SIZE];
378
171k
    UWORD8 au1_src_top_tmp[MAX_CTB_SIZE];
379
171k
    WORD8 au1_sign_up[MAX_CTB_SIZE];
380
171k
    WORD8 u1_sign_down;
381
171k
    WORD32 bit_depth;
382
171k
    UNUSED(pu1_src_top_right);
383
171k
    UNUSED(pu1_src_bot_left);
384
385
171k
    bit_depth = BIT_DEPTH_LUMA;
386
387
    /* Initialize the mask values */
388
171k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
389
390
    /* Update left, top and top-left arrays */
391
171k
    *pu1_src_top_left = pu1_src_top[wd - 1];
392
9.87M
    for(row = 0; row < ht; row++)
393
9.70M
    {
394
9.70M
        pu1_src_left[row] = pu1_src[row * src_strd + wd - 1];
395
9.70M
    }
396
9.89M
    for(col = 0; col < wd; col++)
397
9.72M
    {
398
9.72M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
399
9.72M
    }
400
401
    /* Update height and source pointers based on the availability flags */
402
171k
    if(0 == pu1_avail[2])
403
100k
    {
404
100k
        pu1_src += src_strd;
405
100k
        ht--;
406
6.06M
        for(col = 0; col < wd; col++)
407
5.96M
        {
408
5.96M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - src_strd]);
409
5.96M
        }
410
100k
    }
411
70.8k
    else
412
70.8k
    {
413
3.83M
        for(col = 0; col < wd; col++)
414
3.76M
        {
415
3.76M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col]);
416
3.76M
        }
417
70.8k
    }
418
171k
    if(0 == pu1_avail[3])
419
99.6k
    {
420
99.6k
        ht--;
421
99.6k
    }
422
423
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
424
171k
    {
425
9.67M
        for(row = 0; row < ht; row++)
426
9.50M
        {
427
578M
            for(col = 0; col < wd; col++)
428
568M
            {
429
568M
                WORD32 edge_idx;
430
431
568M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + src_strd]);
432
568M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
433
568M
                au1_sign_up[col] = -u1_sign_down;
434
435
568M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
436
437
568M
                if(0 != edge_idx)
438
29.4M
                {
439
29.4M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
440
29.4M
                }
441
568M
            }
442
443
9.50M
            pu1_src += src_strd;
444
9.50M
        }
445
171k
    }
446
447
9.89M
    for(col = 0; col < wd; col++)
448
9.72M
    {
449
9.72M
        pu1_src_top[col] = au1_src_top_tmp[col];
450
9.72M
    }
451
452
171k
}
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
44.8k
{
470
44.8k
    WORD32 row, col;
471
44.8k
    UWORD8 au1_mask[MAX_CTB_SIZE];
472
44.8k
    UWORD8 au1_src_top_tmp[2 * MAX_CTB_SIZE];
473
44.8k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE];
474
44.8k
    WORD8 u1_sign_down;
475
44.8k
    WORD32 bit_depth;
476
44.8k
    UNUSED(pu1_src_top_right);
477
44.8k
    UNUSED(pu1_src_bot_left);
478
479
44.8k
    bit_depth = BIT_DEPTH_CHROMA;
480
481
    /* Initialize the mask values */
482
44.8k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
483
484
    /* Update left, top and top-left arrays */
485
44.8k
    pu1_src_top_left[0] = pu1_src_top[wd - 2];
486
44.8k
    pu1_src_top_left[1] = pu1_src_top[wd - 1];
487
1.07M
    for(row = 0; row < ht; row++)
488
1.02M
    {
489
1.02M
        pu1_src_left[2 * row] = pu1_src[row * src_strd + wd - 2];
490
1.02M
        pu1_src_left[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
491
1.02M
    }
492
2.10M
    for(col = 0; col < wd; col++)
493
2.06M
    {
494
2.06M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
495
2.06M
    }
496
497
    /* Update height and source pointers based on the availability flags */
498
44.8k
    if(0 == pu1_avail[2])
499
21.0k
    {
500
21.0k
        pu1_src += src_strd;
501
21.0k
        ht--;
502
1.15M
        for(col = 0; col < wd; col++)
503
1.13M
        {
504
1.13M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - src_strd]);
505
1.13M
        }
506
21.0k
    }
507
23.7k
    else
508
23.7k
    {
509
949k
        for(col = 0; col < wd; col++)
510
926k
        {
511
926k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col]);
512
926k
        }
513
23.7k
    }
514
44.8k
    if(0 == pu1_avail[3])
515
20.0k
    {
516
20.0k
        ht--;
517
20.0k
    }
518
519
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
520
44.8k
    {
521
1.02M
        for(row = 0; row < ht; row++)
522
984k
        {
523
52.9M
            for(col = 0; col < wd; col++)
524
51.9M
            {
525
51.9M
                WORD32 edge_idx;
526
51.9M
                WORD8 *pi1_sao_offset;
527
528
51.9M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
529
530
51.9M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + src_strd]);
531
51.9M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
532
51.9M
                au1_sign_up[col] = -u1_sign_down;
533
534
51.9M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
535
536
51.9M
                if(0 != edge_idx)
537
3.71M
                {
538
3.71M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
539
3.71M
                }
540
51.9M
            }
541
542
984k
            pu1_src += src_strd;
543
984k
        }
544
44.8k
    }
545
546
2.10M
    for(col = 0; col < wd; col++)
547
2.06M
    {
548
2.06M
        pu1_src_top[col] = au1_src_top_tmp[col];
549
2.06M
    }
550
551
44.8k
}
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
176k
{
568
176k
    WORD32 row, col;
569
176k
    UWORD8 au1_mask[MAX_CTB_SIZE];
570
176k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE], au1_src_top_tmp[MAX_CTB_SIZE];
571
176k
    UWORD8 u1_src_top_left_tmp;
572
176k
    WORD8 au1_sign_up[MAX_CTB_SIZE + 1], au1_sign_up_tmp[MAX_CTB_SIZE + 1];
573
176k
    WORD8 u1_sign_down;
574
176k
    WORD8 *pu1_sign_up;
575
176k
    WORD8 *pu1_sign_up_tmp;
576
176k
    UWORD8 *pu1_src_left_cpy;
577
578
176k
    WORD32 bit_depth;
579
176k
    UWORD8 u1_pos_0_0_tmp;
580
176k
    UWORD8 u1_pos_wd_ht_tmp;
581
176k
    UNUSED(pu1_src_top_right);
582
176k
    UNUSED(pu1_src_bot_left);
583
584
176k
    bit_depth = BIT_DEPTH_LUMA;
585
176k
    pu1_sign_up = au1_sign_up;
586
176k
    pu1_sign_up_tmp = au1_sign_up_tmp;
587
176k
    pu1_src_left_cpy = pu1_src_left;
588
589
    /* Initialize the mask values */
590
176k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
591
592
    /* Update left, top and top-left arrays */
593
176k
    u1_src_top_left_tmp = pu1_src_top[wd - 1];
594
9.64M
    for(row = 0; row < ht; row++)
595
9.46M
    {
596
9.46M
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
597
9.46M
    }
598
9.68M
    for(col = 0; col < wd; col++)
599
9.50M
    {
600
9.50M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
601
9.50M
    }
602
603
604
    /* If top-left is available, process separately */
605
176k
    if(0 != pu1_avail[4])
606
65.4k
    {
607
65.4k
        WORD32 edge_idx;
608
609
65.4k
        edge_idx = 2 + SIGN(pu1_src[0] - pu1_src_top_left[0]) +
610
65.4k
                        SIGN(pu1_src[0] - pu1_src[1 + src_strd]);
611
612
65.4k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
613
614
65.4k
        if(0 != edge_idx)
615
11.0k
        {
616
11.0k
            u1_pos_0_0_tmp = CLIP3(pu1_src[0] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
617
11.0k
        }
618
54.3k
        else
619
54.3k
        {
620
54.3k
            u1_pos_0_0_tmp = pu1_src[0];
621
54.3k
        }
622
65.4k
    }
623
111k
    else
624
111k
    {
625
111k
        u1_pos_0_0_tmp = pu1_src[0];
626
111k
    }
627
628
    /* If bottom-right is available, process separately */
629
176k
    if(0 != pu1_avail[7])
630
67.7k
    {
631
67.7k
        WORD32 edge_idx;
632
633
67.7k
        edge_idx = 2 + SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd - 1 - src_strd]) +
634
67.7k
                        SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd + 1 + src_strd]);
635
636
67.7k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
637
638
67.7k
        if(0 != edge_idx)
639
13.0k
        {
640
13.0k
            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
13.0k
        }
642
54.6k
        else
643
54.6k
        {
644
54.6k
            u1_pos_wd_ht_tmp = pu1_src[wd - 1 + (ht - 1) * src_strd];
645
54.6k
        }
646
67.7k
    }
647
108k
    else
648
108k
    {
649
108k
        u1_pos_wd_ht_tmp = pu1_src[wd - 1 + (ht - 1) * src_strd];
650
108k
    }
651
652
    /* If Left is not available */
653
176k
    if(0 == pu1_avail[0])
654
85.4k
    {
655
85.4k
        au1_mask[0] = 0;
656
85.4k
    }
657
658
    /* If Top is not available */
659
176k
    if(0 == pu1_avail[2])
660
94.4k
    {
661
94.4k
        pu1_src += src_strd;
662
94.4k
        ht--;
663
94.4k
        pu1_src_left_cpy += 1;
664
5.62M
        for(col = 1; col < wd; col++)
665
5.53M
        {
666
5.53M
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - 1 - src_strd]);
667
5.53M
        }
668
94.4k
    }
669
82.1k
    else
670
82.1k
    {
671
3.87M
        for(col = 1; col < wd; col++)
672
3.79M
        {
673
3.79M
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col - 1]);
674
3.79M
        }
675
82.1k
    }
676
677
    /* If Right is not available */
678
176k
    if(0 == pu1_avail[1])
679
84.9k
    {
680
84.9k
        au1_mask[wd - 1] = 0;
681
84.9k
    }
682
683
    /* If Bottom is not available */
684
176k
    if(0 == pu1_avail[3])
685
92.4k
    {
686
92.4k
        ht--;
687
92.4k
    }
688
689
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
690
176k
    {
691
9.43M
        for(row = 0; row < ht; row++)
692
9.26M
        {
693
9.26M
            pu1_sign_up[0] = SIGN(pu1_src[0] - pu1_src_left_cpy[row - 1]);
694
552M
            for(col = 0; col < wd; col++)
695
543M
            {
696
543M
                WORD32 edge_idx;
697
698
543M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + 1 + src_strd]);
699
543M
                edge_idx = 2 + pu1_sign_up[col] + u1_sign_down;
700
543M
                pu1_sign_up_tmp[col + 1] = -u1_sign_down;
701
702
543M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
703
704
543M
                if(0 != edge_idx)
705
34.8M
                {
706
34.8M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
707
34.8M
                }
708
543M
            }
709
710
            /* Swapping pu1_sign_up_tmp and pu1_sign_up */
711
9.26M
            {
712
9.26M
                WORD8 *pu1_swap_tmp = pu1_sign_up;
713
9.26M
                pu1_sign_up = pu1_sign_up_tmp;
714
9.26M
                pu1_sign_up_tmp = pu1_swap_tmp;
715
9.26M
            }
716
717
9.26M
            pu1_src += src_strd;
718
9.26M
        }
719
720
176k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd] = u1_pos_0_0_tmp;
721
176k
        pu1_src[(pu1_avail[3] ? wd - 1 - src_strd : wd - 1)] = u1_pos_wd_ht_tmp;
722
176k
    }
723
724
176k
    if(0 == pu1_avail[2])
725
94.4k
        ht++;
726
176k
    if(0 == pu1_avail[3])
727
92.4k
        ht++;
728
176k
    *pu1_src_top_left = u1_src_top_left_tmp;
729
9.64M
    for(row = 0; row < ht; row++)
730
9.46M
    {
731
9.46M
        pu1_src_left[row] = au1_src_left_tmp[row];
732
9.46M
    }
733
9.68M
    for(col = 0; col < wd; col++)
734
9.50M
    {
735
9.50M
        pu1_src_top[col] = au1_src_top_tmp[col];
736
9.50M
    }
737
738
176k
}
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
50.3k
{
757
50.3k
    WORD32 row, col;
758
50.3k
    UWORD8 au1_mask[MAX_CTB_SIZE];
759
50.3k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE], au1_src_top_tmp[2 * MAX_CTB_SIZE];
760
50.3k
    UWORD8 au1_src_top_left_tmp[2];
761
50.3k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE + 2], au1_sign_up_tmp[2 * MAX_CTB_SIZE + 2];
762
50.3k
    WORD8 u1_sign_down;
763
50.3k
    WORD8 *pu1_sign_up;
764
50.3k
    WORD8 *pu1_sign_up_tmp;
765
50.3k
    UWORD8 *pu1_src_left_cpy;
766
767
50.3k
    WORD32 bit_depth;
768
769
50.3k
    UWORD8 u1_pos_0_0_tmp_u;
770
50.3k
    UWORD8 u1_pos_0_0_tmp_v;
771
50.3k
    UWORD8 u1_pos_wd_ht_tmp_u;
772
50.3k
    UWORD8 u1_pos_wd_ht_tmp_v;
773
50.3k
    UNUSED(pu1_src_top_right);
774
50.3k
    UNUSED(pu1_src_bot_left);
775
776
777
50.3k
    bit_depth = BIT_DEPTH_CHROMA;
778
50.3k
    pu1_sign_up = au1_sign_up;
779
50.3k
    pu1_sign_up_tmp = au1_sign_up_tmp;
780
50.3k
    pu1_src_left_cpy = pu1_src_left;
781
782
    /* Initialize the mask values */
783
50.3k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
784
785
    /* Update left, top and top-left arrays */
786
50.3k
    au1_src_top_left_tmp[0] = pu1_src_top[wd - 2];
787
50.3k
    au1_src_top_left_tmp[1] = pu1_src_top[wd - 1];
788
951k
    for(row = 0; row < ht; row++)
789
900k
    {
790
900k
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
791
900k
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
792
900k
    }
793
1.87M
    for(col = 0; col < wd; col++)
794
1.82M
    {
795
1.82M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
796
1.82M
    }
797
798
799
    /* If top-left is available, process separately */
800
50.3k
    if(0 != pu1_avail[4])
801
29.9k
    {
802
29.9k
        WORD32 edge_idx;
803
804
        /* U */
805
29.9k
        edge_idx = 2 + SIGN(pu1_src[0] - pu1_src_top_left[0]) +
806
29.9k
                        SIGN(pu1_src[0] - pu1_src[2 + src_strd]);
807
808
29.9k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
809
810
29.9k
        if(0 != edge_idx)
811
8.80k
        {
812
8.80k
            u1_pos_0_0_tmp_u = CLIP3(pu1_src[0] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
813
8.80k
        }
814
21.1k
        else
815
21.1k
        {
816
21.1k
            u1_pos_0_0_tmp_u = pu1_src[0];
817
21.1k
        }
818
819
        /* V */
820
29.9k
        edge_idx = 2 + SIGN(pu1_src[1] - pu1_src_top_left[1]) +
821
29.9k
                        SIGN(pu1_src[1] - pu1_src[1 + 2 + src_strd]);
822
823
29.9k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
824
825
29.9k
        if(0 != edge_idx)
826
8.50k
        {
827
8.50k
            u1_pos_0_0_tmp_v = CLIP3(pu1_src[1] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
828
8.50k
        }
829
21.4k
        else
830
21.4k
        {
831
21.4k
            u1_pos_0_0_tmp_v = pu1_src[1];
832
21.4k
        }
833
29.9k
    }
834
20.4k
    else
835
20.4k
    {
836
20.4k
        u1_pos_0_0_tmp_u = pu1_src[0];
837
20.4k
        u1_pos_0_0_tmp_v = pu1_src[1];
838
20.4k
    }
839
840
    /* If bottom-right is available, process separately */
841
50.3k
    if(0 != pu1_avail[7])
842
33.0k
    {
843
33.0k
        WORD32 edge_idx;
844
845
        /* U */
846
33.0k
        edge_idx = 2 + SIGN(pu1_src[wd - 2 + (ht - 1) * src_strd] - pu1_src[wd - 2 + (ht - 1) * src_strd - 2 - src_strd]) +
847
33.0k
                        SIGN(pu1_src[wd - 2 + (ht - 1) * src_strd] - pu1_src[wd - 2 + (ht - 1) * src_strd + 2 + src_strd]);
848
849
33.0k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
850
851
33.0k
        if(0 != edge_idx)
852
9.36k
        {
853
9.36k
            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
9.36k
        }
855
23.6k
        else
856
23.6k
        {
857
23.6k
            u1_pos_wd_ht_tmp_u = pu1_src[wd - 2 + (ht - 1) * src_strd];
858
23.6k
        }
859
860
        /* V */
861
33.0k
        edge_idx = 2 + SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd - 2 - src_strd]) +
862
33.0k
                        SIGN(pu1_src[wd - 1 + (ht - 1) * src_strd] - pu1_src[wd - 1 + (ht - 1) * src_strd + 2 + src_strd]);
863
864
33.0k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
865
866
33.0k
        if(0 != edge_idx)
867
8.92k
        {
868
8.92k
            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
8.92k
        }
870
24.0k
        else
871
24.0k
        {
872
24.0k
            u1_pos_wd_ht_tmp_v = pu1_src[wd - 1 + (ht - 1) * src_strd];
873
24.0k
        }
874
33.0k
    }
875
17.3k
    else
876
17.3k
    {
877
17.3k
        u1_pos_wd_ht_tmp_u = pu1_src[wd - 2 + (ht - 1) * src_strd];
878
17.3k
        u1_pos_wd_ht_tmp_v = pu1_src[wd - 1 + (ht - 1) * src_strd];
879
17.3k
    }
880
881
    /* If Left is not available */
882
50.3k
    if(0 == pu1_avail[0])
883
13.7k
    {
884
13.7k
        au1_mask[0] = 0;
885
13.7k
    }
886
887
    /* If Top is not available */
888
50.3k
    if(0 == pu1_avail[2])
889
15.9k
    {
890
15.9k
        pu1_src += src_strd;
891
15.9k
        pu1_src_left_cpy += 2;
892
15.9k
        ht--;
893
785k
        for(col = 2; col < wd; col++)
894
769k
        {
895
769k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col - 2 - src_strd]);
896
769k
        }
897
15.9k
    }
898
34.4k
    else
899
34.4k
    {
900
988k
        for(col = 2; col < wd; col++)
901
954k
        {
902
954k
            pu1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col - 2]);
903
954k
        }
904
34.4k
    }
905
906
    /* If Right is not available */
907
50.3k
    if(0 == pu1_avail[1])
908
13.1k
    {
909
13.1k
        au1_mask[(wd - 1) >> 1] = 0;
910
13.1k
    }
911
912
    /* If Bottom is not available */
913
50.3k
    if(0 == pu1_avail[3])
914
12.9k
    {
915
12.9k
        ht--;
916
12.9k
    }
917
918
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
919
50.3k
    {
920
920k
        for(row = 0; row < ht; row++)
921
870k
        {
922
870k
            pu1_sign_up[0] = SIGN(pu1_src[0] - pu1_src_left_cpy[2 * (row - 1)]);
923
870k
            pu1_sign_up[1] = SIGN(pu1_src[1] - pu1_src_left_cpy[2 * (row - 1) + 1]);
924
40.3M
            for(col = 0; col < wd; col++)
925
39.5M
            {
926
39.5M
                WORD32 edge_idx;
927
39.5M
                WORD8 *pi1_sao_offset;
928
929
39.5M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
930
931
39.5M
                u1_sign_down = SIGN(pu1_src[col] - pu1_src[col + 2 + src_strd]);
932
39.5M
                edge_idx = 2 + pu1_sign_up[col] + u1_sign_down;
933
39.5M
                pu1_sign_up_tmp[col + 2] = -u1_sign_down;
934
935
39.5M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
936
937
39.5M
                if(0 != edge_idx)
938
4.93M
                {
939
4.93M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
940
4.93M
                }
941
39.5M
            }
942
943
            /* Swapping pu1_sign_up_tmp and pu1_sign_up */
944
870k
            {
945
870k
                WORD8 *pu1_swap_tmp = pu1_sign_up;
946
870k
                pu1_sign_up = pu1_sign_up_tmp;
947
870k
                pu1_sign_up_tmp = pu1_swap_tmp;
948
870k
            }
949
950
870k
            pu1_src += src_strd;
951
870k
        }
952
953
50.3k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd] = u1_pos_0_0_tmp_u;
954
50.3k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + 1] = u1_pos_0_0_tmp_v;
955
50.3k
        pu1_src[(pu1_avail[3] ? wd - 2 - src_strd : wd - 2)] = u1_pos_wd_ht_tmp_u;
956
50.3k
        pu1_src[(pu1_avail[3] ? wd - 1 - src_strd : wd - 1)] = u1_pos_wd_ht_tmp_v;
957
50.3k
    }
958
959
50.3k
    if(0 == pu1_avail[2])
960
15.9k
        ht++;
961
50.3k
    if(0 == pu1_avail[3])
962
12.9k
        ht++;
963
50.3k
    pu1_src_top_left[0] = au1_src_top_left_tmp[0];
964
50.3k
    pu1_src_top_left[1] = au1_src_top_left_tmp[1];
965
1.85M
    for(row = 0; row < 2 * ht; row++)
966
1.80M
    {
967
1.80M
        pu1_src_left[row] = au1_src_left_tmp[row];
968
1.80M
    }
969
1.87M
    for(col = 0; col < wd; col++)
970
1.82M
    {
971
1.82M
        pu1_src_top[col] = au1_src_top_tmp[col];
972
1.82M
    }
973
974
50.3k
}
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
185k
{
992
185k
    WORD32 row, col;
993
185k
    UWORD8 au1_mask[MAX_CTB_SIZE];
994
185k
    UWORD8 au1_src_top_tmp[MAX_CTB_SIZE];
995
185k
    UWORD8 au1_src_left_tmp[MAX_CTB_SIZE];
996
185k
    UWORD8 u1_src_top_left_tmp;
997
185k
    WORD8 au1_sign_up[MAX_CTB_SIZE];
998
185k
    UWORD8 *pu1_src_left_cpy;
999
185k
    WORD8 u1_sign_down;
1000
185k
    WORD32 bit_depth;
1001
1002
185k
    UWORD8 u1_pos_0_ht_tmp;
1003
185k
    UWORD8 u1_pos_wd_0_tmp;
1004
1005
185k
    bit_depth = BIT_DEPTH_LUMA;
1006
185k
    pu1_src_left_cpy = pu1_src_left;
1007
1008
    /* Initialize the mask values */
1009
185k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
1010
1011
    /* Update left, top and top-left arrays */
1012
185k
    u1_src_top_left_tmp = pu1_src_top[wd - 1];
1013
9.62M
    for(row = 0; row < ht; row++)
1014
9.44M
    {
1015
9.44M
        au1_src_left_tmp[row] = pu1_src[row * src_strd + wd - 1];
1016
9.44M
    }
1017
9.64M
    for(col = 0; col < wd; col++)
1018
9.45M
    {
1019
9.45M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
1020
9.45M
    }
1021
1022
    /* If top-right is available, process separately */
1023
185k
    if(0 != pu1_avail[5])
1024
73.5k
    {
1025
73.5k
        WORD32 edge_idx;
1026
1027
73.5k
        edge_idx = 2 + SIGN(pu1_src[wd - 1] - pu1_src_top_right[0]) +
1028
73.5k
                        SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 - 1 + src_strd]);
1029
1030
73.5k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1031
1032
73.5k
        if(0 != edge_idx)
1033
13.3k
        {
1034
13.3k
            u1_pos_wd_0_tmp = CLIP3(pu1_src[wd - 1] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1035
13.3k
        }
1036
60.1k
        else
1037
60.1k
        {
1038
60.1k
            u1_pos_wd_0_tmp = pu1_src[wd - 1];
1039
60.1k
        }
1040
73.5k
    }
1041
112k
    else
1042
112k
    {
1043
112k
        u1_pos_wd_0_tmp = pu1_src[wd - 1];
1044
112k
    }
1045
1046
    /* If bottom-left is available, process separately */
1047
185k
    if(0 != pu1_avail[6])
1048
78.5k
    {
1049
78.5k
        WORD32 edge_idx;
1050
1051
78.5k
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src[(ht - 1) * src_strd + 1 - src_strd]) +
1052
78.5k
                        SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src_bot_left[0]);
1053
1054
78.5k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1055
1056
78.5k
        if(0 != edge_idx)
1057
14.9k
        {
1058
14.9k
            u1_pos_0_ht_tmp = CLIP3(pu1_src[(ht - 1) * src_strd] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1059
14.9k
        }
1060
63.6k
        else
1061
63.6k
        {
1062
63.6k
            u1_pos_0_ht_tmp = pu1_src[(ht - 1) * src_strd];
1063
63.6k
        }
1064
78.5k
    }
1065
107k
    else
1066
107k
    {
1067
107k
        u1_pos_0_ht_tmp = pu1_src[(ht - 1) * src_strd];
1068
107k
    }
1069
1070
    /* If Left is not available */
1071
185k
    if(0 == pu1_avail[0])
1072
84.1k
    {
1073
84.1k
        au1_mask[0] = 0;
1074
84.1k
    }
1075
1076
    /* If Top is not available */
1077
185k
    if(0 == pu1_avail[2])
1078
96.1k
    {
1079
96.1k
        pu1_src += src_strd;
1080
96.1k
        ht--;
1081
96.1k
        pu1_src_left_cpy += 1;
1082
5.57M
        for(col = 0; col < wd - 1; col++)
1083
5.47M
        {
1084
5.47M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col + 1 - src_strd]);
1085
5.47M
        }
1086
96.1k
    }
1087
89.7k
    else
1088
89.7k
    {
1089
3.88M
        for(col = 0; col < wd - 1; col++)
1090
3.79M
        {
1091
3.79M
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col + 1]);
1092
3.79M
        }
1093
89.7k
    }
1094
1095
    /* If Right is not available */
1096
185k
    if(0 == pu1_avail[1])
1097
84.0k
    {
1098
84.0k
        au1_mask[wd - 1] = 0;
1099
84.0k
    }
1100
1101
    /* If Bottom is not available */
1102
185k
    if(0 == pu1_avail[3])
1103
90.9k
    {
1104
90.9k
        ht--;
1105
90.9k
    }
1106
1107
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
1108
185k
    {
1109
9.43M
        for(row = 0; row < ht; row++)
1110
9.24M
        {
1111
9.24M
            au1_sign_up[wd - 1] = SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 + 1 - src_strd]);
1112
546M
            for(col = 0; col < wd; col++)
1113
537M
            {
1114
537M
                WORD32 edge_idx;
1115
1116
537M
                u1_sign_down = SIGN(pu1_src[col] - ((col == 0) ? pu1_src_left_cpy[row + 1] :
1117
537M
                                                                 pu1_src[col - 1 + src_strd]));
1118
537M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
1119
537M
                if(col > 0)
1120
528M
                    au1_sign_up[col - 1] = -u1_sign_down;
1121
1122
537M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col];
1123
1124
537M
                if(0 != edge_idx)
1125
34.8M
                {
1126
34.8M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1127
34.8M
                }
1128
537M
            }
1129
1130
9.24M
            pu1_src += src_strd;
1131
9.24M
        }
1132
1133
185k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 1] = u1_pos_wd_0_tmp;
1134
185k
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0)] = u1_pos_0_ht_tmp;
1135
185k
    }
1136
1137
185k
    if(0 == pu1_avail[2])
1138
96.1k
        ht++;
1139
185k
    if(0 == pu1_avail[3])
1140
90.9k
        ht++;
1141
185k
    *pu1_src_top_left = u1_src_top_left_tmp;
1142
9.62M
    for(row = 0; row < ht; row++)
1143
9.44M
    {
1144
9.44M
        pu1_src_left[row] = au1_src_left_tmp[row];
1145
9.44M
    }
1146
9.64M
    for(col = 0; col < wd; col++)
1147
9.45M
    {
1148
9.45M
        pu1_src_top[col] = au1_src_top_tmp[col];
1149
9.45M
    }
1150
1151
185k
}
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
59.4k
{
1169
59.4k
    WORD32 row, col;
1170
59.4k
    UWORD8 au1_mask[MAX_CTB_SIZE];
1171
59.4k
    UWORD8 au1_src_left_tmp[2 * MAX_CTB_SIZE], au1_src_top_tmp[2 * MAX_CTB_SIZE];
1172
59.4k
    UWORD8 au1_src_top_left_tmp[2];
1173
59.4k
    WORD8 au1_sign_up[2 * MAX_CTB_SIZE];
1174
59.4k
    UWORD8 *pu1_src_left_cpy;
1175
59.4k
    WORD8 u1_sign_down;
1176
59.4k
    WORD32 bit_depth;
1177
1178
59.4k
    UWORD8 u1_pos_wd_0_tmp_u;
1179
59.4k
    UWORD8 u1_pos_wd_0_tmp_v;
1180
59.4k
    UWORD8 u1_pos_0_ht_tmp_u;
1181
59.4k
    UWORD8 u1_pos_0_ht_tmp_v;
1182
1183
59.4k
    bit_depth = BIT_DEPTH_CHROMA;
1184
59.4k
    pu1_src_left_cpy = pu1_src_left;
1185
1186
    /* Initialize the mask values */
1187
59.4k
    memset(au1_mask, 0xFF, MAX_CTB_SIZE);
1188
1189
    /* Update left, top and top-left arrays */
1190
59.4k
    au1_src_top_left_tmp[0] = pu1_src_top[wd - 2];
1191
59.4k
    au1_src_top_left_tmp[1] = pu1_src_top[wd - 1];
1192
958k
    for(row = 0; row < ht; row++)
1193
898k
    {
1194
898k
        au1_src_left_tmp[2 * row] = pu1_src[row * src_strd + wd - 2];
1195
898k
        au1_src_left_tmp[2 * row + 1] = pu1_src[row * src_strd + wd - 1];
1196
898k
    }
1197
1.86M
    for(col = 0; col < wd; col++)
1198
1.80M
    {
1199
1.80M
        au1_src_top_tmp[col] = pu1_src[(ht - 1) * src_strd + col];
1200
1.80M
    }
1201
1202
1203
    /* If top-right is available, process separately */
1204
59.4k
    if(0 != pu1_avail[5])
1205
36.9k
    {
1206
36.9k
        WORD32 edge_idx;
1207
1208
        /* U */
1209
36.9k
        edge_idx = 2 + SIGN(pu1_src[wd - 2] - pu1_src_top_right[0]) +
1210
36.9k
                        SIGN(pu1_src[wd - 2] - pu1_src[wd - 2 - 2 + src_strd]);
1211
1212
36.9k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1213
1214
36.9k
        if(0 != edge_idx)
1215
9.98k
        {
1216
9.98k
            u1_pos_wd_0_tmp_u = CLIP3(pu1_src[wd - 2] + pi1_sao_offset_u[edge_idx], 0, (1 << bit_depth) - 1);
1217
9.98k
        }
1218
26.9k
        else
1219
26.9k
        {
1220
26.9k
            u1_pos_wd_0_tmp_u = pu1_src[wd - 2];
1221
26.9k
        }
1222
1223
        /* V */
1224
36.9k
        edge_idx = 2 + SIGN(pu1_src[wd - 1] - pu1_src_top_right[1]) +
1225
36.9k
                        SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 - 2 + src_strd]);
1226
1227
36.9k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1228
1229
36.9k
        if(0 != edge_idx)
1230
8.75k
        {
1231
8.75k
            u1_pos_wd_0_tmp_v = CLIP3(pu1_src[wd - 1] + pi1_sao_offset_v[edge_idx], 0, (1 << bit_depth) - 1);
1232
8.75k
        }
1233
28.2k
        else
1234
28.2k
        {
1235
28.2k
            u1_pos_wd_0_tmp_v = pu1_src[wd - 1];
1236
28.2k
        }
1237
36.9k
    }
1238
22.4k
    else
1239
22.4k
    {
1240
22.4k
        u1_pos_wd_0_tmp_u = pu1_src[wd - 2];
1241
22.4k
        u1_pos_wd_0_tmp_v = pu1_src[wd - 1];
1242
22.4k
    }
1243
1244
    /* If bottom-left is available, process separately */
1245
59.4k
    if(0 != pu1_avail[6])
1246
40.5k
    {
1247
40.5k
        WORD32 edge_idx;
1248
1249
        /* U */
1250
40.5k
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src[(ht - 1) * src_strd + 2 - src_strd]) +
1251
40.5k
                        SIGN(pu1_src[(ht - 1) * src_strd] - pu1_src_bot_left[0]);
1252
1253
40.5k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1254
1255
40.5k
        if(0 != edge_idx)
1256
9.98k
        {
1257
9.98k
            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
9.98k
        }
1259
30.5k
        else
1260
30.5k
        {
1261
30.5k
            u1_pos_0_ht_tmp_u = pu1_src[(ht - 1) * src_strd];
1262
30.5k
        }
1263
1264
        /* V */
1265
40.5k
        edge_idx = 2 + SIGN(pu1_src[(ht - 1) * src_strd + 1] - pu1_src[(ht - 1) * src_strd + 1 + 2 - src_strd]) +
1266
40.5k
                        SIGN(pu1_src[(ht - 1) * src_strd + 1] - pu1_src_bot_left[1]);
1267
1268
40.5k
        edge_idx = gi4_ihevc_table_edge_idx[edge_idx];
1269
1270
40.5k
        if(0 != edge_idx)
1271
8.74k
        {
1272
8.74k
            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
8.74k
        }
1274
31.7k
        else
1275
31.7k
        {
1276
31.7k
            u1_pos_0_ht_tmp_v = pu1_src[(ht - 1) * src_strd + 1];
1277
31.7k
        }
1278
40.5k
    }
1279
18.8k
    else
1280
18.8k
    {
1281
18.8k
        u1_pos_0_ht_tmp_u = pu1_src[(ht - 1) * src_strd];
1282
18.8k
        u1_pos_0_ht_tmp_v = pu1_src[(ht - 1) * src_strd + 1];
1283
18.8k
    }
1284
1285
    /* If Left is not available */
1286
59.4k
    if(0 == pu1_avail[0])
1287
13.8k
    {
1288
13.8k
        au1_mask[0] = 0;
1289
13.8k
    }
1290
1291
    /* If Top is not available */
1292
59.4k
    if(0 == pu1_avail[2])
1293
17.2k
    {
1294
17.2k
        pu1_src += src_strd;
1295
17.2k
        ht--;
1296
17.2k
        pu1_src_left_cpy += 2;
1297
730k
        for(col = 0; col < wd - 2; col++)
1298
713k
        {
1299
713k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src[col + 2 - src_strd]);
1300
713k
        }
1301
17.2k
    }
1302
42.1k
    else
1303
42.1k
    {
1304
1.01M
        for(col = 0; col < wd - 2; col++)
1305
969k
        {
1306
969k
            au1_sign_up[col] = SIGN(pu1_src[col] - pu1_src_top[col + 2]);
1307
969k
        }
1308
42.1k
    }
1309
1310
    /* If Right is not available */
1311
59.4k
    if(0 == pu1_avail[1])
1312
13.7k
    {
1313
13.7k
        au1_mask[(wd - 1) >> 1] = 0;
1314
13.7k
    }
1315
1316
    /* If Bottom is not available */
1317
59.4k
    if(0 == pu1_avail[3])
1318
13.4k
    {
1319
13.4k
        ht--;
1320
13.4k
    }
1321
1322
    /* Processing is done on the intermediate buffer and the output is written to the source buffer */
1323
59.4k
    {
1324
924k
        for(row = 0; row < ht; row++)
1325
865k
        {
1326
865k
            au1_sign_up[wd - 2] = SIGN(pu1_src[wd - 2] - pu1_src[wd - 2 + 2 - src_strd]);
1327
865k
            au1_sign_up[wd - 1] = SIGN(pu1_src[wd - 1] - pu1_src[wd - 1 + 2 - src_strd]);
1328
37.1M
            for(col = 0; col < wd; col++)
1329
36.2M
            {
1330
36.2M
                WORD32 edge_idx;
1331
36.2M
                WORD8 *pi1_sao_offset;
1332
1333
36.2M
                pi1_sao_offset = (0 == col % 2) ? pi1_sao_offset_u : pi1_sao_offset_v;
1334
1335
36.2M
                u1_sign_down = SIGN(pu1_src[col] - ((col < 2) ? pu1_src_left_cpy[2 * (row + 1) + col] :
1336
36.2M
                                                                pu1_src[col - 2 + src_strd]));
1337
36.2M
                edge_idx = 2 + au1_sign_up[col] + u1_sign_down;
1338
36.2M
                if(col > 1)
1339
34.5M
                    au1_sign_up[col - 2] = -u1_sign_down;
1340
1341
36.2M
                edge_idx = gi4_ihevc_table_edge_idx[edge_idx] & au1_mask[col >> 1];
1342
1343
36.2M
                if(0 != edge_idx)
1344
4.15M
                {
1345
4.15M
                    pu1_src[col] = CLIP3(pu1_src[col] + pi1_sao_offset[edge_idx], 0, (1 << bit_depth) - 1);
1346
4.15M
                }
1347
36.2M
            }
1348
1349
865k
            pu1_src += src_strd;
1350
865k
        }
1351
1352
59.4k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 2] = u1_pos_wd_0_tmp_u;
1353
59.4k
        pu1_src[-(pu1_avail[2] ? ht : ht + 1) * src_strd + wd - 1] = u1_pos_wd_0_tmp_v;
1354
59.4k
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0)] = u1_pos_0_ht_tmp_u;
1355
59.4k
        pu1_src[(pu1_avail[3] ?  (-src_strd) : 0) + 1] = u1_pos_0_ht_tmp_v;
1356
59.4k
    }
1357
1358
59.4k
    if(0 == pu1_avail[2])
1359
17.2k
        ht++;
1360
59.4k
    if(0 == pu1_avail[3])
1361
13.4k
        ht++;
1362
59.4k
    pu1_src_top_left[0] = au1_src_top_left_tmp[0];
1363
59.4k
    pu1_src_top_left[1] = au1_src_top_left_tmp[1];
1364
1.85M
    for(row = 0; row < 2 * ht; row++)
1365
1.79M
    {
1366
1.79M
        pu1_src_left[row] = au1_src_left_tmp[row];
1367
1.79M
    }
1368
1.86M
    for(col = 0; col < wd; col++)
1369
1.80M
    {
1370
1.80M
        pu1_src_top[col] = au1_src_top_tmp[col];
1371
1.80M
    }
1372
1373
59.4k
}