Coverage Report

Created: 2026-07-15 06:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libhevc/decoder/ihevcd_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 function definitions for sample adaptive offset process
25
 *
26
 * @author
27
 *  Srinivas T
28
 *
29
 * @par List of Functions:
30
 *
31
 * @remarks
32
 *  None
33
 *
34
 *******************************************************************************
35
 */
36
37
#include <stdio.h>
38
#include <stddef.h>
39
#include <stdlib.h>
40
#include <string.h>
41
#include <assert.h>
42
43
#include "ihevc_typedefs.h"
44
#include "iv.h"
45
#include "ivd.h"
46
#include "ihevcd_cxa.h"
47
#include "ithread.h"
48
49
#include "ihevc_defs.h"
50
#include "ihevc_debug.h"
51
#include "ihevc_defs.h"
52
#include "ihevc_structs.h"
53
#include "ihevc_macros.h"
54
#include "ihevc_platform_macros.h"
55
#include "ihevc_cabac_tables.h"
56
#include "ihevc_sao.h"
57
#include "ihevc_mem_fns.h"
58
59
#include "ihevc_error.h"
60
#include "ihevc_common_tables.h"
61
62
#include "ihevcd_trace.h"
63
#include "ihevcd_defs.h"
64
#include "ihevcd_function_selector.h"
65
#include "ihevcd_structs.h"
66
#include "ihevcd_error.h"
67
#include "ihevcd_nal.h"
68
#include "ihevcd_bitstream.h"
69
#include "ihevcd_job_queue.h"
70
#include "ihevcd_utils.h"
71
72
#include "ihevc_deblk.h"
73
#include "ihevc_deblk_tables.h"
74
#include "ihevcd_profile.h"
75
#include "ihevcd_sao.h"
76
#include "ihevcd_debug.h"
77
78
0
#define SAO_SHIFT_CTB    8
79
80
81
82
void ihevcd_sao_shift_ctb(sao_ctxt_t *ps_sao_ctxt)
83
0
{
84
0
    codec_t *ps_codec = ps_sao_ctxt->ps_codec;
85
0
    UWORD8 *pu1_src_luma;
86
0
    UWORD8 *pu1_src_chroma;
87
0
    WORD32 src_strd;
88
0
    WORD32 chroma_strd;
89
0
    WORD32 ctb_size;
90
0
    WORD32 log2_ctb_size;
91
0
    sps_t *ps_sps;
92
0
    sao_t *ps_sao;
93
0
    pps_t *ps_pps;
94
0
    slice_header_t *ps_slice_hdr, *ps_slice_hdr_base;
95
0
    tile_t *ps_tile;
96
0
    UWORD16 *pu1_slice_idx;
97
0
    UWORD16 *pu1_tile_idx;
98
0
    WORD32 row, col;
99
0
    UWORD8 au1_avail_luma[8];
100
0
    UWORD8 au1_avail_chroma[8];
101
0
    UWORD8 au1_tile_slice_boundary[8];
102
0
    UWORD8 au4_ilf_across_tile_slice_enable[8];
103
0
    WORD32 i;
104
0
    UWORD8 *pu1_src_top_luma;
105
0
    UWORD8 *pu1_src_top_chroma;
106
0
    UWORD8 *pu1_src_left_luma;
107
0
    UWORD8 *pu1_src_left_chroma;
108
0
    UWORD8 au1_src_top_right[2];
109
0
    UWORD8 au1_src_bot_left[2];
110
0
    UWORD8 *pu1_no_loop_filter_flag;
111
0
    UWORD8 *pu1_src_backup_luma;
112
0
    UWORD8 *pu1_src_backup_chroma;
113
0
    WORD32 backup_strd;
114
0
    WORD32 loop_filter_strd;
115
116
0
    WORD32 no_loop_filter_enabled_luma = 0;
117
0
    WORD32 no_loop_filter_enabled_chroma = 0;
118
0
    UWORD8 *pu1_sao_src_top_left_chroma_curr_ctb;
119
0
    UWORD8 *pu1_sao_src_top_left_luma_curr_ctb;
120
0
    UWORD8 *pu1_sao_src_luma_top_left_ctb;
121
0
    UWORD8 *pu1_sao_src_chroma_top_left_ctb;
122
0
    UWORD8 *pu1_sao_src_top_left_luma_top_right;
123
0
    UWORD8 *pu1_sao_src_top_left_chroma_top_right;
124
0
    UWORD8  u1_sao_src_top_left_luma_bot_left;
125
0
    UWORD8  *pu1_sao_src_top_left_luma_bot_left;
126
0
    UWORD8 *au1_sao_src_top_left_chroma_bot_left;
127
0
    UWORD8 *pu1_sao_src_top_left_chroma_bot_left;
128
    /* Only first 5 values are used, but arrays are large
129
     enough so that SIMD functions can read 64 bits at a time */
130
0
    WORD8 ai1_offset_y[8] = {0};
131
0
    WORD8 ai1_offset_cb[8] = {0};
132
0
    WORD8 ai1_offset_cr[8] = {0};
133
0
    WORD32  chroma_yuv420sp_vu = ps_sao_ctxt->is_chroma_yuv420sp_vu;
134
135
0
    PROFILE_DISABLE_SAO();
136
137
0
    ps_sps = ps_sao_ctxt->ps_sps;
138
0
    ps_pps = ps_sao_ctxt->ps_pps;
139
0
    ps_tile = ps_sao_ctxt->ps_tile;
140
141
0
    WORD32 is_yuv444 = ps_sps->i1_chroma_format_idc == CHROMA_FMT_IDC_YUV444 ? 1 : 0;
142
0
    WORD32 h_samp_factor = (CHROMA_FMT_IDC_YUV444 == ps_sps->i1_chroma_format_idc) ? 1 : 2;
143
0
    WORD32 v_samp_factor = (CHROMA_FMT_IDC_YUV420 == ps_sps->i1_chroma_format_idc) ? 2 : 1;
144
0
    WORD32 chroma_pixel_strd = 2;
145
146
0
    log2_ctb_size = ps_sps->i1_log2_ctb_size;
147
0
    ctb_size = (1 << log2_ctb_size);
148
0
    src_strd = ps_sao_ctxt->ps_codec->i4_strd;
149
0
    chroma_strd = src_strd * chroma_pixel_strd / h_samp_factor;
150
0
    ps_slice_hdr_base = ps_sao_ctxt->ps_codec->ps_slice_hdr_base;
151
0
    ps_slice_hdr = ps_slice_hdr_base + (ps_sao_ctxt->i4_cur_slice_idx & (MAX_SLICE_HDR_CNT - 1));
152
153
0
    pu1_slice_idx = ps_sao_ctxt->pu1_slice_idx;
154
0
    pu1_tile_idx = ps_sao_ctxt->pu1_tile_idx;
155
0
    pu1_src_luma = ps_sao_ctxt->pu1_cur_pic_luma + ((ps_sao_ctxt->i4_ctb_x + ps_sao_ctxt->i4_ctb_y * ps_sao_ctxt->ps_codec->i4_strd) << (log2_ctb_size));
156
0
    pu1_src_chroma = ps_sao_ctxt->pu1_cur_pic_chroma
157
0
                    + ((ps_sao_ctxt->i4_ctb_x * chroma_pixel_strd / h_samp_factor
158
0
                    + ps_sao_ctxt->i4_ctb_y * ps_sao_ctxt->ps_codec->i4_strd * chroma_pixel_strd / (h_samp_factor * v_samp_factor)) << (log2_ctb_size));
159
160
    /*Stores the left value for each row ctbs- Needed for column tiles*/
161
0
    pu1_sao_src_top_left_luma_curr_ctb = ps_sao_ctxt->pu1_sao_src_top_left_luma_curr_ctb + ((ps_sao_ctxt->i4_ctb_y));
162
0
    pu1_sao_src_top_left_chroma_curr_ctb = ps_sao_ctxt->pu1_sao_src_top_left_chroma_curr_ctb + (2 * (ps_sao_ctxt->i4_ctb_y));
163
0
    pu1_sao_src_luma_top_left_ctb = ps_sao_ctxt->pu1_sao_src_luma_top_left_ctb + ((ps_sao_ctxt->i4_ctb_y));
164
0
    pu1_sao_src_chroma_top_left_ctb = ps_sao_ctxt->pu1_sao_src_chroma_top_left_ctb + (2 * ps_sao_ctxt->i4_ctb_y);
165
0
    u1_sao_src_top_left_luma_bot_left = ps_sao_ctxt->u1_sao_src_top_left_luma_bot_left; // + ((ps_sao_ctxt->i4_ctb_y));
166
0
    pu1_sao_src_top_left_luma_bot_left = ps_sao_ctxt->pu1_sao_src_top_left_luma_bot_left + ((ps_sao_ctxt->i4_ctb_y));
167
0
    au1_sao_src_top_left_chroma_bot_left = ps_sao_ctxt->au1_sao_src_top_left_chroma_bot_left; // + (2 * ps_sao_ctxt->i4_ctb_y);
168
0
    pu1_sao_src_top_left_chroma_bot_left = ps_sao_ctxt->pu1_sao_src_top_left_chroma_bot_left + (2 * ps_sao_ctxt->i4_ctb_y);
169
0
    pu1_sao_src_top_left_luma_top_right = ps_sao_ctxt->pu1_sao_src_top_left_luma_top_right + ((ps_sao_ctxt->i4_ctb_x));
170
0
    pu1_sao_src_top_left_chroma_top_right = ps_sao_ctxt->pu1_sao_src_top_left_chroma_top_right + (2 * ps_sao_ctxt->i4_ctb_x);
171
172
0
    ps_sao = ps_sao_ctxt->ps_pic_sao + ps_sao_ctxt->i4_ctb_x + ps_sao_ctxt->i4_ctb_y * ps_sps->i2_pic_wd_in_ctb;
173
0
    loop_filter_strd =  (ps_sps->i2_pic_width_in_luma_samples + 63) >> 6;
174
0
    backup_strd = 2 * MAX_CTB_SIZE;
175
176
0
    DEBUG_INIT_TMP_BUF(ps_sao_ctxt->pu1_tmp_buf_luma, ps_sao_ctxt->pu1_tmp_buf_chroma);
177
178
0
    {
179
        /* Check the loop filter flags and copy the original values for back up */
180
        /* Luma */
181
182
        /* Done unconditionally since SAO is done on a shifted CTB and the constituent CTBs
183
         * can belong to different slice with their own sao_enable flag */
184
0
        {
185
0
            UWORD32 u4_no_loop_filter_flag;
186
0
            WORD32 loop_filter_bit_pos;
187
0
            WORD32 log2_min_cu = 3;
188
0
            WORD32 min_cu = (1 << log2_min_cu);
189
0
            UWORD8 *pu1_src_tmp_luma = pu1_src_luma;
190
0
            WORD32 sao_blk_ht = ctb_size - SAO_SHIFT_CTB;
191
0
            WORD32 sao_blk_wd = ctb_size;
192
0
            WORD32 remaining_rows;
193
0
            WORD32 remaining_cols;
194
195
0
            remaining_rows = ps_sps->i2_pic_height_in_luma_samples - ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) + ctb_size - SAO_SHIFT_CTB);
196
0
            remaining_cols = ps_sps->i2_pic_width_in_luma_samples - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) + ctb_size - SAO_SHIFT_CTB);
197
0
            if(remaining_rows <= SAO_SHIFT_CTB)
198
0
                sao_blk_ht += remaining_rows;
199
0
            if(remaining_cols <= SAO_SHIFT_CTB)
200
0
                sao_blk_wd += remaining_cols;
201
202
0
            pu1_src_tmp_luma -= ps_sao_ctxt->i4_ctb_x ? SAO_SHIFT_CTB : 0;
203
0
            pu1_src_tmp_luma -= ps_sao_ctxt->i4_ctb_y ? SAO_SHIFT_CTB * src_strd : 0;
204
205
0
            pu1_src_backup_luma = ps_sao_ctxt->pu1_tmp_buf_luma;
206
207
0
            loop_filter_bit_pos = (ps_sao_ctxt->i4_ctb_x << (log2_ctb_size - 3)) +
208
0
                            (ps_sao_ctxt->i4_ctb_y << (log2_ctb_size - 3)) * (loop_filter_strd << 3);
209
0
            if(ps_sao_ctxt->i4_ctb_x > 0)
210
0
                loop_filter_bit_pos -= 1;
211
212
0
            pu1_no_loop_filter_flag = ps_sao_ctxt->pu1_pic_no_loop_filter_flag +
213
0
                            (loop_filter_bit_pos >> 3);
214
215
0
            for(i = -(ps_sao_ctxt->i4_ctb_y ? SAO_SHIFT_CTB : 0) >> log2_min_cu;
216
0
                            i < (sao_blk_ht + (min_cu - 1)) >> log2_min_cu; i++)
217
0
            {
218
0
                WORD32 tmp_wd = sao_blk_wd;
219
220
0
                u4_no_loop_filter_flag = (*(UWORD32 *)(pu1_no_loop_filter_flag + i * loop_filter_strd)) >>
221
0
                                (loop_filter_bit_pos & 7);
222
0
                u4_no_loop_filter_flag &= (1 << ((tmp_wd + (min_cu - 1)) >> log2_min_cu)) - 1;
223
224
0
                if(u4_no_loop_filter_flag)
225
0
                {
226
0
                    no_loop_filter_enabled_luma = 1;
227
0
                    while(tmp_wd > 0)
228
0
                    {
229
0
                        if(CTZ(u4_no_loop_filter_flag))
230
0
                        {
231
0
                            pu1_src_tmp_luma += MIN((WORD32)(CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
232
0
                            pu1_src_backup_luma += MIN((WORD32)(CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
233
0
                            tmp_wd -= (WORD32)(CTZ(u4_no_loop_filter_flag) << log2_min_cu);
234
0
                            u4_no_loop_filter_flag  >>= (CTZ(u4_no_loop_filter_flag));
235
0
                        }
236
0
                        else
237
0
                        {
238
0
                            for(row = 0; row < min_cu; row++)
239
0
                            {
240
0
                                for(col = 0; col < MIN((WORD32)(CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd); col++)
241
0
                                {
242
0
                                    pu1_src_backup_luma[row * backup_strd + col] = pu1_src_tmp_luma[row * src_strd + col];
243
0
                                }
244
0
                            }
245
0
                            pu1_src_tmp_luma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
246
0
                            pu1_src_backup_luma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
247
0
                            tmp_wd -= (WORD32)(CTZ(~u4_no_loop_filter_flag) << log2_min_cu);
248
0
                            u4_no_loop_filter_flag  >>= (CTZ(~u4_no_loop_filter_flag));
249
0
                        }
250
0
                    }
251
252
0
                    pu1_src_tmp_luma -= sao_blk_wd;
253
0
                    pu1_src_backup_luma -= sao_blk_wd;
254
0
                }
255
256
0
                pu1_src_tmp_luma += (src_strd << log2_min_cu);
257
0
                pu1_src_backup_luma += (backup_strd << log2_min_cu);
258
0
            }
259
0
        }
260
261
        /* Chroma */
262
263
0
        if (CHROMA_FMT_IDC_MONOCHROME != ps_sps->i1_chroma_format_idc)
264
0
        {
265
0
            UWORD32 u4_no_loop_filter_flag;
266
0
            WORD32 loop_filter_bit_pos;
267
0
            WORD32 log2_min_cu = 3;
268
0
            WORD32 min_cu = (1 << log2_min_cu);
269
0
            UWORD8 *pu1_src_tmp_chroma = pu1_src_chroma;
270
0
            WORD32 sao_blk_ht = ctb_size - 2 * SAO_SHIFT_CTB;
271
0
            WORD32 sao_blk_wd = ctb_size;
272
0
            WORD32 remaining_rows;
273
0
            WORD32 remaining_cols;
274
275
0
            remaining_rows = ps_sps->i2_pic_height_in_luma_samples - ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) + ctb_size - 2 * SAO_SHIFT_CTB);
276
0
            remaining_cols = ps_sps->i2_pic_width_in_luma_samples - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) + ctb_size - 2 * SAO_SHIFT_CTB);
277
0
            if(remaining_rows <= 2 * SAO_SHIFT_CTB)
278
0
                sao_blk_ht += remaining_rows;
279
0
            if(remaining_cols <= 2 * SAO_SHIFT_CTB)
280
0
                sao_blk_wd += remaining_cols;
281
282
0
            pu1_src_tmp_chroma -= ps_sao_ctxt->i4_ctb_x ? SAO_SHIFT_CTB * 2 : 0;
283
0
            pu1_src_tmp_chroma -= ps_sao_ctxt->i4_ctb_y ? SAO_SHIFT_CTB * chroma_strd : 0;
284
285
0
            pu1_src_backup_chroma = ps_sao_ctxt->pu1_tmp_buf_chroma;
286
287
0
            loop_filter_bit_pos = (ps_sao_ctxt->i4_ctb_x << (log2_ctb_size - 3)) +
288
0
                            (ps_sao_ctxt->i4_ctb_y << (log2_ctb_size - 3)) * (loop_filter_strd << 3);
289
0
            if(ps_sao_ctxt->i4_ctb_x > 0)
290
0
                loop_filter_bit_pos -= (is_yuv444 ? 1 : 2);
291
292
0
            pu1_no_loop_filter_flag = ps_sao_ctxt->pu1_pic_no_loop_filter_flag +
293
0
                            (loop_filter_bit_pos >> 3);
294
295
0
            for(i = -(ps_sao_ctxt->i4_ctb_y ? 2 * SAO_SHIFT_CTB : 0) >> log2_min_cu;
296
0
                            i < (sao_blk_ht + (min_cu - 1)) >> log2_min_cu; i++)
297
0
            {
298
0
                WORD32 tmp_wd = sao_blk_wd;
299
300
0
                u4_no_loop_filter_flag = (*(UWORD32 *)(pu1_no_loop_filter_flag + i * loop_filter_strd)) >>
301
0
                                (loop_filter_bit_pos & 7);
302
0
                u4_no_loop_filter_flag &= (1 << ((tmp_wd + (min_cu - 1)) >> log2_min_cu)) - 1;
303
304
0
                if(u4_no_loop_filter_flag)
305
0
                {
306
0
                    no_loop_filter_enabled_chroma = 1;
307
0
                    while(tmp_wd > 0)
308
0
                    {
309
0
                        if(CTZ(u4_no_loop_filter_flag))
310
0
                        {
311
0
                            pu1_src_tmp_chroma += MIN(((WORD32)CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * chroma_pixel_strd / h_samp_factor;
312
0
                            pu1_src_backup_chroma += MIN(((WORD32)CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * chroma_pixel_strd / h_samp_factor;
313
0
                            tmp_wd -= (WORD32)(CTZ(u4_no_loop_filter_flag) << log2_min_cu);
314
0
                            u4_no_loop_filter_flag  >>= (CTZ(u4_no_loop_filter_flag));
315
0
                        }
316
0
                        else
317
0
                        {
318
0
                            for(row = 0; row < min_cu / v_samp_factor; row++)
319
0
                            {
320
0
                                for(col = 0; col < MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * chroma_pixel_strd / h_samp_factor; col++)
321
0
                                {
322
0
                                    pu1_src_backup_chroma[row * backup_strd * (chroma_pixel_strd / h_samp_factor) + col] = pu1_src_tmp_chroma[row * chroma_strd + col];
323
0
                                }
324
0
                            }
325
326
0
                            pu1_src_tmp_chroma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * chroma_pixel_strd / h_samp_factor;
327
0
                            pu1_src_backup_chroma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * chroma_pixel_strd / h_samp_factor;
328
0
                            tmp_wd -= (WORD32)(CTZ(~u4_no_loop_filter_flag) << log2_min_cu);
329
0
                            u4_no_loop_filter_flag  >>= (CTZ(~u4_no_loop_filter_flag));
330
0
                        }
331
0
                    }
332
333
0
                    pu1_src_tmp_chroma -= sao_blk_wd * (chroma_pixel_strd / h_samp_factor);
334
0
                    pu1_src_backup_chroma -= sao_blk_wd * (chroma_pixel_strd / h_samp_factor);
335
0
                }
336
337
0
                pu1_src_tmp_chroma += (((src_strd * chroma_pixel_strd) / (h_samp_factor * v_samp_factor)) << log2_min_cu);
338
0
                pu1_src_backup_chroma += (((backup_strd * chroma_pixel_strd) / (h_samp_factor * v_samp_factor)) << log2_min_cu);
339
0
            }
340
0
        }
341
0
    }
342
343
0
    DEBUG_PROCESS_TMP_BUF(ps_sao_ctxt->pu1_tmp_buf_luma, ps_sao_ctxt->pu1_tmp_buf_chroma);
344
345
    /* Top-left CTB */
346
0
    if(ps_sao_ctxt->i4_ctb_x > 0 && ps_sao_ctxt->i4_ctb_y > 0)
347
0
    {
348
0
        WORD32 sao_wd_luma = SAO_SHIFT_CTB;
349
0
        WORD32 sao_wd_chroma = 2 * SAO_SHIFT_CTB;
350
0
        WORD32 sao_ht_luma = SAO_SHIFT_CTB;
351
0
        WORD32 sao_ht_chroma = SAO_SHIFT_CTB;
352
353
0
        WORD32 ctbx_tl_t = 0, ctbx_tl_l = 0, ctbx_tl_r = 0, ctbx_tl_d = 0, ctbx_tl = 0;
354
0
        WORD32 ctby_tl_t = 0, ctby_tl_l = 0, ctby_tl_r = 0, ctby_tl_d = 0, ctby_tl = 0;
355
0
        WORD32 au4_idx_tl[8], idx_tl;
356
357
0
        slice_header_t *ps_slice_hdr_top_left;
358
0
        {
359
0
            WORD32 top_left_ctb_indx = (ps_sao_ctxt->i4_ctb_y - 1) * ps_sps->i2_pic_wd_in_ctb +
360
0
                                        (ps_sao_ctxt->i4_ctb_x - 1);
361
0
            ps_slice_hdr_top_left = ps_slice_hdr_base + pu1_slice_idx[top_left_ctb_indx];
362
0
        }
363
364
365
0
        pu1_src_luma -= (sao_wd_luma + sao_ht_luma * src_strd);
366
0
        pu1_src_chroma -= (sao_wd_chroma + sao_ht_chroma * chroma_strd);
367
0
        ps_sao -= (1 + ps_sps->i2_pic_wd_in_ctb);
368
0
        pu1_src_top_luma = ps_sao_ctxt->pu1_sao_src_top_luma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) - sao_wd_luma;
369
0
        pu1_src_top_chroma = ps_sao_ctxt->pu1_sao_src_top_chroma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor) - sao_wd_chroma;
370
0
        pu1_src_left_luma = ps_sao_ctxt->pu1_sao_src_left_luma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) - sao_ht_luma;
371
0
        pu1_src_left_chroma = ps_sao_ctxt->pu1_sao_src_left_chroma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) * (chroma_pixel_strd / v_samp_factor) - (2 * sao_ht_chroma);
372
373
0
        if(ps_slice_hdr_top_left->i1_slice_sao_luma_flag)
374
0
        {
375
0
            if(0 == ps_sao->b3_y_type_idx)
376
0
            {
377
                /* Update left, top and top-left */
378
0
                for(row = 0; row < sao_ht_luma; row++)
379
0
                {
380
0
                    pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
381
0
                }
382
0
                pu1_sao_src_luma_top_left_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
383
384
0
                memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
385
386
387
0
            }
388
389
0
            else if(1 == ps_sao->b3_y_type_idx)
390
0
            {
391
0
                ai1_offset_y[1] = ps_sao->b4_y_offset_1;
392
0
                ai1_offset_y[2] = ps_sao->b4_y_offset_2;
393
0
                ai1_offset_y[3] = ps_sao->b4_y_offset_3;
394
0
                ai1_offset_y[4] = ps_sao->b4_y_offset_4;
395
396
0
                ps_codec->s_func_selector.ihevc_sao_band_offset_luma_fptr(pu1_src_luma,
397
0
                                                                          src_strd,
398
0
                                                                          pu1_src_left_luma,
399
0
                                                                          pu1_src_top_luma,
400
0
                                                                          pu1_sao_src_luma_top_left_ctb,
401
0
                                                                          ps_sao->b5_y_band_pos,
402
0
                                                                          ai1_offset_y,
403
0
                                                                          sao_wd_luma,
404
0
                                                                          sao_ht_luma
405
0
                                                                         );
406
0
            }
407
408
0
            else // if(2 <= ps_sao->b3_y_type_idx)
409
0
            {
410
0
                ai1_offset_y[1] = ps_sao->b4_y_offset_1;
411
0
                ai1_offset_y[2] = ps_sao->b4_y_offset_2;
412
0
                ai1_offset_y[3] = ps_sao->b4_y_offset_3;
413
0
                ai1_offset_y[4] = ps_sao->b4_y_offset_4;
414
415
0
                for(i = 0; i < 8; i++)
416
0
                {
417
0
                    au1_avail_luma[i] = 255;
418
0
                    au1_tile_slice_boundary[i] = 0;
419
0
                    au4_idx_tl[i] = 0;
420
0
                    au4_ilf_across_tile_slice_enable[i] = 1;
421
0
                }
422
423
                /******************************************************************
424
                 * Derive the  Top-left CTB's neighbor pixel's slice indices.
425
                 *
426
                 *          TL_T
427
                 *       4  _2__5________
428
                 *     0   |    |       |
429
                 *    TL_L | TL | 1 TL_R|
430
                 *         |____|_______|____
431
                 *        6|TL_D|7      |    |
432
                 *         | 3  |       |    |
433
                 *         |____|_______|    |
434
                 *              |            |
435
                 *              |            |
436
                 *              |____________|
437
                 *
438
                 *****************************************************************/
439
440
                /*In case of slices, unless we encounter multiple slice/tiled clips, don't enter*/
441
0
                {
442
0
                    if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
443
0
                    {
444
0
                        {
445
                            /*Assuming that sao shift is uniform along x and y directions*/
446
0
                            if((0 == (1 << log2_ctb_size) - sao_wd_luma) && (ps_sao_ctxt->i4_ctb_y > 1) && (ps_sao_ctxt->i4_ctb_x > 1))
447
0
                            {
448
0
                                ctby_tl_t = ps_sao_ctxt->i4_ctb_y - 2;
449
0
                                ctbx_tl_l = ps_sao_ctxt->i4_ctb_x - 2;
450
0
                            }
451
0
                            else if(!(0 == (1 << log2_ctb_size) - sao_wd_luma))
452
0
                            {
453
0
                                ctby_tl_t = ps_sao_ctxt->i4_ctb_y - 1;
454
0
                                ctbx_tl_l = ps_sao_ctxt->i4_ctb_x - 1;
455
0
                            }
456
0
                            ctbx_tl_t = ps_sao_ctxt->i4_ctb_x - 1;
457
0
                            ctby_tl_l = ps_sao_ctxt->i4_ctb_y - 1;
458
459
0
                            ctbx_tl_r = ps_sao_ctxt->i4_ctb_x;
460
0
                            ctby_tl_r = ps_sao_ctxt->i4_ctb_y - 1;
461
462
0
                            ctbx_tl_d =  ps_sao_ctxt->i4_ctb_x - 1;
463
0
                            ctby_tl_d =  ps_sao_ctxt->i4_ctb_y;
464
465
0
                            ctbx_tl = ps_sao_ctxt->i4_ctb_x - 1;
466
0
                            ctby_tl = ps_sao_ctxt->i4_ctb_y - 1;
467
0
                        }
468
469
0
                        if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
470
0
                        {
471
                            /*Calculate slice indices for neighbor pixels*/
472
0
                            idx_tl   = pu1_slice_idx[ctbx_tl + (ctby_tl * ps_sps->i2_pic_wd_in_ctb)];
473
0
                            au4_idx_tl[2] = au4_idx_tl[4] = *(pu1_slice_idx + ctbx_tl_t + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb));
474
0
                            au4_idx_tl[0] =  pu1_slice_idx[ctbx_tl_l + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
475
0
                            au4_idx_tl[1] = au4_idx_tl[5] = pu1_slice_idx[ctbx_tl_r + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
476
0
                            au4_idx_tl[3] = au4_idx_tl[6] =   pu1_slice_idx[ctbx_tl_d + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
477
0
                            au4_idx_tl[7] = pu1_slice_idx[ctbx_tl_d + 1 + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
478
479
0
                            if((0 == (1 << log2_ctb_size) - sao_wd_luma))
480
0
                            {
481
0
                                if(ps_sao_ctxt->i4_ctb_x == 1)
482
0
                                {
483
0
                                    au4_idx_tl[6] = -1;
484
0
                                    au4_idx_tl[4] = -1;
485
0
                                }
486
0
                                else
487
0
                                {
488
0
                                    au4_idx_tl[6] = pu1_slice_idx[(ctbx_tl_d - 1) + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
489
0
                                }
490
0
                                if(ps_sao_ctxt->i4_ctb_y == 1)
491
0
                                {
492
0
                                    au4_idx_tl[5] = -1;
493
0
                                    au4_idx_tl[4] = -1;
494
0
                                }
495
0
                                else
496
0
                                {
497
0
                                    au4_idx_tl[5] = pu1_slice_idx[(ctbx_tl_l + 1) + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
498
0
                                    au4_idx_tl[4] = pu1_slice_idx[(ctbx_tl_t - 1) + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb)];
499
0
                                }
500
0
                                au4_idx_tl[7] = pu1_slice_idx[(ctbx_tl_d + 1) + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
501
0
                            }
502
503
                            /* Verify that the neighbor ctbs dont cross pic boundary.
504
                             * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
505
                             * of the pixel having a greater address is checked. Accordingly, set the availability flags.
506
                             * Hence, for top and left pixels, current ctb flag is checked. For right and down pixels,
507
                             * the respective pixel's flags are checked
508
                             */
509
510
0
                            if((0 == (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) - sao_wd_luma))
511
0
                            {
512
0
                                au4_ilf_across_tile_slice_enable[4] = 0;
513
0
                                au4_ilf_across_tile_slice_enable[6] = 0;
514
0
                            }
515
0
                            else
516
0
                            {
517
0
                                au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + au4_idx_tl[6])->i1_slice_loop_filter_across_slices_enabled_flag;
518
0
                            }
519
0
                            if((0 == (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) - sao_ht_luma))
520
0
                            {
521
0
                                au4_ilf_across_tile_slice_enable[5] = 0;
522
0
                                au4_ilf_across_tile_slice_enable[4] = 0;
523
0
                            }
524
0
                            else
525
0
                            {
526
0
                                au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
527
0
                                au4_ilf_across_tile_slice_enable[4] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
528
0
                            }
529
0
                            au4_ilf_across_tile_slice_enable[2] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
530
0
                            au4_ilf_across_tile_slice_enable[0] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
531
0
                            au4_ilf_across_tile_slice_enable[1] = (ps_slice_hdr_base + au4_idx_tl[1])->i1_slice_loop_filter_across_slices_enabled_flag;
532
0
                            au4_ilf_across_tile_slice_enable[3] = (ps_slice_hdr_base + au4_idx_tl[3])->i1_slice_loop_filter_across_slices_enabled_flag;
533
0
                            au4_ilf_across_tile_slice_enable[7] = (ps_slice_hdr_base + au4_idx_tl[7])->i1_slice_loop_filter_across_slices_enabled_flag;
534
535
0
                            if(au4_idx_tl[5] > idx_tl)
536
0
                            {
537
0
                                au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + au4_idx_tl[5])->i1_slice_loop_filter_across_slices_enabled_flag;
538
0
                            }
539
540
                            /*
541
                             * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
542
                             * of the pixel having a greater address is checked. Accordingly, set the availability flags.
543
                             * Hence, for top and left pixels, current ctb flag is checked. For right and down pixels,
544
                             * the respective pixel's flags are checked
545
                             */
546
0
                            for(i = 0; i < 8; i++)
547
0
                            {
548
                                /*Sets the edges that lie on the slice/tile boundary*/
549
0
                                if(au4_idx_tl[i] != idx_tl)
550
0
                                {
551
0
                                    au1_tile_slice_boundary[i] = 1;
552
0
                                }
553
0
                                else
554
0
                                {
555
0
                                    au4_ilf_across_tile_slice_enable[i] = 1;
556
0
                                }
557
0
                            }
558
559
0
                            memset((UWORD8 *)au4_idx_tl, 0, 8 * sizeof(WORD32));
560
0
                        }
561
562
0
                        if(ps_pps->i1_tiles_enabled_flag)
563
0
                        {
564
                            /* Calculate availability flags at slice boundary */
565
0
                            if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
566
0
                            {
567
                                /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
568
0
                                if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
569
0
                                {
570
                                    /*Set the boundary arrays*/
571
                                    /*Calculate tile indices for neighbor pixels*/
572
0
                                    idx_tl   = pu1_tile_idx[ctbx_tl + (ctby_tl * ps_sps->i2_pic_wd_in_ctb)];
573
0
                                    au4_idx_tl[2] = au4_idx_tl[4] = *(pu1_tile_idx + ctbx_tl_t + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb));
574
0
                                    au4_idx_tl[0] =  pu1_tile_idx[ctbx_tl_l + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
575
0
                                    au4_idx_tl[1] = au4_idx_tl[5] = pu1_tile_idx[ctbx_tl_r + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
576
0
                                    au4_idx_tl[3] = au4_idx_tl[6] =   pu1_tile_idx[ctbx_tl_d + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
577
0
                                    au4_idx_tl[7] = pu1_tile_idx[ctbx_tl_d + 1 + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
578
579
0
                                    if((0 == (1 << log2_ctb_size) - sao_wd_luma))
580
0
                                    {
581
0
                                        if(ps_sao_ctxt->i4_ctb_x == 1)
582
0
                                        {
583
0
                                            au4_idx_tl[6] = -1;
584
0
                                            au4_idx_tl[4] = -1;
585
0
                                        }
586
0
                                        else
587
0
                                        {
588
0
                                            au4_idx_tl[6] = pu1_tile_idx[(ctbx_tl_d - 1) + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
589
0
                                        }
590
0
                                        if(ps_sao_ctxt->i4_ctb_y == 1)
591
0
                                        {
592
0
                                            au4_idx_tl[5] = -1;
593
0
                                            au4_idx_tl[4] = -1;
594
0
                                        }
595
0
                                        else
596
0
                                        {
597
0
                                            au4_idx_tl[5] = pu1_tile_idx[(ctbx_tl_l + 1) + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
598
0
                                            au4_idx_tl[4] = pu1_tile_idx[(ctbx_tl_t - 1) + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb)];
599
0
                                        }
600
0
                                        au4_idx_tl[7] = pu1_tile_idx[(ctbx_tl_d + 1) + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
601
0
                                    }
602
0
                                    for(i = 0; i < 8; i++)
603
0
                                    {
604
                                        /*Sets the edges that lie on the tile boundary*/
605
0
                                        if(au4_idx_tl[i] != idx_tl)
606
0
                                        {
607
0
                                            au1_tile_slice_boundary[i] |= 1;
608
0
                                            au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag; //=0
609
0
                                        }
610
0
                                    }
611
0
                                }
612
0
                            }
613
0
                        }
614
615
616
                        /*Set availability flags based on tile and slice boundaries*/
617
0
                        for(i = 0; i < 8; i++)
618
0
                        {
619
                            /*Sets the edges that lie on the slice/tile boundary*/
620
0
                            if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
621
0
                            {
622
0
                                au1_avail_luma[i] = 0;
623
0
                            }
624
0
                        }
625
0
                    }
626
0
                }
627
628
0
                if(0 == (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) - sao_wd_luma)
629
0
                {
630
0
                    au1_avail_luma[0] = 0;
631
0
                    au1_avail_luma[4] = 0;
632
0
                    au1_avail_luma[6] = 0;
633
0
                }
634
635
0
                if(ps_sps->i2_pic_wd_in_ctb == ps_sao_ctxt->i4_ctb_x)
636
0
                {
637
0
                    au1_avail_luma[1] = 0;
638
0
                    au1_avail_luma[5] = 0;
639
0
                    au1_avail_luma[7] = 0;
640
0
                }
641
                //y==1 case
642
0
                if((0 == (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) - sao_ht_luma))
643
0
                {
644
0
                    au1_avail_luma[2] = 0;
645
0
                    au1_avail_luma[4] = 0;
646
0
                    au1_avail_luma[5] = 0;
647
0
                }
648
0
                if(ps_sps->i2_pic_ht_in_ctb == ps_sao_ctxt->i4_ctb_y)
649
0
                {
650
0
                    au1_avail_luma[3] = 0;
651
0
                    au1_avail_luma[6] = 0;
652
0
                    au1_avail_luma[7] = 0;
653
0
                }
654
655
0
                {
656
0
                    au1_src_top_right[0] = pu1_src_top_luma[sao_wd_luma];
657
0
                    u1_sao_src_top_left_luma_bot_left = pu1_src_left_luma[sao_ht_luma];
658
0
                    ps_codec->apf_sao_luma[ps_sao->b3_y_type_idx - 2](pu1_src_luma,
659
0
                                                                      src_strd,
660
0
                                                                      pu1_src_left_luma,
661
0
                                                                      pu1_src_top_luma,
662
0
                                                                      pu1_sao_src_luma_top_left_ctb,
663
0
                                                                      au1_src_top_right,
664
0
                                                                      &u1_sao_src_top_left_luma_bot_left,
665
0
                                                                      au1_avail_luma,
666
0
                                                                      ai1_offset_y,
667
0
                                                                      sao_wd_luma,
668
0
                                                                      sao_ht_luma);
669
0
                }
670
0
            }
671
672
0
        }
673
0
        else if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
674
0
        {
675
            /* Update left, top and top-left */
676
0
            for(row = 0; row < sao_ht_luma; row++)
677
0
            {
678
0
                pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
679
0
            }
680
0
            pu1_sao_src_luma_top_left_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
681
682
0
            memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
683
0
        }
684
685
0
        if(CHROMA_FMT_IDC_MONOCHROME != ps_sps->i1_chroma_format_idc && ps_slice_hdr_top_left->i1_slice_sao_chroma_flag)
686
0
        {
687
0
            if(0 == ps_sao->b3_cb_type_idx)
688
0
            {
689
0
                for(row = 0; row < sao_ht_chroma; row++)
690
0
                {
691
0
                    pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
692
0
                    pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
693
0
                }
694
0
                pu1_sao_src_chroma_top_left_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
695
0
                pu1_sao_src_chroma_top_left_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
696
697
0
                memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
698
699
0
            }
700
701
0
            else if(1 == ps_sao->b3_cb_type_idx)
702
0
            {
703
0
                ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
704
0
                ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
705
0
                ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
706
0
                ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
707
708
0
                ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
709
0
                ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
710
0
                ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
711
0
                ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
712
713
0
                if(chroma_yuv420sp_vu)
714
0
                {
715
0
                    ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
716
0
                                                                                chroma_strd,
717
0
                                                                                pu1_src_left_chroma,
718
0
                                                                                pu1_src_top_chroma,
719
0
                                                                                pu1_sao_src_chroma_top_left_ctb,
720
0
                                                                                ps_sao->b5_cr_band_pos,
721
0
                                                                                ps_sao->b5_cb_band_pos,
722
0
                                                                                ai1_offset_cr,
723
0
                                                                                ai1_offset_cb,
724
0
                                                                                sao_wd_chroma,
725
0
                                                                                sao_ht_chroma
726
0
                                                                               );
727
0
                }
728
0
                else
729
0
                {
730
0
                    ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
731
0
                                                                                chroma_strd,
732
0
                                                                                pu1_src_left_chroma,
733
0
                                                                                pu1_src_top_chroma,
734
0
                                                                                pu1_sao_src_chroma_top_left_ctb,
735
0
                                                                                ps_sao->b5_cb_band_pos,
736
0
                                                                                ps_sao->b5_cr_band_pos,
737
0
                                                                                ai1_offset_cb,
738
0
                                                                                ai1_offset_cr,
739
0
                                                                                sao_wd_chroma,
740
0
                                                                                sao_ht_chroma
741
0
                                                                               );
742
0
                }
743
0
            }
744
745
0
            else // if(2 <= ps_sao->b3_cb_type_idx)
746
0
            {
747
0
                ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
748
0
                ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
749
0
                ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
750
0
                ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
751
752
0
                ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
753
0
                ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
754
0
                ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
755
0
                ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
756
0
                for(i = 0; i < 8; i++)
757
0
                {
758
0
                    au1_avail_chroma[i] = 255;
759
0
                    au1_tile_slice_boundary[i] = 0;
760
0
                    au4_idx_tl[i] = 0;
761
0
                    au4_ilf_across_tile_slice_enable[i] = 1;
762
0
                }
763
                /*In case of slices*/
764
0
                {
765
0
                    if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
766
0
                    {
767
0
                        if((0 == (1 << log2_ctb_size) - sao_wd_chroma) && (ps_sao_ctxt->i4_ctb_y > 1) && (ps_sao_ctxt->i4_ctb_x > 1))
768
0
                        {
769
0
                            ctby_tl_t = ps_sao_ctxt->i4_ctb_y - 2;
770
0
                            ctbx_tl_l = ps_sao_ctxt->i4_ctb_x - 2;
771
0
                        }
772
0
                        else if(!(0 == (1 << log2_ctb_size) - sao_wd_chroma))
773
0
                        {
774
0
                            ctby_tl_t = ps_sao_ctxt->i4_ctb_y - 1;
775
0
                            ctbx_tl_l = ps_sao_ctxt->i4_ctb_x - 1;
776
0
                        }
777
0
                        ctbx_tl_t = ps_sao_ctxt->i4_ctb_x - 1;
778
0
                        ctby_tl_l = ps_sao_ctxt->i4_ctb_y - 1;
779
780
0
                        ctbx_tl_r = ps_sao_ctxt->i4_ctb_x;
781
0
                        ctby_tl_r = ps_sao_ctxt->i4_ctb_y - 1;
782
783
0
                        ctbx_tl_d =  ps_sao_ctxt->i4_ctb_x - 1;
784
0
                        ctby_tl_d =  ps_sao_ctxt->i4_ctb_y;
785
786
0
                        ctbx_tl = ps_sao_ctxt->i4_ctb_x - 1;
787
0
                        ctby_tl = ps_sao_ctxt->i4_ctb_y - 1;
788
789
0
                        if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
790
0
                        {
791
792
0
                            idx_tl   = pu1_slice_idx[ctbx_tl + (ctby_tl * ps_sps->i2_pic_wd_in_ctb)];
793
0
                            au4_idx_tl[2] = au4_idx_tl[4] = *(pu1_slice_idx + ctbx_tl_t + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb));
794
0
                            au4_idx_tl[0] =  pu1_slice_idx[ctbx_tl_l + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
795
0
                            au4_idx_tl[1] = au4_idx_tl[5] = pu1_slice_idx[ctbx_tl_r + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
796
0
                            au4_idx_tl[3] = au4_idx_tl[6] =   pu1_slice_idx[ctbx_tl_d + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
797
0
                            au4_idx_tl[7] = pu1_slice_idx[ctbx_tl_d + 1 + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
798
799
0
                            if((0 == (1 << log2_ctb_size) - sao_wd_chroma))
800
0
                            {
801
0
                                if(ps_sao_ctxt->i4_ctb_x == 1)
802
0
                                {
803
0
                                    au4_idx_tl[6] = -1;
804
0
                                    au4_idx_tl[4] = -1;
805
0
                                }
806
0
                                else
807
0
                                {
808
0
                                    au4_idx_tl[6] = pu1_slice_idx[(ctbx_tl_d - 1) + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
809
0
                                }
810
0
                                if(ps_sao_ctxt->i4_ctb_y == 1)
811
0
                                {
812
0
                                    au4_idx_tl[5] = -1;
813
0
                                    au4_idx_tl[4] = -1;
814
0
                                }
815
0
                                else
816
0
                                {
817
0
                                    au4_idx_tl[5] = pu1_slice_idx[(ctbx_tl_l + 1) + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
818
0
                                    if(ctbx_tl_t > 0)
819
0
                                        au4_idx_tl[4] = pu1_slice_idx[(ctbx_tl_t - 1) + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb)];
820
0
                                }
821
0
                                au4_idx_tl[7] = pu1_slice_idx[(ctbx_tl_d + 1) + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
822
0
                            }
823
824
                            /* Verify that the neighbor ctbs don't cross pic boundary
825
                             * Also, the ILF flag belonging to the higher pixel address (between neighbor and current pixels) must be assigned*/
826
0
                            if((0 == ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor)) - sao_wd_chroma))
827
0
                            {
828
0
                                au4_ilf_across_tile_slice_enable[4] = 0;
829
0
                                au4_ilf_across_tile_slice_enable[6] = 0;
830
0
                            }
831
0
                            else
832
0
                            {
833
0
                                au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
834
0
                            }
835
0
                            if((0 == ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) / v_samp_factor) - sao_ht_chroma))
836
0
                            {
837
0
                                au4_ilf_across_tile_slice_enable[5] = 0;
838
0
                                au4_ilf_across_tile_slice_enable[4] = 0;
839
0
                            }
840
0
                            else
841
0
                            {
842
0
                                au4_ilf_across_tile_slice_enable[4] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
843
0
                                au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
844
0
                            }
845
846
0
                            if(au4_idx_tl[5] > idx_tl)
847
0
                            {
848
0
                                au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + au4_idx_tl[5])->i1_slice_loop_filter_across_slices_enabled_flag;
849
0
                            }
850
0
                            if(au4_idx_tl[6] > idx_tl)
851
0
                            {
852
0
                                au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + au4_idx_tl[6])->i1_slice_loop_filter_across_slices_enabled_flag;
853
0
                            }
854
0
                            au4_ilf_across_tile_slice_enable[2] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
855
0
                            au4_ilf_across_tile_slice_enable[0] = (ps_slice_hdr_base + idx_tl)->i1_slice_loop_filter_across_slices_enabled_flag;
856
0
                            au4_ilf_across_tile_slice_enable[1] = (ps_slice_hdr_base + au4_idx_tl[1])->i1_slice_loop_filter_across_slices_enabled_flag;
857
0
                            au4_ilf_across_tile_slice_enable[3] = (ps_slice_hdr_base + au4_idx_tl[3])->i1_slice_loop_filter_across_slices_enabled_flag;
858
0
                            au4_ilf_across_tile_slice_enable[7] = (ps_slice_hdr_base + au4_idx_tl[7])->i1_slice_loop_filter_across_slices_enabled_flag;
859
                            /*
860
                             * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
861
                             * of the pixel having a greater address is checked. Accordingly, set the availability flags
862
                             */
863
0
                            for(i = 0; i < 8; i++)
864
0
                            {
865
                                /*Sets the edges that lie on the slice/tile boundary*/
866
0
                                if(au4_idx_tl[i] != idx_tl)
867
0
                                {
868
0
                                    au1_tile_slice_boundary[i] = 1;
869
0
                                }
870
0
                                else
871
0
                                {
872
0
                                    au4_ilf_across_tile_slice_enable[i] = 1;
873
0
                                }
874
0
                            }
875
876
                            /*Reset indices*/
877
0
                            for(i = 0; i < 8; i++)
878
0
                            {
879
0
                                au4_idx_tl[i] = 0;
880
0
                            }
881
0
                        }
882
0
                        if(ps_pps->i1_tiles_enabled_flag)
883
0
                        {
884
                            /* Calculate availability flags at slice boundary */
885
0
                            if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
886
0
                            {
887
                                /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
888
0
                                if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
889
0
                                {
890
                                    /*Set the boundary arrays*/
891
                                    /*Calculate tile indices for neighbor pixels*/
892
0
                                    idx_tl   = pu1_tile_idx[ctbx_tl + (ctby_tl * ps_sps->i2_pic_wd_in_ctb)];
893
0
                                    au4_idx_tl[2] = au4_idx_tl[4] = *(pu1_tile_idx + ctbx_tl_t + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb));
894
0
                                    au4_idx_tl[0] =  pu1_tile_idx[ctbx_tl_l + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
895
0
                                    au4_idx_tl[1] = au4_idx_tl[5] = pu1_tile_idx[ctbx_tl_r + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
896
0
                                    au4_idx_tl[3] = au4_idx_tl[6] =   pu1_tile_idx[ctbx_tl_d + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
897
0
                                    au4_idx_tl[7] = pu1_tile_idx[ctbx_tl_d + 1 + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
898
899
0
                                    if((0 == (1 << log2_ctb_size) - sao_wd_luma))
900
0
                                    {
901
0
                                        if(ps_sao_ctxt->i4_ctb_x == 1)
902
0
                                        {
903
0
                                            au4_idx_tl[6] = -1;
904
0
                                            au4_idx_tl[4] = -1;
905
0
                                        }
906
0
                                        else
907
0
                                        {
908
0
                                            au4_idx_tl[6] = pu1_tile_idx[(ctbx_tl_d - 1) + (ctby_tl_r * ps_sps->i2_pic_wd_in_ctb)];
909
0
                                        }
910
0
                                        if(ps_sao_ctxt->i4_ctb_y == 1)
911
0
                                        {
912
0
                                            au4_idx_tl[5] = -1;
913
0
                                            au4_idx_tl[4] = -1;
914
0
                                        }
915
0
                                        else
916
0
                                        {
917
0
                                            au4_idx_tl[5] = pu1_tile_idx[(ctbx_tl_l + 1) + (ctby_tl_l * ps_sps->i2_pic_wd_in_ctb)];
918
0
                                            au4_idx_tl[4] = pu1_tile_idx[(ctbx_tl_t - 1) + (ctby_tl_t * ps_sps->i2_pic_wd_in_ctb)];
919
0
                                        }
920
0
                                        au4_idx_tl[7] = pu1_tile_idx[(ctbx_tl_d + 1) + (ctby_tl_d * ps_sps->i2_pic_wd_in_ctb)];
921
0
                                    }
922
0
                                    for(i = 0; i < 8; i++)
923
0
                                    {
924
                                        /*Sets the edges that lie on the tile boundary*/
925
0
                                        if(au4_idx_tl[i] != idx_tl)
926
0
                                        {
927
0
                                            au1_tile_slice_boundary[i] |= 1;
928
0
                                            au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag; //=0
929
0
                                        }
930
0
                                    }
931
0
                                }
932
0
                            }
933
0
                        }
934
935
0
                        for(i = 0; i < 8; i++)
936
0
                        {
937
                            /*Sets the edges that lie on the slice/tile boundary*/
938
0
                            if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
939
0
                            {
940
0
                                au1_avail_chroma[i] = 0;
941
0
                            }
942
0
                        }
943
0
                    }
944
0
                }
945
946
0
                if(0 == ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor)) - sao_wd_chroma)
947
0
                {
948
0
                    au1_avail_chroma[0] = 0;
949
0
                    au1_avail_chroma[4] = 0;
950
0
                    au1_avail_chroma[6] = 0;
951
0
                }
952
0
                if(ps_sps->i2_pic_wd_in_ctb == ps_sao_ctxt->i4_ctb_x)
953
0
                {
954
0
                    au1_avail_chroma[1] = 0;
955
0
                    au1_avail_chroma[5] = 0;
956
0
                    au1_avail_chroma[7] = 0;
957
0
                }
958
959
0
                if(0 == ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) / v_samp_factor) - sao_ht_chroma)
960
0
                {
961
0
                    au1_avail_chroma[2] = 0;
962
0
                    au1_avail_chroma[4] = 0;
963
0
                    au1_avail_chroma[5] = 0;
964
0
                }
965
0
                if(ps_sps->i2_pic_ht_in_ctb == ps_sao_ctxt->i4_ctb_y)
966
0
                {
967
0
                    au1_avail_chroma[3] = 0;
968
0
                    au1_avail_chroma[6] = 0;
969
0
                    au1_avail_chroma[7] = 0;
970
0
                }
971
972
0
                {
973
0
                    au1_src_top_right[0] = pu1_src_top_chroma[sao_wd_chroma];
974
0
                    au1_src_top_right[1] = pu1_src_top_chroma[sao_wd_chroma + 1];
975
0
                    au1_sao_src_top_left_chroma_bot_left[0] = pu1_src_left_chroma[2 * sao_ht_chroma];
976
0
                    au1_sao_src_top_left_chroma_bot_left[1] = pu1_src_left_chroma[2 * sao_ht_chroma + 1];
977
0
                    if((ctb_size == 16) && (ps_sao_ctxt->i4_ctb_y != ps_sps->i2_pic_ht_in_ctb - 1))
978
0
                    {
979
0
                        au1_sao_src_top_left_chroma_bot_left[0] = pu1_src_chroma[sao_ht_chroma * chroma_strd - 2];
980
0
                        au1_sao_src_top_left_chroma_bot_left[1] = pu1_src_chroma[sao_ht_chroma * chroma_strd - 1];
981
0
                    }
982
983
0
                    if(chroma_yuv420sp_vu)
984
0
                    {
985
0
                        ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
986
0
                                                                             chroma_strd,
987
0
                                                                             pu1_src_left_chroma,
988
0
                                                                             pu1_src_top_chroma,
989
0
                                                                             pu1_sao_src_chroma_top_left_ctb,
990
0
                                                                             au1_src_top_right,
991
0
                                                                             au1_sao_src_top_left_chroma_bot_left,
992
0
                                                                             au1_avail_chroma,
993
0
                                                                             ai1_offset_cr,
994
0
                                                                             ai1_offset_cb,
995
0
                                                                             sao_wd_chroma,
996
0
                                                                             sao_ht_chroma);
997
0
                    }
998
0
                    else
999
0
                    {
1000
0
                        ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
1001
0
                                                                             chroma_strd,
1002
0
                                                                             pu1_src_left_chroma,
1003
0
                                                                             pu1_src_top_chroma,
1004
0
                                                                             pu1_sao_src_chroma_top_left_ctb,
1005
0
                                                                             au1_src_top_right,
1006
0
                                                                             au1_sao_src_top_left_chroma_bot_left,
1007
0
                                                                             au1_avail_chroma,
1008
0
                                                                             ai1_offset_cb,
1009
0
                                                                             ai1_offset_cr,
1010
0
                                                                             sao_wd_chroma,
1011
0
                                                                             sao_ht_chroma);
1012
0
                    }
1013
0
                }
1014
0
            }
1015
0
        }
1016
0
        else if(CHROMA_FMT_IDC_MONOCHROME != ps_sps->i1_chroma_format_idc && ((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag)))
1017
0
        {
1018
0
            for(row = 0; row < sao_ht_chroma; row++)
1019
0
            {
1020
0
                pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
1021
0
                pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
1022
0
            }
1023
0
            pu1_sao_src_chroma_top_left_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
1024
0
            pu1_sao_src_chroma_top_left_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
1025
1026
0
            memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
1027
0
        }
1028
1029
0
        pu1_src_luma += sao_wd_luma + sao_ht_luma * src_strd;
1030
0
        pu1_src_chroma += sao_wd_chroma + sao_ht_chroma * chroma_strd;
1031
0
        ps_sao += (1 + ps_sps->i2_pic_wd_in_ctb);
1032
0
    }
1033
1034
1035
    /* Top CTB */
1036
0
    if((ps_sao_ctxt->i4_ctb_y > 0))
1037
0
    {
1038
0
        WORD32 sao_wd_luma = ctb_size - SAO_SHIFT_CTB;
1039
0
        WORD32 sao_wd_chroma = ctb_size * (chroma_pixel_strd / h_samp_factor) - 2 * SAO_SHIFT_CTB;
1040
0
        WORD32 sao_ht_luma = SAO_SHIFT_CTB;
1041
0
        WORD32 sao_ht_chroma = SAO_SHIFT_CTB;
1042
1043
0
        WORD32 ctbx_t_t = 0, ctbx_t_l = 0, ctbx_t_r = 0, ctbx_t_d = 0, ctbx_t = 0;
1044
0
        WORD32 ctby_t_t = 0, ctby_t_l = 0, ctby_t_r = 0, ctby_t_d = 0, ctby_t = 0;
1045
0
        WORD32 au4_idx_t[8], idx_t;
1046
1047
0
        WORD32 remaining_cols;
1048
1049
0
        slice_header_t *ps_slice_hdr_top;
1050
0
        {
1051
0
            WORD32 top_ctb_indx = (ps_sao_ctxt->i4_ctb_y - 1) * ps_sps->i2_pic_wd_in_ctb +
1052
0
                                        (ps_sao_ctxt->i4_ctb_x);
1053
0
            ps_slice_hdr_top = ps_slice_hdr_base + pu1_slice_idx[top_ctb_indx];
1054
0
        }
1055
1056
0
        remaining_cols = ps_sps->i2_pic_width_in_luma_samples - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) + sao_wd_luma);
1057
0
        if(remaining_cols <= SAO_SHIFT_CTB)
1058
0
        {
1059
0
            sao_wd_luma += remaining_cols;
1060
0
        }
1061
0
        remaining_cols = ps_sps->i2_pic_width_in_luma_samples * (chroma_pixel_strd / h_samp_factor) - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor) + sao_wd_chroma);
1062
0
        if(remaining_cols <= 2 * SAO_SHIFT_CTB)
1063
0
        {
1064
0
            sao_wd_chroma += remaining_cols;
1065
0
        }
1066
1067
0
        pu1_src_luma -= (sao_ht_luma * src_strd);
1068
0
        pu1_src_chroma -= (sao_ht_chroma * chroma_strd);
1069
0
        ps_sao -= (ps_sps->i2_pic_wd_in_ctb);
1070
0
        pu1_src_top_luma = ps_sao_ctxt->pu1_sao_src_top_luma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size);
1071
0
        pu1_src_top_chroma = ps_sao_ctxt->pu1_sao_src_top_chroma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor);
1072
0
        pu1_src_left_luma = ps_sao_ctxt->pu1_sao_src_left_luma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) - sao_ht_chroma;
1073
0
        pu1_src_left_chroma = ps_sao_ctxt->pu1_sao_src_left_chroma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) * (chroma_pixel_strd / v_samp_factor) - (2 * sao_ht_chroma);
1074
1075
0
        if(0 != sao_wd_luma)
1076
0
        {
1077
0
            if(ps_slice_hdr_top->i1_slice_sao_luma_flag)
1078
0
            {
1079
0
                if(0 == ps_sao->b3_y_type_idx)
1080
0
                {
1081
                    /* Update left, top and top-left */
1082
0
                    for(row = 0; row < sao_ht_luma; row++)
1083
0
                    {
1084
0
                        pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
1085
0
                    }
1086
0
                    pu1_sao_src_luma_top_left_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
1087
1088
0
                    memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
1089
1090
0
                }
1091
1092
0
                else if(1 == ps_sao->b3_y_type_idx)
1093
0
                {
1094
0
                    ai1_offset_y[1] = ps_sao->b4_y_offset_1;
1095
0
                    ai1_offset_y[2] = ps_sao->b4_y_offset_2;
1096
0
                    ai1_offset_y[3] = ps_sao->b4_y_offset_3;
1097
0
                    ai1_offset_y[4] = ps_sao->b4_y_offset_4;
1098
1099
0
                    ps_codec->s_func_selector.ihevc_sao_band_offset_luma_fptr(pu1_src_luma,
1100
0
                                                                              src_strd,
1101
0
                                                                              pu1_src_left_luma,
1102
0
                                                                              pu1_src_top_luma,
1103
0
                                                                              pu1_sao_src_luma_top_left_ctb,
1104
0
                                                                              ps_sao->b5_y_band_pos,
1105
0
                                                                              ai1_offset_y,
1106
0
                                                                              sao_wd_luma,
1107
0
                                                                              sao_ht_luma
1108
0
                                                                             );
1109
0
                }
1110
1111
0
                else // if(2 <= ps_sao->b3_y_type_idx)
1112
0
                {
1113
0
                    ai1_offset_y[1] = ps_sao->b4_y_offset_1;
1114
0
                    ai1_offset_y[2] = ps_sao->b4_y_offset_2;
1115
0
                    ai1_offset_y[3] = ps_sao->b4_y_offset_3;
1116
0
                    ai1_offset_y[4] = ps_sao->b4_y_offset_4;
1117
1118
0
                    memset(au1_avail_luma, 255, 8);
1119
0
                    memset(au1_tile_slice_boundary, 0, 8);
1120
0
                    memset((UWORD8 *)au4_idx_t, 0, 8 * sizeof(WORD32));
1121
1122
0
                    for(i = 0; i < 8; i++)
1123
0
                    {
1124
1125
0
                        au4_ilf_across_tile_slice_enable[i] = 1;
1126
0
                    }
1127
                    /******************************************************************
1128
                     * Derive the  Top-left CTB's neighbor pixel's slice indices.
1129
                     *
1130
                     *               T_T
1131
                     *          ____________
1132
                     *         |    |       |
1133
                     *         | T_L|  T    |T_R
1134
                     *         |    | ______|____
1135
                     *         |    |  T_D  |    |
1136
                     *         |    |       |    |
1137
                     *         |____|_______|    |
1138
                     *              |            |
1139
                     *              |            |
1140
                     *              |____________|
1141
                     *
1142
                     *****************************************************************/
1143
1144
                    /*In case of slices*/
1145
0
                    {
1146
0
                        if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
1147
0
                        {
1148
1149
0
                            ctbx_t_t = ps_sao_ctxt->i4_ctb_x;
1150
0
                            ctby_t_t = ps_sao_ctxt->i4_ctb_y - 1;
1151
1152
0
                            ctbx_t_l = ps_sao_ctxt->i4_ctb_x - 1;
1153
0
                            ctby_t_l = ps_sao_ctxt->i4_ctb_y - 1;
1154
1155
0
                            ctbx_t_r = ps_sao_ctxt->i4_ctb_x;
1156
0
                            ctby_t_r = ps_sao_ctxt->i4_ctb_y - 1;
1157
1158
0
                            ctbx_t_d =  ps_sao_ctxt->i4_ctb_x;
1159
0
                            ctby_t_d =  ps_sao_ctxt->i4_ctb_y;
1160
1161
0
                            ctbx_t = ps_sao_ctxt->i4_ctb_x;
1162
0
                            ctby_t = ps_sao_ctxt->i4_ctb_y - 1;
1163
1164
0
                            if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
1165
0
                            {
1166
                                /*Calculate neighbor ctb slice indices*/
1167
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
1168
0
                                {
1169
0
                                    au4_idx_t[0] = -1;
1170
0
                                    au4_idx_t[6] = -1;
1171
0
                                    au4_idx_t[4] = -1;
1172
0
                                }
1173
0
                                else
1174
0
                                {
1175
0
                                    au4_idx_t[0] = au4_idx_t[4] = pu1_slice_idx[ctbx_t_l + (ctby_t_l * ps_sps->i2_pic_wd_in_ctb)];
1176
0
                                    au4_idx_t[6] = pu1_slice_idx[ctbx_t_d - 1 + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1177
0
                                }
1178
0
                                idx_t   = pu1_slice_idx[ctbx_t + (ctby_t * ps_sps->i2_pic_wd_in_ctb)];
1179
0
                                au4_idx_t[2] = au4_idx_t[5] = pu1_slice_idx[ctbx_t_t + (ctby_t_t * ps_sps->i2_pic_wd_in_ctb)];
1180
0
                                au4_idx_t[1] = pu1_slice_idx[ctbx_t_r + (ctby_t_r * ps_sps->i2_pic_wd_in_ctb)];
1181
0
                                au4_idx_t[3] = au4_idx_t[7] = pu1_slice_idx[ctbx_t_d + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1182
1183
                                /*Verify that the neighbor ctbs don't cross pic boundary.*/
1184
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
1185
0
                                {
1186
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
1187
0
                                    au4_ilf_across_tile_slice_enable[6] = 0;
1188
0
                                    au4_ilf_across_tile_slice_enable[0] = 0;
1189
0
                                }
1190
0
                                else
1191
0
                                {
1192
0
                                    au4_ilf_across_tile_slice_enable[4] = au4_ilf_across_tile_slice_enable[0] = (ps_slice_hdr_base + idx_t)->i1_slice_loop_filter_across_slices_enabled_flag;
1193
0
                                    au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + au4_idx_t[6])->i1_slice_loop_filter_across_slices_enabled_flag;
1194
0
                                }
1195
1196
1197
1198
0
                                au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + idx_t)->i1_slice_loop_filter_across_slices_enabled_flag;
1199
0
                                au4_ilf_across_tile_slice_enable[2] = (ps_slice_hdr_base + idx_t)->i1_slice_loop_filter_across_slices_enabled_flag;
1200
0
                                au4_ilf_across_tile_slice_enable[1] = (ps_slice_hdr_base + au4_idx_t[1])->i1_slice_loop_filter_across_slices_enabled_flag;
1201
0
                                au4_ilf_across_tile_slice_enable[3] = (ps_slice_hdr_base + au4_idx_t[3])->i1_slice_loop_filter_across_slices_enabled_flag;
1202
0
                                au4_ilf_across_tile_slice_enable[7] = (ps_slice_hdr_base + au4_idx_t[7])->i1_slice_loop_filter_across_slices_enabled_flag;
1203
1204
0
                                if(au4_idx_t[6] < idx_t)
1205
0
                                {
1206
0
                                    au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + idx_t)->i1_slice_loop_filter_across_slices_enabled_flag;
1207
0
                                }
1208
1209
                                /*
1210
                                 * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
1211
                                 * of the pixel having a greater address is checked. Accordingly, set the availability flags
1212
                                 */
1213
1214
0
                                for(i = 0; i < 8; i++)
1215
0
                                {
1216
                                    /*Sets the edges that lie on the slice/tile boundary*/
1217
0
                                    if(au4_idx_t[i] != idx_t)
1218
0
                                    {
1219
0
                                        au1_tile_slice_boundary[i] = 1;
1220
                                        /*Check for slice flag at such boundaries*/
1221
0
                                    }
1222
0
                                    else
1223
0
                                    {
1224
0
                                        au4_ilf_across_tile_slice_enable[i] = 1;
1225
0
                                    }
1226
0
                                }
1227
                                /*Reset indices*/
1228
0
                                for(i = 0; i < 8; i++)
1229
0
                                {
1230
0
                                    au4_idx_t[i] = 0;
1231
0
                                }
1232
0
                            }
1233
1234
0
                            if(ps_pps->i1_tiles_enabled_flag)
1235
0
                            {
1236
                                /* Calculate availability flags at slice boundary */
1237
0
                                if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
1238
0
                                {
1239
                                    /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
1240
0
                                    if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
1241
0
                                    {
1242
                                        /*Calculate neighbor ctb slice indices*/
1243
0
                                        if(0 == ps_sao_ctxt->i4_ctb_x)
1244
0
                                        {
1245
0
                                            au4_idx_t[0] = -1;
1246
0
                                            au4_idx_t[6] = -1;
1247
0
                                            au4_idx_t[4] = -1;
1248
0
                                        }
1249
0
                                        else
1250
0
                                        {
1251
0
                                            au4_idx_t[0] = au4_idx_t[4] = pu1_tile_idx[ctbx_t_l + (ctby_t_l * ps_sps->i2_pic_wd_in_ctb)];
1252
0
                                            au4_idx_t[6] = pu1_tile_idx[ctbx_t_d - 1 + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1253
0
                                        }
1254
0
                                        idx_t   = pu1_tile_idx[ctbx_t + (ctby_t * ps_sps->i2_pic_wd_in_ctb)];
1255
0
                                        au4_idx_t[2] = au4_idx_t[5] = pu1_tile_idx[ctbx_t_t + (ctby_t_t * ps_sps->i2_pic_wd_in_ctb)];
1256
0
                                        au4_idx_t[1] = pu1_tile_idx[ctbx_t_r + (ctby_t_r * ps_sps->i2_pic_wd_in_ctb)];
1257
0
                                        au4_idx_t[3] = au4_idx_t[7] = pu1_tile_idx[ctbx_t_d + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1258
1259
0
                                        for(i = 0; i < 8; i++)
1260
0
                                        {
1261
                                            /*Sets the edges that lie on the tile boundary*/
1262
0
                                            if(au4_idx_t[i] != idx_t)
1263
0
                                            {
1264
0
                                                au1_tile_slice_boundary[i] |= 1;
1265
0
                                                au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag;
1266
0
                                            }
1267
0
                                        }
1268
0
                                    }
1269
0
                                }
1270
0
                            }
1271
1272
0
                            for(i = 0; i < 8; i++)
1273
0
                            {
1274
                                /*Sets the edges that lie on the slice/tile boundary*/
1275
0
                                if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
1276
0
                                {
1277
0
                                    au1_avail_luma[i] = 0;
1278
0
                                }
1279
0
                            }
1280
0
                        }
1281
0
                    }
1282
1283
1284
0
                    if(0 == ps_sao_ctxt->i4_ctb_x)
1285
0
                    {
1286
0
                        au1_avail_luma[0] = 0;
1287
0
                        au1_avail_luma[4] = 0;
1288
0
                        au1_avail_luma[6] = 0;
1289
0
                    }
1290
1291
0
                    if(ps_sps->i2_pic_width_in_luma_samples - (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) <= sao_wd_luma)
1292
0
                    {
1293
0
                        au1_avail_luma[1] = 0;
1294
0
                        au1_avail_luma[5] = 0;
1295
0
                        au1_avail_luma[7] = 0;
1296
0
                    }
1297
1298
0
                    if(0 == (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) - sao_ht_luma)
1299
0
                    {
1300
0
                        au1_avail_luma[2] = 0;
1301
0
                        au1_avail_luma[4] = 0;
1302
0
                        au1_avail_luma[5] = 0;
1303
0
                    }
1304
1305
0
                    if(ps_sps->i2_pic_ht_in_ctb == ps_sao_ctxt->i4_ctb_y)
1306
0
                    {
1307
0
                        au1_avail_luma[3] = 0;
1308
0
                        au1_avail_luma[6] = 0;
1309
0
                        au1_avail_luma[7] = 0;
1310
0
                    }
1311
1312
0
                    {
1313
0
                        au1_src_top_right[0] = pu1_sao_src_top_left_luma_top_right[0];
1314
0
                        u1_sao_src_top_left_luma_bot_left = pu1_src_luma[sao_ht_luma * src_strd - 1];
1315
0
                        ps_codec->apf_sao_luma[ps_sao->b3_y_type_idx - 2](pu1_src_luma,
1316
0
                                                                          src_strd,
1317
0
                                                                          pu1_src_left_luma,
1318
0
                                                                          pu1_src_top_luma,
1319
0
                                                                          pu1_sao_src_luma_top_left_ctb,
1320
0
                                                                          au1_src_top_right,
1321
0
                                                                          &u1_sao_src_top_left_luma_bot_left,
1322
0
                                                                          au1_avail_luma,
1323
0
                                                                          ai1_offset_y,
1324
0
                                                                          sao_wd_luma,
1325
0
                                                                          sao_ht_luma);
1326
0
                    }
1327
0
                }
1328
0
            }
1329
0
            else if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
1330
0
            {
1331
                /* Update left, top and top-left */
1332
0
                for(row = 0; row < sao_ht_luma; row++)
1333
0
                {
1334
0
                    pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
1335
0
                }
1336
0
                pu1_sao_src_luma_top_left_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
1337
1338
0
                memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
1339
0
            }
1340
0
        }
1341
1342
0
        if(CHROMA_FMT_IDC_MONOCHROME != ps_sps->i1_chroma_format_idc && 0 != sao_wd_chroma)
1343
0
        {
1344
0
            if(ps_slice_hdr_top->i1_slice_sao_chroma_flag)
1345
0
            {
1346
0
                if(0 == ps_sao->b3_cb_type_idx)
1347
0
                {
1348
1349
0
                    for(row = 0; row < sao_ht_chroma; row++)
1350
0
                    {
1351
0
                        pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
1352
0
                        pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
1353
0
                    }
1354
0
                    pu1_sao_src_chroma_top_left_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
1355
0
                    pu1_sao_src_chroma_top_left_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
1356
1357
0
                    memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
1358
1359
0
                }
1360
1361
0
                else if(1 == ps_sao->b3_cb_type_idx)
1362
0
                {
1363
0
                    ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
1364
0
                    ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
1365
0
                    ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
1366
0
                    ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
1367
1368
0
                    ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
1369
0
                    ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
1370
0
                    ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
1371
0
                    ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
1372
1373
0
                    if(chroma_yuv420sp_vu)
1374
0
                    {
1375
0
                        ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
1376
0
                                                                                    chroma_strd,
1377
0
                                                                                    pu1_src_left_chroma,
1378
0
                                                                                    pu1_src_top_chroma,
1379
0
                                                                                    pu1_sao_src_chroma_top_left_ctb,
1380
0
                                                                                    ps_sao->b5_cr_band_pos,
1381
0
                                                                                    ps_sao->b5_cb_band_pos,
1382
0
                                                                                    ai1_offset_cr,
1383
0
                                                                                    ai1_offset_cb,
1384
0
                                                                                    sao_wd_chroma,
1385
0
                                                                                    sao_ht_chroma
1386
0
                                                                                   );
1387
0
                    }
1388
0
                    else
1389
0
                    {
1390
0
                        ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
1391
0
                                                                                    chroma_strd,
1392
0
                                                                                    pu1_src_left_chroma,
1393
0
                                                                                    pu1_src_top_chroma,
1394
0
                                                                                    pu1_sao_src_chroma_top_left_ctb,
1395
0
                                                                                    ps_sao->b5_cb_band_pos,
1396
0
                                                                                    ps_sao->b5_cr_band_pos,
1397
0
                                                                                    ai1_offset_cb,
1398
0
                                                                                    ai1_offset_cr,
1399
0
                                                                                    sao_wd_chroma,
1400
0
                                                                                    sao_ht_chroma
1401
0
                                                                                   );
1402
0
                    }
1403
0
                }
1404
0
                else // if(2 <= ps_sao->b3_cb_type_idx)
1405
0
                {
1406
0
                    ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
1407
0
                    ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
1408
0
                    ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
1409
0
                    ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
1410
1411
0
                    ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
1412
0
                    ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
1413
0
                    ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
1414
0
                    ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
1415
1416
0
                    for(i = 0; i < 8; i++)
1417
0
                    {
1418
0
                        au1_avail_chroma[i] = 255;
1419
0
                        au1_tile_slice_boundary[i] = 0;
1420
0
                        au4_idx_t[i] = 0;
1421
0
                        au4_ilf_across_tile_slice_enable[i] = 1;
1422
0
                    }
1423
1424
0
                    {
1425
0
                        if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
1426
0
                        {
1427
0
                            ctbx_t_t = ps_sao_ctxt->i4_ctb_x;
1428
0
                            ctby_t_t = ps_sao_ctxt->i4_ctb_y - 1;
1429
1430
0
                            ctbx_t_l = ps_sao_ctxt->i4_ctb_x - 1;
1431
0
                            ctby_t_l = ps_sao_ctxt->i4_ctb_y - 1;
1432
1433
0
                            ctbx_t_r = ps_sao_ctxt->i4_ctb_x;
1434
0
                            ctby_t_r = ps_sao_ctxt->i4_ctb_y - 1;
1435
1436
0
                            ctbx_t_d =  ps_sao_ctxt->i4_ctb_x;
1437
0
                            ctby_t_d =  ps_sao_ctxt->i4_ctb_y;
1438
1439
0
                            ctbx_t = ps_sao_ctxt->i4_ctb_x;
1440
0
                            ctby_t = ps_sao_ctxt->i4_ctb_y - 1;
1441
1442
0
                            if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
1443
0
                            {
1444
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
1445
0
                                {
1446
0
                                    au4_idx_t[0] = -1;
1447
0
                                    au4_idx_t[6] = -1;
1448
0
                                    au4_idx_t[4] = -1;
1449
0
                                }
1450
0
                                else
1451
0
                                {
1452
0
                                    au4_idx_t[0] = au4_idx_t[4] = pu1_slice_idx[ctbx_t_l + (ctby_t_l * ps_sps->i2_pic_wd_in_ctb)];
1453
0
                                    au4_idx_t[6] = pu1_slice_idx[ctbx_t_d - 1 + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1454
0
                                }
1455
0
                                idx_t   = pu1_slice_idx[ctbx_t + (ctby_t * ps_sps->i2_pic_wd_in_ctb)];
1456
0
                                au4_idx_t[2] = au4_idx_t[5] = pu1_slice_idx[ctbx_t_t + (ctby_t_t * ps_sps->i2_pic_wd_in_ctb)];
1457
0
                                au4_idx_t[1] = pu1_slice_idx[ctbx_t_r + (ctby_t_r * ps_sps->i2_pic_wd_in_ctb)];
1458
0
                                au4_idx_t[3] = au4_idx_t[7] = pu1_slice_idx[ctbx_t_d + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1459
1460
                                /*Verify that the neighbor ctbs don't cross pic boundary.*/
1461
1462
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
1463
0
                                {
1464
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
1465
0
                                    au4_ilf_across_tile_slice_enable[6] = 0;
1466
0
                                    au4_ilf_across_tile_slice_enable[0] = 0;
1467
0
                                }
1468
0
                                else
1469
0
                                {
1470
0
                                    au4_ilf_across_tile_slice_enable[4] = au4_ilf_across_tile_slice_enable[0] = (ps_slice_hdr_base + idx_t)->i1_slice_loop_filter_across_slices_enabled_flag;
1471
0
                                    au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + au4_idx_t[6])->i1_slice_loop_filter_across_slices_enabled_flag;
1472
0
                                }
1473
1474
0
                                au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + au4_idx_t[5])->i1_slice_loop_filter_across_slices_enabled_flag;
1475
0
                                au4_ilf_across_tile_slice_enable[2] = (ps_slice_hdr_base + idx_t)->i1_slice_loop_filter_across_slices_enabled_flag;
1476
0
                                au4_ilf_across_tile_slice_enable[1] = (ps_slice_hdr_base + au4_idx_t[1])->i1_slice_loop_filter_across_slices_enabled_flag;
1477
0
                                au4_ilf_across_tile_slice_enable[3] = (ps_slice_hdr_base + au4_idx_t[3])->i1_slice_loop_filter_across_slices_enabled_flag;
1478
0
                                au4_ilf_across_tile_slice_enable[7] = (ps_slice_hdr_base + au4_idx_t[7])->i1_slice_loop_filter_across_slices_enabled_flag;
1479
1480
0
                                if(idx_t > au4_idx_t[6])
1481
0
                                {
1482
0
                                    au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + idx_t)->i1_slice_loop_filter_across_slices_enabled_flag;
1483
0
                                }
1484
1485
                                /*
1486
                                 * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
1487
                                 * of the pixel having a greater address is checked. Accordingly, set the availability flags
1488
                                 */
1489
0
                                for(i = 0; i < 8; i++)
1490
0
                                {
1491
                                    /*Sets the edges that lie on the slice/tile boundary*/
1492
0
                                    if(au4_idx_t[i] != idx_t)
1493
0
                                    {
1494
0
                                        au1_tile_slice_boundary[i] = 1;
1495
0
                                    }
1496
0
                                    else
1497
0
                                    {
1498
                                        /*Indicates that the neighbour belongs to same/dependent slice*/
1499
0
                                        au4_ilf_across_tile_slice_enable[i] = 1;
1500
0
                                    }
1501
0
                                }
1502
                                /*Reset indices*/
1503
0
                                for(i = 0; i < 8; i++)
1504
0
                                {
1505
0
                                    au4_idx_t[i] = 0;
1506
0
                                }
1507
0
                            }
1508
0
                            if(ps_pps->i1_tiles_enabled_flag)
1509
0
                            {
1510
                                /* Calculate availability flags at slice boundary */
1511
0
                                if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
1512
0
                                {
1513
                                    /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
1514
0
                                    if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
1515
0
                                    {
1516
                                        /*Calculate neighbor ctb slice indices*/
1517
0
                                        if(0 == ps_sao_ctxt->i4_ctb_x)
1518
0
                                        {
1519
0
                                            au4_idx_t[0] = -1;
1520
0
                                            au4_idx_t[6] = -1;
1521
0
                                            au4_idx_t[4] = -1;
1522
0
                                        }
1523
0
                                        else
1524
0
                                        {
1525
0
                                            au4_idx_t[0] = au4_idx_t[4] = pu1_tile_idx[ctbx_t_l + (ctby_t_l * ps_sps->i2_pic_wd_in_ctb)];
1526
0
                                            au4_idx_t[6] = pu1_tile_idx[ctbx_t_d - 1 + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1527
0
                                        }
1528
0
                                        idx_t   = pu1_tile_idx[ctbx_t + (ctby_t * ps_sps->i2_pic_wd_in_ctb)];
1529
0
                                        au4_idx_t[2] = au4_idx_t[5] = pu1_tile_idx[ctbx_t_t + (ctby_t_t * ps_sps->i2_pic_wd_in_ctb)];
1530
0
                                        au4_idx_t[1] = pu1_tile_idx[ctbx_t_r + (ctby_t_r * ps_sps->i2_pic_wd_in_ctb)];
1531
0
                                        au4_idx_t[3] = au4_idx_t[7] = pu1_tile_idx[ctbx_t_d + (ctby_t_d * ps_sps->i2_pic_wd_in_ctb)];
1532
1533
0
                                        for(i = 0; i < 8; i++)
1534
0
                                        {
1535
                                            /*Sets the edges that lie on the tile boundary*/
1536
0
                                            if(au4_idx_t[i] != idx_t)
1537
0
                                            {
1538
0
                                                au1_tile_slice_boundary[i] |= 1;
1539
0
                                                au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag;
1540
0
                                            }
1541
0
                                        }
1542
0
                                    }
1543
0
                                }
1544
0
                            }
1545
0
                            for(i = 0; i < 8; i++)
1546
0
                            {
1547
                                /*Sets the edges that lie on the slice/tile boundary*/
1548
0
                                if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
1549
0
                                {
1550
0
                                    au1_avail_chroma[i] = 0;
1551
0
                                }
1552
0
                            }
1553
1554
0
                        }
1555
0
                    }
1556
0
                    if(0 == ps_sao_ctxt->i4_ctb_x)
1557
0
                    {
1558
0
                        au1_avail_chroma[0] = 0;
1559
0
                        au1_avail_chroma[4] = 0;
1560
0
                        au1_avail_chroma[6] = 0;
1561
0
                    }
1562
1563
0
                    if(ps_sps->i2_pic_width_in_luma_samples * (chroma_pixel_strd / h_samp_factor) - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor)) <= sao_wd_chroma)
1564
0
                    {
1565
0
                        au1_avail_chroma[1] = 0;
1566
0
                        au1_avail_chroma[5] = 0;
1567
0
                        au1_avail_chroma[7] = 0;
1568
0
                    }
1569
1570
0
                    if(0 == ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) / v_samp_factor) - sao_ht_chroma)
1571
0
                    {
1572
0
                        au1_avail_chroma[2] = 0;
1573
0
                        au1_avail_chroma[4] = 0;
1574
0
                        au1_avail_chroma[5] = 0;
1575
0
                    }
1576
1577
0
                    if(ps_sps->i2_pic_ht_in_ctb == ps_sao_ctxt->i4_ctb_y)
1578
0
                    {
1579
0
                        au1_avail_chroma[3] = 0;
1580
0
                        au1_avail_chroma[6] = 0;
1581
0
                        au1_avail_chroma[7] = 0;
1582
0
                    }
1583
1584
0
                    {
1585
0
                        au1_src_top_right[0] = pu1_sao_src_top_left_chroma_top_right[0];
1586
0
                        au1_src_top_right[1] = pu1_sao_src_top_left_chroma_top_right[1];
1587
0
                        au1_sao_src_top_left_chroma_bot_left[0] = pu1_src_chroma[sao_ht_chroma * chroma_strd - 2];
1588
0
                        au1_sao_src_top_left_chroma_bot_left[1] = pu1_src_chroma[sao_ht_chroma * chroma_strd - 1];
1589
1590
0
                        if(chroma_yuv420sp_vu)
1591
0
                        {
1592
0
                            ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
1593
0
                                                                                 chroma_strd,
1594
0
                                                                                 pu1_src_left_chroma,
1595
0
                                                                                 pu1_src_top_chroma,
1596
0
                                                                                 pu1_sao_src_chroma_top_left_ctb,
1597
0
                                                                                 au1_src_top_right,
1598
0
                                                                                 au1_sao_src_top_left_chroma_bot_left,
1599
0
                                                                                 au1_avail_chroma,
1600
0
                                                                                 ai1_offset_cr,
1601
0
                                                                                 ai1_offset_cb,
1602
0
                                                                                 sao_wd_chroma,
1603
0
                                                                                 sao_ht_chroma);
1604
0
                        }
1605
0
                        else
1606
0
                        {
1607
0
                            ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
1608
0
                                                                                 chroma_strd,
1609
0
                                                                                 pu1_src_left_chroma,
1610
0
                                                                                 pu1_src_top_chroma,
1611
0
                                                                                 pu1_sao_src_chroma_top_left_ctb,
1612
0
                                                                                 au1_src_top_right,
1613
0
                                                                                 au1_sao_src_top_left_chroma_bot_left,
1614
0
                                                                                 au1_avail_chroma,
1615
0
                                                                                 ai1_offset_cb,
1616
0
                                                                                 ai1_offset_cr,
1617
0
                                                                                 sao_wd_chroma,
1618
0
                                                                                 sao_ht_chroma);
1619
0
                        }
1620
0
                    }
1621
1622
0
                }
1623
0
            }
1624
0
            else if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
1625
0
            {
1626
0
                for(row = 0; row < sao_ht_chroma; row++)
1627
0
                {
1628
0
                    pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
1629
0
                    pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
1630
0
                }
1631
0
                pu1_sao_src_chroma_top_left_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
1632
0
                pu1_sao_src_chroma_top_left_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
1633
1634
0
                memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
1635
0
            }
1636
0
        }
1637
1638
0
        pu1_src_luma += sao_ht_luma * src_strd;
1639
0
        pu1_src_chroma += sao_ht_chroma * chroma_strd;
1640
0
        ps_sao += (ps_sps->i2_pic_wd_in_ctb);
1641
0
    }
1642
1643
    /* Left CTB */
1644
0
    if(ps_sao_ctxt->i4_ctb_x > 0)
1645
0
    {
1646
0
        WORD32 sao_wd_luma = SAO_SHIFT_CTB;
1647
0
        WORD32 sao_wd_chroma = 2 * SAO_SHIFT_CTB;
1648
0
        WORD32 sao_ht_luma = ctb_size - SAO_SHIFT_CTB;
1649
0
        WORD32 sao_ht_chroma = (ctb_size / v_samp_factor) - SAO_SHIFT_CTB;
1650
1651
0
        WORD32 ctbx_l_t = 0, ctbx_l_l = 0, ctbx_l_r = 0, ctbx_l_d = 0, ctbx_l = 0;
1652
0
        WORD32 ctby_l_t = 0, ctby_l_l = 0, ctby_l_r = 0, ctby_l_d = 0, ctby_l = 0;
1653
0
        WORD32 au4_idx_l[8], idx_l;
1654
1655
0
        WORD32 remaining_rows;
1656
0
        slice_header_t *ps_slice_hdr_left;
1657
0
        {
1658
0
            WORD32 left_ctb_indx = (ps_sao_ctxt->i4_ctb_y) * ps_sps->i2_pic_wd_in_ctb +
1659
0
                                        (ps_sao_ctxt->i4_ctb_x - 1);
1660
0
            ps_slice_hdr_left = ps_slice_hdr_base + pu1_slice_idx[left_ctb_indx];
1661
0
        }
1662
1663
0
        remaining_rows = ps_sps->i2_pic_height_in_luma_samples - ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) + sao_ht_luma);
1664
0
        if(remaining_rows <= SAO_SHIFT_CTB)
1665
0
        {
1666
0
            sao_ht_luma += remaining_rows;
1667
0
        }
1668
0
        remaining_rows = ps_sps->i2_pic_height_in_luma_samples / v_samp_factor - (((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) / v_samp_factor) + sao_ht_chroma);
1669
0
        if(remaining_rows <= SAO_SHIFT_CTB)
1670
0
        {
1671
0
            sao_ht_chroma += remaining_rows;
1672
0
        }
1673
1674
0
        pu1_src_luma -= sao_wd_luma;
1675
0
        pu1_src_chroma -= sao_wd_chroma;
1676
0
        ps_sao -= 1;
1677
0
        pu1_src_top_luma = ps_sao_ctxt->pu1_sao_src_top_luma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) - sao_wd_luma;
1678
0
        pu1_src_top_chroma = ps_sao_ctxt->pu1_sao_src_top_chroma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor) - sao_wd_chroma;
1679
0
        pu1_src_left_luma = ps_sao_ctxt->pu1_sao_src_left_luma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size);
1680
0
        pu1_src_left_chroma = ps_sao_ctxt->pu1_sao_src_left_chroma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) * (chroma_pixel_strd / v_samp_factor);
1681
1682
1683
0
        if(0 != sao_ht_luma)
1684
0
        {
1685
0
            if(ps_slice_hdr_left->i1_slice_sao_luma_flag)
1686
0
            {
1687
0
                if(0 == ps_sao->b3_y_type_idx)
1688
0
                {
1689
                    /* Update left, top and top-left */
1690
0
                    for(row = 0; row < sao_ht_luma; row++)
1691
0
                    {
1692
0
                        pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
1693
0
                    }
1694
                    /*Update in next location*/
1695
0
                    pu1_sao_src_top_left_luma_curr_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
1696
1697
0
                    memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
1698
1699
0
                }
1700
1701
0
                else if(1 == ps_sao->b3_y_type_idx)
1702
0
                {
1703
0
                    ai1_offset_y[1] = ps_sao->b4_y_offset_1;
1704
0
                    ai1_offset_y[2] = ps_sao->b4_y_offset_2;
1705
0
                    ai1_offset_y[3] = ps_sao->b4_y_offset_3;
1706
0
                    ai1_offset_y[4] = ps_sao->b4_y_offset_4;
1707
1708
0
                    ps_codec->s_func_selector.ihevc_sao_band_offset_luma_fptr(pu1_src_luma,
1709
0
                                                                              src_strd,
1710
0
                                                                              pu1_src_left_luma,
1711
0
                                                                              pu1_src_top_luma,
1712
0
                                                                              pu1_sao_src_top_left_luma_curr_ctb,
1713
0
                                                                              ps_sao->b5_y_band_pos,
1714
0
                                                                              ai1_offset_y,
1715
0
                                                                              sao_wd_luma,
1716
0
                                                                              sao_ht_luma
1717
0
                                                                             );
1718
0
                }
1719
1720
0
                else // if(2 <= ps_sao->b3_y_type_idx)
1721
0
                {
1722
0
                    ai1_offset_y[1] = ps_sao->b4_y_offset_1;
1723
0
                    ai1_offset_y[2] = ps_sao->b4_y_offset_2;
1724
0
                    ai1_offset_y[3] = ps_sao->b4_y_offset_3;
1725
0
                    ai1_offset_y[4] = ps_sao->b4_y_offset_4;
1726
1727
0
                    for(i = 0; i < 8; i++)
1728
0
                    {
1729
0
                        au1_avail_luma[i] = 255;
1730
0
                        au1_tile_slice_boundary[i] = 0;
1731
0
                        au4_idx_l[i] = 0;
1732
0
                        au4_ilf_across_tile_slice_enable[i] = 1;
1733
0
                    }
1734
                    /******************************************************************
1735
                     * Derive the  Top-left CTB's neighbour pixel's slice indices.
1736
                     *
1737
                     *
1738
                     *          ____________
1739
                     *         |    |       |
1740
                     *         | L_T|       |
1741
                     *         |____|_______|____
1742
                     *         |    |       |    |
1743
                     *     L_L |  L |  L_R  |    |
1744
                     *         |____|_______|    |
1745
                     *              |            |
1746
                     *          L_D |            |
1747
                     *              |____________|
1748
                     *
1749
                     *****************************************************************/
1750
1751
                    /*In case of slices or tiles*/
1752
0
                    {
1753
0
                        if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
1754
0
                        {
1755
0
                            ctbx_l_t = ps_sao_ctxt->i4_ctb_x - 1;
1756
0
                            ctby_l_t = ps_sao_ctxt->i4_ctb_y - 1;
1757
1758
0
                            ctbx_l_l = ps_sao_ctxt->i4_ctb_x - 1;
1759
0
                            ctby_l_l = ps_sao_ctxt->i4_ctb_y;
1760
1761
0
                            ctbx_l_r = ps_sao_ctxt->i4_ctb_x;
1762
0
                            ctby_l_r = ps_sao_ctxt->i4_ctb_y;
1763
1764
0
                            ctbx_l_d =  ps_sao_ctxt->i4_ctb_x - 1;
1765
0
                            ctby_l_d =  ps_sao_ctxt->i4_ctb_y;
1766
1767
0
                            ctbx_l = ps_sao_ctxt->i4_ctb_x - 1;
1768
0
                            ctby_l = ps_sao_ctxt->i4_ctb_y;
1769
1770
0
                            if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
1771
0
                            {
1772
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
1773
0
                                {
1774
0
                                    au4_idx_l[2] = -1;
1775
0
                                    au4_idx_l[4] = -1;
1776
0
                                    au4_idx_l[5] = -1;
1777
0
                                }
1778
0
                                else
1779
0
                                {
1780
0
                                    au4_idx_l[2] = au4_idx_l[4] = pu1_slice_idx[ctbx_l_t + (ctby_l_t * ps_sps->i2_pic_wd_in_ctb)];
1781
0
                                    au4_idx_l[5] =  pu1_slice_idx[ctbx_l_t + 1 + (ctby_l_t  * ps_sps->i2_pic_wd_in_ctb)];
1782
0
                                }
1783
0
                                idx_l   = au4_idx_l[6] = pu1_slice_idx[ctbx_l + (ctby_l * ps_sps->i2_pic_wd_in_ctb)];
1784
0
                                au4_idx_l[0] = pu1_slice_idx[ctbx_l_l + (ctby_l_l * ps_sps->i2_pic_wd_in_ctb)];
1785
0
                                au4_idx_l[1] = au4_idx_l[7] = pu1_slice_idx[ctbx_l_r + (ctby_l_r * ps_sps->i2_pic_wd_in_ctb)];
1786
0
                                au4_idx_l[3] = pu1_slice_idx[ctbx_l_d + (ctby_l_d * ps_sps->i2_pic_wd_in_ctb)];
1787
1788
                                /*Verify that the neighbor ctbs don't cross pic boundary.*/
1789
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
1790
0
                                {
1791
0
                                    au4_ilf_across_tile_slice_enable[2] = 0;
1792
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
1793
0
                                    au4_ilf_across_tile_slice_enable[5] = 0;
1794
0
                                }
1795
0
                                else
1796
0
                                {
1797
0
                                    au4_ilf_across_tile_slice_enable[2] =  (ps_slice_hdr_base + idx_l)->i1_slice_loop_filter_across_slices_enabled_flag;
1798
0
                                    au4_ilf_across_tile_slice_enable[5] = au4_ilf_across_tile_slice_enable[4] = au4_ilf_across_tile_slice_enable[2];
1799
1800
0
                                }
1801
                                //TODO: ILF flag checks for [0] and [6] is missing.
1802
0
                                au4_ilf_across_tile_slice_enable[1] = (ps_slice_hdr_base + au4_idx_l[1])->i1_slice_loop_filter_across_slices_enabled_flag;
1803
0
                                au4_ilf_across_tile_slice_enable[3] = (ps_slice_hdr_base + au4_idx_l[3])->i1_slice_loop_filter_across_slices_enabled_flag;
1804
0
                                au4_ilf_across_tile_slice_enable[7] = (ps_slice_hdr_base + au4_idx_l[7])->i1_slice_loop_filter_across_slices_enabled_flag;
1805
1806
0
                                if(idx_l < au4_idx_l[5])
1807
0
                                {
1808
0
                                    au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + au4_idx_l[5])->i1_slice_loop_filter_across_slices_enabled_flag;
1809
0
                                }
1810
1811
                                /*
1812
                                 * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
1813
                                 * of the pixel having a greater address is checked. Accordingly, set the availability flags
1814
                                 */
1815
0
                                for(i = 0; i < 8; i++)
1816
0
                                {
1817
                                    /*Sets the edges that lie on the slice/tile boundary*/
1818
0
                                    if(au4_idx_l[i] != idx_l)
1819
0
                                    {
1820
0
                                        au1_tile_slice_boundary[i] = 1;
1821
0
                                    }
1822
0
                                    else
1823
0
                                    {
1824
0
                                        au4_ilf_across_tile_slice_enable[i] = 1;
1825
0
                                    }
1826
0
                                }
1827
                                /*Reset indices*/
1828
0
                                for(i = 0; i < 8; i++)
1829
0
                                {
1830
0
                                    au4_idx_l[i] = 0;
1831
0
                                }
1832
0
                            }
1833
1834
0
                            if(ps_pps->i1_tiles_enabled_flag)
1835
0
                            {
1836
                                /* Calculate availability flags at slice boundary */
1837
0
                                if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
1838
0
                                {
1839
                                    /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
1840
0
                                    if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
1841
0
                                    {
1842
0
                                        if(0 == ps_sao_ctxt->i4_ctb_y)
1843
0
                                        {
1844
0
                                            au4_idx_l[2] = -1;
1845
0
                                            au4_idx_l[4] = -1;
1846
0
                                            au4_idx_l[5] = -1;
1847
0
                                        }
1848
0
                                        else
1849
0
                                        {
1850
0
                                            au4_idx_l[2] = au4_idx_l[4] = pu1_tile_idx[ctbx_l_t + (ctby_l_t * ps_sps->i2_pic_wd_in_ctb)];
1851
0
                                            au4_idx_l[5] =  pu1_tile_idx[ctbx_l_t + 1 + (ctby_l_t  * ps_sps->i2_pic_wd_in_ctb)];
1852
0
                                        }
1853
1854
0
                                        idx_l   = au4_idx_l[6] = pu1_tile_idx[ctbx_l + (ctby_l * ps_sps->i2_pic_wd_in_ctb)];
1855
0
                                        au4_idx_l[0] = pu1_tile_idx[ctbx_l_l + (ctby_l_l * ps_sps->i2_pic_wd_in_ctb)];
1856
0
                                        au4_idx_l[1] = au4_idx_l[7] = pu1_tile_idx[ctbx_l_r + (ctby_l_r * ps_sps->i2_pic_wd_in_ctb)];
1857
0
                                        au4_idx_l[3] = pu1_tile_idx[ctbx_l_d + (ctby_l_d * ps_sps->i2_pic_wd_in_ctb)];
1858
1859
0
                                        for(i = 0; i < 8; i++)
1860
0
                                        {
1861
                                            /*Sets the edges that lie on the slice/tile boundary*/
1862
0
                                            if(au4_idx_l[i] != idx_l)
1863
0
                                            {
1864
0
                                                au1_tile_slice_boundary[i] |= 1;
1865
0
                                                au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag;
1866
0
                                            }
1867
0
                                        }
1868
0
                                    }
1869
0
                                }
1870
0
                            }
1871
1872
0
                            for(i = 0; i < 8; i++)
1873
0
                            {
1874
                                /*Sets the edges that lie on the slice/tile boundary*/
1875
0
                                if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
1876
0
                                {
1877
0
                                    au1_avail_luma[i] = 0;
1878
0
                                }
1879
0
                            }
1880
0
                        }
1881
0
                    }
1882
0
                    if(0 == (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) - sao_wd_luma)
1883
0
                    {
1884
0
                        au1_avail_luma[0] = 0;
1885
0
                        au1_avail_luma[4] = 0;
1886
0
                        au1_avail_luma[6] = 0;
1887
0
                    }
1888
0
                    if(ps_sps->i2_pic_wd_in_ctb == ps_sao_ctxt->i4_ctb_x)
1889
0
                    {
1890
0
                        au1_avail_luma[1] = 0;
1891
0
                        au1_avail_luma[5] = 0;
1892
0
                        au1_avail_luma[7] = 0;
1893
0
                    }
1894
1895
0
                    if(0 == ps_sao_ctxt->i4_ctb_y)
1896
0
                    {
1897
0
                        au1_avail_luma[2] = 0;
1898
0
                        au1_avail_luma[4] = 0;
1899
0
                        au1_avail_luma[5] = 0;
1900
0
                    }
1901
1902
0
                    if(ps_sps->i2_pic_height_in_luma_samples - (ps_sao_ctxt->i4_ctb_y  << log2_ctb_size) <= sao_ht_luma)
1903
0
                    {
1904
0
                        au1_avail_luma[3] = 0;
1905
0
                        au1_avail_luma[6] = 0;
1906
0
                        au1_avail_luma[7] = 0;
1907
0
                    }
1908
1909
0
                    {
1910
0
                        au1_src_top_right[0] = pu1_src_top_luma[sao_wd_luma];
1911
0
                        u1_sao_src_top_left_luma_bot_left = pu1_sao_src_top_left_luma_bot_left[0];
1912
0
                        ps_codec->apf_sao_luma[ps_sao->b3_y_type_idx - 2](pu1_src_luma,
1913
0
                                                                          src_strd,
1914
0
                                                                          pu1_src_left_luma,
1915
0
                                                                          pu1_src_top_luma,
1916
0
                                                                          pu1_sao_src_top_left_luma_curr_ctb,
1917
0
                                                                          au1_src_top_right,
1918
0
                                                                          &u1_sao_src_top_left_luma_bot_left,
1919
0
                                                                          au1_avail_luma,
1920
0
                                                                          ai1_offset_y,
1921
0
                                                                          sao_wd_luma,
1922
0
                                                                          sao_ht_luma);
1923
0
                    }
1924
1925
0
                }
1926
0
            }
1927
0
            else if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
1928
0
            {
1929
                /* Update left, top and top-left */
1930
0
                for(row = 0; row < sao_ht_luma; row++)
1931
0
                {
1932
0
                    pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
1933
0
                }
1934
                /*Update in next location*/
1935
0
                pu1_sao_src_top_left_luma_curr_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
1936
1937
0
                memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
1938
0
            }
1939
0
        }
1940
1941
0
        if(CHROMA_FMT_IDC_MONOCHROME != ps_sps->i1_chroma_format_idc && 0 != sao_ht_chroma)
1942
0
        {
1943
0
            if(ps_slice_hdr_left->i1_slice_sao_chroma_flag)
1944
0
            {
1945
0
                if(0 == ps_sao->b3_cb_type_idx)
1946
0
                {
1947
0
                    for(row = 0; row < sao_ht_chroma; row++)
1948
0
                    {
1949
0
                        pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
1950
0
                        pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
1951
0
                    }
1952
0
                    pu1_sao_src_top_left_chroma_curr_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
1953
0
                    pu1_sao_src_top_left_chroma_curr_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
1954
1955
0
                    memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
1956
0
                }
1957
1958
0
                else if(1 == ps_sao->b3_cb_type_idx)
1959
0
                {
1960
0
                    ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
1961
0
                    ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
1962
0
                    ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
1963
0
                    ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
1964
1965
0
                    ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
1966
0
                    ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
1967
0
                    ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
1968
0
                    ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
1969
1970
0
                    if(chroma_yuv420sp_vu)
1971
0
                    {
1972
0
                        ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
1973
0
                                                                                    chroma_strd,
1974
0
                                                                                    pu1_src_left_chroma,
1975
0
                                                                                    pu1_src_top_chroma,
1976
0
                                                                                    pu1_sao_src_top_left_chroma_curr_ctb,
1977
0
                                                                                    ps_sao->b5_cr_band_pos,
1978
0
                                                                                    ps_sao->b5_cb_band_pos,
1979
0
                                                                                    ai1_offset_cr,
1980
0
                                                                                    ai1_offset_cb,
1981
0
                                                                                    sao_wd_chroma,
1982
0
                                                                                    sao_ht_chroma
1983
0
                                                                                   );
1984
0
                    }
1985
0
                    else
1986
0
                    {
1987
0
                        ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
1988
0
                                                                                    chroma_strd,
1989
0
                                                                                    pu1_src_left_chroma,
1990
0
                                                                                    pu1_src_top_chroma,
1991
0
                                                                                    pu1_sao_src_top_left_chroma_curr_ctb,
1992
0
                                                                                    ps_sao->b5_cb_band_pos,
1993
0
                                                                                    ps_sao->b5_cr_band_pos,
1994
0
                                                                                    ai1_offset_cb,
1995
0
                                                                                    ai1_offset_cr,
1996
0
                                                                                    sao_wd_chroma,
1997
0
                                                                                    sao_ht_chroma
1998
0
                                                                                   );
1999
0
                    }
2000
0
                }
2001
2002
0
                else // if(2 <= ps_sao->b3_cb_type_idx)
2003
0
                {
2004
0
                    ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
2005
0
                    ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
2006
0
                    ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
2007
0
                    ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
2008
2009
0
                    ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
2010
0
                    ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
2011
0
                    ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
2012
0
                    ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
2013
2014
0
                    for(i = 0; i < 8; i++)
2015
0
                    {
2016
0
                        au1_avail_chroma[i] = 255;
2017
0
                        au1_tile_slice_boundary[i] = 0;
2018
0
                        au4_idx_l[i] = 0;
2019
0
                        au4_ilf_across_tile_slice_enable[i] = 1;
2020
0
                    }
2021
                    /*In case of slices*/
2022
0
                    {
2023
0
                        if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
2024
0
                        {
2025
0
                            ctbx_l_t = ps_sao_ctxt->i4_ctb_x - 1;
2026
0
                            ctby_l_t = ps_sao_ctxt->i4_ctb_y - 1;
2027
2028
0
                            ctbx_l_l = ps_sao_ctxt->i4_ctb_x - 1;
2029
0
                            ctby_l_l = ps_sao_ctxt->i4_ctb_y;
2030
2031
0
                            ctbx_l_r = ps_sao_ctxt->i4_ctb_x;
2032
0
                            ctby_l_r = ps_sao_ctxt->i4_ctb_y;
2033
2034
0
                            ctbx_l_d =  ps_sao_ctxt->i4_ctb_x - 1;
2035
0
                            ctby_l_d =  ps_sao_ctxt->i4_ctb_y;
2036
2037
0
                            ctbx_l = ps_sao_ctxt->i4_ctb_x - 1;
2038
0
                            ctby_l = ps_sao_ctxt->i4_ctb_y;
2039
2040
0
                            if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
2041
0
                            {
2042
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
2043
0
                                {
2044
0
                                    au4_idx_l[2] = -1;
2045
0
                                    au4_idx_l[4] = -1;
2046
0
                                    au4_idx_l[5] = -1;
2047
0
                                }
2048
0
                                else
2049
0
                                {
2050
0
                                    au4_idx_l[2] = au4_idx_l[4] = pu1_slice_idx[ctbx_l_t + (ctby_l_t * ps_sps->i2_pic_wd_in_ctb)];
2051
0
                                    au4_idx_l[5] =  pu1_slice_idx[ctbx_l_t + 1 + (ctby_l_t  * ps_sps->i2_pic_wd_in_ctb)];
2052
0
                                }
2053
0
                                idx_l   = au4_idx_l[6] = pu1_slice_idx[ctbx_l + (ctby_l * ps_sps->i2_pic_wd_in_ctb)];
2054
0
                                au4_idx_l[0] = pu1_slice_idx[ctbx_l_l + (ctby_l_l * ps_sps->i2_pic_wd_in_ctb)];
2055
0
                                au4_idx_l[1] = au4_idx_l[7] = pu1_slice_idx[ctbx_l_r + (ctby_l_r * ps_sps->i2_pic_wd_in_ctb)];
2056
0
                                au4_idx_l[3] = pu1_slice_idx[ctbx_l_d + (ctby_l_d * ps_sps->i2_pic_wd_in_ctb)];
2057
2058
                                /*Verify that the neighbour ctbs dont cross pic boundary.*/
2059
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
2060
0
                                {
2061
0
                                    au4_ilf_across_tile_slice_enable[2] = 0;
2062
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
2063
0
                                    au4_ilf_across_tile_slice_enable[5] = 0;
2064
0
                                }
2065
0
                                else
2066
0
                                {
2067
0
                                    au4_ilf_across_tile_slice_enable[2] =  (ps_slice_hdr_base + idx_l)->i1_slice_loop_filter_across_slices_enabled_flag;
2068
0
                                    au4_ilf_across_tile_slice_enable[5] = au4_ilf_across_tile_slice_enable[4] = au4_ilf_across_tile_slice_enable[2];
2069
0
                                }
2070
2071
0
                                if(au4_idx_l[5] > idx_l)
2072
0
                                {
2073
0
                                    au4_ilf_across_tile_slice_enable[5] = (ps_slice_hdr_base + au4_idx_l[5])->i1_slice_loop_filter_across_slices_enabled_flag;
2074
0
                                }
2075
2076
                                //  au4_ilf_across_tile_slice_enable[5] = au4_ilf_across_tile_slice_enable[2] = (ps_slice_hdr_base + idx_l)->i1_slice_loop_filter_across_slices_enabled_flag;
2077
0
                                au4_ilf_across_tile_slice_enable[1] = (ps_slice_hdr_base + au4_idx_l[1])->i1_slice_loop_filter_across_slices_enabled_flag;
2078
0
                                au4_ilf_across_tile_slice_enable[3] = (ps_slice_hdr_base + au4_idx_l[3])->i1_slice_loop_filter_across_slices_enabled_flag;
2079
0
                                au4_ilf_across_tile_slice_enable[7] = (ps_slice_hdr_base + au4_idx_l[7])->i1_slice_loop_filter_across_slices_enabled_flag;
2080
                                /*
2081
                                 * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
2082
                                 * of the pixel having a greater address is checked. Accordingly, set the availability flags
2083
                                 */
2084
0
                                for(i = 0; i < 8; i++)
2085
0
                                {
2086
                                    /*Sets the edges that lie on the slice/tile boundary*/
2087
0
                                    if(au4_idx_l[i] != idx_l)
2088
0
                                    {
2089
0
                                        au1_tile_slice_boundary[i] = 1;
2090
0
                                    }
2091
0
                                    else
2092
0
                                    {
2093
0
                                        au4_ilf_across_tile_slice_enable[i] = 1;
2094
0
                                    }
2095
0
                                }
2096
                                /*Reset indices*/
2097
0
                                for(i = 0; i < 8; i++)
2098
0
                                {
2099
0
                                    au4_idx_l[i] = 0;
2100
0
                                }
2101
0
                            }
2102
0
                            if(ps_pps->i1_tiles_enabled_flag)
2103
0
                            {
2104
                                /* Calculate availability flags at slice boundary */
2105
0
                                if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
2106
0
                                {
2107
                                    /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
2108
0
                                    if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
2109
0
                                    {
2110
0
                                        if(0 == ps_sao_ctxt->i4_ctb_y)
2111
0
                                        {
2112
0
                                            au4_idx_l[2] = -1;
2113
0
                                            au4_idx_l[4] = -1;
2114
0
                                            au4_idx_l[5] = -1;
2115
0
                                        }
2116
0
                                        else
2117
0
                                        {
2118
0
                                            au4_idx_l[2] = au4_idx_l[4] = pu1_tile_idx[ctbx_l_t + (ctby_l_t * ps_sps->i2_pic_wd_in_ctb)];
2119
0
                                            au4_idx_l[5] =  pu1_tile_idx[ctbx_l_t + 1 + (ctby_l_t  * ps_sps->i2_pic_wd_in_ctb)];
2120
0
                                        }
2121
2122
0
                                        idx_l   = au4_idx_l[6] = pu1_tile_idx[ctbx_l + (ctby_l * ps_sps->i2_pic_wd_in_ctb)];
2123
0
                                        au4_idx_l[0] = pu1_tile_idx[ctbx_l_l + (ctby_l_l * ps_sps->i2_pic_wd_in_ctb)];
2124
0
                                        au4_idx_l[1] = au4_idx_l[7] = pu1_tile_idx[ctbx_l_r + (ctby_l_r * ps_sps->i2_pic_wd_in_ctb)];
2125
0
                                        au4_idx_l[3] = pu1_tile_idx[ctbx_l_d + (ctby_l_d * ps_sps->i2_pic_wd_in_ctb)];
2126
2127
0
                                        for(i = 0; i < 8; i++)
2128
0
                                        {
2129
                                            /*Sets the edges that lie on the slice/tile boundary*/
2130
0
                                            if(au4_idx_l[i] != idx_l)
2131
0
                                            {
2132
0
                                                au1_tile_slice_boundary[i] |= 1;
2133
0
                                                au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag; //=0
2134
0
                                            }
2135
0
                                        }
2136
0
                                    }
2137
0
                                }
2138
0
                            }
2139
0
                            for(i = 0; i < 8; i++)
2140
0
                            {
2141
                                /*Sets the edges that lie on the slice/tile boundary*/
2142
0
                                if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
2143
0
                                {
2144
0
                                    au1_avail_chroma[i] = 0;
2145
0
                                }
2146
0
                            }
2147
0
                        }
2148
0
                    }
2149
0
                    if(0 == ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor)) - sao_wd_chroma)
2150
0
                    {
2151
0
                        au1_avail_chroma[0] = 0;
2152
0
                        au1_avail_chroma[4] = 0;
2153
0
                        au1_avail_chroma[6] = 0;
2154
0
                    }
2155
2156
0
                    if(ps_sps->i2_pic_wd_in_ctb == ps_sao_ctxt->i4_ctb_x)
2157
0
                    {
2158
0
                        au1_avail_chroma[1] = 0;
2159
0
                        au1_avail_chroma[5] = 0;
2160
0
                        au1_avail_chroma[7] = 0;
2161
0
                    }
2162
2163
0
                    if(0 == ps_sao_ctxt->i4_ctb_y)
2164
0
                    {
2165
0
                        au1_avail_chroma[2] = 0;
2166
0
                        au1_avail_chroma[4] = 0;
2167
0
                        au1_avail_chroma[5] = 0;
2168
0
                    }
2169
2170
0
                    if((ps_sps->i2_pic_height_in_luma_samples / v_samp_factor) - ((ps_sao_ctxt->i4_ctb_y  << log2_ctb_size) / v_samp_factor) <= sao_ht_chroma)
2171
0
                    {
2172
0
                        au1_avail_chroma[3] = 0;
2173
0
                        au1_avail_chroma[6] = 0;
2174
0
                        au1_avail_chroma[7] = 0;
2175
0
                    }
2176
2177
0
                    {
2178
0
                        au1_src_top_right[0] = pu1_src_top_chroma[sao_wd_chroma];
2179
0
                        au1_src_top_right[1] = pu1_src_top_chroma[sao_wd_chroma + 1];
2180
0
                        au1_src_bot_left[0] = pu1_sao_src_top_left_chroma_bot_left[0];
2181
0
                        au1_src_bot_left[1] = pu1_sao_src_top_left_chroma_bot_left[1];
2182
                        //au1_src_bot_left[0] = pu1_src_chroma[sao_ht_chroma * src_strd - 2];
2183
                        //au1_src_bot_left[1] = pu1_src_chroma[sao_ht_chroma * src_strd - 1];
2184
0
                        if((ctb_size == 16) && (ps_sao_ctxt->i4_ctb_x != ps_sps->i2_pic_wd_in_ctb - 1))
2185
0
                        {
2186
0
                            au1_src_top_right[0] = pu1_src_chroma[sao_wd_chroma - chroma_strd];
2187
0
                            au1_src_top_right[1] = pu1_src_chroma[sao_wd_chroma - chroma_strd + 1];
2188
0
                        }
2189
2190
2191
0
                        if(chroma_yuv420sp_vu)
2192
0
                        {
2193
0
                            ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
2194
0
                                                                                 chroma_strd,
2195
0
                                                                                 pu1_src_left_chroma,
2196
0
                                                                                 pu1_src_top_chroma,
2197
0
                                                                                 pu1_sao_src_top_left_chroma_curr_ctb,
2198
0
                                                                                 au1_src_top_right,
2199
0
                                                                                 au1_src_bot_left,
2200
0
                                                                                 au1_avail_chroma,
2201
0
                                                                                 ai1_offset_cr,
2202
0
                                                                                 ai1_offset_cb,
2203
0
                                                                                 sao_wd_chroma,
2204
0
                                                                                 sao_ht_chroma);
2205
0
                        }
2206
0
                        else
2207
0
                        {
2208
0
                            ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
2209
0
                                                                                 chroma_strd,
2210
0
                                                                                 pu1_src_left_chroma,
2211
0
                                                                                 pu1_src_top_chroma,
2212
0
                                                                                 pu1_sao_src_top_left_chroma_curr_ctb,
2213
0
                                                                                 au1_src_top_right,
2214
0
                                                                                 au1_src_bot_left,
2215
0
                                                                                 au1_avail_chroma,
2216
0
                                                                                 ai1_offset_cb,
2217
0
                                                                                 ai1_offset_cr,
2218
0
                                                                                 sao_wd_chroma,
2219
0
                                                                                 sao_ht_chroma);
2220
0
                        }
2221
0
                    }
2222
2223
0
                }
2224
0
            }
2225
0
            else if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
2226
0
            {
2227
0
                for(row = 0; row < sao_ht_chroma; row++)
2228
0
                {
2229
0
                    pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
2230
0
                    pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
2231
0
                }
2232
0
                pu1_sao_src_top_left_chroma_curr_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
2233
0
                pu1_sao_src_top_left_chroma_curr_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
2234
2235
0
                memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
2236
0
            }
2237
2238
0
        }
2239
0
        pu1_src_luma += sao_wd_luma;
2240
0
        pu1_src_chroma += sao_wd_chroma;
2241
0
        ps_sao += 1;
2242
0
    }
2243
2244
2245
    /* Current CTB */
2246
0
    {
2247
0
        WORD32 sao_wd_luma = ctb_size - SAO_SHIFT_CTB;
2248
0
        WORD32 sao_wd_chroma = ctb_size * (chroma_pixel_strd / h_samp_factor) - SAO_SHIFT_CTB * 2;
2249
0
        WORD32 sao_ht_luma = ctb_size - SAO_SHIFT_CTB;
2250
0
        WORD32 sao_ht_chroma = (ctb_size / v_samp_factor) - SAO_SHIFT_CTB;
2251
0
        WORD32 ctbx_c_t = 0, ctbx_c_l = 0, ctbx_c_r = 0, ctbx_c_d = 0, ctbx_c = 0;
2252
0
        WORD32 ctby_c_t = 0, ctby_c_l = 0, ctby_c_r = 0, ctby_c_d = 0, ctby_c = 0;
2253
0
        WORD32 au4_idx_c[8], idx_c;
2254
0
        WORD32 chroma_strd = is_yuv444 ? src_strd * 2 : src_strd;
2255
2256
0
        WORD32 remaining_rows;
2257
0
        WORD32 remaining_cols;
2258
2259
0
        remaining_cols = ps_sps->i2_pic_width_in_luma_samples - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) + sao_wd_luma);
2260
0
        if(remaining_cols <= SAO_SHIFT_CTB)
2261
0
        {
2262
0
            sao_wd_luma += remaining_cols;
2263
0
        }
2264
0
        remaining_cols = ps_sps->i2_pic_width_in_luma_samples * (chroma_pixel_strd / h_samp_factor) - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor) + sao_wd_chroma);
2265
0
        if(remaining_cols <= 2 * SAO_SHIFT_CTB)
2266
0
        {
2267
0
            sao_wd_chroma += remaining_cols;
2268
0
        }
2269
2270
0
        remaining_rows = ps_sps->i2_pic_height_in_luma_samples - ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) + sao_ht_luma);
2271
0
        if(remaining_rows <= SAO_SHIFT_CTB)
2272
0
        {
2273
0
            sao_ht_luma += remaining_rows;
2274
0
        }
2275
0
        remaining_rows = ps_sps->i2_pic_height_in_luma_samples / v_samp_factor - (((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) / v_samp_factor) + sao_ht_chroma);
2276
0
        if(remaining_rows <= SAO_SHIFT_CTB)
2277
0
        {
2278
0
            sao_ht_chroma += remaining_rows;
2279
0
        }
2280
2281
0
        pu1_src_top_luma = ps_sao_ctxt->pu1_sao_src_top_luma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size);
2282
0
        pu1_src_top_chroma = ps_sao_ctxt->pu1_sao_src_top_chroma + (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor);
2283
0
        pu1_src_left_luma = ps_sao_ctxt->pu1_sao_src_left_luma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size);
2284
0
        pu1_src_left_chroma = ps_sao_ctxt->pu1_sao_src_left_chroma + (ps_sao_ctxt->i4_ctb_y << log2_ctb_size) * (chroma_pixel_strd / v_samp_factor);
2285
2286
0
        if((0 != sao_wd_luma) && (0 != sao_ht_luma))
2287
0
        {
2288
0
            if(ps_sao_ctxt->ps_slice_hdr->i1_slice_sao_luma_flag)
2289
0
            {
2290
0
                if(0 == ps_sao->b3_y_type_idx)
2291
0
                {
2292
                    /* Update left, top and top-left */
2293
0
                    for(row = 0; row < sao_ht_luma; row++)
2294
0
                    {
2295
0
                        pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
2296
0
                    }
2297
0
                    pu1_sao_src_top_left_luma_curr_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
2298
2299
0
                    memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
2300
2301
0
                    pu1_sao_src_top_left_luma_top_right[0] = pu1_src_luma[(sao_ht_luma - 1) * src_strd + sao_wd_luma];
2302
2303
0
                }
2304
2305
0
                else if(1 == ps_sao->b3_y_type_idx)
2306
0
                {
2307
0
                    ai1_offset_y[1] = ps_sao->b4_y_offset_1;
2308
0
                    ai1_offset_y[2] = ps_sao->b4_y_offset_2;
2309
0
                    ai1_offset_y[3] = ps_sao->b4_y_offset_3;
2310
0
                    ai1_offset_y[4] = ps_sao->b4_y_offset_4;
2311
2312
0
                    ps_codec->s_func_selector.ihevc_sao_band_offset_luma_fptr(pu1_src_luma,
2313
0
                                                                              src_strd,
2314
0
                                                                              pu1_src_left_luma,
2315
0
                                                                              pu1_src_top_luma,
2316
0
                                                                              pu1_sao_src_top_left_luma_curr_ctb,
2317
0
                                                                              ps_sao->b5_y_band_pos,
2318
0
                                                                              ai1_offset_y,
2319
0
                                                                              sao_wd_luma,
2320
0
                                                                              sao_ht_luma
2321
0
                                                                             );
2322
0
                }
2323
2324
0
                else // if(2 <= ps_sao->b3_y_type_idx)
2325
0
                {
2326
0
                    ai1_offset_y[1] = ps_sao->b4_y_offset_1;
2327
0
                    ai1_offset_y[2] = ps_sao->b4_y_offset_2;
2328
0
                    ai1_offset_y[3] = ps_sao->b4_y_offset_3;
2329
0
                    ai1_offset_y[4] = ps_sao->b4_y_offset_4;
2330
2331
0
                    for(i = 0; i < 8; i++)
2332
0
                    {
2333
0
                        au1_avail_luma[i] = 255;
2334
0
                        au1_tile_slice_boundary[i] = 0;
2335
0
                        au4_idx_c[i] = 0;
2336
0
                        au4_ilf_across_tile_slice_enable[i] = 1;
2337
0
                    }
2338
                    /******************************************************************
2339
                     * Derive the  Top-left CTB's neighbour pixel's slice indices.
2340
                     *
2341
                     *
2342
                     *          ____________
2343
                     *         |    |       |
2344
                     *         |    | C_T   |
2345
                     *         |____|_______|____
2346
                     *         |    |       |    |
2347
                     *         | C_L|   C   | C_R|
2348
                     *         |____|_______|    |
2349
                     *              |  C_D       |
2350
                     *              |            |
2351
                     *              |____________|
2352
                     *
2353
                     *****************************************************************/
2354
2355
                    /*In case of slices*/
2356
0
                    {
2357
0
                        if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
2358
0
                        {
2359
0
                            ctbx_c_t = ps_sao_ctxt->i4_ctb_x;
2360
0
                            ctby_c_t = ps_sao_ctxt->i4_ctb_y - 1;
2361
2362
0
                            ctbx_c_l = ps_sao_ctxt->i4_ctb_x - 1;
2363
0
                            ctby_c_l = ps_sao_ctxt->i4_ctb_y;
2364
2365
0
                            ctbx_c_r = ps_sao_ctxt->i4_ctb_x;
2366
0
                            ctby_c_r = ps_sao_ctxt->i4_ctb_y;
2367
2368
0
                            ctbx_c_d =  ps_sao_ctxt->i4_ctb_x;
2369
0
                            ctby_c_d =  ps_sao_ctxt->i4_ctb_y;
2370
2371
0
                            ctbx_c = ps_sao_ctxt->i4_ctb_x;
2372
0
                            ctby_c = ps_sao_ctxt->i4_ctb_y;
2373
2374
0
                            if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
2375
0
                            {
2376
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
2377
0
                                {
2378
0
                                    au4_idx_c[6] = -1;
2379
0
                                    au4_idx_c[0] = -1;
2380
0
                                    au4_idx_c[4] = -1;
2381
0
                                }
2382
0
                                else
2383
0
                                {
2384
0
                                    au4_idx_c[0] =  au4_idx_c[6] = pu1_slice_idx[ctbx_c_l + (ctby_c_l * ps_sps->i2_pic_wd_in_ctb)];
2385
0
                                }
2386
2387
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
2388
0
                                {
2389
0
                                    au4_idx_c[2] = -1;
2390
0
                                    au4_idx_c[5] = -1;
2391
0
                                    au4_idx_c[4] = -1;
2392
0
                                }
2393
0
                                else
2394
0
                                {
2395
0
                                    au4_idx_c[4] =  pu1_slice_idx[ctbx_c_t - 1 + (ctby_c_t  * ps_sps->i2_pic_wd_in_ctb)];
2396
0
                                    au4_idx_c[2] = au4_idx_c[5] = pu1_slice_idx[ctbx_c_t + (ctby_c_t * ps_sps->i2_pic_wd_in_ctb)];
2397
0
                                }
2398
0
                                idx_c   = pu1_slice_idx[ctbx_c + (ctby_c * ps_sps->i2_pic_wd_in_ctb)];
2399
0
                                au4_idx_c[1] = au4_idx_c[7] = pu1_slice_idx[ctbx_c_r + (ctby_c_r * ps_sps->i2_pic_wd_in_ctb)];
2400
0
                                au4_idx_c[3] = pu1_slice_idx[ctbx_c_d + (ctby_c_d * ps_sps->i2_pic_wd_in_ctb)];
2401
2402
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
2403
0
                                {
2404
0
                                    au4_ilf_across_tile_slice_enable[6] = 0;
2405
0
                                    au4_ilf_across_tile_slice_enable[0] = 0;
2406
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
2407
0
                                }
2408
0
                                else
2409
0
                                {
2410
0
                                    au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + au4_idx_c[6])->i1_slice_loop_filter_across_slices_enabled_flag;
2411
0
                                    au4_ilf_across_tile_slice_enable[0] = (ps_slice_hdr_base + idx_c)->i1_slice_loop_filter_across_slices_enabled_flag;;
2412
0
                                }
2413
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
2414
0
                                {
2415
0
                                    au4_ilf_across_tile_slice_enable[2] = 0;
2416
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
2417
0
                                    au4_ilf_across_tile_slice_enable[5] = 0;
2418
0
                                }
2419
0
                                else
2420
0
                                {
2421
0
                                    au4_ilf_across_tile_slice_enable[2] = (ps_slice_hdr_base + idx_c)->i1_slice_loop_filter_across_slices_enabled_flag;
2422
0
                                    au4_ilf_across_tile_slice_enable[5] = au4_ilf_across_tile_slice_enable[4] = au4_ilf_across_tile_slice_enable[2];
2423
0
                                }
2424
0
                                au4_ilf_across_tile_slice_enable[1] = (ps_slice_hdr_base + au4_idx_c[1])->i1_slice_loop_filter_across_slices_enabled_flag;
2425
0
                                au4_ilf_across_tile_slice_enable[3] = (ps_slice_hdr_base + au4_idx_c[3])->i1_slice_loop_filter_across_slices_enabled_flag;
2426
0
                                au4_ilf_across_tile_slice_enable[7] = (ps_slice_hdr_base + au4_idx_c[7])->i1_slice_loop_filter_across_slices_enabled_flag;
2427
2428
0
                                if(au4_idx_c[6] < idx_c)
2429
0
                                {
2430
0
                                    au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + idx_c)->i1_slice_loop_filter_across_slices_enabled_flag;
2431
0
                                }
2432
2433
                                /*
2434
                                 * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
2435
                                 * of the pixel having a greater address is checked. Accordingly, set the availability flags
2436
                                 */
2437
0
                                for(i = 0; i < 8; i++)
2438
0
                                {
2439
                                    /*Sets the edges that lie on the slice/tile boundary*/
2440
0
                                    if(au4_idx_c[i] != idx_c)
2441
0
                                    {
2442
0
                                        au1_tile_slice_boundary[i] = 1;
2443
0
                                    }
2444
0
                                    else
2445
0
                                    {
2446
0
                                        au4_ilf_across_tile_slice_enable[i] = 1;
2447
0
                                    }
2448
0
                                }
2449
                                /*Reset indices*/
2450
0
                                for(i = 0; i < 8; i++)
2451
0
                                {
2452
0
                                    au4_idx_c[i] = 0;
2453
0
                                }
2454
0
                            }
2455
2456
0
                            if(ps_pps->i1_tiles_enabled_flag)
2457
0
                            {
2458
                                /* Calculate availability flags at slice boundary */
2459
0
                                if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
2460
0
                                {
2461
                                    /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
2462
0
                                    if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
2463
0
                                    {
2464
0
                                        if(0 == ps_sao_ctxt->i4_ctb_x)
2465
0
                                        {
2466
0
                                            au4_idx_c[6] = -1;
2467
0
                                            au4_idx_c[0] = -1;
2468
0
                                            au4_idx_c[4] = -1;
2469
0
                                        }
2470
0
                                        else
2471
0
                                        {
2472
0
                                            au4_idx_c[0] =  au4_idx_c[6] = pu1_tile_idx[ctbx_c_l + (ctby_c_l * ps_sps->i2_pic_wd_in_ctb)];
2473
0
                                        }
2474
2475
0
                                        if(0 == ps_sao_ctxt->i4_ctb_y)
2476
0
                                        {
2477
0
                                            au4_idx_c[2] = -1;
2478
0
                                            au4_idx_c[5] = -1;
2479
0
                                            au4_idx_c[4] = -1;
2480
0
                                        }
2481
0
                                        else
2482
0
                                        {
2483
0
                                            au4_idx_c[4] =  pu1_tile_idx[ctbx_c_t - 1 + (ctby_c_t  * ps_sps->i2_pic_wd_in_ctb)];
2484
0
                                            au4_idx_c[2] = au4_idx_c[5] = pu1_tile_idx[ctbx_c_t + (ctby_c_t * ps_sps->i2_pic_wd_in_ctb)];
2485
0
                                        }
2486
0
                                        idx_c   = pu1_tile_idx[ctbx_c + (ctby_c * ps_sps->i2_pic_wd_in_ctb)];
2487
0
                                        au4_idx_c[1] = au4_idx_c[7] = pu1_tile_idx[ctbx_c_r + (ctby_c_r * ps_sps->i2_pic_wd_in_ctb)];
2488
0
                                        au4_idx_c[3] = pu1_tile_idx[ctbx_c_d + (ctby_c_d * ps_sps->i2_pic_wd_in_ctb)];
2489
2490
0
                                        for(i = 0; i < 8; i++)
2491
0
                                        {
2492
                                            /*Sets the edges that lie on the slice/tile boundary*/
2493
0
                                            if(au4_idx_c[i] != idx_c)
2494
0
                                            {
2495
0
                                                au1_tile_slice_boundary[i] |= 1;
2496
0
                                                au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag; //=0
2497
0
                                            }
2498
0
                                        }
2499
0
                                    }
2500
0
                                }
2501
0
                            }
2502
2503
0
                            for(i = 0; i < 8; i++)
2504
0
                            {
2505
                                /*Sets the edges that lie on the slice/tile boundary*/
2506
0
                                if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
2507
0
                                {
2508
0
                                    au1_avail_luma[i] = 0;
2509
0
                                }
2510
0
                            }
2511
2512
0
                        }
2513
0
                    }
2514
0
                    if(0 == ps_sao_ctxt->i4_ctb_x)
2515
0
                    {
2516
0
                        au1_avail_luma[0] = 0;
2517
0
                        au1_avail_luma[4] = 0;
2518
0
                        au1_avail_luma[6] = 0;
2519
0
                    }
2520
2521
0
                    if(ps_sps->i2_pic_width_in_luma_samples - (ps_sao_ctxt->i4_ctb_x << log2_ctb_size) <= sao_wd_luma)
2522
0
                    {
2523
0
                        au1_avail_luma[1] = 0;
2524
0
                        au1_avail_luma[5] = 0;
2525
0
                        au1_avail_luma[7] = 0;
2526
0
                    }
2527
2528
0
                    if(0 == ps_sao_ctxt->i4_ctb_y)
2529
0
                    {
2530
0
                        au1_avail_luma[2] = 0;
2531
0
                        au1_avail_luma[4] = 0;
2532
0
                        au1_avail_luma[5] = 0;
2533
0
                    }
2534
2535
0
                    if(ps_sps->i2_pic_height_in_luma_samples - (ps_sao_ctxt->i4_ctb_y  << log2_ctb_size) <= sao_ht_luma)
2536
0
                    {
2537
0
                        au1_avail_luma[3] = 0;
2538
0
                        au1_avail_luma[6] = 0;
2539
0
                        au1_avail_luma[7] = 0;
2540
0
                    }
2541
2542
0
                    {
2543
0
                        au1_src_top_right[0] = pu1_src_luma[sao_wd_luma - src_strd];
2544
0
                        u1_sao_src_top_left_luma_bot_left = pu1_src_luma[sao_ht_luma * src_strd - 1];
2545
2546
0
                        ps_codec->apf_sao_luma[ps_sao->b3_y_type_idx - 2](pu1_src_luma,
2547
0
                                                                          src_strd,
2548
0
                                                                          pu1_src_left_luma,
2549
0
                                                                          pu1_src_top_luma,
2550
0
                                                                          pu1_sao_src_top_left_luma_curr_ctb,
2551
0
                                                                          au1_src_top_right,
2552
0
                                                                          &u1_sao_src_top_left_luma_bot_left,
2553
0
                                                                          au1_avail_luma,
2554
0
                                                                          ai1_offset_y,
2555
0
                                                                          sao_wd_luma,
2556
0
                                                                          sao_ht_luma);
2557
0
                    }
2558
0
                    pu1_sao_src_top_left_luma_top_right[0] = pu1_src_luma[(sao_ht_luma - 1) * src_strd + sao_wd_luma];
2559
0
                    pu1_sao_src_top_left_luma_bot_left[0] = pu1_src_luma[(sao_ht_luma)*src_strd + sao_wd_luma - 1];
2560
0
                }
2561
0
            }
2562
0
            else if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
2563
0
            {
2564
                /* Update left, top and top-left */
2565
0
                for(row = 0; row < sao_ht_luma; row++)
2566
0
                {
2567
0
                    pu1_src_left_luma[row] = pu1_src_luma[row * src_strd + (sao_wd_luma - 1)];
2568
0
                }
2569
0
                pu1_sao_src_top_left_luma_curr_ctb[0] = pu1_src_top_luma[sao_wd_luma - 1];
2570
2571
0
                memcpy(pu1_src_top_luma, &pu1_src_luma[(sao_ht_luma - 1) * src_strd], sao_wd_luma);
2572
2573
0
                pu1_sao_src_top_left_luma_top_right[0] = pu1_src_luma[(sao_ht_luma - 1) * src_strd + sao_wd_luma];
2574
0
            }
2575
0
        }
2576
2577
0
        if(CHROMA_FMT_IDC_MONOCHROME != ps_sps->i1_chroma_format_idc && (0 != sao_wd_chroma) && (0 != sao_ht_chroma))
2578
0
        {
2579
0
            if(ps_sao_ctxt->ps_slice_hdr->i1_slice_sao_chroma_flag)
2580
0
            {
2581
0
                if(0 == ps_sao->b3_cb_type_idx)
2582
0
                {
2583
0
                    for(row = 0; row < sao_ht_chroma; row++)
2584
0
                    {
2585
0
                        pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
2586
0
                        pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
2587
0
                    }
2588
0
                    pu1_sao_src_top_left_chroma_curr_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
2589
0
                    pu1_sao_src_top_left_chroma_curr_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
2590
2591
0
                    memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
2592
2593
0
                    pu1_sao_src_top_left_chroma_top_right[0] = pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd + sao_wd_chroma];
2594
0
                    pu1_sao_src_top_left_chroma_top_right[1] = pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd + sao_wd_chroma + 1];
2595
0
                }
2596
2597
0
                else if(1 == ps_sao->b3_cb_type_idx)
2598
0
                {
2599
0
                    ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
2600
0
                    ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
2601
0
                    ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
2602
0
                    ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
2603
2604
0
                    ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
2605
0
                    ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
2606
0
                    ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
2607
0
                    ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
2608
2609
0
                    if(chroma_yuv420sp_vu)
2610
0
                    {
2611
0
                        ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
2612
0
                                                                                    chroma_strd,
2613
0
                                                                                    pu1_src_left_chroma,
2614
0
                                                                                    pu1_src_top_chroma,
2615
0
                                                                                    pu1_sao_src_top_left_chroma_curr_ctb,
2616
0
                                                                                    ps_sao->b5_cr_band_pos,
2617
0
                                                                                    ps_sao->b5_cb_band_pos,
2618
0
                                                                                    ai1_offset_cr,
2619
0
                                                                                    ai1_offset_cb,
2620
0
                                                                                    sao_wd_chroma,
2621
0
                                                                                    sao_ht_chroma
2622
0
                                                                                   );
2623
0
                    }
2624
0
                    else
2625
0
                    {
2626
0
                        ps_codec->s_func_selector.ihevc_sao_band_offset_chroma_fptr(pu1_src_chroma,
2627
0
                                                                                    chroma_strd,
2628
0
                                                                                    pu1_src_left_chroma,
2629
0
                                                                                    pu1_src_top_chroma,
2630
0
                                                                                    pu1_sao_src_top_left_chroma_curr_ctb,
2631
0
                                                                                    ps_sao->b5_cb_band_pos,
2632
0
                                                                                    ps_sao->b5_cr_band_pos,
2633
0
                                                                                    ai1_offset_cb,
2634
0
                                                                                    ai1_offset_cr,
2635
0
                                                                                    sao_wd_chroma,
2636
0
                                                                                    sao_ht_chroma
2637
0
                                                                                   );
2638
0
                    }
2639
0
                }
2640
2641
0
                else // if(2 <= ps_sao->b3_cb_type_idx)
2642
0
                {
2643
0
                    ai1_offset_cb[1] = ps_sao->b4_cb_offset_1;
2644
0
                    ai1_offset_cb[2] = ps_sao->b4_cb_offset_2;
2645
0
                    ai1_offset_cb[3] = ps_sao->b4_cb_offset_3;
2646
0
                    ai1_offset_cb[4] = ps_sao->b4_cb_offset_4;
2647
2648
0
                    ai1_offset_cr[1] = ps_sao->b4_cr_offset_1;
2649
0
                    ai1_offset_cr[2] = ps_sao->b4_cr_offset_2;
2650
0
                    ai1_offset_cr[3] = ps_sao->b4_cr_offset_3;
2651
0
                    ai1_offset_cr[4] = ps_sao->b4_cr_offset_4;
2652
2653
0
                    for(i = 0; i < 8; i++)
2654
0
                    {
2655
0
                        au1_avail_chroma[i] = 255;
2656
0
                        au1_tile_slice_boundary[i] = 0;
2657
0
                        au4_idx_c[i] = 0;
2658
0
                        au4_ilf_across_tile_slice_enable[i] = 1;
2659
0
                    }
2660
0
                    {
2661
0
                        if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
2662
0
                        {
2663
0
                            ctbx_c_t = ps_sao_ctxt->i4_ctb_x;
2664
0
                            ctby_c_t = ps_sao_ctxt->i4_ctb_y - 1;
2665
2666
0
                            ctbx_c_l = ps_sao_ctxt->i4_ctb_x - 1;
2667
0
                            ctby_c_l = ps_sao_ctxt->i4_ctb_y;
2668
2669
0
                            ctbx_c_r = ps_sao_ctxt->i4_ctb_x;
2670
0
                            ctby_c_r = ps_sao_ctxt->i4_ctb_y;
2671
2672
0
                            ctbx_c_d =  ps_sao_ctxt->i4_ctb_x;
2673
0
                            ctby_c_d =  ps_sao_ctxt->i4_ctb_y;
2674
2675
0
                            ctbx_c = ps_sao_ctxt->i4_ctb_x;
2676
0
                            ctby_c = ps_sao_ctxt->i4_ctb_y;
2677
2678
0
                            if(!ps_slice_hdr->i1_first_slice_in_pic_flag)
2679
0
                            {
2680
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
2681
0
                                {
2682
0
                                    au4_idx_c[0] = -1;
2683
0
                                    au4_idx_c[4] = -1;
2684
0
                                    au4_idx_c[6] = -1;
2685
0
                                }
2686
0
                                else
2687
0
                                {
2688
0
                                    au4_idx_c[0] =  au4_idx_c[6] = pu1_slice_idx[ctbx_c_l + (ctby_c_l * ps_sps->i2_pic_wd_in_ctb)];
2689
0
                                }
2690
2691
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
2692
0
                                {
2693
0
                                    au4_idx_c[2] = -1;
2694
0
                                    au4_idx_c[4] = -1;
2695
0
                                    au4_idx_c[5] = -1;
2696
0
                                }
2697
0
                                else
2698
0
                                {
2699
0
                                    au4_idx_c[2] = au4_idx_c[5] = pu1_slice_idx[ctbx_c_t + (ctby_c_t * ps_sps->i2_pic_wd_in_ctb)];
2700
0
                                    au4_idx_c[4] =  pu1_slice_idx[ctbx_c_t - 1 + (ctby_c_t  * ps_sps->i2_pic_wd_in_ctb)];
2701
0
                                }
2702
0
                                idx_c = pu1_slice_idx[ctbx_c + (ctby_c * ps_sps->i2_pic_wd_in_ctb)];
2703
0
                                au4_idx_c[1] = au4_idx_c[7] = pu1_slice_idx[ctbx_c_r + (ctby_c_r * ps_sps->i2_pic_wd_in_ctb)];
2704
0
                                au4_idx_c[3] = pu1_slice_idx[ctbx_c_d + (ctby_c_d * ps_sps->i2_pic_wd_in_ctb)];
2705
2706
0
                                if(0 == ps_sao_ctxt->i4_ctb_x)
2707
0
                                {
2708
0
                                    au4_ilf_across_tile_slice_enable[0] = 0;
2709
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
2710
0
                                    au4_ilf_across_tile_slice_enable[6] = 0;
2711
0
                                }
2712
0
                                else
2713
0
                                {
2714
0
                                    au4_ilf_across_tile_slice_enable[6] &= (ps_slice_hdr_base + au4_idx_c[6])->i1_slice_loop_filter_across_slices_enabled_flag;
2715
0
                                    au4_ilf_across_tile_slice_enable[0] &= (ps_slice_hdr_base + idx_c)->i1_slice_loop_filter_across_slices_enabled_flag;
2716
0
                                }
2717
2718
0
                                if(0 == ps_sao_ctxt->i4_ctb_y)
2719
0
                                {
2720
0
                                    au4_ilf_across_tile_slice_enable[2] = 0;
2721
0
                                    au4_ilf_across_tile_slice_enable[4] = 0;
2722
0
                                    au4_ilf_across_tile_slice_enable[5] = 0;
2723
0
                                }
2724
0
                                else
2725
0
                                {
2726
0
                                    au4_ilf_across_tile_slice_enable[2] &= (ps_slice_hdr_base + idx_c)->i1_slice_loop_filter_across_slices_enabled_flag;
2727
0
                                    au4_ilf_across_tile_slice_enable[5] = au4_ilf_across_tile_slice_enable[4] = au4_ilf_across_tile_slice_enable[2];
2728
0
                                }
2729
2730
0
                                au4_ilf_across_tile_slice_enable[1] &= (ps_slice_hdr_base + au4_idx_c[1])->i1_slice_loop_filter_across_slices_enabled_flag;
2731
0
                                au4_ilf_across_tile_slice_enable[3] &= (ps_slice_hdr_base + au4_idx_c[3])->i1_slice_loop_filter_across_slices_enabled_flag;
2732
0
                                au4_ilf_across_tile_slice_enable[7] &= (ps_slice_hdr_base + au4_idx_c[7])->i1_slice_loop_filter_across_slices_enabled_flag;
2733
2734
0
                                if(idx_c > au4_idx_c[6])
2735
0
                                {
2736
0
                                    au4_ilf_across_tile_slice_enable[6] = (ps_slice_hdr_base + idx_c)->i1_slice_loop_filter_across_slices_enabled_flag;
2737
0
                                }
2738
2739
                                /*
2740
                                 * Between each neighbor and the current CTB, the i1_slice_loop_filter_across_slices_enabled_flag
2741
                                 * of the pixel having a greater address is checked. Accordingly, set the availability flags
2742
                                 */
2743
0
                                for(i = 0; i < 8; i++)
2744
0
                                {
2745
                                    /*Sets the edges that lie on the slice/tile boundary*/
2746
0
                                    if(au4_idx_c[i] != idx_c)
2747
0
                                    {
2748
0
                                        au1_tile_slice_boundary[i] = 1;
2749
0
                                    }
2750
0
                                    else
2751
0
                                    {
2752
0
                                        au4_ilf_across_tile_slice_enable[i] = 1;
2753
0
                                    }
2754
0
                                }
2755
                                /*Reset indices*/
2756
0
                                for(i = 0; i < 8; i++)
2757
0
                                {
2758
0
                                    au4_idx_c[i] = 0;
2759
0
                                }
2760
0
                            }
2761
2762
0
                            if(ps_pps->i1_tiles_enabled_flag)
2763
0
                            {
2764
                                /* Calculate availability flags at slice boundary */
2765
0
                                if(((ps_tile->u1_pos_x == ps_sao_ctxt->i4_ctb_x) || (ps_tile->u1_pos_y == ps_sao_ctxt->i4_ctb_y)) && (!((0 == ps_tile->u1_pos_x) && (0 == ps_tile->u1_pos_y))))
2766
0
                                {
2767
                                    /*If ilf across tiles is enabled, boundary availability for tiles is not checked. */
2768
0
                                    if(!ps_pps->i1_loop_filter_across_tiles_enabled_flag)
2769
0
                                    {
2770
0
                                        if(0 == ps_sao_ctxt->i4_ctb_x)
2771
0
                                        {
2772
0
                                            au4_idx_c[6] = -1;
2773
0
                                            au4_idx_c[0] = -1;
2774
0
                                            au4_idx_c[4] = -1;
2775
0
                                        }
2776
0
                                        else
2777
0
                                        {
2778
0
                                            au4_idx_c[0] =  au4_idx_c[6] = pu1_tile_idx[ctbx_c_l + (ctby_c_l * ps_sps->i2_pic_wd_in_ctb)];
2779
0
                                        }
2780
2781
0
                                        if(0 == ps_sao_ctxt->i4_ctb_y)
2782
0
                                        {
2783
0
                                            au4_idx_c[2] = -1;
2784
0
                                            au4_idx_c[5] = -1;
2785
0
                                            au4_idx_c[4] = -1;
2786
0
                                        }
2787
0
                                        else
2788
0
                                        {
2789
0
                                            au4_idx_c[4] =  pu1_tile_idx[ctbx_c_t - 1 + (ctby_c_t  * ps_sps->i2_pic_wd_in_ctb)];
2790
0
                                            au4_idx_c[2] = au4_idx_c[5] = pu1_tile_idx[ctbx_c_t + (ctby_c_t * ps_sps->i2_pic_wd_in_ctb)];
2791
0
                                        }
2792
0
                                        idx_c   = pu1_tile_idx[ctbx_c + (ctby_c * ps_sps->i2_pic_wd_in_ctb)];
2793
0
                                        au4_idx_c[1] = au4_idx_c[7] = pu1_tile_idx[ctbx_c_r + (ctby_c_r * ps_sps->i2_pic_wd_in_ctb)];
2794
0
                                        au4_idx_c[3] = pu1_tile_idx[ctbx_c_d + (ctby_c_d * ps_sps->i2_pic_wd_in_ctb)];
2795
2796
0
                                        for(i = 0; i < 8; i++)
2797
0
                                        {
2798
                                            /*Sets the edges that lie on the slice/tile boundary*/
2799
0
                                            if(au4_idx_c[i] != idx_c)
2800
0
                                            {
2801
0
                                                au1_tile_slice_boundary[i] |= 1;
2802
0
                                                au4_ilf_across_tile_slice_enable[i] &= ps_pps->i1_loop_filter_across_tiles_enabled_flag; //=0
2803
0
                                            }
2804
0
                                        }
2805
0
                                    }
2806
0
                                }
2807
0
                            }
2808
2809
0
                            for(i = 0; i < 8; i++)
2810
0
                            {
2811
                                /*Sets the edges that lie on the slice/tile boundary*/
2812
0
                                if((au1_tile_slice_boundary[i]) && !(au4_ilf_across_tile_slice_enable[i]))
2813
0
                                {
2814
0
                                    au1_avail_chroma[i] = 0;
2815
0
                                }
2816
0
                            }
2817
0
                        }
2818
0
                    }
2819
2820
0
                    if(0 == ps_sao_ctxt->i4_ctb_x)
2821
0
                    {
2822
0
                        au1_avail_chroma[0] = 0;
2823
0
                        au1_avail_chroma[4] = 0;
2824
0
                        au1_avail_chroma[6] = 0;
2825
0
                    }
2826
2827
0
                    if(ps_sps->i2_pic_width_in_luma_samples * (chroma_pixel_strd / h_samp_factor) - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) * (chroma_pixel_strd / h_samp_factor)) <= sao_wd_chroma)
2828
0
                    {
2829
0
                        au1_avail_chroma[1] = 0;
2830
0
                        au1_avail_chroma[5] = 0;
2831
0
                        au1_avail_chroma[7] = 0;
2832
0
                    }
2833
2834
0
                    if(0 == ps_sao_ctxt->i4_ctb_y)
2835
0
                    {
2836
0
                        au1_avail_chroma[2] = 0;
2837
0
                        au1_avail_chroma[4] = 0;
2838
0
                        au1_avail_chroma[5] = 0;
2839
0
                    }
2840
2841
0
                    if(ps_sps->i2_pic_height_in_luma_samples / v_samp_factor - ((ps_sao_ctxt->i4_ctb_y  << log2_ctb_size) / v_samp_factor) <= sao_ht_chroma)
2842
0
                    {
2843
0
                        au1_avail_chroma[3] = 0;
2844
0
                        au1_avail_chroma[6] = 0;
2845
0
                        au1_avail_chroma[7] = 0;
2846
0
                    }
2847
2848
0
                    {
2849
0
                        au1_src_top_right[0] = pu1_src_chroma[sao_wd_chroma - chroma_strd];
2850
0
                        au1_src_top_right[1] = pu1_src_chroma[sao_wd_chroma - chroma_strd + 1];
2851
2852
0
                        au1_sao_src_top_left_chroma_bot_left[0] = pu1_src_chroma[sao_ht_chroma * chroma_strd - 2];
2853
0
                        au1_sao_src_top_left_chroma_bot_left[1] = pu1_src_chroma[sao_ht_chroma * chroma_strd - 1];
2854
2855
0
                        if(chroma_yuv420sp_vu)
2856
0
                        {
2857
0
                            ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
2858
0
                                                                                 chroma_strd,
2859
0
                                                                                 pu1_src_left_chroma,
2860
0
                                                                                 pu1_src_top_chroma,
2861
0
                                                                                 pu1_sao_src_top_left_chroma_curr_ctb,
2862
0
                                                                                 au1_src_top_right,
2863
0
                                                                                 au1_sao_src_top_left_chroma_bot_left,
2864
0
                                                                                 au1_avail_chroma,
2865
0
                                                                                 ai1_offset_cr,
2866
0
                                                                                 ai1_offset_cb,
2867
0
                                                                                 sao_wd_chroma,
2868
0
                                                                                 sao_ht_chroma);
2869
0
                        }
2870
0
                        else
2871
0
                        {
2872
0
                            ps_codec->apf_sao_chroma[ps_sao->b3_cb_type_idx - 2](pu1_src_chroma,
2873
0
                                                                                 chroma_strd,
2874
0
                                                                                 pu1_src_left_chroma,
2875
0
                                                                                 pu1_src_top_chroma,
2876
0
                                                                                 pu1_sao_src_top_left_chroma_curr_ctb,
2877
0
                                                                                 au1_src_top_right,
2878
0
                                                                                 au1_sao_src_top_left_chroma_bot_left,
2879
0
                                                                                 au1_avail_chroma,
2880
0
                                                                                 ai1_offset_cb,
2881
0
                                                                                 ai1_offset_cr,
2882
0
                                                                                 sao_wd_chroma,
2883
0
                                                                                 sao_ht_chroma);
2884
0
                        }
2885
0
                    }
2886
2887
0
                }
2888
0
                pu1_sao_src_top_left_chroma_top_right[0] = pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd + sao_wd_chroma];
2889
0
                pu1_sao_src_top_left_chroma_top_right[1] = pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd + sao_wd_chroma + 1];
2890
2891
0
                pu1_sao_src_top_left_chroma_bot_left[0] = pu1_src_chroma[(sao_ht_chroma) * chroma_strd + sao_wd_chroma - 2];
2892
0
                pu1_sao_src_top_left_chroma_bot_left[1] = pu1_src_chroma[(sao_ht_chroma) * chroma_strd + sao_wd_chroma - 1];
2893
0
            }
2894
0
            else if((!ps_slice_hdr->i1_first_slice_in_pic_flag) || (ps_pps->i1_tiles_enabled_flag))
2895
0
            {
2896
0
                for(row = 0; row < sao_ht_chroma; row++)
2897
0
                {
2898
0
                    pu1_src_left_chroma[2 * row] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 2)];
2899
0
                    pu1_src_left_chroma[2 * row + 1] = pu1_src_chroma[row * chroma_strd + (sao_wd_chroma - 1)];
2900
0
                }
2901
0
                pu1_sao_src_top_left_chroma_curr_ctb[0] = pu1_src_top_chroma[sao_wd_chroma - 2];
2902
0
                pu1_sao_src_top_left_chroma_curr_ctb[1] = pu1_src_top_chroma[sao_wd_chroma - 1];
2903
2904
0
                memcpy(pu1_src_top_chroma, &pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd], sao_wd_chroma);
2905
2906
0
                pu1_sao_src_top_left_chroma_top_right[0] = pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd + sao_wd_chroma];
2907
0
                pu1_sao_src_top_left_chroma_top_right[1] = pu1_src_chroma[(sao_ht_chroma - 1) * chroma_strd + sao_wd_chroma + 1];
2908
0
            }
2909
2910
0
        }
2911
0
    }
2912
2913
2914
2915
2916
/* If no loop filter is enabled copy the backed up values */
2917
0
    {
2918
        /* Luma */
2919
0
        if(no_loop_filter_enabled_luma)
2920
0
        {
2921
0
            UWORD32 u4_no_loop_filter_flag;
2922
0
            WORD32 loop_filter_bit_pos;
2923
0
            WORD32 log2_min_cu = 3;
2924
0
            WORD32 min_cu = (1 << log2_min_cu);
2925
0
            UWORD8 *pu1_src_tmp_luma = pu1_src_luma;
2926
0
            WORD32 sao_blk_ht = ctb_size - SAO_SHIFT_CTB;
2927
0
            WORD32 sao_blk_wd = ctb_size;
2928
0
            WORD32 remaining_rows;
2929
0
            WORD32 remaining_cols;
2930
2931
0
            remaining_rows = ps_sps->i2_pic_height_in_luma_samples - ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) + ctb_size - SAO_SHIFT_CTB);
2932
0
            remaining_cols = ps_sps->i2_pic_width_in_luma_samples - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) + ctb_size - SAO_SHIFT_CTB);
2933
0
            if(remaining_rows <= SAO_SHIFT_CTB)
2934
0
                sao_blk_ht += remaining_rows;
2935
0
            if(remaining_cols <= SAO_SHIFT_CTB)
2936
0
                sao_blk_wd += remaining_cols;
2937
2938
0
            pu1_src_tmp_luma -= ps_sao_ctxt->i4_ctb_x ? SAO_SHIFT_CTB : 0;
2939
0
            pu1_src_tmp_luma -= ps_sao_ctxt->i4_ctb_y ? SAO_SHIFT_CTB * src_strd : 0;
2940
2941
0
            pu1_src_backup_luma = ps_sao_ctxt->pu1_tmp_buf_luma;
2942
2943
0
            loop_filter_bit_pos = (ps_sao_ctxt->i4_ctb_x << (log2_ctb_size - 3)) +
2944
0
                            (ps_sao_ctxt->i4_ctb_y << (log2_ctb_size - 3)) * (loop_filter_strd << 3);
2945
0
            if(ps_sao_ctxt->i4_ctb_x > 0)
2946
0
                loop_filter_bit_pos -= 1;
2947
2948
0
            pu1_no_loop_filter_flag = ps_sao_ctxt->pu1_pic_no_loop_filter_flag +
2949
0
                            (loop_filter_bit_pos >> 3);
2950
2951
0
            for(i = -(ps_sao_ctxt->i4_ctb_y ? SAO_SHIFT_CTB : 0) >> log2_min_cu;
2952
0
                            i < (sao_blk_ht + (min_cu - 1)) >> log2_min_cu; i++)
2953
0
            {
2954
0
                WORD32 tmp_wd = sao_blk_wd;
2955
2956
0
                u4_no_loop_filter_flag = (*(UWORD32 *)(pu1_no_loop_filter_flag + i * loop_filter_strd)) >>
2957
0
                                (loop_filter_bit_pos & 7);
2958
0
                u4_no_loop_filter_flag &= (1 << ((tmp_wd + (min_cu - 1)) >> log2_min_cu)) - 1;
2959
2960
0
                if(u4_no_loop_filter_flag)
2961
0
                {
2962
0
                    while(tmp_wd > 0)
2963
0
                    {
2964
0
                        if(CTZ(u4_no_loop_filter_flag))
2965
0
                        {
2966
0
                            pu1_src_tmp_luma += MIN(((WORD32)CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
2967
0
                            pu1_src_backup_luma += MIN(((WORD32)CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
2968
0
                            tmp_wd -= (WORD32)(CTZ(u4_no_loop_filter_flag) << log2_min_cu);
2969
0
                            u4_no_loop_filter_flag  >>= (CTZ(u4_no_loop_filter_flag));
2970
0
                        }
2971
0
                        else
2972
0
                        {
2973
0
                            for(row = 0; row < min_cu; row++)
2974
0
                            {
2975
0
                                for(col = 0; col < MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd); col++)
2976
0
                                {
2977
0
                                    pu1_src_tmp_luma[row * src_strd + col] = pu1_src_backup_luma[row * backup_strd + col];
2978
0
                                }
2979
0
                            }
2980
0
                            pu1_src_tmp_luma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
2981
0
                            pu1_src_backup_luma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd);
2982
0
                            tmp_wd -= (WORD32)(CTZ(~u4_no_loop_filter_flag) << log2_min_cu);
2983
0
                            u4_no_loop_filter_flag  >>= (CTZ(~u4_no_loop_filter_flag));
2984
0
                        }
2985
0
                    }
2986
2987
0
                    pu1_src_tmp_luma -= sao_blk_wd;
2988
0
                    pu1_src_backup_luma -= sao_blk_wd;
2989
0
                }
2990
2991
0
                pu1_src_tmp_luma += (src_strd << log2_min_cu);
2992
0
                pu1_src_backup_luma += (backup_strd << log2_min_cu);
2993
0
            }
2994
0
        }
2995
2996
        /* Chroma */
2997
0
        if(CHROMA_FMT_IDC_MONOCHROME != ps_sps->i1_chroma_format_idc && no_loop_filter_enabled_chroma)
2998
0
        {
2999
0
            UWORD32 u4_no_loop_filter_flag;
3000
0
            WORD32 loop_filter_bit_pos;
3001
0
            WORD32 log2_min_cu = 3;
3002
0
            WORD32 min_cu = (1 << log2_min_cu);
3003
0
            UWORD8 *pu1_src_tmp_chroma = pu1_src_chroma;
3004
0
            WORD32 sao_blk_ht = ctb_size - 2 * SAO_SHIFT_CTB;
3005
0
            WORD32 sao_blk_wd = ctb_size;
3006
0
            WORD32 remaining_rows;
3007
0
            WORD32 remaining_cols;
3008
3009
0
            remaining_rows = ps_sps->i2_pic_height_in_luma_samples - ((ps_sao_ctxt->i4_ctb_y << log2_ctb_size) + ctb_size - 2 * SAO_SHIFT_CTB);
3010
0
            remaining_cols = ps_sps->i2_pic_width_in_luma_samples - ((ps_sao_ctxt->i4_ctb_x << log2_ctb_size) + ctb_size - 2 * SAO_SHIFT_CTB);
3011
0
            if(remaining_rows <= 2 * SAO_SHIFT_CTB)
3012
0
                sao_blk_ht += remaining_rows;
3013
0
            if(remaining_cols <= 2 * SAO_SHIFT_CTB)
3014
0
                sao_blk_wd += remaining_cols;
3015
3016
0
            pu1_src_tmp_chroma -= ps_sao_ctxt->i4_ctb_x ? SAO_SHIFT_CTB * 2 : 0;
3017
0
            pu1_src_tmp_chroma -= ps_sao_ctxt->i4_ctb_y ? SAO_SHIFT_CTB * chroma_strd : 0;
3018
3019
0
            pu1_src_backup_chroma = ps_sao_ctxt->pu1_tmp_buf_chroma;
3020
3021
0
            loop_filter_bit_pos = (ps_sao_ctxt->i4_ctb_x << (log2_ctb_size - 3)) +
3022
0
                            (ps_sao_ctxt->i4_ctb_y << (log2_ctb_size - 3)) * (loop_filter_strd << 3);
3023
0
            if(ps_sao_ctxt->i4_ctb_x > 0)
3024
0
                loop_filter_bit_pos -= (is_yuv444 ? 1 : 2);
3025
3026
0
            pu1_no_loop_filter_flag = ps_sao_ctxt->pu1_pic_no_loop_filter_flag +
3027
0
                            (loop_filter_bit_pos >> 3);
3028
3029
0
            for(i = -(ps_sao_ctxt->i4_ctb_y ? 2 * SAO_SHIFT_CTB : 0) >> log2_min_cu;
3030
0
                            i < (sao_blk_ht + (min_cu - 1)) >> log2_min_cu; i++)
3031
0
            {
3032
0
                WORD32 tmp_wd = sao_blk_wd;
3033
3034
0
                u4_no_loop_filter_flag = (*(UWORD32 *)(pu1_no_loop_filter_flag + i * loop_filter_strd)) >>
3035
0
                                (loop_filter_bit_pos & 7);
3036
0
                u4_no_loop_filter_flag &= (1 << ((tmp_wd + (min_cu - 1)) >> log2_min_cu)) - 1;
3037
3038
0
                if(u4_no_loop_filter_flag)
3039
0
                {
3040
0
                    while(tmp_wd > 0)
3041
0
                    {
3042
0
                        if(CTZ(u4_no_loop_filter_flag))
3043
0
                        {
3044
0
                            pu1_src_tmp_chroma += MIN(((WORD32)CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * (chroma_pixel_strd / h_samp_factor);
3045
0
                            pu1_src_backup_chroma += MIN(((WORD32)CTZ(u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * (chroma_pixel_strd / h_samp_factor);
3046
0
                            tmp_wd -= (WORD32)(CTZ(u4_no_loop_filter_flag) << log2_min_cu);
3047
0
                            u4_no_loop_filter_flag  >>= (CTZ(u4_no_loop_filter_flag));
3048
0
                        }
3049
0
                        else
3050
0
                        {
3051
0
                            for(row = 0; row < min_cu / v_samp_factor; row++)
3052
0
                            {
3053
0
                                for(col = 0; col < MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * (chroma_pixel_strd / h_samp_factor); col++)
3054
0
                                {
3055
0
                                    pu1_src_tmp_chroma[row * chroma_strd + col] = pu1_src_backup_chroma[row * backup_strd * (chroma_pixel_strd / h_samp_factor) + col];
3056
0
                                }
3057
0
                            }
3058
3059
0
                            pu1_src_tmp_chroma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * (chroma_pixel_strd / h_samp_factor);
3060
0
                            pu1_src_backup_chroma += MIN(((WORD32)CTZ(~u4_no_loop_filter_flag) << log2_min_cu), tmp_wd) * (chroma_pixel_strd / h_samp_factor);
3061
0
                            tmp_wd -= (WORD32)(CTZ(~u4_no_loop_filter_flag) << log2_min_cu);
3062
0
                            u4_no_loop_filter_flag  >>= (CTZ(~u4_no_loop_filter_flag));
3063
0
                        }
3064
0
                    }
3065
3066
0
                    pu1_src_tmp_chroma -= sao_blk_wd * (chroma_pixel_strd / h_samp_factor);
3067
0
                    pu1_src_backup_chroma -= sao_blk_wd * (chroma_pixel_strd / h_samp_factor);
3068
0
                }
3069
3070
0
                pu1_src_tmp_chroma += (((src_strd * chroma_pixel_strd) / (h_samp_factor * v_samp_factor)) << log2_min_cu);
3071
0
                pu1_src_backup_chroma += (((backup_strd * chroma_pixel_strd) / (h_samp_factor * v_samp_factor)) << log2_min_cu);
3072
0
            }
3073
0
        }
3074
0
    }
3075
3076
0
}
3077