/******************************************************************************
 *
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *****************************************************************************
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
 */
/**
 *******************************************************************************
 * @file
 *  isvcd_residual_resamp.c
 *
 * @brief
 *  Contains routines that resample for SVC resampling
 *
 * @author
 *  Kishore
 *
 * @par List of Functions:
 *  - isvcd_residual_chroma_dyadic_alt()
 *  - isvcd_residual_chroma_dyadic()
 *  - isvcd_residual_luma_dyadic()
 *  - isvcd_ref_layer_ptr_incr()
 *  - isvcd_residual_reflayer_const_non_boundary_mb()
 *  - isvcd_residual_reflayer_const_boundary_mb()
 *  - isvcd_residual_reflayer_const()
 *  - isvcd_interpolate_residual()
 *  - isvcd_residual_samp_mb()
 *  - isvcd_residual_samp_mb_dyadic()
 *  - isvcd_residual_samp_populate_list()
 *  - isvcd_residual_samp_res_init()
 *
 * @remarks
 *  None
 *
 *******************************************************************************
 */

#include <assert.h>
#include <string.h>
#include "ih264_typedefs.h"
#include "ih264_macros.h"
#include "ih264_platform_macros.h"
#include "ih264d_bitstrm.h"
#include "ih264d_defs.h"
#include "ih264d_debug.h"
#include "isvcd_structs.h"
#include "ih264d_defs.h"
#include "ih264d_parse_cavlc.h"
#include "ih264d_mb_utils.h"
#include "ih264d_deblocking.h"
#include "ih264d_dpb_manager.h"
#include "ih264d_mvpred.h"
#include "ih264d_inter_pred.h"
#include "ih264d_process_pslice.h"
#include "ih264d_error_handler.h"
#include "ih264d_cabac.h"
#include "ih264d_debug.h"
#include "ih264d_tables.h"
#include "ih264d_parse_slice.h"
#include "ih264d_utils.h"
#include "ih264d_parse_islice.h"
#include "ih264d_process_bslice.h"
#include "ih264d_process_intra_mb.h"
#include "ih264_debug.h"

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_chroma_dyadic_alt                          */
/*                                                                           */
/*  Description   : this fucntion does the upsampling of chroma residuals for*/
/*                  Dyadic cases and specific chroma phase cases             */
/*                                                                           */
/*  Inputs        : pv_residual_samp_ctxt : Residual upsampling context      */
/*                  pu1_inp_data : input 8 bit data pointer                  */
/*                  i4_inp_data_stride : input buffer stride                 */
/*                  pi2_out_res : output 16 bit buffer pointer               */
/*                  i4_out_res_stride : Output buffer stride                 */
/*                  pu1_inp_bitmap : input packed sign bit data pointer      */
/*                  i4_inp_bitmap_stride : sign bit buffer stride            */
/*                  i4_start_bit_pos : bit position in the byte of packed    */
/*                                      sign values                          */
/*  Globals       : none                                                     */
/*  Processing    : it does the upsampling with intial phase values          */
/*                                                                           */
/*  Outputs       : Upsampled residuals for chroma                           */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         25 09 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
void isvcd_residual_chroma_dyadic_alt(void *pv_residual_samp_ctxt, UWORD16 u2_mb_x, UWORD16 u2_mb_y,
                                      mem_element_t *ps_ref_mb_mode, WORD16 *pi2_inp_data,
                                      WORD32 i4_inp_data_stride, WORD16 *pi2_out_res,
                                      WORD32 i4_out_res_stride, WORD32 i4_cr_flag)
{
    residual_sampling_ctxt_t *ps_ctxt;
    res_lyr_ctxt *ps_lyr_ctxt;
    ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;
    ps_lyr_ctxt = &ps_ctxt->as_res_lyrs[ps_ctxt->i4_res_lyr_id];
    /* ----------------- Processing ------------------------------- */
    {
        ref_pixel_map_t *ps_pos_phase;
        residual_samp_map_ctxt_t *ps_chroma_map;
        ref_mb_map_t *ps_x_off_len_chroma;
        ref_mb_map_t *ps_y_off_len_chroma;
        WORD32 i4_i;
        WORD16 *pi2_ref_data_byte;
        WORD32 *pi4_ref_array;
        WORD32 i4_phase1, i4_phase2;
        WORD32 i4_offset_x, i4_offset_y;
        WORD32 i4_chrm_horz_int_mode, i4_chrm_vert_int_mode;
        WORD32 i4_horz_intp_ctr = SUB_BLOCK_HEIGHT;

        ps_chroma_map = &ps_lyr_ctxt->s_chroma_map_ctxt;
        ps_x_off_len_chroma = ps_chroma_map->ps_x_offset_length;
        ps_y_off_len_chroma = ps_chroma_map->ps_y_offset_length;

        /* get the actual offset for the buffers */
        i4_offset_x = ps_x_off_len_chroma[u2_mb_x].i2_offset;
        i4_offset_y = ps_y_off_len_chroma[u2_mb_y].i2_offset;

        {
            UWORD8 u1_mask;
            WORD32 i4_mb_x, i4_mb_y;
            WORD32 i4_chrm_nnz;
            WORD32 i4_num_element_stride;
            inter_lyr_mb_prms_t *ps_inter_lyr_mb_prms, *ps_inter_lyr_mb_prms_curr;

            u1_mask = (SVCD_TRUE == i4_cr_flag) ? 0xF0 : 0x0F;

            /* Top Left */
            i4_mb_x = i4_offset_x >> 3;
            i4_mb_y = i4_offset_y >> 3;

            /* get the location of the byte which has the current mb mode */
            ps_inter_lyr_mb_prms = ps_ref_mb_mode->pv_buffer;
            i4_num_element_stride = ps_ref_mb_mode->i4_num_element_stride;

            ps_inter_lyr_mb_prms_curr = ps_inter_lyr_mb_prms + i4_mb_x;
            ps_inter_lyr_mb_prms_curr += i4_mb_y * i4_num_element_stride;
            i4_chrm_nnz = ps_inter_lyr_mb_prms_curr->u1_chroma_nnz & u1_mask;

            /* Top Right */
            i4_mb_x = (i4_offset_x + 4) >> 3;
            ps_inter_lyr_mb_prms_curr = ps_inter_lyr_mb_prms + i4_mb_x;
            ps_inter_lyr_mb_prms_curr += i4_mb_y * i4_num_element_stride;
            i4_chrm_nnz |= ps_inter_lyr_mb_prms_curr->u1_chroma_nnz & u1_mask;

            /* Bottom Left */
            i4_mb_x = i4_offset_x >> 3;
            i4_mb_y = (i4_offset_y + 4) >> 3;
            ps_inter_lyr_mb_prms_curr = ps_inter_lyr_mb_prms + i4_mb_x;
            ps_inter_lyr_mb_prms_curr += i4_mb_y * i4_num_element_stride;
            i4_chrm_nnz |= ps_inter_lyr_mb_prms_curr->u1_chroma_nnz & u1_mask;

            /* Bottom Right */
            i4_mb_x = (i4_offset_x + 4) >> 3;
            ps_inter_lyr_mb_prms_curr = ps_inter_lyr_mb_prms + i4_mb_x;
            ps_inter_lyr_mb_prms_curr += i4_mb_y * i4_num_element_stride;

            i4_chrm_nnz |= ps_inter_lyr_mb_prms_curr->u1_chroma_nnz & u1_mask;
            if(0 == i4_chrm_nnz)
            {
                return;
            }
        }

        i4_chrm_horz_int_mode = ps_lyr_ctxt->i4_chrm_horz_int_mode;
        i4_chrm_vert_int_mode = ps_lyr_ctxt->i4_chrm_vert_int_mode;

        if(0 == i4_chrm_horz_int_mode)
        {
            if(i4_offset_x >= 0)
            {
                pi2_inp_data++;
            }
        }

        if(0 == i4_chrm_vert_int_mode)
        {
            if(i4_offset_y >= 0)
            {
                pi2_inp_data += i4_inp_data_stride;
            }
        }
        else
        {
            /* extra additional row of interpolation required for this case */
            i4_horz_intp_ctr++;
        }

        /* ----------- Horizontal Interpolation ---------------- */
        pi2_ref_data_byte = pi2_inp_data;
        ps_pos_phase = ps_lyr_ctxt->s_chroma_map_ctxt.ps_x_pos_phase;

        pi4_ref_array = (WORD32 *) ps_ctxt->pi2_refarray_buffer;
        i4_phase1 = ps_pos_phase[0].i2_phase;
        i4_phase2 = (i4_phase1 + 8) & 0x0F;

        /* interchange the phase values for corner case */
        if(1 == i4_chrm_horz_int_mode)
        {
            WORD32 i4_temp;
            i4_temp = i4_phase1;
            i4_phase1 = i4_phase2;
            i4_phase2 = i4_temp;
        }

        for(i4_i = 0; i4_i < i4_horz_intp_ctr; i4_i++)
        {
            WORD16 i2_coeff1, i2_coeff2;

            i2_coeff1 = (WORD16) (pi2_ref_data_byte[0]);

            if(0 == i4_chrm_horz_int_mode)
            {
                /* populate the first inter sample */
                *pi4_ref_array++ = i2_coeff1 << 4;
            }

            /* unroll count 1 */
            i2_coeff2 = (WORD16) (pi2_ref_data_byte[2]);

            /* populate 2 samples based on current coeffs */
            *pi4_ref_array++ = ((16 - i4_phase2) * i2_coeff1 + i4_phase2 * i2_coeff2);
            *pi4_ref_array++ = ((16 - i4_phase1) * i2_coeff1 + i4_phase1 * i2_coeff2);

            /* unroll count 2 */
            i2_coeff1 = (WORD16) (pi2_ref_data_byte[4]);

            /* populate 2 samples based on current coeffs */
            *pi4_ref_array++ = ((16 - i4_phase2) * i2_coeff2 + i4_phase2 * i2_coeff1);
            *pi4_ref_array++ = ((16 - i4_phase1) * i2_coeff2 + i4_phase1 * i2_coeff1);

            /* unroll count 3 */
            i2_coeff2 = (WORD16) (pi2_ref_data_byte[6]);

            /* populate 2 samples based on current coeffs */
            *pi4_ref_array++ = ((16 - i4_phase2) * i2_coeff1 + i4_phase2 * i2_coeff2);
            *pi4_ref_array++ = ((16 - i4_phase1) * i2_coeff1 + i4_phase1 * i2_coeff2);

            /* populate the last inter sample */
            *pi4_ref_array++ = i2_coeff2 << 4;

            if(1 == i4_chrm_horz_int_mode)
            {
                i2_coeff1 = (WORD16) (pi2_ref_data_byte[4]);

                /* populate the last inter sample */
                *pi4_ref_array++ = i2_coeff1 << 4;
            }

            /* vertical loop updates */
            pi2_ref_data_byte = pi2_inp_data + ((i4_i + 1) * i4_inp_data_stride);
        }

        /* ----------- Vertical Interpolation ---------------- */
        pi4_ref_array = (WORD32 *) ps_ctxt->pi2_refarray_buffer;
        ps_pos_phase = ps_lyr_ctxt->s_chroma_map_ctxt.ps_y_pos_phase;
        i4_phase1 = ps_pos_phase[0].i2_phase;
        i4_phase2 = (i4_phase1 + 8) & 0x0F;

        /* interchange the phase values for corner case */
        if(0 != i4_chrm_vert_int_mode)
        {
            WORD32 i4_temp;
            i4_temp = i4_phase1;
            i4_phase1 = i4_phase2;
            i4_phase2 = i4_temp;
        }

        for(i4_i = 0; i4_i < BLOCK_WIDTH; i4_i++)
        {
            WORD16 *pi2_out;
            WORD32 *pi4_ref_array_temp;
            WORD32 i4_horz_samp_1, i4_horz_samp_2;
            pi2_out = pi2_out_res;
            pi4_ref_array_temp = pi4_ref_array;

            /* populate the first inter sample */
            i4_horz_samp_1 = *pi4_ref_array_temp;
            pi4_ref_array_temp += BLOCK_WIDTH;

            if(1 != i4_chrm_vert_int_mode)
            {
                *pi2_out = (i4_horz_samp_1 + 8) >> 4;
                pi2_out += i4_out_res_stride;
            }

            if(2 == i4_chrm_vert_int_mode)
            {
                i4_horz_samp_1 = *pi4_ref_array_temp;
                pi4_ref_array_temp += BLOCK_WIDTH;
                *pi2_out = (i4_horz_samp_1 + 8) >> 4;
                pi2_out += i4_out_res_stride;
            }

            /* unroll count 1 */
            i4_horz_samp_2 = *pi4_ref_array_temp;
            pi4_ref_array_temp += BLOCK_WIDTH;

            /* populate 2 samples based on current coeffs */
            *pi2_out = ((16 - i4_phase2) * i4_horz_samp_1 + i4_phase2 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 2 */
            *pi2_out = ((16 - i4_phase1) * i4_horz_samp_1 + i4_phase1 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 3 */
            i4_horz_samp_1 = *pi4_ref_array_temp;
            pi4_ref_array_temp += BLOCK_WIDTH;

            /* populate 2 samples based on current coeffs */
            *pi2_out = ((16 - i4_phase2) * i4_horz_samp_2 + i4_phase2 * i4_horz_samp_1 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 4 */
            *pi2_out = ((16 - i4_phase1) * i4_horz_samp_2 + i4_phase1 * i4_horz_samp_1 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 5 */
            i4_horz_samp_2 = *pi4_ref_array_temp;

            /* populate 2 samples based on current coeffs */
            *pi2_out = ((16 - i4_phase2) * i4_horz_samp_1 + i4_phase2 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 6 */
            *pi2_out = ((16 - i4_phase1) * i4_horz_samp_1 + i4_phase1 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            if(2 != i4_chrm_vert_int_mode)
            {
                /* populate the last inter sample */
                *pi2_out = (i4_horz_samp_2 + 8) >> 4;

                if(1 == i4_chrm_vert_int_mode)
                {
                    pi2_out += i4_out_res_stride;
                    pi4_ref_array_temp += BLOCK_WIDTH;
                    i4_horz_samp_1 = *pi4_ref_array_temp;

                    /* populate the last inter sample */
                    *pi2_out = (i4_horz_samp_1 + 8) >> 4;
                }
            }
            /* horizontal loop updates */
            pi4_ref_array++;
            pi2_out_res += 2;
        }
    }
    return;
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_chroma_dyadic                              */
/*                                                                           */
/*  Description   : this fucntion does the upsampling of chroma residuals for*/
/*                  Dyadic cases                                             */
/*                                                                           */
/*  Inputs        : pv_residual_samp_ctxt : Residual upsampling context      */
/*                  pu1_inp_data : input 8 bit data pointer                  */
/*                  i4_inp_data_stride : input buffer stride                 */
/*                  pi2_out_res : output 16 bit buffer pointer               */
/*                  i4_out_res_stride : Output buffer stride                 */
/*                  pu1_inp_bitmap : input packed sign bit data pointer      */
/*                  i4_inp_bitmap_stride : sign bit buffer stride            */
/*                  i4_start_bit_pos : bit position in the byte of packed    */
/*                                      sign values                          */
/*  Globals       : none                                                     */
/*  Processing    : it does the upsampling with intial phase values          */
/*                                                                           */
/*  Outputs       : Upsampled residuals for chroma                           */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         25 09 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
void isvcd_residual_chroma_dyadic(void *pv_residual_samp_ctxt, WORD16 *pi2_inp_data,
                                  WORD32 i4_inp_data_stride, WORD16 *pi2_out_res,
                                  WORD32 i4_out_res_stride)
{
    residual_sampling_ctxt_t *ps_ctxt;
    res_lyr_ctxt *ps_lyr_ctxt;
    ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;
    ps_lyr_ctxt = &ps_ctxt->as_res_lyrs[ps_ctxt->i4_res_lyr_id];
    /* ----------------- Processing ------------------------------- */
    {
        WORD32 i4_i;
        WORD16 *pi2_ref_data_byte;
        WORD32 *pi4_ref_array;
        ref_pixel_map_t *ps_pos_phase;
        WORD32 i4_phase1, i4_phase2;

        pi2_ref_data_byte = pi2_inp_data;
        ps_pos_phase = ps_lyr_ctxt->s_chroma_map_ctxt.ps_x_pos_phase;

        /* ----------- Horizontal Interpolation ---------------- */
        pi4_ref_array = (WORD32 *) ps_ctxt->pi2_refarray_buffer;
        i4_phase1 = ps_pos_phase[0].i2_phase;
        i4_phase2 = (i4_phase1 + 8) & 0x0F;

        for(i4_i = 0; i4_i < SUB_BLOCK_HEIGHT; i4_i++)
        {
            WORD16 i2_coeff1, i2_coeff2;
            i2_coeff1 = (WORD16) (pi2_ref_data_byte[0]);

            /* populate the first inter sample */
            *pi4_ref_array++ = i2_coeff1 << 4;

            /* unroll count 1 */
            i2_coeff2 = (WORD16) (pi2_ref_data_byte[2]);

            /* populate 2 samples based on current coeffs */
            *pi4_ref_array++ = ((16 - i4_phase2) * i2_coeff1 + i4_phase2 * i2_coeff2);

            /* unroll count 2 */
            *pi4_ref_array++ = ((16 - i4_phase1) * i2_coeff1 + i4_phase1 * i2_coeff2);

            /* unroll count 3 */
            i2_coeff1 = (WORD16) (pi2_ref_data_byte[4]);

            /* populate 2 samples based on current coeffs */
            *pi4_ref_array++ = ((16 - i4_phase2) * i2_coeff2 + i4_phase2 * i2_coeff1);

            /* unroll count 4 */
            *pi4_ref_array++ = ((16 - i4_phase1) * i2_coeff2 + i4_phase1 * i2_coeff1);

            /* unroll count 5 */
            i2_coeff2 = (WORD16) (pi2_ref_data_byte[6]);

            /* populate 2 samples based on current coeffs */
            *pi4_ref_array++ = ((16 - i4_phase2) * i2_coeff1 + i4_phase2 * i2_coeff2);

            /* unroll count 6 */
            *pi4_ref_array++ = ((16 - i4_phase1) * i2_coeff1 + i4_phase1 * i2_coeff2);

            /* populate the last inter sample */
            *pi4_ref_array++ = i2_coeff2 << 4;

            /* vertical loop uopdates */
            pi2_ref_data_byte = pi2_inp_data + ((i4_i + 1) * i4_inp_data_stride);
        }

        /* ----------- Vertical Interpolation ---------------- */
        pi4_ref_array = (WORD32 *) ps_ctxt->pi2_refarray_buffer;
        ps_pos_phase = ps_lyr_ctxt->s_chroma_map_ctxt.ps_y_pos_phase;
        i4_phase1 = ps_pos_phase[0].i2_phase;
        i4_phase2 = (i4_phase1 + 8) & 0x0F;

        for(i4_i = 0; i4_i < BLOCK_WIDTH; i4_i++)
        {
            WORD16 *pi2_out;
            WORD32 *pi4_ref_array_temp;
            WORD32 i4_horz_samp_1, i4_horz_samp_2;
            pi2_out = pi2_out_res;
            pi4_ref_array_temp = pi4_ref_array;

            /* populate the first inter sample */
            i4_horz_samp_1 = *pi4_ref_array_temp;
            pi4_ref_array_temp += BLOCK_WIDTH;
            *pi2_out = (i4_horz_samp_1 + 8) >> 4;
            pi2_out += i4_out_res_stride;

            /* unroll count 1 */
            i4_horz_samp_2 = *pi4_ref_array_temp;
            pi4_ref_array_temp += BLOCK_WIDTH;

            /* populate 2 samples based on current coeffs */
            *pi2_out = ((16 - i4_phase2) * i4_horz_samp_1 + i4_phase2 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 2 */
            *pi2_out = ((16 - i4_phase1) * i4_horz_samp_1 + i4_phase1 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 3 */
            i4_horz_samp_1 = *pi4_ref_array_temp;
            pi4_ref_array_temp += BLOCK_WIDTH;

            /* populate 2 samples based on current coeffs */
            *pi2_out = ((16 - i4_phase2) * i4_horz_samp_2 + i4_phase2 * i4_horz_samp_1 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 4 */
            *pi2_out = ((16 - i4_phase1) * i4_horz_samp_2 + i4_phase1 * i4_horz_samp_1 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 5 */
            i4_horz_samp_2 = *pi4_ref_array_temp;

            /* populate 2 samples based on current coeffs */
            *pi2_out = ((16 - i4_phase2) * i4_horz_samp_1 + i4_phase2 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* unroll count 6 */
            *pi2_out = ((16 - i4_phase1) * i4_horz_samp_1 + i4_phase1 * i4_horz_samp_2 + 128) >> 8;
            pi2_out += i4_out_res_stride;

            /* populate the last inter sample */
            *pi2_out = (i4_horz_samp_2 + 8) >> 4;

            /* horizontal loop updates */
            pi4_ref_array++;
            pi2_out_res += 2;
        }
    }
    return;
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_luma_dyadic                                */
/*                                                                           */
/*  Description   : this fucntion does the upsampling of luma residuals for  */
/*                  Dyadic cases                                             */
/*                                                                           */
/*  Inputs        : pv_residual_samp_ctxt : Residual upsampling context      */
/*                  pu1_inp_data : input 8 bit data pointer                  */
/*                  i4_inp_data_stride : input buffer stride                 */
/*                  pi2_out_res : output 16 bit buffer pointer               */
/*                  i4_out_res_stride : Output buffer stride                 */
/*                  pu1_inp_bitmap : input packed sign bit data pointer      */
/*                  i4_inp_bitmap_stride : sign bit buffer stride            */
/*                  ps_ref_mb_mode : reference mb mode pointer of base layer */
/*                  ps_coord : mb co-ordinate pointer                        */
/*  Globals       : none                                                     */
/*  Processing    : it does the upsampling with fixed phase values and       */
/*                  reference layer transform size                           */
/*  Outputs       : Upsampled residuals for luma                             */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         25 09 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
void isvcd_residual_luma_dyadic(void *pv_residual_samp_ctxt, WORD16 *pi2_inp_data,
                                WORD32 i4_inp_data_stride, WORD16 *pi2_out_res,
                                WORD32 i4_out_res_stride, mem_element_t *ps_ref_mb_mode,
                                UWORD16 u2_mb_x, UWORD16 u2_mb_y, WORD32 i4_ref_nnz,
                                WORD32 i4_ref_tx_size)

{
    WORD16 *pi2_refarray_buffer;
    WORD32 i4_blk_ctr;
    residual_sampling_ctxt_t *ps_ctxt;

    UNUSED(ps_ref_mb_mode);
    UNUSED(u2_mb_x);
    UNUSED(u2_mb_y);

    ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;
    pi2_refarray_buffer = ps_ctxt->pi2_refarray_buffer;

    /* based on transform size the counter and interpolation width and */
    /* height are intialised as follows                                */
    if((i4_ref_tx_size) && (0 != i4_ref_nnz))
    {
        WORD16 *pi2_ref_data_byte;
        WORD32 *pi4_ref_array;
        WORD32 i4_i, i4_j;

        pi2_ref_data_byte = pi2_inp_data;

        /* ----------- Horizontal Interpolation ---------------- */
        pi4_ref_array = (WORD32 *) pi2_refarray_buffer;
        for(i4_i = 0; i4_i < BLOCK_HEIGHT; i4_i++)
        {
            WORD16 i2_coeff1, i2_coeff2;
            i2_coeff1 = (WORD16) (*pi2_ref_data_byte++);

            /* populate the first inter sample */
            *pi4_ref_array++ = i2_coeff1 << 2;

            for(i4_j = 0; i4_j < 14; i4_j += 2)
            {
                i2_coeff2 = (WORD16) (*pi2_ref_data_byte++);

                /* populate 2 samples based on current coeffs */
                *pi4_ref_array++ = ((i2_coeff1 << 1) + (i2_coeff1) + (i2_coeff2));
                *pi4_ref_array++ = ((i2_coeff2 << 1) + (i2_coeff2) + (i2_coeff1));

                /* store the coeff 2 to coeff 1 */
                /* (used in next iteration)     */
                i2_coeff1 = i2_coeff2;
            }

            /* populate the last inter sample */
            *pi4_ref_array++ = i2_coeff1 << 2;

            /* vertical loop uopdates */
            pi2_ref_data_byte = pi2_inp_data + ((i4_i + 1) * i4_inp_data_stride);
        }

        /* ----------- Vertical Interpolation ---------------- */
        pi4_ref_array = (WORD32 *) pi2_refarray_buffer;

        for(i4_i = 0; i4_i < MB_WIDTH; i4_i++)
        {
            WORD32 *pi4_ref_array_temp;
            WORD16 *pi2_out;
            WORD32 i4_horz_samp_1, i4_horz_samp_2;

            pi4_ref_array_temp = pi4_ref_array;
            pi2_out = pi2_out_res;
            i4_horz_samp_1 = *pi4_ref_array_temp;

            /* populate the first inter sample */
            *pi2_out = (i4_horz_samp_1 + 2) >> 2;
            pi2_out += i4_out_res_stride;

            for(i4_j = 0; i4_j < 14; i4_j += 2)
            {
                pi4_ref_array_temp += MB_WIDTH;
                i4_horz_samp_2 = *pi4_ref_array_temp;

                /* populate 2 samples based on current coeffs */
                *pi2_out = ((i4_horz_samp_1 << 1) + (i4_horz_samp_1) + (i4_horz_samp_2) + 8) >> 4;
                pi2_out += i4_out_res_stride;
                *pi2_out = ((i4_horz_samp_2 << 1) + (i4_horz_samp_2) + (i4_horz_samp_1) + 8) >> 4;
                pi2_out += i4_out_res_stride;

                /* store the coeff 2 to coeff 1 */
                /* (used in next iteration)     */
                i4_horz_samp_1 = i4_horz_samp_2;
            }

            /* populate the first inter sample */
            *pi2_out = (i4_horz_samp_1 + 2) >> 2;

            /* horizontal loop updates */
            pi4_ref_array++;
            pi2_out_res++;
        }
    }
    else
    {
        /* ----------------------------------------------------------------- */
        /* LOOP over number of blocks                                        */
        /* ----------------------------------------------------------------- */
        for(i4_blk_ctr = 0; i4_blk_ctr < 4; i4_blk_ctr++)
        {
            WORD16 *pi2_ref_data_byte;
            WORD32 *pi4_ref_array;
            WORD32 i4_i;

            /* if reference layer is not coded then no processing */
            if(0 != (i4_ref_nnz & 0x1))
            {
                pi2_ref_data_byte = pi2_inp_data;

                /* ----------- Horizontal Interpolation ---------------- */
                pi4_ref_array = (WORD32 *) pi2_refarray_buffer;

                for(i4_i = 0; i4_i < SUB_BLOCK_HEIGHT; i4_i++)
                {
                    WORD16 i2_coeff1, i2_coeff2;
                    i2_coeff1 = (WORD16) (*pi2_ref_data_byte++);

                    /* populate the first inter sample */
                    *pi4_ref_array++ = i2_coeff1 << 2;

                    i2_coeff2 = (WORD16) (*pi2_ref_data_byte++);

                    /* populate 2 samples based on current coeffs */
                    *pi4_ref_array++ = ((i2_coeff1 << 1) + (i2_coeff1) + (i2_coeff2));
                    *pi4_ref_array++ = ((i2_coeff2 << 1) + (i2_coeff2) + (i2_coeff1));

                    i2_coeff1 = (WORD16) (*pi2_ref_data_byte++);

                    /* populate 2 samples based on current coeffs */
                    *pi4_ref_array++ = ((i2_coeff2 << 1) + (i2_coeff2) + (i2_coeff1));
                    *pi4_ref_array++ = ((i2_coeff1 << 1) + (i2_coeff1) + (i2_coeff2));

                    i2_coeff2 = (WORD16) (*pi2_ref_data_byte++);

                    /* populate 2 samples based on current coeffs */
                    *pi4_ref_array++ = ((i2_coeff1 << 1) + (i2_coeff1) + (i2_coeff2));
                    *pi4_ref_array++ = ((i2_coeff2 << 1) + (i2_coeff2) + (i2_coeff1));

                    /* populate the last inter sample */
                    *pi4_ref_array++ = i2_coeff2 << 2;

                    /* vertical loop uopdates */
                    pi2_ref_data_byte = pi2_inp_data + ((i4_i + 1) * i4_inp_data_stride);
                }

                /* ----------- Vertical Interpolation ---------------- */
                pi4_ref_array = (WORD32 *) pi2_refarray_buffer;

                for(i4_i = 0; i4_i < BLOCK_WIDTH; i4_i++)
                {
                    WORD32 *pi4_ref_array_temp;
                    WORD16 *pi2_out;
                    WORD32 i4_horz_samp_1, i4_horz_samp_2;

                    pi4_ref_array_temp = pi4_ref_array;
                    pi2_out = pi2_out_res;
                    i4_horz_samp_1 = *pi4_ref_array_temp;

                    /* populate the first inter sample */
                    *pi2_out = (i4_horz_samp_1 + 2) >> 2;
                    pi2_out += i4_out_res_stride;

                    /* unroll loop count 1 */
                    pi4_ref_array_temp += BLOCK_WIDTH;
                    i4_horz_samp_2 = *pi4_ref_array_temp;

                    /* populate 2 samples based on current coeffs */
                    *pi2_out =
                        ((i4_horz_samp_1 << 1) + (i4_horz_samp_1) + (i4_horz_samp_2) + 8) >> 4;
                    pi2_out += i4_out_res_stride;
                    *pi2_out =
                        ((i4_horz_samp_2 << 1) + (i4_horz_samp_2) + (i4_horz_samp_1) + 8) >> 4;
                    pi2_out += i4_out_res_stride;

                    /* unroll loop count 2 */
                    pi4_ref_array_temp += BLOCK_WIDTH;
                    i4_horz_samp_1 = *pi4_ref_array_temp;

                    /* populate 2 samples based on current coeffs */
                    *pi2_out =
                        ((i4_horz_samp_2 << 1) + (i4_horz_samp_2) + (i4_horz_samp_1) + 8) >> 4;
                    pi2_out += i4_out_res_stride;
                    *pi2_out =
                        ((i4_horz_samp_1 << 1) + (i4_horz_samp_1) + (i4_horz_samp_2) + 8) >> 4;
                    pi2_out += i4_out_res_stride;

                    /* unroll loop count 3 */
                    pi4_ref_array_temp += BLOCK_WIDTH;
                    i4_horz_samp_2 = *pi4_ref_array_temp;

                    /* populate 2 samples based on current coeffs */
                    *pi2_out =
                        ((i4_horz_samp_1 << 1) + (i4_horz_samp_1) + (i4_horz_samp_2) + 8) >> 4;
                    pi2_out += i4_out_res_stride;
                    *pi2_out =
                        ((i4_horz_samp_2 << 1) + (i4_horz_samp_2) + (i4_horz_samp_1) + 8) >> 4;
                    pi2_out += i4_out_res_stride;

                    /* populate the last inter sample */
                    *pi2_out = (i4_horz_samp_2 + 2) >> 2;

                    /* horizontal loop updates */
                    pi4_ref_array++;
                    pi2_out_res++;
                }
            }
            else
            {
                pi2_out_res += BLOCK_WIDTH;
            }

            /* Block level loop updates */
            if(1 == i4_blk_ctr)
            {
                pi2_inp_data -= SUB_BLOCK_WIDTH;
                pi2_inp_data += (i4_inp_data_stride * SUB_BLOCK_HEIGHT);
                pi2_out_res -= MB_WIDTH;
                pi2_out_res += (i4_out_res_stride * BLOCK_HEIGHT);
                i4_ref_nnz >>= 2;
            }
            else
            {
                pi2_inp_data += SUB_BLOCK_WIDTH;
            }

            i4_ref_nnz >>= 1;

        } /* end of loop over all the blocks */
    }
    return;
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name :  isvcd_ref_layer_ptr_incr                                 */
/*                                                                           */
/*  Description   :  this function returns the pointer increments for        */
/*                   the operand2 of the bilinear interpolation              */
/*  Inputs        : pi1_ref_mb_modes : reference mb modes                    */
/*                  i4_ref_mode_stride : mb mode buffer stride               */
/*                    i4_element_size : size of reference mb mode            */
/*                  i4_x_offset : ref offset x                               */
/*                  i4_y_offset : ref offset y                               */
/*                    i4_refary_wd : reference array width                   */
/*                    i4_refary_ht : reference array height                  */
/*                  pu1_ref_x_ptr_incr : ptr increment buffer for x          */
/*                  pu1_ref_y_ptr_incr : ptr increment buffer for y          */
/*                    i4_chroma_flag : chroma processing flag                */
/*  Globals       : none                                                     */
/*  Processing    : it calculates the increment as per the transform size    */
/*                                                                           */
/*  Outputs       : none                                                     */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         18 08 2021   Kishore              creation                        */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_ref_layer_ptr_incr(WORD8 *pi1_ref_mb_modes, WORD32 i4_ref_mode_stride,
                                WORD32 i4_element_size, WORD32 i4_x_offset, WORD32 i4_y_offset,
                                WORD32 i4_refary_wd, WORD32 i4_refary_ht,
                                UWORD8 *pu1_ref_x_ptr_incr, UWORD8 *pu1_ref_y_ptr_incr,
                                WORD32 i4_chroma_flag)
{
    WORD32 i4_x, i4_y;
    WORD32 i4_x_idx, i4_y_idx;
    WORD32 i4_prev_x, i4_prev_y;
    WORD32 i4_const_val;
    WORD32 i4_pos_x, i4_pos_y;
    WORD32 i4_trans_size;
    WORD32 i4_act_ary_wd, i4_act_ary_ht;
    WORD32 i4_and_const;
    UWORD8 *pu1_incr_x, *pu1_incr_y;
    WORD32 i4_mb_sft;
    WORD32 i4_mb_x, i4_mb_y;
    WORD8 *pi1_ref_mb_modes_incr;
    WORD8 *pi1_ref_mb_modes_incr_temp;
    inter_lyr_mb_prms_t *ps_inter_lyr_mb_prms;
    WORD32 i4_mb_x_strt, i4_mb_y_strt;
    WORD32 i4_mb_quard1_part_x, i4_mb_quard1_part_y;
    WORD32 i4_x_ref, i4_y_ref;
    WORD32 i4_tx_size, i4_tx_size_q0, i4_tx_size_q1, i4_tx_size_q2, i4_tx_size_q3;
    WORD8 i1_mb_mode_q0, i1_mb_mode_q1, i1_mb_mode_q2, i1_mb_mode_q3;
    WORD32 i4_mb_wd;
    WORD32 i4_mb_ht;

    i4_mb_wd = MB_WIDTH >> i4_chroma_flag;
    i4_mb_ht = MB_HEIGHT >> i4_chroma_flag;

    /* Memset to 1 the increment buffers */
    memset(pu1_ref_x_ptr_incr, 1, (i4_refary_wd * i4_refary_ht));
    memset(pu1_ref_y_ptr_incr, 1, (i4_refary_wd * i4_refary_ht));

    /* Initialise actual width and height */
    i4_act_ary_wd = i4_refary_wd;
    i4_act_ary_ht = i4_refary_ht;

    /* Initialize x and y */
    i4_x = 0;
    i4_y = 0;
    i4_prev_y = 0;
    i4_mb_sft = (MB_WIDTH_SHIFT - i4_chroma_flag);

    /* Loop over all MBs in the reference array */
    if(0 == i4_chroma_flag)
    {
        i4_x_ref = i4_x_offset + 0;
        i4_y_ref = i4_y_offset + 0;
        i4_mb_x_strt = i4_x_ref % i4_mb_wd;
        i4_mb_y_strt = i4_y_ref % i4_mb_ht;
        i4_mb_quard1_part_x = i4_mb_wd - i4_mb_x_strt;
        i4_mb_quard1_part_y = i4_mb_ht - i4_mb_y_strt;

        if(!(i4_mb_quard1_part_x >= 0))
        {
            return NOT_OK;
        }
        if(!(i4_mb_quard1_part_y >= 0))
        {
            return NOT_OK;
        }

        /* Take care of negative offsets */
        if(i4_x_ref > 0)
        {
            i4_mb_x = (i4_x_ref >> i4_mb_sft);
        }
        else
        {
            i4_mb_x = 0;
        }
        if(i4_y_ref > 0)
        {
            i4_mb_y = (i4_y_ref >> i4_mb_sft);
        }
        else
        {
            i4_mb_y = 0;
        }

        /* get the location of the byte which has the current mb mode */
        pi1_ref_mb_modes_incr = pi1_ref_mb_modes + (i4_mb_y * i4_ref_mode_stride * i4_element_size);
        pi1_ref_mb_modes_incr += (i4_mb_x * i4_element_size);
        ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr;
        i1_mb_mode_q0 = ps_inter_lyr_mb_prms->i1_mb_mode;
        i4_tx_size_q0 =
            (i1_mb_mode_q0 <= SVC_INTER_MB)
                ? ((ps_inter_lyr_mb_prms->i1_tx_size < 0) ? 1 : ps_inter_lyr_mb_prms->i1_tx_size)
                : 1;

        pi1_ref_mb_modes_incr_temp = pi1_ref_mb_modes_incr;
        if(i4_mb_quard1_part_x > 0)
        {
            pi1_ref_mb_modes_incr_temp = pi1_ref_mb_modes_incr + i4_element_size;
            ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr_temp;
            i1_mb_mode_q1 = ps_inter_lyr_mb_prms->i1_mb_mode;
            i4_tx_size_q1 =
                (i1_mb_mode_q1 <= SVC_INTER_MB)
                    ? ((ps_inter_lyr_mb_prms->i1_tx_size < 0) ? 1
                                                              : ps_inter_lyr_mb_prms->i1_tx_size)
                    : 1;
        }

        if(i4_mb_quard1_part_y > 0)
        {
            pi1_ref_mb_modes_incr_temp =
                pi1_ref_mb_modes_incr + (i4_ref_mode_stride * i4_element_size);
            ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr_temp;
            i1_mb_mode_q2 = ps_inter_lyr_mb_prms->i1_mb_mode;
            i4_tx_size_q2 =
                (i1_mb_mode_q2 <= SVC_INTER_MB)
                    ? ((ps_inter_lyr_mb_prms->i1_tx_size < 0) ? 1
                                                              : ps_inter_lyr_mb_prms->i1_tx_size)
                    : 1;
        }

        if((i4_mb_quard1_part_x > 0) && (i4_mb_quard1_part_y > 0))
        {
            pi1_ref_mb_modes_incr_temp =
                pi1_ref_mb_modes_incr + (i4_ref_mode_stride * i4_element_size) + i4_element_size;
            ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr_temp;
            i1_mb_mode_q3 = ps_inter_lyr_mb_prms->i1_mb_mode;
            i4_tx_size_q3 =
                (i1_mb_mode_q3 <= SVC_INTER_MB)
                    ? ((ps_inter_lyr_mb_prms->i1_tx_size < 0) ? 1
                                                              : ps_inter_lyr_mb_prms->i1_tx_size)
                    : 1;
        }

        do
        {
            WORD32 i4_idx;
            WORD32 i4_wd, i4_ht;
            WORD32 i4_max_pos_x, i4_max_pos_y;

            i4_prev_x = i4_x;
            i4_x_ref = i4_x_offset + i4_x;
            i4_y_ref = i4_y_offset + i4_y;
            i4_tx_size = i4_tx_size_q0;
            if(i4_x >= i4_mb_quard1_part_x)
            {
                if(i4_y < i4_mb_quard1_part_y)
                {
                    i4_tx_size = i4_tx_size_q1;
                }
                else if(i4_y >= i4_mb_quard1_part_y)
                {
                    i4_tx_size = i4_tx_size_q3;
                }
            }
            else if(i4_x < i4_mb_quard1_part_x)
            {
                if(i4_y >= i4_mb_quard1_part_y)
                {
                    i4_tx_size = i4_tx_size_q2;
                }
            }

            /* Get the transform size as 4 or 8 */
            i4_trans_size = ((i4_tx_size + 1) << 2);
            i4_const_val = i4_trans_size - 1;
            i4_and_const = i4_const_val;

            /* Fill horizontal tx block edges of current reference mb with 0 */
            pu1_incr_x = pu1_ref_x_ptr_incr + i4_x;
            pu1_incr_x += (i4_y * i4_refary_wd);
            i4_ht = (16 - (i4_y_ref & 0xF));
            i4_ht = MIN((i4_act_ary_ht - i4_y), i4_ht);

            i4_x_idx = i4_x;
            i4_pos_x = i4_x_ref & 0xF;
            i4_max_pos_x = 16;
            i4_x += (16 - i4_pos_x);

            /* Get the transform block edge pos */
            i4_idx = (i4_const_val - (i4_pos_x & i4_and_const));
            i4_x_idx += i4_idx;

            while((i4_pos_x < i4_max_pos_x) && (i4_x_idx < i4_act_ary_wd))
            {
                WORD32 i4_i;
                UWORD8 *pu1_incr;

                pu1_incr = pu1_incr_x + i4_idx;
                for(i4_i = 0; i4_i < i4_ht; i4_i++)
                {
                    /* Fill the block edge with 0s */
                    *pu1_incr = 0;
                    pu1_incr += i4_refary_wd;
                }

                /* Updates */
                i4_pos_x += i4_trans_size;
                pu1_incr_x += i4_trans_size;
                i4_x_idx += MIN(i4_trans_size, (i4_act_ary_wd - i4_x_idx));
            }

            /* Fill vertical tx block edges of current reference mb with 0 */
            pu1_incr_y = pu1_ref_y_ptr_incr + i4_prev_x;
            pu1_incr_y += (i4_y * i4_refary_wd);
            i4_wd = (16 - (i4_x_ref & 0xF));
            i4_wd = MIN((i4_act_ary_wd - i4_prev_x), i4_wd);
            i4_y_idx = i4_y;
            i4_pos_y = i4_y_ref & 0xF;
            i4_max_pos_y = 16;
            i4_y += (16 - i4_pos_y);

            /* Get the transform block edge pos */
            i4_idx = (i4_const_val - (i4_pos_y & i4_and_const));
            i4_y_idx += i4_idx;

            while((i4_pos_y < i4_max_pos_y) && (i4_y_idx < i4_act_ary_ht))
            {
                WORD32 i4_i;
                UWORD8 *pu1_incr;

                pu1_incr = pu1_incr_y + i4_idx * i4_refary_wd;
                for(i4_i = 0; i4_i < i4_wd; i4_i++)
                {
                    /* Fill the block edge with 0s */
                    *pu1_incr = 0;
                    pu1_incr++;
                }

                /* Updates */
                i4_pos_y += i4_trans_size;
                pu1_incr_y += i4_trans_size * i4_refary_wd;
                i4_y_idx += MIN(i4_trans_size, (i4_act_ary_ht - i4_y_idx));
            }

            /* Loop updates */
            if(i4_x < i4_act_ary_wd)
            {
                i4_y = i4_prev_y;
            }
            else if(i4_y < i4_act_ary_ht)
            {
                i4_prev_y = i4_y;
                i4_x = 0;
            }

        } while((i4_y < i4_act_ary_ht) || (i4_x < i4_act_ary_wd));

    } /* End of if 0 == i4_chroma_flag */
    else
    {
        /* Set the transform size as 4 */
        i4_trans_size = 4;
        i4_const_val = 3;

        do
        {
            WORD32 i4_x_ref, i4_y_ref;
            WORD32 i4_idx;
            WORD32 i4_wd, i4_ht;
            WORD32 i4_max_pos_x, i4_max_pos_y;

            i4_prev_x = i4_x;
            i4_x_ref = i4_x_offset + i4_x;
            i4_y_ref = i4_y_offset + i4_y;

            /* Fill horizontal tx block edges of current reference mb with 0 */
            pu1_incr_x = pu1_ref_x_ptr_incr + i4_x;
            pu1_incr_x += (i4_y * i4_refary_wd);
            i4_ht = (8 - (i4_y_ref & 0x7));
            i4_ht = MIN((i4_act_ary_ht - i4_y), i4_ht);
            i4_x_idx = i4_x;
            i4_pos_x = i4_x_ref & 0x7;
            i4_max_pos_x = 8;
            i4_x += (8 - i4_pos_x);

            /* Get the transform block edge pos */
            i4_idx = (i4_const_val - (i4_pos_x & 0x3));
            i4_x_idx += i4_idx;

            while((i4_pos_x < i4_max_pos_x) && (i4_x_idx < i4_act_ary_wd))
            {
                WORD32 i4_i;
                UWORD8 *pu1_incr;

                pu1_incr = pu1_incr_x + i4_idx;
                for(i4_i = 0; i4_i < i4_ht; i4_i++)
                {
                    /* Fill the block edge with 0s */
                    *pu1_incr = 0;
                    pu1_incr += i4_refary_wd;
                }

                /* Updates */
                i4_pos_x += i4_trans_size;
                pu1_incr_x += i4_trans_size;
                i4_x_idx += MIN(i4_trans_size, (i4_act_ary_wd - i4_x_idx));
            }

            /* Fill vertical tx block edges of current reference mb with 0 */
            pu1_incr_y = pu1_ref_y_ptr_incr + i4_prev_x;
            pu1_incr_y += (i4_y * i4_refary_wd);
            i4_wd = (8 - (i4_x_ref & 0x7));
            i4_wd = MIN((i4_act_ary_wd - i4_prev_x), i4_wd);
            i4_y_idx = i4_y;
            i4_pos_y = i4_y_ref & 0x7;
            i4_max_pos_y = 8;
            i4_y += (8 - i4_pos_y);

            /* Get the transform block edge pos */
            i4_idx = (i4_const_val - (i4_pos_y & 0x3));
            i4_y_idx += i4_idx;

            while((i4_pos_y < i4_max_pos_y) && (i4_y_idx < i4_act_ary_ht))
            {
                WORD32 i4_i;
                UWORD8 *pu1_incr;

                pu1_incr = pu1_incr_y + i4_idx * i4_refary_wd;
                for(i4_i = 0; i4_i < i4_wd; i4_i++)
                {
                    /* Fill the block edge with 0s */
                    *pu1_incr = 0;
                    pu1_incr++;
                }

                /* Updates */
                i4_pos_y += i4_trans_size;
                pu1_incr_y += i4_trans_size * i4_refary_wd;
                i4_y_idx += MIN(i4_trans_size, (i4_act_ary_ht - i4_y_idx));
            }

            /* Loop updates */
            if(i4_x < i4_act_ary_wd)
            {
                i4_y = i4_prev_y;
            }
            else if(i4_y < i4_act_ary_ht)
            {
                i4_prev_y = i4_y;
                i4_x = 0;
            }

        } while((i4_y < i4_act_ary_ht) || (i4_x < i4_act_ary_wd));

    } /* End of chroma */
    return OK;

} /* End of "isvcd_ref_layer_ptr_incr" */

void isvcd_residual_reflayer_const_non_boundary_mb(
    WORD16 *pi2_inp_data, WORD32 i4_inp_data_stride, WORD16 *pi2_ref_array, WORD32 i4_refarray_wd,
    WORD32 i4_refarray_ht, WORD32 i4_ref_mb_type_q0, WORD32 i4_ref_mb_type_q1,
    WORD32 i4_ref_mb_type_q2, WORD32 i4_ref_mb_type_q3, WORD32 i4_mb_quard1_part_x,
    WORD32 i4_mb_quard1_part_y, WORD32 i4_chroma_flag)
{
    WORD32 i4_x_ref, i4_y_ref;
    WORD32 i4_x, i4_y;
    WORD32 i4_ref_mb_type;
    WORD16 *pi2_ref_data_byte;
    WORD16 *pi2_ref_array_temp;

    for(i4_y = 0; i4_y < i4_refarray_ht; i4_y++)
    {
        for(i4_x = 0; i4_x < i4_refarray_wd; i4_x++)
        {
            i4_y_ref = i4_y;
            i4_x_ref = i4_x;

            i4_ref_mb_type = i4_ref_mb_type_q0;
            if(i4_x >= i4_mb_quard1_part_x)
            {
                if(i4_y < i4_mb_quard1_part_y)
                {
                    i4_ref_mb_type = i4_ref_mb_type_q1;
                }
                else if(i4_y >= i4_mb_quard1_part_y)
                {
                    i4_ref_mb_type = i4_ref_mb_type_q3;
                }
            }
            else if(i4_x < i4_mb_quard1_part_x)
            {
                if(i4_y >= i4_mb_quard1_part_y)
                {
                    i4_ref_mb_type = i4_ref_mb_type_q2;
                }
            }

            /****************************************************************/
            /* Reference layer Residual Buffer is maintained as 8-bit data  */
            /* Buffer and 1-bit sign bit packed buffer. Sign Byte is read   */
            /* and sign of the data sample is extracted depending upon bit  */
            /* postition.                                                   */
            /****************************************************************/

            /* update the buffer pointers to appropriate locations */
            pi2_ref_array_temp = pi2_ref_array + i4_x;
            pi2_ref_array_temp += i4_y * i4_refarray_wd;

            /* extract the residual value and fill the buffer */
            if(SVC_INTER_MB == i4_ref_mb_type)
            {
                /* derive the reference data pointers */
                pi2_ref_data_byte = pi2_inp_data + (i4_x_ref << i4_chroma_flag);
                pi2_ref_data_byte += i4_y_ref * i4_inp_data_stride;

                /* store the residual value */
                *pi2_ref_array_temp = (WORD16) (*pi2_ref_data_byte);
            }
            else
            {
                /* if non inter MB then store the 0 */
                *pi2_ref_array_temp = 0;
            }
        }
    }
}

void isvcd_residual_reflayer_const_boundary_mb(WORD16 *pi2_inp_data, WORD32 i4_inp_data_stride,
                                               WORD16 *pi2_ref_array, WORD32 i4_refarray_wd,
                                               WORD32 i4_refarray_ht, WORD32 i4_ref_wd,
                                               WORD32 i4_ref_ht, WORD32 i4_x_offset,
                                               WORD32 i4_y_offset, WORD32 i4_ref_mb_type_q0,
                                               WORD32 i4_ref_mb_type_q1, WORD32 i4_ref_mb_type_q2,
                                               WORD32 i4_ref_mb_type_q3, WORD32 i4_mb_quard1_part_x,
                                               WORD32 i4_mb_quard1_part_y, WORD32 i4_chroma_flag)
{
    WORD32 i4_x_ref, i4_y_ref;
    WORD32 i4_x, i4_y;
    WORD16 *pi2_ref_data_byte;
    WORD16 *pi2_ref_array_temp;

    /*Quard 0*/
    for(i4_y = 0; i4_y < i4_mb_quard1_part_y; i4_y++)
    {
        for(i4_x = 0; i4_x < i4_mb_quard1_part_x; i4_x++)
        {
            i4_y_ref = MAX(0, MIN(i4_ref_ht - 1, i4_y + i4_y_offset));
            i4_x_ref = MAX(0, MIN(i4_ref_wd - 1, i4_x + i4_x_offset));

            /****************************************************************/
            /* Reference layer Residual Buffer is maintained as 8-bit data  */
            /* Buffer and 1-bit sign bit packed buffer. Sign Byte is read   */
            /* and sign of the data sample is extracted depending upon bit  */
            /* postition.                                                   */
            /****************************************************************/

            /* update the buffer pointers to appropriate locations */
            pi2_ref_array_temp = pi2_ref_array + i4_x;
            pi2_ref_array_temp += i4_y * i4_refarray_wd;

            /* extract the residual value and fill the buffer */
            if(SVC_INTER_MB == i4_ref_mb_type_q0)
            {
                /* input pointer will be pointing to (xoffset,yoffset) */
                /* So subtract the correction to reference location    */
                if(0 <= i4_x_offset)
                {
                    /* if only inside frame dimension */
                    i4_x_ref = i4_x_ref - i4_x_offset;
                }

                if(0 <= i4_y_offset)
                {
                    /* if only inside frame dimension */
                    i4_y_ref = i4_y_ref - i4_y_offset;
                }
                /* derive the reference data pointers */

                pi2_ref_data_byte = pi2_inp_data + (i4_x_ref << i4_chroma_flag);
                pi2_ref_data_byte += i4_y_ref * i4_inp_data_stride;

                /* store the residual value */
                *pi2_ref_array_temp = (WORD16) (*pi2_ref_data_byte);
            }
            else
            {
                /* if non inter MB then store the 0 */
                *pi2_ref_array_temp = 0;
            }
        }
    }

    /*Quard 1*/
    for(i4_y = 0; i4_y < i4_mb_quard1_part_y; i4_y++)
    {
        for(i4_x = i4_mb_quard1_part_x; i4_x < i4_refarray_wd; i4_x++)
        {
            i4_y_ref = MAX(0, MIN(i4_ref_ht - 1, i4_y + i4_y_offset));
            i4_x_ref = MAX(0, MIN(i4_ref_wd - 1, i4_x + i4_x_offset));

            /****************************************************************/
            /* Reference layer Residual Buffer is maintained as 8-bit data  */
            /* Buffer and 1-bit sign bit packed buffer. Sign Byte is read   */
            /* and sign of the data sample is extracted depending upon bit  */
            /* postition.                                                   */
            /****************************************************************/

            /* update the buffer pointers to appropriate locations */
            pi2_ref_array_temp = pi2_ref_array + i4_x;
            pi2_ref_array_temp += i4_y * i4_refarray_wd;

            /* extract the residual value and fill the buffer */
            if(SVC_INTER_MB == i4_ref_mb_type_q1)
            {
                /* input pointer will be pointing to (xoffset,yoffset) */
                /* So subtract the correction to reference location    */
                if(0 <= i4_x_offset)
                {
                    /* if only inside frame dimension */
                    i4_x_ref = i4_x_ref - i4_x_offset;
                }
                if(0 <= i4_y_offset)
                {
                    /* if only inside frame dimension */
                    i4_y_ref = i4_y_ref - i4_y_offset;
                }
                /* derive the reference data pointers */

                pi2_ref_data_byte = pi2_inp_data + (i4_x_ref << i4_chroma_flag);
                pi2_ref_data_byte += i4_y_ref * i4_inp_data_stride;

                /* store the residual value */
                *pi2_ref_array_temp = (WORD16) (*pi2_ref_data_byte);
            }
            else
            {
                /* if non inter MB then store the 0 */
                *pi2_ref_array_temp = 0;
            }
        }
    }

    /*Quard 2*/
    for(i4_y = i4_mb_quard1_part_y; i4_y < i4_refarray_ht; i4_y++)
    {
        for(i4_x = 0; i4_x < i4_mb_quard1_part_x; i4_x++)
        {
            i4_y_ref = MAX(0, MIN(i4_ref_ht - 1, i4_y + i4_y_offset));
            i4_x_ref = MAX(0, MIN(i4_ref_wd - 1, i4_x + i4_x_offset));

            /****************************************************************/
            /* Reference layer Residual Buffer is maintained as 8-bit data  */
            /* Buffer and 1-bit sign bit packed buffer. Sign Byte is read   */
            /* and sign of the data sample is extracted depending upon bit  */
            /* postition.                                                   */
            /****************************************************************/

            /* update the buffer pointers to appropriate locations */
            pi2_ref_array_temp = pi2_ref_array + i4_x;
            pi2_ref_array_temp += i4_y * i4_refarray_wd;

            /* extract the residual value and fill the buffer */
            if(SVC_INTER_MB == i4_ref_mb_type_q2)
            {
                /* input pointer will be pointing to (xoffset,yoffset) */
                /* So subtract the correction to reference location    */
                if(0 <= i4_x_offset)
                {
                    /* if only inside frame dimension */
                    i4_x_ref = i4_x_ref - i4_x_offset;
                }
                if(0 <= i4_y_offset)
                {
                    /* if only inside frame dimension */
                    i4_y_ref = i4_y_ref - i4_y_offset;
                }
                /* derive the reference data pointers */
                pi2_ref_data_byte = pi2_inp_data + (i4_x_ref << i4_chroma_flag);
                pi2_ref_data_byte += i4_y_ref * i4_inp_data_stride;

                /* store the residual value */
                *pi2_ref_array_temp = (WORD16) (*pi2_ref_data_byte);
            }
            else
            {
                /* if non inter MB then store the 0 */
                *pi2_ref_array_temp = 0;
            }
        }
    }

    /*Quard 3*/
    for(i4_y = i4_mb_quard1_part_y; i4_y < i4_refarray_ht; i4_y++)
    {
        for(i4_x = i4_mb_quard1_part_x; i4_x < i4_refarray_wd; i4_x++)
        {
            i4_y_ref = MAX(0, MIN(i4_ref_ht - 1, i4_y + i4_y_offset));
            i4_x_ref = MAX(0, MIN(i4_ref_wd - 1, i4_x + i4_x_offset));

            /****************************************************************/
            /* Reference layer Residual Buffer is maintained as 8-bit data  */
            /* Buffer and 1-bit sign bit packed buffer. Sign Byte is read   */
            /* and sign of the data sample is extracted depending upon bit  */
            /* postition.                                                   */
            /****************************************************************/

            /* update the buffer pointers to appropriate locations */
            pi2_ref_array_temp = pi2_ref_array + i4_x;
            pi2_ref_array_temp += i4_y * i4_refarray_wd;

            /* extract the residual value and fill the buffer */
            if(SVC_INTER_MB == i4_ref_mb_type_q3)
            {
                /* input pointer will be pointing to (xoffset,yoffset) */
                /* So subtract the correction to reference location    */
                if(0 <= i4_x_offset)
                {
                    /* if only inside frame dimension */
                    i4_x_ref = i4_x_ref - i4_x_offset;
                }
                if(0 <= i4_y_offset)
                {
                    /* if only inside frame dimension */
                    i4_y_ref = i4_y_ref - i4_y_offset;
                }
                /* derive the reference data pointers */
                pi2_ref_data_byte = pi2_inp_data + (i4_x_ref << i4_chroma_flag);
                pi2_ref_data_byte += i4_y_ref * i4_inp_data_stride;

                /* store the residual value */
                *pi2_ref_array_temp = (WORD16) (*pi2_ref_data_byte);
            }
            else
            {
                /* if non inter MB then store the 0 */
                *pi2_ref_array_temp = 0;
            }
        }
    }
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_reflayer_const                             */
/*                                                                           */
/*  Description   :  This function constructs the reference array buffer     */
/*                    used for residual resampling of a component in an MB   */
/*                                                                           */
/*  Inputs        : pv_residual_samp_ctxt: intra sampling context            */
/*                  pu1_inp : input (reference layer data)                   */
/*                  i4_inp_stride : input buffer stride                      */
/*                  pu1_inp_bitmap : input (reference layer sign bits)       */
/*                  i4_inp_stride : input buffer stride                      */
/*                  ps_ref_mb_mode : ref layer mb mode buffer desc           */
/*                  pi4_refarr_wd : pointer to store the reference array WD  */
/*                  pi4_refarr_ht : pointer to store the reference array HT  */
/*                  pi4_x_offset : pointer to store the reference X offset   */
/*                  pi4_y_offset : pointer to store the reference Y offset   */
/*                  ps_coord     : mb co-ordinate structure                  */
/*                  i4_chroma_flag : chroma processing flag                  */
/*  Globals       : none                                                     */
/*  Processing    : it fills the reference layer data if they are falling in */
/*                  INTRA MB region. If all the pixels are not filled  it    */
/*                  calls the border extension algorithm to fill them        */
/*  Outputs       : none                                                     */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 07 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_residual_reflayer_const(void *pv_residual_samp_ctxt, WORD16 *pi2_inp_data,
                                     WORD32 i4_inp_data_stride, mem_element_t *ps_ref_mb_mode,
                                     WORD32 *pi4_refarr_wd, mb_coord_t *ps_coord,
                                     WORD32 i4_chroma_flag)
{
    residual_sampling_ctxt_t *ps_ctxt;
    res_lyr_ctxt *ps_lyr_ctxt;
    WORD8 *pi1_ref_mb_modes;
    WORD32 i4_ref_mode_stride;
    WORD32 i4_element_size;
    WORD32 i4_ref_wd;
    WORD32 i4_ref_ht;
    WORD32 i4_x_offset;
    WORD32 i4_y_offset;
    WORD32 i4_refarray_wd;
    WORD32 i4_refarray_ht;
    WORD8 i1_edge_mb;
    WORD16 *pi2_ref_array;
    WORD32 i4_mb_sft;
    WORD32 i4_mb_x, i4_mb_y;
    WORD32 i4_mb_x_strt, i4_mb_y_strt;
    WORD32 i4_mb_quard1_part_x, i4_mb_quard1_part_y;
    WORD8 *pi1_ref_mb_modes_incr;
    WORD8 *pi1_ref_mb_modes_incr_temp;
    inter_lyr_mb_prms_t *ps_inter_lyr_mb_prms;

    WORD32 i4_mb_wd;
    WORD32 i4_mb_ht;
    WORD32 i4_x_ref, i4_y_ref;
    WORD32 i4_ref_mb_type_q0, i4_ref_mb_type_q1, i4_ref_mb_type_q2, i4_ref_mb_type_q3;
    WORD8 i1_mb_mode_q0, i1_mb_mode_q1, i1_mb_mode_q2, i1_mb_mode_q3;
    WORD32 ret;

    ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;
    ps_lyr_ctxt = &ps_ctxt->as_res_lyrs[ps_ctxt->i4_res_lyr_id];
    pi2_ref_array = ps_ctxt->pi2_refarray_buffer;

    pi1_ref_mb_modes = (WORD8 *) ps_ref_mb_mode->pv_buffer;
    i4_ref_mode_stride = ps_ref_mb_mode->i4_num_element_stride;
    i4_element_size = ps_ref_mb_mode->i4_element_size;

    if(NULL == pi1_ref_mb_modes)
    {
        return NOT_OK;
    }

    i4_mb_wd = MB_WIDTH >> i4_chroma_flag;
    i4_mb_ht = MB_HEIGHT >> i4_chroma_flag;

    /* ----------------------------------------------------------------- */
    /* Deriving the parameters required for further processing           */
    /* ----------------------------------------------------------------- */
    {
        ref_mb_map_t *ps_x_off_len;
        ref_mb_map_t *ps_y_off_len;
        WORD32 i4_mbaddr_x;
        WORD32 i4_mbaddr_y;
        WORD32 i4_base_width;
        WORD32 i4_base_height;
        residual_samp_map_ctxt_t *ps_map_ctxt;

        if(1 == i4_chroma_flag)
            ps_map_ctxt = &ps_lyr_ctxt->s_chroma_map_ctxt;
        else
            ps_map_ctxt = &ps_lyr_ctxt->s_luma_map_ctxt;

        i4_mbaddr_y = ps_coord->u2_mb_y;
        i4_mbaddr_x = ps_coord->u2_mb_x;
        i4_base_width = ps_lyr_ctxt->i4_ref_width;
        i4_base_height = ps_lyr_ctxt->i4_ref_height;
        i4_ref_wd = i4_base_width >> i4_chroma_flag;
        i4_ref_ht = i4_base_height >> i4_chroma_flag;

        /* --------------------------------------------------------------------- */
        /* Extracting information from the mapping context                       */
        /* --------------------------------------------------------------------- */
        ps_x_off_len = ps_map_ctxt->ps_x_offset_length;
        ps_y_off_len = ps_map_ctxt->ps_y_offset_length;
        i4_x_offset = ps_x_off_len[i4_mbaddr_x].i2_offset;
        i4_y_offset = ps_y_off_len[i4_mbaddr_y].i2_offset;
        i4_refarray_wd = ps_x_off_len[i4_mbaddr_x].i2_length;
        i4_refarray_ht = ps_y_off_len[i4_mbaddr_y].i2_length;
    }

    /* Call the module to fill the increments based on transform blocks */
    ret = isvcd_ref_layer_ptr_incr(pi1_ref_mb_modes, i4_ref_mode_stride, i4_element_size,
                                   i4_x_offset, i4_y_offset, i4_refarray_wd, i4_refarray_ht,
                                   ps_ctxt->pu1_ref_x_ptr_incr, ps_ctxt->pu1_ref_y_ptr_incr,
                                   i4_chroma_flag);

    if(ret != OK)
    {
        return ret;
    }
    i4_mb_sft = (MB_WIDTH_SHIFT - i4_chroma_flag);

    /* --------------------------------------------------------------------- */
    /* MB Level Resampling for the MB - Pointers sent for MB in both layers  */
    /* This has been written according to the dyadic case                    */
    /* --------------------------------------------------------------------- */
    i4_y_ref = MAX(0, MIN(i4_ref_ht - 1, 0 + i4_y_offset));
    i4_x_ref = MAX(0, MIN(i4_ref_wd - 1, 0 + i4_x_offset));
    i4_mb_x_strt = i4_x_ref % i4_mb_wd;
    i4_mb_y_strt = i4_y_ref % i4_mb_ht;

    i4_mb_quard1_part_x = i4_mb_wd - i4_mb_x_strt;
    i4_mb_quard1_part_y = i4_mb_ht - i4_mb_y_strt;
    if(!(i4_mb_quard1_part_x >= 0))
    {
        return NOT_OK;
    }
    if(!(i4_mb_quard1_part_y >= 0))
    {
        return NOT_OK;
    }

    i4_mb_x = (i4_x_ref >> i4_mb_sft);
    i4_mb_y = (i4_y_ref >> i4_mb_sft);

    /* get the location of the byte which has the current mb mode */
    pi1_ref_mb_modes_incr = pi1_ref_mb_modes + (i4_mb_y * i4_ref_mode_stride * i4_element_size);
    pi1_ref_mb_modes_incr += (i4_mb_x * i4_element_size);
    ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr;
    i1_mb_mode_q0 = ps_inter_lyr_mb_prms->i1_mb_mode;
    i1_mb_mode_q1 = i1_mb_mode_q0;
    i1_mb_mode_q2 = i1_mb_mode_q0;
    i1_mb_mode_q3 = i1_mb_mode_q0;

    pi1_ref_mb_modes_incr_temp = pi1_ref_mb_modes_incr;
    if(i4_mb_quard1_part_x > 0)
    {
        pi1_ref_mb_modes_incr_temp = pi1_ref_mb_modes_incr + i4_element_size;
        ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr_temp;
        i1_mb_mode_q1 = ps_inter_lyr_mb_prms->i1_mb_mode;
    }

    if(i4_mb_quard1_part_y > 0)
    {
        pi1_ref_mb_modes_incr_temp = pi1_ref_mb_modes_incr + (i4_ref_mode_stride * i4_element_size);
        ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr_temp;
        i1_mb_mode_q2 = ps_inter_lyr_mb_prms->i1_mb_mode;
    }

    if((i4_mb_quard1_part_x > 0) && (i4_mb_quard1_part_y > 0))
    {
        pi1_ref_mb_modes_incr_temp =
            pi1_ref_mb_modes_incr + (i4_ref_mode_stride * i4_element_size) + i4_element_size;
        ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) pi1_ref_mb_modes_incr_temp;
        i1_mb_mode_q3 = ps_inter_lyr_mb_prms->i1_mb_mode;
    }

    i4_ref_mb_type_q0 = (i1_mb_mode_q0 <= SVC_INTER_MB) ? SVC_INTER_MB : SVC_INTRA_MB;
    i4_ref_mb_type_q1 = (i1_mb_mode_q1 <= SVC_INTER_MB) ? SVC_INTER_MB : SVC_INTRA_MB;
    i4_ref_mb_type_q2 = (i1_mb_mode_q2 <= SVC_INTER_MB) ? SVC_INTER_MB : SVC_INTRA_MB;
    i4_ref_mb_type_q3 = (i1_mb_mode_q3 <= SVC_INTER_MB) ? SVC_INTER_MB : SVC_INTRA_MB;

    i1_edge_mb = (ps_coord->u2_mb_x == 0 || ps_coord->u2_mb_y == 0 ||
                  (ps_coord->u2_mb_x == ((ps_lyr_ctxt->i4_curr_width >> MB_WIDTH_SHIFT) - 1)) ||
                  (ps_coord->u2_mb_y == ((ps_lyr_ctxt->i4_curr_height >> MB_HEIGHT_SHIFT) - 1)));
    if(i1_edge_mb)
    {
        ps_ctxt->pf_residual_reflayer_const_boundary_mb(
            pi2_inp_data, i4_inp_data_stride, pi2_ref_array, i4_refarray_wd, i4_refarray_ht,
            i4_ref_wd, i4_ref_ht, i4_x_offset, i4_y_offset, i4_ref_mb_type_q0, i4_ref_mb_type_q1,
            i4_ref_mb_type_q2, i4_ref_mb_type_q3, i4_mb_quard1_part_x, i4_mb_quard1_part_y,
            i4_chroma_flag);
    }
    else
    {
        ps_ctxt->pf_residual_reflayer_const_non_boundary_mb(
            pi2_inp_data, i4_inp_data_stride, pi2_ref_array, i4_refarray_wd, i4_refarray_ht,
            i4_ref_mb_type_q0, i4_ref_mb_type_q1, i4_ref_mb_type_q2, i4_ref_mb_type_q3,
            i4_mb_quard1_part_x, i4_mb_quard1_part_y, i4_chroma_flag);
    }
    /* store the values into the place holders */
    *pi4_refarr_wd = i4_refarray_wd;

    return OK;
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_interpolate_residual                                */
/*                                                                           */
/*  Description   : This function takes the refernce array buffer and perform*/
/*                    interpolation of a component to find the residual      */
/*                     resampled value                                       */
/*  Inputs        : pv_residual_samp_ctxt : residual sampling context        */
/*                  pi2_out : output buffer pointer                          */
/*                  i4_out_stride : output buffer stride                     */
/*                  i4_refarray_wd : reference array width                   */
/*                  i4_x_offset : offset in reference layer in horz direction*/
/*                  ps_coord : current mb co-ordinate                        */
/*                  i4_chroma_flag : chroma processing flag                  */
/*  Globals       : none                                                     */
/*  Processing    : it does the interpolation in vertical direction followed */
/*                  by horizontal direction                                  */
/*  Outputs       : resampled pixels                                         */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 07 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
void isvcd_interpolate_residual(void *pv_residual_samp_ctxt, WORD16 *pi2_out, WORD32 i4_out_stride,
                                WORD32 i4_refarray_wd, UWORD16 u2_mb_x, UWORD16 u2_mb_y,
                                WORD32 i4_chroma_flag)
{
    residual_sampling_ctxt_t *ps_ctxt;
    residual_samp_map_ctxt_t *ps_map_ctxt;
    res_lyr_ctxt *ps_lyr_ctxt;
    ref_pixel_map_t *ps_x_pos_phase;
    ref_pixel_map_t *ps_y_pos_phase;

    WORD32 i4_x, i4_y;
    WORD32 i4_frm_mb_x, i4_frm_mb_y;
    WORD32 i4_temp_array_ht;
    WORD32 i4_mb_wd;
    WORD32 i4_mb_ht;
    WORD16 *pi2_ref_array;
    UWORD8 *pu1_ref_x_ptr_incr, *pu1_ref_y_ptr_incr;

    ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;
    ps_lyr_ctxt = &ps_ctxt->as_res_lyrs[ps_ctxt->i4_res_lyr_id];
    pi2_ref_array = ps_ctxt->pi2_refarray_buffer;
    pu1_ref_x_ptr_incr = ps_ctxt->pu1_ref_x_ptr_incr;
    pu1_ref_y_ptr_incr = ps_ctxt->pu1_ref_y_ptr_incr;

    /* --------------------------------------------------------------------- */
    /* Extracting information from the mapping context                       */
    /* --------------------------------------------------------------------- */
    if(1 == i4_chroma_flag)
        ps_map_ctxt = &ps_lyr_ctxt->s_chroma_map_ctxt;
    else
        ps_map_ctxt = &ps_lyr_ctxt->s_luma_map_ctxt;

    i4_mb_wd = MB_WIDTH >> i4_chroma_flag;
    i4_mb_ht = MB_HEIGHT >> i4_chroma_flag;

    ps_x_pos_phase = ps_map_ctxt->ps_x_pos_phase;
    ps_y_pos_phase = ps_map_ctxt->ps_y_pos_phase;
    i4_temp_array_ht = i4_mb_ht;
    i4_frm_mb_y = u2_mb_y * i4_mb_ht;
    i4_frm_mb_x = u2_mb_x * i4_mb_wd;

    /* --------------------------------------------------------------------- */
    /* Loop for interpolation                                                */
    /* --------------------------------------------------------------------- */
    for(i4_y = 0; i4_y < (i4_temp_array_ht); i4_y++)
    {
        for(i4_x = 0; i4_x < (i4_mb_wd); i4_x++)
        {
            WORD32 i4_i;
            WORD32 i4_y_ref;
            WORD32 i4_y_phase;
            WORD32 i4_x_ref;
            WORD32 i4_x_phase;
            WORD32 i4_x_ref_round;
            WORD16 *pi2_out_curr;
            WORD32 ai4_temp_pred[2] = {0};
            UWORD8 *pu1_ref_y_ptr_incr_temp;
            WORD32 *pi4_temp_pred;
            UWORD8 u1_incr_y;
            WORD16 i2_res;

            /* derive the current output pointer */
            pi2_out_curr = pi2_out + (i4_x << i4_chroma_flag) + (i4_y * i4_out_stride);

            /* -------------------------------------------------------------- */
            /* Finding the offset                                             */
            /* -------------------------------------------------------------- */
            i4_y_ref = ps_y_pos_phase[i4_y + i4_frm_mb_y].i2_ref_pos;
            i4_y_phase = ps_y_pos_phase[i4_y + i4_frm_mb_y].i2_phase;
            i4_x_ref = ps_x_pos_phase[i4_x + i4_frm_mb_x].i2_ref_pos;
            i4_x_phase = ps_x_pos_phase[i4_x + i4_frm_mb_x].i2_phase;

            /* horizontal processing*/
            for(i4_i = 0; i4_i < 2; i4_i++)
            {
                UWORD8 *pu1_ref_x_ptr_incr_temp;
                UWORD8 u1_incr;
                WORD16 *pi2_ref_array_1, *pi2_ref_array_2;

                /* derive appropriate pointers */
                pu1_ref_x_ptr_incr_temp = pu1_ref_x_ptr_incr + i4_x_ref;
                pu1_ref_x_ptr_incr_temp += ((i4_y_ref + i4_i) * i4_refarray_wd);
                u1_incr = *pu1_ref_x_ptr_incr_temp;
                pi2_ref_array_1 = pi2_ref_array + i4_x_ref;
                pi2_ref_array_1 += ((i4_y_ref + i4_i) * i4_refarray_wd);

                if(!u1_incr)
                {
                    pi2_ref_array_1 += (i4_x_phase >> 3);
                }

                pi2_ref_array_2 = pi2_ref_array_1 + u1_incr;
                ai4_temp_pred[i4_i] =
                    (16 - i4_x_phase) * (*pi2_ref_array_1) + i4_x_phase * (*pi2_ref_array_2);
            }

            /* vertical processing */
            i4_x_ref_round = (i4_x_ref + (i4_x_phase >> 3));
            pu1_ref_y_ptr_incr_temp =
                pu1_ref_y_ptr_incr + i4_x_ref_round + (i4_y_ref * i4_refarray_wd);
            u1_incr_y = *pu1_ref_y_ptr_incr_temp;

            pi4_temp_pred = &ai4_temp_pred[0];
            if(!u1_incr_y)
            {
                pi4_temp_pred += (i4_y_phase >> 3);
            }

            i2_res = (((16 - i4_y_phase) * pi4_temp_pred[0] +
                       i4_y_phase * pi4_temp_pred[u1_incr_y] + 128) >>
                      8);

            /* store back the final residual */
            *pi2_out_curr = i2_res;
        } /* end of loop over width */
    }     /* end of loop over height */

    return;
} /* End of Interpolation Function */
/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_samp_mb                                    */
/*                                                                           */
/*  Description   : MB level function whcih perform the residual resampling  */
/*                  of data of an MB (luma and chroma insclusive)            */
/*                                                                           */
/*  Inputs        : pv_residual_samp_ctxt : residual sampling context        */
/*                  ps_ref_luma : reference layer luma data buffer desc      */
/*                  ps_ref_chroma : reference layer chroma data buffer desc  */
/*                  ps_ref_luma_bitmap : ref layer luma bit map buffer desc  */
/*                  ps_ref_chroma_bitmap : ref layer chroma bit map buff des */
/*                  ps_ref_mb_mode : ref layer mb mode map buff desc         */
/*                  ps_out_luma : current layer out luma buffer desc         */
/*                  ps_out_chroma : current layer out chroma buffer desc     */
/*                  ps_mb_coord : current mb coorinate                       */
/*  Globals       : none                                                     */
/*  Processing    : it calls the reference layer construction followed by    */
/*                   interplaotion function for luma and cb and cr           */
/*  Outputs       : inter resampled data of current MB                       */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         26 06 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_residual_samp_mb(void *pv_residual_samp_ctxt, mem_element_t *ps_ref_luma,
                              mem_element_t *ps_ref_chroma, mem_element_t *ps_ref_mb_mode,
                              mem_element_t *ps_out_luma, mem_element_t *ps_out_chroma,
                              UWORD16 u2_mb_x, UWORD16 u2_mb_y)
{
    /* --------------------------------------------------------------------- */
    /* I/O buffer params                                                     */
    /* --------------------------------------------------------------------- */
    residual_sampling_ctxt_t *ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;
    WORD16 *pi2_inp;
    WORD16 *pi2_out;
    WORD32 i4_inp_stride;
    WORD32 i4_out_stride;
    WORD32 i4_refarray_wd;
    mb_coord_t s_mb_coord = {0};
    WORD32 ret;
    s_mb_coord.u2_mb_x = u2_mb_x;
    s_mb_coord.u2_mb_y = u2_mb_y;

    /* --------------------------------------------------------------------- */
    /* LUMA PROCESSING                                                        */
    /* --------------------------------------------------------------------- */
    pi2_inp = (WORD16 *) ps_ref_luma->pv_buffer;
    pi2_out = (WORD16 *) ps_out_luma->pv_buffer;
    i4_inp_stride = ps_ref_luma->i4_num_element_stride;
    i4_out_stride = ps_out_luma->i4_num_element_stride;

    /* ------- Constructing refSampleArray ----------------------- */
    ret = isvcd_residual_reflayer_const(pv_residual_samp_ctxt, pi2_inp, i4_inp_stride,
                                        ps_ref_mb_mode, &i4_refarray_wd, &s_mb_coord, 0);

    if(ret != OK) return ret;
    /* ---- Interpolation process for Residual prediction     ------ */
    ps_ctxt->pf_interpolate_residual(pv_residual_samp_ctxt, pi2_out, i4_out_stride, i4_refarray_wd,
                                     s_mb_coord.u2_mb_x, s_mb_coord.u2_mb_y, 0);

    /* --------------------------------------------------------------------- */
    /* CHROMA PROCESSING                                                       */
    /* --------------------------------------------------------------------- */
    /* CB */
    pi2_inp = (WORD16 *) ps_ref_chroma->pv_buffer;
    pi2_out = (WORD16 *) ps_out_chroma->pv_buffer;
    i4_inp_stride = ps_ref_chroma->i4_num_element_stride;
    i4_out_stride = ps_out_chroma->i4_num_element_stride;

    /* ------- Constructing refSampleArray ----------------------- */
    ret = isvcd_residual_reflayer_const(pv_residual_samp_ctxt, pi2_inp, i4_inp_stride,
                                        ps_ref_mb_mode, &i4_refarray_wd, &s_mb_coord, 1);

    if(ret != OK) return ret;
    /* ---- Interpolation process for Residual prediction     ------ */
    ps_ctxt->pf_interpolate_residual(pv_residual_samp_ctxt, pi2_out, i4_out_stride, i4_refarray_wd,
                                     s_mb_coord.u2_mb_x, s_mb_coord.u2_mb_y, 1);

    /* CR */
    pi2_inp += 1;
    pi2_out += 1;

    /* ------- Constructing refSampleArray ----------------------- */
    ret = isvcd_residual_reflayer_const(pv_residual_samp_ctxt, pi2_inp, i4_inp_stride,
                                        ps_ref_mb_mode, &i4_refarray_wd, &s_mb_coord, 1);

    if(ret != OK) return ret;
    /* ---- Interpolation process for Residual prediction --------- */
    ps_ctxt->pf_interpolate_residual(pv_residual_samp_ctxt, pi2_out, i4_out_stride, i4_refarray_wd,
                                     s_mb_coord.u2_mb_x, s_mb_coord.u2_mb_y, 1);
    return OK;
}
/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_samp_mb_dyadic                             */
/*                                                                           */
/*  Description   : MB level function whcih perform the residual resampling  */
/*                  of data of an MB (luma and chroma insclusive)            */
/*                  for Dyadic cases                                         */
/*  Inputs        : pv_residual_samp_ctxt : residual sampling context        */
/*                  ps_ref_luma : reference layer luma data buffer desc      */
/*                  ps_ref_chroma : reference layer chroma data buffer desc  */
/*                  ps_ref_luma_bitmap : ref layer luma bit map buffer desc  */
/*                  ps_ref_chroma_bitmap : ref layer chroma bit map buff des */
/*                  ps_ref_mb_mode : ref layer mb mode map buff desc         */
/*                  ps_out_luma : current layer out luma buffer desc         */
/*                  ps_out_chroma : current layer out chroma buffer desc     */
/*                  ps_mb_coord : current mb coorinate                       */
/*  Globals       : none                                                     */
/*  Processing    : it calls the reference layer construction followed by    */
/*                   interplaotion function for luma and cb and cr           */
/*  Outputs       : inter resampled data of current MB                       */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         26 06 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_residual_samp_mb_dyadic(void *pv_residual_samp_ctxt, mem_element_t *ps_ref_luma,
                                     mem_element_t *ps_ref_chroma, mem_element_t *ps_ref_mb_mode,
                                     mem_element_t *ps_out_luma, mem_element_t *ps_out_chroma,
                                     UWORD16 u2_mb_x, UWORD16 u2_mb_y)
{
    residual_sampling_ctxt_t *ps_ctxt;
    res_lyr_ctxt *ps_lyr_ctxt;
    /* --------------------------------------------------------------------- */
    /* I/O buffer params                                                     */
    /* --------------------------------------------------------------------- */
    WORD16 *pi2_inp;
    WORD16 *pi2_out;
    WORD32 i4_inp_stride;
    WORD32 i4_out_stride;
    WORD32 i4_luma_nnz;
    WORD32 i4_chroma_nnz;
    WORD32 i4_tx_size;

    ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;
    ps_lyr_ctxt = &ps_ctxt->as_res_lyrs[ps_ctxt->i4_res_lyr_id];

    /* --------------------------------------------------------------------- */
    /* LUMA PROCESSING                                                        */
    /* --------------------------------------------------------------------- */
    pi2_inp = (WORD16 *) ps_ref_luma->pv_buffer;
    pi2_out = (WORD16 *) ps_out_luma->pv_buffer;
    i4_inp_stride = ps_ref_luma->i4_num_element_stride;
    i4_out_stride = ps_out_luma->i4_num_element_stride;

    {
        WORD32 i4_offset_x, i4_offset_y;
        residual_samp_map_ctxt_t *ps_luma_map;
        ref_mb_map_t *ps_x_off_len_luma;
        ref_mb_map_t *ps_y_off_len_luma;

        ps_luma_map = &ps_lyr_ctxt->s_luma_map_ctxt;
        ps_x_off_len_luma = ps_luma_map->ps_x_offset_length;
        ps_y_off_len_luma = ps_luma_map->ps_y_offset_length;

        /* get the actual offset for the buffers */
        i4_offset_x = ps_x_off_len_luma[u2_mb_x].i2_offset;
        i4_offset_y = ps_y_off_len_luma[u2_mb_y].i2_offset;

        {
            inter_lyr_mb_prms_t *ps_inter_lyr_mb_prms;
            WORD32 i4_mb_x, i4_mb_y;
            UWORD16 u2_luma_mask = 0x0033;
            UWORD8 u1_chrm_mask = 0x11;
            WORD32 i4_luma_rt_sft_amt = 0;
            WORD32 i4_chrm_rt_sft_amt = 0;

            i4_mb_x = ((i4_offset_x + 1) >> MB_WIDTH_SHIFT);
            i4_mb_y = ((i4_offset_y + 1) >> MB_HEIGHT_SHIFT);

            /* get the location of the byte which has the current mb mode */
            ps_inter_lyr_mb_prms = (inter_lyr_mb_prms_t *) ps_ref_mb_mode->pv_buffer;
            ps_inter_lyr_mb_prms += i4_mb_x;
            ps_inter_lyr_mb_prms += i4_mb_y * ps_ref_mb_mode->i4_num_element_stride;

            /* get the approp block in base layer in horz direction */
            if(0 != ((i4_offset_x + 1) & 15))
            {
                u2_luma_mask <<= 2;
                i4_luma_rt_sft_amt += 2;
                u1_chrm_mask <<= 1;
                i4_chrm_rt_sft_amt += 1;
            }
            /* get the approp block in base layer in vert direction */
            if(0 != ((i4_offset_y + 1) & 15))
            {
                u2_luma_mask <<= 8;
                i4_luma_rt_sft_amt += 8;

                u1_chrm_mask <<= 2;
                i4_chrm_rt_sft_amt += 2;
            }

            /* extract the nnz and store it */
            i4_luma_nnz = (ps_inter_lyr_mb_prms->u2_luma_nnz & u2_luma_mask) >> i4_luma_rt_sft_amt;
            i4_chroma_nnz =
                (ps_inter_lyr_mb_prms->u1_chroma_nnz & u1_chrm_mask) >> i4_chrm_rt_sft_amt;
            i4_tx_size =
                (ps_inter_lyr_mb_prms->i1_tx_size < 0) ? 1 : ps_inter_lyr_mb_prms->i1_tx_size;
        }

        /* since in dyadic case the window width and height will be 10x10   */
        /* and the window start offsets will be always 1 column left and    */
        /* 1 row above the block boundary. so the pointer and the required  */
        /* positions are appropriately modified                             */
        if(i4_offset_x >= 0)
        {
            pi2_inp++;
        }

        if(i4_offset_y >= 0)
        {
            pi2_inp += i4_inp_stride;
        }

        ps_ctxt->pf_residual_luma_dyadic(pv_residual_samp_ctxt, pi2_inp, i4_inp_stride, pi2_out,
                                         i4_out_stride, ps_ref_mb_mode, u2_mb_x, u2_mb_y,
                                         i4_luma_nnz, i4_tx_size);
    }

    /* --------------------------------------------------------------------- */
    /* CHROMA PROCESSING                                                       */
    /* --------------------------------------------------------------------- */
    /* CB */
    pi2_inp = (WORD16 *) ps_ref_chroma->pv_buffer;
    pi2_out = (WORD16 *) ps_out_chroma->pv_buffer;
    i4_inp_stride = ps_ref_chroma->i4_num_element_stride;
    i4_out_stride = ps_out_chroma->i4_num_element_stride;

    /* choose the appropriate chroma processing routine */
    if(SVCD_FALSE == ps_lyr_ctxt->i4_chrm_alt_proc)
    {
        WORD32 i4_offset_x, i4_offset_y;
        residual_samp_map_ctxt_t *ps_chroma_map;
        ref_mb_map_t *ps_x_off_len_chroma;
        ref_mb_map_t *ps_y_off_len_chroma;

        ps_chroma_map = &ps_lyr_ctxt->s_chroma_map_ctxt;
        ps_x_off_len_chroma = ps_chroma_map->ps_x_offset_length;
        ps_y_off_len_chroma = ps_chroma_map->ps_y_offset_length;

        /* get the actual offset for the buffers */
        i4_offset_x = ps_x_off_len_chroma[u2_mb_x].i2_offset;
        i4_offset_y = ps_y_off_len_chroma[u2_mb_y].i2_offset;

        /* since in dyadic case the window width and height will be 6x6     */
        /* and the window start offsets will be always 1 column left and    */
        /* 1 row above the block boundary. so the pointer and the required  */
        /* positions are appropriately modified                             */
        if(i4_offset_x >= 0)
        {
            pi2_inp += 2;
        }

        if(i4_offset_y >= 0)
        {
            pi2_inp += i4_inp_stride;
        }

        if(0 != (i4_chroma_nnz & 0x01))
        {
            ps_ctxt->pf_residual_chroma_dyadic(pv_residual_samp_ctxt, pi2_inp, i4_inp_stride,
                                               pi2_out, i4_out_stride);
        }
    }
    else
    {
        ps_ctxt->pf_residual_chroma_dyadic_alt(pv_residual_samp_ctxt, u2_mb_x, u2_mb_y,
                                               ps_ref_mb_mode, pi2_inp, i4_inp_stride, pi2_out,
                                               i4_out_stride, SVCD_FALSE);
    }

    /* CR */
    pi2_inp += 1;
    pi2_out += 1;

    if(SVCD_FALSE == ps_lyr_ctxt->i4_chrm_alt_proc)
    {
        if(0 != (i4_chroma_nnz & 0x10))
        {
            ps_ctxt->pf_residual_chroma_dyadic(pv_residual_samp_ctxt, pi2_inp, i4_inp_stride,
                                               pi2_out, i4_out_stride);
        }
    }
    else
    {
        ps_ctxt->pf_residual_chroma_dyadic_alt(pv_residual_samp_ctxt, u2_mb_x, u2_mb_y,
                                               ps_ref_mb_mode, pi2_inp, i4_inp_stride, pi2_out,
                                               i4_out_stride, SVCD_TRUE);
    }
    return OK;
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_samp_populate_list                         */
/*                                                                           */
/*  Description   : This is a seq or frame level init function which fills   */
/*                  all offsets, projected locations arrays based on         */
/*                  the two resolutions  and cropping parameters             */
/*  Inputs        : refer to doxygen comments below                          */
/*  Globals       : none                                                     */
/*  Processing    : it projects the locations and computes the values        */
/*                                                                           */
/*  Outputs       : none                                                     */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 07 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
void isvcd_residual_samp_populate_list(residual_samp_map_ctxt_t *ps_map_ctxt,
                                       dec_seq_params_t *ps_sps,
                                       dec_svc_seq_params_t *ps_subset_sps,
                                       res_prms_t *ps_curr_res_prms, res_prms_t *ps_ref_res_prms,
                                       WORD32 i4_chroma_flag)
{
    /* --------------------------------------------------------------------- */
    /* Local variables required for finding the mapping between the layers     */
    /* --------------------------------------------------------------------- */
    UWORD32 u4_shift_x;
    UWORD32 u4_shift_y;
    UWORD32 u4_scale_x;
    UWORD32 u4_scale_y;
    WORD32 i4_offset_x;
    WORD32 i4_offset_y;
    WORD32 i4_add_x;
    WORD32 i4_add_y;
    WORD32 i4_delta_x;
    WORD32 i4_delta_y;
    WORD32 i4_refphase_x;
    WORD32 i4_refphase_y;
    WORD32 i4_phase_x;
    WORD32 i4_phase_y;
    WORD32 i4_sub_wd;
    WORD32 i4_sub_ht;
    WORD32 i4_mb_wd;
    WORD32 i4_mb_ht;
    /* --------------------------------------------------------------------- */
    /* Local Pointer Declaration for arrays in Mapping context                 */
    /* --------------------------------------------------------------------- */
    ref_mb_map_t *ps_x_off_len;
    ref_mb_map_t *ps_y_off_len;
    UWORD32 i4_ref_wd;
    UWORD32 i4_ref_ht;
    UWORD32 i4_scaled_wd;
    UWORD32 i4_scaled_ht;
    WORD32 i4_curr_lyr_width;
    WORD32 i4_curr_lyr_height;

    /* --------------------------------------------------------------------- */
    /* Local Flag Declaration                                                 */
    /* --------------------------------------------------------------------- */
    WORD32 i4_ref_layer_field_pic_flag;
    WORD32 i4_field_pic_flag;
    WORD32 i4_frame_mbs_only_flag;
    WORD32 i4_ref_layer_frame_Mbs_only_flag;
    WORD32 i4_field_Mb_flag;
    WORD32 i4_bot_field_flag;

    /* --------------------------------------------------------------------- */
    /* Cropping Parameters Declaration                                         */
    /* --------------------------------------------------------------------- */
    WORD32 i4_scaled_ref_layer_left_offset;
    WORD32 i4_scaled_ref_layer_top_offset;

    /* --------------------------------------------------------------------- */
    /* Hardcoding flag information    (assuming no field support) */
    /* --------------------------------------------------------------------- */
    i4_ref_layer_field_pic_flag = SVCD_FALSE;
    i4_field_pic_flag = SVCD_FALSE;
    i4_frame_mbs_only_flag = SVCD_TRUE;
    i4_field_Mb_flag = SVCD_FALSE;
    i4_bot_field_flag = SVCD_FALSE;
    i4_ref_layer_frame_Mbs_only_flag = SVCD_TRUE;

    /* --------------------------------------------------------------------- */
    /* Pointer and Paramater are intialized    - Chroma and Luma */
    /* --------------------------------------------------------------------- */
    {
        WORD32 i4_base_width;
        WORD32 i4_base_height;
        WORD32 i4_ref_layer_chroma_phase_x_plus1_flag;
        WORD32 i4_ref_layer_chroma_phase_y_plus1;
        WORD32 i4_chroma_phase_x_plus1_flag;
        WORD32 i4_chroma_phase_y_plus1;

        /* ------------------------------------------------------------- */
        /* HARD CODED FOR 420                                             */
        /* ------------------------------------------------------------- */
        WORD32 i4_sub_wd_chroma = 2;
        WORD32 i4_sub_ht_chroma = 2;

        i4_base_width = ps_ref_res_prms->i4_res_width;
        i4_base_height = ps_ref_res_prms->i4_res_height;

        i4_ref_layer_chroma_phase_x_plus1_flag =
            ps_curr_res_prms->i1_ref_lyr_chroma_phase_x_plus1_flag;
        i4_ref_layer_chroma_phase_y_plus1 = ps_curr_res_prms->i1_ref_lyr_chroma_phase_y_plus1;
        i4_chroma_phase_x_plus1_flag =
            ps_subset_sps->s_sps_svc_ext.u1_seq_ref_layer_chroma_phase_x_plus1_flag;
        i4_chroma_phase_y_plus1 =
            ps_subset_sps->s_sps_svc_ext.u1_seq_ref_layer_chroma_phase_y_plus1;
        i4_scaled_ref_layer_left_offset = ps_curr_res_prms->s_ref_lyr_scaled_offset.i2_left;
        i4_scaled_ref_layer_top_offset = ps_curr_res_prms->s_ref_lyr_scaled_offset.i2_top;

        /* ----------------------------------------------------------------- */
        /* Computing Effective Frame Dimensions                                 */
        /* ------------------------------------------------------------------*/
        i4_ref_wd = (i4_base_width >> i4_chroma_flag);
        i4_ref_ht = (i4_base_height >> i4_chroma_flag) * (1 + i4_ref_layer_field_pic_flag);
        i4_scaled_wd = ps_curr_res_prms->u2_scaled_ref_width;
        i4_scaled_ht = ps_curr_res_prms->u2_scaled_ref_height;
        i4_scaled_wd = (i4_scaled_wd >> i4_chroma_flag);
        i4_scaled_ht = (i4_scaled_ht >> i4_chroma_flag) * (1 + i4_field_pic_flag);

        if(1 == i4_chroma_flag)
        {
            i4_refphase_x = i4_ref_layer_chroma_phase_x_plus1_flag - 1;
            i4_refphase_y = i4_ref_layer_chroma_phase_y_plus1 - 1;
            i4_phase_x = i4_chroma_phase_x_plus1_flag - 1;
            i4_phase_y = i4_chroma_phase_y_plus1 - 1;
            i4_sub_wd = i4_sub_wd_chroma;
            i4_sub_ht = i4_sub_ht_chroma;
            i4_mb_wd = MB_WIDTH >> 1;
            i4_mb_ht = MB_HEIGHT >> 1;
        }
        else
        {
            i4_refphase_x = 0;
            i4_refphase_y = 0;
            i4_phase_x = 0;
            i4_phase_y = 0;
            i4_sub_wd = 1;
            i4_sub_ht = 1;
            i4_mb_wd = MB_WIDTH;
            i4_mb_ht = MB_HEIGHT;
        }
    }

    /* --------------------------------------------------------------------- */
    /* Derive shift x and y based on level idd                               */
    /* --------------------------------------------------------------------- */
    if(ps_sps->u1_level_idc <= 30)
    {
        u4_shift_x = 16;
        u4_shift_y = 16;
    }
    else
    {
        u4_shift_x = 31 - isvcd_get_ceil_log2(i4_ref_wd);
        u4_shift_y = 31 - isvcd_get_ceil_log2(i4_ref_ht);
    }

    /* --------------------------------------------------------------------- */
    /* The following condition is not true in our case for time being         */
    /* --------------------------------------------------------------------- */
    if((SVCD_FALSE == i4_frame_mbs_only_flag) || (SVCD_FALSE == i4_ref_layer_frame_Mbs_only_flag))
    {
        i4_phase_y = i4_phase_y + 4 * i4_bot_field_flag;

        if(1 == i4_ref_layer_frame_Mbs_only_flag)
            i4_refphase_y = (2 * i4_refphase_y) + 2;
        else
            i4_refphase_y = i4_refphase_y + (4 * i4_bot_field_flag);
    }

    /* --------------------------------------------------------------------- */
    /* Dx and Dy Computation - Ratio of the base and enhance layer width     */
    /* --------------------------------------------------------------------- */
    u4_scale_x = ((i4_ref_wd << u4_shift_x) + (i4_scaled_wd >> 1)) / (i4_scaled_wd);

    u4_scale_y = ((i4_ref_ht << u4_shift_y) + (i4_scaled_ht >> 1)) / (i4_scaled_ht);

    i4_offset_x = i4_scaled_ref_layer_left_offset / i4_sub_wd;
    i4_add_x = (((i4_ref_wd * (2 + i4_phase_x)) << (u4_shift_x - 2)) + (i4_scaled_wd >> 1)) /
                   i4_scaled_wd +
               (1 << (u4_shift_x - 5));
    i4_delta_x = 4 * (2 + i4_refphase_x);

    if((SVCD_TRUE == i4_frame_mbs_only_flag) && (SVCD_TRUE == i4_ref_layer_frame_Mbs_only_flag))
    {
        i4_offset_y = i4_scaled_ref_layer_top_offset / i4_sub_ht;
        i4_add_y = (((i4_ref_ht * (2 + i4_phase_y)) << (u4_shift_y - 2)) + (i4_scaled_ht >> 1)) /
                       i4_scaled_ht +
                   (1 << (u4_shift_y - 5));
        i4_delta_y = 4 * (2 + i4_refphase_y);
    }
    else
    {
        i4_offset_y = i4_scaled_ref_layer_top_offset / (2 * i4_sub_ht);
        i4_add_y = (((i4_ref_ht * (2 + i4_phase_y)) << (u4_shift_y - 3)) + (i4_scaled_ht >> 1)) /
                       i4_scaled_ht +
                   (1 << (u4_shift_y - 5));
        i4_delta_y = 2 * (2 + i4_refphase_y);
    }

    /* --------------------------------------------------------------------- */
    /* Intializing Local Pointers    - Chroma and Luma                       */
    /* --------------------------------------------------------------------- */
    ps_x_off_len = ps_map_ctxt->ps_x_offset_length;
    ps_y_off_len = ps_map_ctxt->ps_y_offset_length;
    i4_curr_lyr_width = ps_curr_res_prms->i4_res_width >> i4_chroma_flag;
    i4_curr_lyr_height = ps_curr_res_prms->i4_res_height >> i4_chroma_flag;

    {
        WORD32 i4_i, i4_j;

        /* ----------------------------------------------------------------- */
        /* Computation of offsetX refArrayW Xmin and Xmax Lists               */
        /* ----------------------------------------------------------------- */
        for(i4_i = 0; i4_i < i4_curr_lyr_width; i4_i = i4_i + i4_mb_wd)
        {
            WORD32 i4_x_refmin16;
            WORD32 i4_x_refmax16;
            WORD32 i4_x_offset;

            i4_x_refmin16 = (WORD64) (((WORD64) ((i4_i - i4_offset_x) * u4_scale_x) + i4_add_x) >>
                                      ((WORD32) (u4_shift_x - 4))) -
                            i4_delta_x;

            i4_x_refmax16 =
                (WORD64) (((WORD64) (i4_i + i4_mb_wd - 1 - i4_offset_x) * u4_scale_x + i4_add_x) >>
                          ((WORD32) (u4_shift_x - 4))) -
                i4_delta_x;

            /* AC205 */
            i4_x_offset = i4_x_refmin16 >> 4;
            ps_x_off_len->i2_offset = i4_x_offset;
            ps_x_off_len->i2_length = (i4_x_refmax16 >> 4) - i4_x_offset + 2;

            /* increment the pointer */
            ps_x_off_len++;

        } /* end of loop over current layer width */

        /* ----------------------------------------------------------------- */
        /* Computation of offsetY refArrayH Ymin and Ymax Lists              */
        /* ----------------------------------------------------------------- */
        for(i4_j = 0; i4_j < i4_curr_lyr_height; i4_j = i4_j + i4_mb_ht)
        {
            WORD32 i4_y_refmin16;
            WORD32 i4_y_refmax16;
            WORD32 i4_y_offset;

            i4_y_refmin16 = (WORD64) (((WORD64) (i4_j - i4_offset_y) * u4_scale_y + i4_add_y) >>
                                      ((WORD32) (u4_shift_y - 4))) -
                            i4_delta_y;

            i4_y_refmax16 =
                (WORD64) (((WORD64) (i4_j + i4_mb_ht - 1 - i4_offset_y) * u4_scale_y + i4_add_y) >>
                          ((WORD32) (u4_shift_y - 4))) -
                i4_delta_y;

            /* AC205 */
            i4_y_offset = i4_y_refmin16 >> 4;
            ps_y_off_len->i2_offset = i4_y_offset;
            ps_y_off_len->i2_length = (i4_y_refmax16 >> 4) - i4_y_offset + 2;

            /* increment the pointer */
            ps_y_off_len++;

        } /* end of loop over current layer height */
    }

    /* --------------------------------------------------------------------- */
    /* Computation of Xref and Xphase List as per standard                     */
    /* --------------------------------------------------------------------- */
    ps_x_off_len = ps_map_ctxt->ps_x_offset_length;
    ps_y_off_len = ps_map_ctxt->ps_y_offset_length;

    {
        WORD32 i4_xc;
        WORD32 i4_offset_x_index;
        ref_pixel_map_t *ps_x_pos_phase;

        ps_x_pos_phase = ps_map_ctxt->ps_x_pos_phase;

        for(i4_xc = 0; i4_xc < i4_curr_lyr_width; i4_xc++)
        {
            WORD32 i4_x_offset;
            WORD32 i4_x_ref16;

            i4_offset_x_index = i4_xc / i4_mb_wd;
            i4_x_offset = ps_x_off_len[i4_offset_x_index].i2_offset;
            i4_x_ref16 = (WORD64) (((WORD64) (i4_xc - i4_offset_x) * u4_scale_x + i4_add_x) >>
                                   ((WORD32) (u4_shift_x - 4))) -
                         i4_delta_x;

            /* store the values */
            ps_x_pos_phase->i2_ref_pos = (i4_x_ref16 >> 4) - i4_x_offset;
            ps_x_pos_phase->i2_phase = (i4_x_ref16 - (16 * i4_x_offset)) & 15;

            /* increment the pointer */
            ps_x_pos_phase++;
        } /* end of loop over scaled width */
    }

    /* --------------------------------------------------------------------- */
    /* Computation of Yref and Yphase List as per standard                     */
    /* --------------------------------------------------------------------- */
    {
        WORD32 i4_yc;
        WORD32 i4_offset_y_index;
        ref_pixel_map_t *ps_y_pos_phase;

        ps_y_pos_phase = ps_map_ctxt->ps_y_pos_phase;

        for(i4_yc = 0; i4_yc < i4_curr_lyr_height; i4_yc++)
        {
            WORD32 i4_y_offset;
            WORD32 i4_y_ref16;

            i4_offset_y_index = i4_yc / i4_mb_ht;
            i4_y_offset = ps_y_off_len[i4_offset_y_index].i2_offset;

            if((SVCD_FALSE == i4_frame_mbs_only_flag) ||
               (SVCD_FALSE == i4_ref_layer_frame_Mbs_only_flag))
            {
                i4_yc = i4_yc >> (1 - i4_field_Mb_flag);
            }

            i4_y_ref16 = (WORD64) ((((WORD64) (i4_yc - i4_offset_y) * u4_scale_y + i4_add_y) >>
                                    ((WORD32) (u4_shift_y - 4))) -
                                   i4_delta_y);
            ps_y_pos_phase->i2_ref_pos = (i4_y_ref16 >> 4) - i4_y_offset;
            ps_y_pos_phase->i2_phase = (i4_y_ref16 - (16 * i4_y_offset)) & 15;

            /* increment the pointer */
            ps_y_pos_phase++;
        } /* end of loop over scaled height */
    }
    return;
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_residual_samp_res_init                              */
/*                                                                           */
/*  Description   : this function calculates the scale factors and initialise*/
/*                  the context structure                                    */
/*                                                                           */
/*  Inputs        : pv_residual_samp_ctxt: handle to private structure       */
/*                  ps_curr_lyr_res_prms: pointer to current resolution      */
/*                                               params                      */
/*  Globals       : none                                                     */
/*  Processing    : it stores the layer dimensions                           */
/*                                                                           */
/*  Outputs       : none                                                     */
/*  Returns       : none                                                     */
/*                                                                           */
/*  Issues        : none                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         26 06 2021   vijayakumar          creation                        */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_residual_samp_res_init(void *pv_svc_dec)
{
    residual_sampling_ctxt_t *ps_ctxt;
    res_lyr_ctxt *ps_lyr_ctxt;
    dec_seq_params_t *ps_sps;
    dec_svc_seq_params_t *ps_subset_sps;
    svc_dec_lyr_struct_t *ps_svc_lyr_dec = (svc_dec_lyr_struct_t *) pv_svc_dec;
    dec_struct_t *ps_dec = &ps_svc_lyr_dec->s_dec;

    void *pv_residual_samp_ctxt = ps_svc_lyr_dec->pv_residual_sample_ctxt;
    res_prms_t *ps_curr_lyr_res_prms = &ps_svc_lyr_dec->s_res_prms;
    ref_mb_map_t **pps_luma_map_horz = &ps_svc_lyr_dec->ps_ressam_luma_map_horz;
    ref_mb_map_t **pps_chroma_map_horz = &ps_svc_lyr_dec->ps_ressam_chroma_map_horz;
    ref_mb_map_t **pps_luma_map_vert = &ps_svc_lyr_dec->ps_ressam_luma_map_vert;
    ref_mb_map_t **pps_chroma_map_vert = &ps_svc_lyr_dec->ps_ressam_chroma_map_vert;

    if((NULL == pv_residual_samp_ctxt) || (NULL == ps_curr_lyr_res_prms) ||
       (NULL == pps_luma_map_horz) || (NULL == pps_chroma_map_horz) ||
       (NULL == pps_luma_map_vert) || (NULL == pps_chroma_map_vert))
    {
        return NOT_OK;
    }

    ps_ctxt = (residual_sampling_ctxt_t *) pv_residual_samp_ctxt;

    /* if called for base resolution store deafult values */
    if(SVCD_TRUE == ps_svc_lyr_dec->u1_base_res_flag)
    {
        *pps_luma_map_horz = NULL;
        *pps_chroma_map_horz = NULL;
        *pps_luma_map_vert = NULL;
        *pps_chroma_map_vert = NULL;
        ps_ctxt->i4_res_lyr_id = -1;
        ps_ctxt->i4_ref_width = ps_curr_lyr_res_prms->i4_res_width;
        ps_ctxt->i4_ref_height = ps_curr_lyr_res_prms->i4_res_height;
        return OK;
    }

    /* derive the current sps */
    ps_sps = ps_dec->ps_cur_sps;
    ps_subset_sps = ps_svc_lyr_dec->ps_cur_subset_sps;

    /* store the res id appropriately */
    ps_ctxt->i4_res_lyr_id = ps_svc_lyr_dec->u1_layer_id - 1;

    /* get the current layer ctxt */
    ps_lyr_ctxt = &ps_ctxt->as_res_lyrs[ps_svc_lyr_dec->u1_layer_id - 1];

    /* get the width and heights */
    ps_lyr_ctxt->i4_curr_width = ps_curr_lyr_res_prms->i4_res_width;
    ps_lyr_ctxt->i4_curr_height = ps_curr_lyr_res_prms->i4_res_height;
    ps_lyr_ctxt->i4_ref_width = ps_ctxt->i4_ref_width;
    ps_lyr_ctxt->i4_ref_height = ps_ctxt->i4_ref_height;

    /* store the strcuture pointer containing projected locations */
    *pps_luma_map_horz = ps_lyr_ctxt->s_luma_map_ctxt.ps_x_offset_length;
    *pps_chroma_map_horz = ps_lyr_ctxt->s_chroma_map_ctxt.ps_x_offset_length;
    *pps_luma_map_vert = ps_lyr_ctxt->s_luma_map_ctxt.ps_y_offset_length;
    *pps_chroma_map_vert = ps_lyr_ctxt->s_chroma_map_ctxt.ps_y_offset_length;

    /* check for recomputation of mapping required */
    if(SVCD_TRUE == ps_curr_lyr_res_prms->u1_remap_req_flag)
    {
        res_prms_t s_ref_res_prms = {0};

        /* store the reference layer resolution width and height */
        s_ref_res_prms.i4_res_width = ps_ctxt->i4_ref_width;
        s_ref_res_prms.i4_res_height = ps_ctxt->i4_ref_height;

        /* call the frame level projections calculation function */
        isvcd_residual_samp_populate_list(&ps_lyr_ctxt->s_luma_map_ctxt, ps_sps, ps_subset_sps,
                                          ps_curr_lyr_res_prms, &s_ref_res_prms, 0);
        isvcd_residual_samp_populate_list(&ps_lyr_ctxt->s_chroma_map_ctxt, ps_sps, ps_subset_sps,
                                          ps_curr_lyr_res_prms, &s_ref_res_prms, 1);

        /* default values for flags */
        ps_lyr_ctxt->pf_residual_samp_mb = &isvcd_residual_samp_mb;
        ps_lyr_ctxt->i4_chrm_horz_int_mode = 0;
        ps_lyr_ctxt->i4_chrm_vert_int_mode = 0;
        ps_lyr_ctxt->i4_chrm_alt_proc = SVCD_FALSE;

        /* Store the Dyadic flag */
        ps_lyr_ctxt->i4_dyadic_flag = ps_curr_lyr_res_prms->u1_dyadic_flag;

        /* set the appropriate chroma processing routine based on */
        /* phase values */
        if(SVCD_TRUE == ps_curr_lyr_res_prms->u1_dyadic_flag)
        {
            WORD32 i4_ref_layer_chroma_phase_x_plus1_flag;
            WORD32 i4_ref_layer_chroma_phase_y_plus1;
            WORD32 i4_chroma_phase_x_plus1_flag;
            WORD32 i4_chroma_phase_y_plus1;

            ps_lyr_ctxt->pf_residual_samp_mb = &isvcd_residual_samp_mb_dyadic;
            i4_ref_layer_chroma_phase_x_plus1_flag =
                ps_curr_lyr_res_prms->i1_ref_lyr_chroma_phase_x_plus1_flag;
            i4_ref_layer_chroma_phase_y_plus1 =
                ps_curr_lyr_res_prms->i1_ref_lyr_chroma_phase_y_plus1;
            i4_chroma_phase_x_plus1_flag =
                ps_subset_sps->s_sps_svc_ext.u1_seq_ref_layer_chroma_phase_x_plus1_flag;
            i4_chroma_phase_y_plus1 =
                ps_subset_sps->s_sps_svc_ext.u1_seq_ref_layer_chroma_phase_y_plus1;
            if((0 == i4_ref_layer_chroma_phase_x_plus1_flag) && (1 == i4_chroma_phase_x_plus1_flag))
            {
                ps_lyr_ctxt->i4_chrm_horz_int_mode = 1;
                ps_lyr_ctxt->i4_chrm_alt_proc = SVCD_TRUE;
            }

            if((0 == i4_ref_layer_chroma_phase_y_plus1) && (1 == i4_chroma_phase_y_plus1))
            {
                ps_lyr_ctxt->i4_chrm_vert_int_mode = 1;
                ps_lyr_ctxt->i4_chrm_alt_proc = SVCD_TRUE;
            }

            if((0 == i4_ref_layer_chroma_phase_y_plus1) && (2 == i4_chroma_phase_y_plus1))
            {
                ps_lyr_ctxt->i4_chrm_vert_int_mode = 1;
                ps_lyr_ctxt->i4_chrm_alt_proc = SVCD_TRUE;
            }

            if((2 == i4_ref_layer_chroma_phase_y_plus1) && (0 == i4_chroma_phase_y_plus1))
            {
                ps_lyr_ctxt->i4_chrm_vert_int_mode = 2;
                ps_lyr_ctxt->i4_chrm_alt_proc = SVCD_TRUE;
            }
        }
    }
    else
    {
        /* should take false value */
        if(SVCD_FALSE != ps_curr_lyr_res_prms->u1_remap_req_flag)
        {
            return NOT_OK;
        }
    }

    /* store the current layer width and height to context */
    ps_ctxt->i4_ref_width = ps_curr_lyr_res_prms->i4_res_width;
    ps_ctxt->i4_ref_height = ps_curr_lyr_res_prms->i4_res_height;

    /* assert on max ranges of width and shift values */
    if((ps_lyr_ctxt->i4_curr_width > H264_MAX_FRAME_WIDTH) ||
       (ps_lyr_ctxt->i4_ref_width > H264_MAX_FRAME_WIDTH) ||
       (ps_lyr_ctxt->i4_curr_height > H264_MAX_FRAME_HEIGHT) ||
       (ps_lyr_ctxt->i4_ref_height > H264_MAX_FRAME_HEIGHT))
    {
        return NOT_OK;
    }
    return OK;
}