/******************************************************************************
 *
 * 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_nal.c
 *
 * \brief
 *    Contains routines that resample for SVC resampling
 *
 * Detailed_description
 *
 * \date
 *
 *
 * \author : Kishore
 **************************************************************************
 */

/******************************************************************************
 *
 * 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 Name         : isvcd_nal.c                                          */
/*                                                                           */
/*  Description       : Contains fucntions which help in NAL extraction from */
/*                      the bitstream                                        */
/*                                                                           */
/*  List of Functions : isvcd_nal_find_start_code,                           */
/*                      isvcd_get_annex_b_nal_unit,                          */
/*                      isvcd_get_rfc_nal_unit,                              */
/*                      isvcd_nal_rbsp_to_sodb,                              */
/*                      isvcd_reset_emulation_ctxt,                          */
/*                      isvcd_nal_byte_swap_emulation,                       */
/*                      isvcd_set_default_nal_header_prms,                   */
/*                      isvcd_dec_nal_hdr,                                   */
/*                      isvcd_parse_part_slice_hdr,                          */
/*                      isvcd_get_int_tgt_lyr_attr,                          */
/*                      isvcd_discard_nal                                    */
/*                                                                           */
/*  Issues / Problems : None                                                 */
/*                                                                           */
/*  Revision History:                                                        */
/*          DD MM YYYY   Author(s)       Changes                             */
/*          14 09 2021   Kishore         Draft                               */
/*                                                                           */
/*****************************************************************************/
/*****************************************************************************/
/* File Includes                                                             */
/*****************************************************************************/

/* System include files */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <stddef.h>
#include <assert.h>

/* standard interface include files */
#include "ih264_typedefs.h"
#include "ih264_macros.h"
#include "ih264_platform_macros.h"
#include "ih264d_tables.h"
#include "iv.h"
#include "ivd.h"
#include "ih264d_defs.h"
#include "ih264_debug.h"
#include "ih264d_parse_cavlc.h"
#include "ih264d_inter_pred.h"
#include "isvcd_structs.h"
#include "ih264d_nal.h"
#include "ih264d_error_handler.h"
#include "ih264d_defs.h"

/*****************************************************************************/
/*Extern Variable Declarations                                               */
/*****************************************************************************/

/*****************************************************************************/
/* Global Variable Definitions                                               */
/*****************************************************************************/

/*****************************************************************************/
/* Static Global Variable Definitions                                        */
/*****************************************************************************/

/*****************************************************************************/
/* Static function Definitions                                               */
/*****************************************************************************/

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_reset_nal_buf                                      */
/*                                                                           */
/*  Description   : Performs the reset of NAL buffer structure               */
/*  Inputs        : 1. Pointer to NAL buffer structure                       */
/*  Globals       : None                                                     */
/*  Processing    : Updates different fields of the structure                */
/*  Outputs       : None                                                     */
/*  Returns       :                                                          */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 09 2021   Vijay      Draft                                     */
/*                                                                           */
/*****************************************************************************/
void isvcd_nal_buf_reset(void *pv_nal_buf)
{
    nal_buf_t *ps_nal_buf = pv_nal_buf;

    ps_nal_buf->i4_valid_flag = SVCD_FALSE;
    ps_nal_buf->i4_buf_size = 0;
    ps_nal_buf->u4_max_bits = 0;
    ps_nal_buf->pu1_buf = NULL;
}
/*****************************************************************************/
/*                                                                           */
/*  Function Name :svcd_nal_find_start_code                                  */
/*                                                                           */
/*  Description   : Finds the position of the start code in the stream       */
/*                                                                           */
/*                                                                           */
/*  Inputs        : 1. Pointer to buffer start                               */
/*                  2. start position                                        */
/*                  3. Maximum number of bytes in the buffer                 */
/*                  4. pointer to zero byte count                            */
/*                  5. pointer to bytes consumed variable                    */
/*  Globals       :                                                          */
/*  Processing    : Searches for the start code in the bitstream and updates */
/*                  consumed variable                                        */
/*                                                                           */
/*  Outputs       : Bytes consumed variable                                  */
/*  Returns       : If start code is found then it returns SC_FOUND otherwise*/
/*                  it returns SC_NOT_FOUND                                  */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 09 2021   Vijay      Draft                                     */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_nal_find_start_code(UWORD8 *pu1_buf_start, WORD32 i4_cur_pos, WORD32 i4_max_num_bytes,
                                 WORD32 *pi4_zero_cnt, UWORD32 *pu4_bytes_consumed)
{
    UWORD8 *pu1_buf = pu1_buf_start + i4_cur_pos;
    WORD32 i4_i;

    for(i4_i = 0; i4_i < (i4_max_num_bytes - i4_cur_pos); i4_i++)
    {
        /*-------------------------------------------------------------------*/
        /* If zero increment the zero byte counter                           */
        /*-------------------------------------------------------------------*/
        if(0 == *pu1_buf)
        {
            (*pi4_zero_cnt)++;
        }

        /*-------------------------------------------------------------------*/
        /* If start code found then increment the byte consumed and return   */
        /*-------------------------------------------------------------------*/
        else if(0x01 == *pu1_buf && *pi4_zero_cnt >= NUM_OF_ZERO_BYTES_BEFORE_START_CODE)
        {
            (*pu4_bytes_consumed)++;
            return (SC_FOUND);
        }
        /*-------------------------------------------------------------------*/
        /* If non zero byte and value is not equal to 1 a then reset zero    */
        /* byte counter                                                      */
        /*-------------------------------------------------------------------*/
        else
        {
            *pi4_zero_cnt = 0;
        }

        (*pu4_bytes_consumed)++;
        pu1_buf++;
    }

    return (SC_NOT_FOUND);
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_get_first_start_code                               */
/*                                                                           */
/*  Description   : Searches for the first start code in the bitstream       */
/*                                                                           */
/*                                                                           */
/*  Inputs        : 1. input buffer structure                                */
/*                  2. Bytes consumed variable                               */
/*  Globals       : None                                                     */
/*  Processing    : None                                                     */
/*                                                                           */
/*  Outputs       : Updates bytes consumed variable                          */
/*  Returns       : Start code is found or not                               */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 09 2021   Vijay      Draft                                     */
/*                                                                           */
/*****************************************************************************/

WORD32 isvcd_get_first_start_code(UWORD8 *pu1_stream_buffer, UWORD32 *pu4_bytes_consumed,
                                  UWORD32 *pu4_num_bytes)
{
    WORD32 i4_zero_cnt = 0, i4_status;
    UWORD32 u4_bytes_consumed_temp = 0;

    i4_status = isvcd_nal_find_start_code(pu1_stream_buffer, 0, *pu4_num_bytes, &i4_zero_cnt,
                                          &u4_bytes_consumed_temp);

    /*-----------------------------------------------------------------------*/
    /* If start code is not found then return and start searching for it     */
    /* again in the next process call. This process is repeated till we      */
    /* get a start code                                                      */
    /*-----------------------------------------------------------------------*/
    if(SC_NOT_FOUND == i4_status)
    {
        *pu4_bytes_consumed += u4_bytes_consumed_temp;
        return (i4_status);
    }
    else
    {
        /*-------------------------------------------------------------------*/
        /* If start code found then proceed with bitstream extraction        */
        /*-------------------------------------------------------------------*/
        *pu4_bytes_consumed += u4_bytes_consumed_temp;
        return (i4_status);
    }
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_get_annex_b_nal_unit                               */
/*                                                                           */
/*  Description   : This function gets one NAL unit from the Annex B based   */
/*                  input bitstream                                          */
/*                                                                           */
/*                                                                           */
/*  Inputs        : 1. Input buffer pointer                                  */
/*                  2. Current position in the input buffer                  */
/*                  3. Input buffer size                                     */
/*                  4. Pointer to state of NAL boundary detection variable   */
/*                  5. Pointer to bytes consumed variable                    */
/*                  6. pointer to nal structure                              */
/*  Globals       :                                                          */
/*  Processing    : This fucntion searches for start code from the current   */
/*                  position and once gets one start code it searches for    */
/*                  another start code to get a NAL unit.                    */
/*                                                                           */
/*  Outputs       : Updates the state of NAL boundary detection logic        */
/*                  Updates the bytes consumed variable from 0 to bytes      */
/*                  consumed in this call                                    */
/*  Returns       : start of nal flag                                        */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 09 2021   Vijay      Draft                                     */
/*                                                                           */
/*****************************************************************************/

WORD32 isvcd_get_annex_b_nal_unit(UWORD8 *pu1_buf_start, WORD32 i4_cur_pos, WORD32 i4_max_num_bytes,
                                  WORD32 *pi4_state, WORD32 *pi4_zero_byte_cnt,
                                  UWORD32 *pu4_bytes_consumed, void *pv_nal_unit,
                                  WORD32 *pi4_more_data_flag)
{
    nal_unit_t *ps_nal_unit = (nal_unit_t *) pv_nal_unit;
    WORD32 i4_status, i4_nal_start_flag = SVCD_FALSE;

    /*-----------------------------------------------------------------------*/
    /* Initialization                                                        */
    /*-----------------------------------------------------------------------*/
    *pu4_bytes_consumed = 0;
    *pi4_more_data_flag = SVCD_TRUE;

    /*------------------------ check ----------------------------------------*/
    /* Assumptions is that this fucntion should not be called with this state*/
    /* hence it is responsibility of the caller to reset the state after the */
    /* NAL_END.                                                              */
    /*-----------------------------------------------------------------------*/
    if(NAL_END == *pi4_state)
    {
        return i4_nal_start_flag;
    }

    /*-----------------------------------------------------------------------*/
    /* ps_nal_unit->apu1_bufs[0] is expected to point to start of buffer of  */
    /* current NAL unit of the current process call. If a NAL unit is frag-  */
    /* -mented across multiple process call then this buffer should point to */
    /* start address of buffers. But when start of NAL is present in the     */
    /* buffer of current process call then ps_nal_unit->apu1_bufs[0] is      */
    /* expected to point to start adress of NAL unit (should be pointing to) */
    /* NAL header)                                                           */
    /*-----------------------------------------------------------------------*/
    ps_nal_unit->pu1_bufs = pu1_buf_start + i4_cur_pos;

    if(NAL_START == *pi4_state)
    {
        if(0 != *pi4_zero_byte_cnt)
        {
            return i4_nal_start_flag;
        }
        i4_nal_start_flag = SVCD_TRUE;
        ps_nal_unit->i4_num_bufs = 1;
        ps_nal_unit->i4_buf_sizes = 0;
        *pi4_state = FIND_NAL_END;
    }

    i4_status = isvcd_nal_find_start_code(pu1_buf_start, i4_cur_pos, i4_max_num_bytes,
                                          pi4_zero_byte_cnt, pu4_bytes_consumed);

    if(SC_NOT_FOUND == i4_status)
    {
        /*-------------------------------------------------------------------*/
        /* If start code is not found then there are 2 possibilities         */
        /* 1. We are in the middle of decoding the start code. This means    */
        /*    that we might have decoded the one or 2 zeroes of the start    */
        /*    code. In such cases, we should not consume these bytes. Though */
        /*    doing so we might encounter spurious cases where 0's are not   */
        /*    actually corresponds to start code but these will not harm us  */
        /* 2. Not of above case. Straightforward one                         */
        /*-------------------------------------------------------------------*/
        ps_nal_unit->i4_buf_sizes = *pu4_bytes_consumed;
        *pi4_more_data_flag = SVCD_FALSE;

        return (i4_nal_start_flag);
    }
    else
    {
        /*-------------------------------------------------------------------*/
        /* If NAL END is found then increment the bytes consumed appropriatly*/
        /* reset the zero byte counter                                       */
        /*-------------------------------------------------------------------*/
        *pi4_state = NAL_END;
        ps_nal_unit->i4_buf_sizes = *pu4_bytes_consumed - 1;
        *pi4_zero_byte_cnt = 0;
        return (i4_nal_start_flag);
    }
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_nal_rbsp_to_sodb                                   */
/*                                                                           */
/*  Description   : Converts the RBSP data to SODB data                      */
/*                                                                           */
/*                                                                           */
/*  Inputs        : 1. Input buffer containing the NAL unit                  */
/*                  2. Length of NAL unit (in bytes)                         */
/*  Globals       : None                                                     */
/*  Processing    : Finds the RBSP stop bit, if present then finds the length*/
/*                  of SODB data                                             */
/*                                                                           */
/*  Outputs       :                                                          */
/*  Returns       : Number of bits in the SODB data                          */
/*                                                                           */
/*  Issues        :                                                          */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 09 2021   Vijay      Draft                                     */
/*                                                                           */
/*****************************************************************************/

UWORD32 isvcd_nal_rbsp_to_sodb(UWORD8 *pu1_buf, WORD32 i4_nal_len_in_bytes, UWORD8 u1_ecd_mode)
{
    UWORD32 u4_last_word_pos;
    UWORD32 u4_word, u4_max_bit_offset;
    UWORD8 i4_num_bits;
    WORD32 i4_i;
    WORD64 i8_nal_len;
    UWORD32 *pu4_buf;

    if(0 >= i4_nal_len_in_bytes)
    {
        return (0);
    }

    /* Get offset in bits */
    i8_nal_len = (WORD64) i4_nal_len_in_bytes << 3;
    u4_max_bit_offset = (UWORD32) i8_nal_len;

    /* If NAL is coded in CABAC then SODB */
    /* length has to account for CABAC    */
    /* ZERO WORDS also                    */
    if(1 == u1_ecd_mode)
    {
        return (u4_max_bit_offset);
    }

    /* Calculate the position of last word */
    u4_last_word_pos = i4_nal_len_in_bytes >> 2;

    /* Load the last word                 */
    i4_i = i4_nal_len_in_bytes & 0x03;
    if(0 != i4_i)
    {
        pu4_buf = (UWORD32 *) pu1_buf;
        pu4_buf += u4_last_word_pos;
        u4_word = *pu4_buf;
        i4_num_bits = i4_i << 3;
        u4_word >>= (32 - i4_num_bits);
    }
    else
    {
        pu4_buf = (UWORD32 *) pu1_buf;
        pu4_buf += (u4_last_word_pos - 1);
        u4_word = *pu4_buf;
        i4_num_bits = 32;
    }

    /* Search for RBSP stop bit          */
    do
    {
        for(i4_i = 0; (i4_i < i4_num_bits) && !CHECKBIT(u4_word, i4_i); i4_i++)
            ;

        u4_max_bit_offset -= i4_i;

        /* RBSP stop bit is found then   */
        /* come out of the loop          */
        if(0 != CHECKBIT(u4_word, i4_i))
        {
            /* Remove RBSP stop bit */
            u4_max_bit_offset -= 1;
            break;
        }

        pu4_buf -= 1;
        u4_word = *pu4_buf;
        i4_num_bits = 32;
    } while(u4_max_bit_offset > 0);

    return (u4_max_bit_offset);
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_reset_emulation_ctxt                               */
/*                                                                           */
/*  Description   : Resets the emulation prevention context structure        */
/*                                                                           */
/*  Inputs        : pv_emulation_ctxt - pointer to emulation prevention      */
/*                      context structure                                    */
/*                                                                           */
/*  Globals       : None                                                     */
/*                                                                           */
/*  Processing    : None                                                     */
/*                                                                           */
/*  Outputs       : None                                                     */
/*                                                                           */
/*  Returns       : None                                                     */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*          DD MM YYYY   Author(s)       Changes                             */
/*          06 09 2021   Vijay      Draft                                    */
/*                                                                           */
/*****************************************************************************/

void isvcd_reset_emulation_ctxt(void *pv_emulation_ctxt)
{
    emulation_prevent_ctxt_t *ps_emulation_ctxt = (emulation_prevent_ctxt_t *) pv_emulation_ctxt;

    /*! Reset the emulation prevention context */
    ps_emulation_ctxt->i4_state = NOT_STUFFED_BYTE;
    ps_emulation_ctxt->i4_zeroes_cnt = 0;
    ps_emulation_ctxt->u4_bytes_in_word = 0;
    ps_emulation_ctxt->u4_word = 0;
}

/****************************************************************************/
/*                                                                          */
/* Function Name  : isvcd_nal_byte_swap_emulation                           */
/*                                                                          */
/* Description    : This function is does byte swap or emulation or both    */
/*                  in the stream.                                          */
/*                                                                          */
/* Inputs         :  pu4_out_stream : Pointer to bitstream out buffer       */
/*                   pu4_out_len    : Pointer to variable for out len       */
/*                   pu1_in_stream  : Pointer to bitstream in buffer        */
/*                   u4_in_len      : Input bitstream buffer length         */
/*                   u4_prev_0s     : In case of fragemented NAL 0s in last */
/*                                    fragmented unit                       */
/*                   u4_0s_bfr_sc   : Number of zeros before start code     */
/*                   u4_bytes       : Number of bytes in last fragmented    */
/*                                    word                                  */
/*                   u4_word        : Last fragmented word                  */
/*                                                                          */
/* Globals        :  None                                                   */
/*                                                                          */
/* Processing     :  It has three mode of operations                        */
/*                   1. Byte Swap and Emulation for H.264 WMV9 AP DEC       */
/*                      supports both fragmented and non fragmented packets */
/*                      set u4_prev_0s = last valid zeros for this operation*/
/*                   2. Byte Swap only for MPEG2 and MPEG4 WMV9 MP DEC      */
/*                      supports both fragmented and non fragmented packets */
/*                      set u4_prev_0s = 0 and  u4_0s_bfr_sc = u4_in_len    */
/*                   3. Annex B stream                                      */
/*                      only non fragmented                                 */
/*                      set u4_prev_0s = 0 for this operation               */
/* Outputs        :  pu4_out_len output length of the bit stream            */
/*                                                                          */
/* Returns        :  Number of zeros in case of framented start code        */
/*                                                                          */
/* Known Issues   :                                                         */
/*                                                                          */
/* Revision History                                                         */
/*                                                                          */
/*      DD MM YY            Author        Changes                           */
/*      06 09 2021          Vijay                                           */
/****************************************************************************/
UWORD32 isvcd_nal_byte_swap_emulation(UWORD32 *pu4_out_stream, UWORD32 *pu4_out_len,
                                      UWORD8 *pu1_in_stream, UWORD32 u4_in_len, WORD32 i4_0s_bfr_sc,
                                      void *pv_emulation_ctxt)
{
    UWORD32 u4_i, u4_num_bytes, u4_offset;
    UWORD8 u1_cur_byte;
    emulation_prevent_ctxt_t *ps_emulation_ctxt = (emulation_prevent_ctxt_t *) pv_emulation_ctxt;

    u4_offset = ps_emulation_ctxt->u4_bytes_in_word;
    u4_num_bytes = ps_emulation_ctxt->u4_bytes_in_word;

    for(u4_i = 0; u4_i < u4_in_len; u4_i++)
    {
        UWORD8 u1_cur_byte_emu, u1_cur_byte_sc;
        UWORD64 u8_sft_word;

        u1_cur_byte = *pu1_in_stream++;
        u1_cur_byte_emu = (EMULATION_PREVENTION_BYTE == u1_cur_byte);
        u1_cur_byte_sc = (START_CODE_BYTE == u1_cur_byte);

        if((ps_emulation_ctxt->i4_zeroes_cnt >= i4_0s_bfr_sc) & (u1_cur_byte_emu | u1_cur_byte_sc) &
           (NOT_STUFFED_BYTE == ps_emulation_ctxt->i4_state))
        {
            if(u1_cur_byte_sc)
            {
                break;
            }
            ps_emulation_ctxt->i4_zeroes_cnt = 0;
            ps_emulation_ctxt->i4_state = STUFFED_BYTE;
            continue;
        }

        u8_sft_word = (UWORD64) ps_emulation_ctxt->u4_word << 8;
        ps_emulation_ctxt->u4_word = (UWORD32) (u8_sft_word | u1_cur_byte);
        ps_emulation_ctxt->u4_bytes_in_word++;
        u4_num_bytes++;
        ps_emulation_ctxt->i4_zeroes_cnt++;
        if(u1_cur_byte != 0x00)
        {
            ps_emulation_ctxt->i4_zeroes_cnt = 0;
        }

        if((u4_num_bytes & 0x03) == 0x00)
        {
            *pu4_out_stream = ps_emulation_ctxt->u4_word;
            ps_emulation_ctxt->u4_bytes_in_word = 0;
            pu4_out_stream++;
        }

        ps_emulation_ctxt->i4_state = NOT_STUFFED_BYTE;
    }

    if(ps_emulation_ctxt->u4_bytes_in_word)
    {
        UWORD64 temp_out_stream = (UWORD64) ps_emulation_ctxt->u4_word
                                  << ((4 - ps_emulation_ctxt->u4_bytes_in_word) << 3);
        *pu4_out_stream = (UWORD32) temp_out_stream;
    }

    *pu4_out_len = (u4_num_bytes - u4_offset);
    return ((u4_num_bytes & 0xFFFFFFFC));
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_set_default_nal_header_prms                        */
/*                                                                           */
/*  Description   : Sets the members of NAL header structures to default     */
/*                  values                                                   */
/*                                                                           */
/*  Inputs        : pv_nal_prms - pointer nal header prms structure          */
/*                  i4_temp_id - default value of temporal id                */
/*                                                                           */
/*  Globals       : None                                                     */
/*                                                                           */
/*  Processing    : None                                                     */
/*                                                                           */
/*  Outputs       : None                                                     */
/*                                                                           */
/*  Returns       : None                                                     */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*          DD MM YYYY   Author(s)       Changes                             */
/*          06 09 2021   Vijay      Draft                                    */
/*                                                                           */
/*****************************************************************************/
void isvcd_set_default_nal_prms(void *pv_nal_prms)
{
    nal_prms_t *ps_nal_prms;
    ps_nal_prms = (nal_prms_t *) pv_nal_prms;

    /* Set default values */
    ps_nal_prms->i4_dependency_id = 0;
    ps_nal_prms->i4_derived_nal_type = 0xFF;
    ps_nal_prms->i4_idr_pic_flag = SVCD_FALSE;
    ps_nal_prms->i4_nal_header_len = 0;
    ps_nal_prms->i4_nal_ref_idc = 0xFF;
    ps_nal_prms->i4_nal_unit_type = 0xFF;
    ps_nal_prms->i4_no_int_lyr_pred = 1;
    ps_nal_prms->i4_priority_id = 0;
    ps_nal_prms->i4_quality_id = 0;
    ps_nal_prms->i4_discard_flag = 0;
    ps_nal_prms->i4_dqid = 0;
    ps_nal_prms->i4_use_ref_base_pic_flag = 0;
    ps_nal_prms->i4_temporal_id = 0;
    ps_nal_prms->i4_idr_pic_num = 0;
    ps_nal_prms->u2_frm_num = 0;
    ps_nal_prms->i4_poc_lsb = 0;
    ps_nal_prms->i4_delta_poc_bot = 0;
    ps_nal_prms->ai4_delta_poc[0] = 0;
    ps_nal_prms->ai4_delta_poc[1] = 0;
    ps_nal_prms->u1_pps_id = 0;
}
/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_dec_nal_hdr                                        */
/*                                                                           */
/*  Description   : None                                                     */
/*                                                                           */
/*  Inputs        : pv_buf_ptr - Pointer to buffer constaining start of NAL  */
/*                  pv_nal_header_buf - Temporray working buffer             */
/*                  pv_nal_prms - Pointer to nal header prms                 */
/*                      structure                                            */
/*                                                                           */
/*  Globals       : None                                                     */
/*                                                                           */
/*  Processing    : None                                                     */
/*                                                                           */
/*  Outputs       : None                                                     */
/*                                                                           */
/*  Returns       : None                                                     */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*          DD MM YYYY   Author(s)       Changes                             */
/*          06 09 2021   Vijay      Draft                                    */
/*                                                                           */
/*****************************************************************************/
void isvcd_dec_nal_hdr(void *pv_buf_ptr, WORD32 i4_buf_size, void *pv_nal_header_buf,
                       void *pv_nal_prms, void *pv_prefix_nal_buf, void *pv_prefix_nal_prms,
                       UWORD32 *pu4_err_code)
{
    nal_prms_t *ps_nal_prms;
    nal_prms_t *ps_prefix_nal_prms;
    nal_buf_t *ps_prefix_nal_buf;
    dec_bit_stream_t s_stream_ctxt = {0};
    WORD32 i4_forbidden_zero_bit;

    /* byte swapping */
    UWORD8 *pu1_buf = (UWORD8 *) pv_nal_header_buf;
    UWORD8 *pu1_src = (UWORD8 *) pv_buf_ptr;

    ps_nal_prms = (nal_prms_t *) pv_nal_prms;
    ps_prefix_nal_prms = (nal_prms_t *) pv_prefix_nal_prms;
    ps_prefix_nal_buf = (nal_buf_t *) pv_prefix_nal_buf;

    /* The NAL header syntax elements are read through bitstream fucntions.  */
    /* Hence bitstream context structure initializaton is needed before      */
    /* parsing from the bitstream                                            */
    /* Also bitstream fucntions assume the buffer is byteswapped. Hence the  */
    /* byte swapping is also done for 4 bytes                                */
    s_stream_ctxt.u4_ofst = 0;
    s_stream_ctxt.pu4_buffer = pv_nal_header_buf;
    s_stream_ctxt.u4_max_ofst = (i4_buf_size << 3);

    *pu4_err_code = 0;

    /* Check the size of bitstream buffer */
    if(s_stream_ctxt.u4_max_ofst < 8)
    {
        *pu4_err_code = (UWORD32) NAL_INSUFFICIENT_DATA;
        return;
    }

    if(s_stream_ctxt.u4_max_ofst >= 32)
    {
        *pu1_buf++ = *(pu1_src + 3);
        *pu1_buf++ = *(pu1_src + 2);
        *pu1_buf++ = *(pu1_src + 1);
        *pu1_buf++ = *pu1_src;
    }
    else
    {
        *pu1_buf++ = *pu1_src;
    }

    /*-----------------------------------------------------------------------*/
    /*! Parse the NAL header and update the NAL header structure members     */
    /*-----------------------------------------------------------------------*/
    /* Read forbidden 0 bit */
    i4_forbidden_zero_bit = ih264d_get_bit_h264(&s_stream_ctxt);

    if(0 != i4_forbidden_zero_bit)
    {
        *pu4_err_code = (UWORD32) NAL_CORRUPT_DATA;
        return;
    }

    /*---------------- Read NAL ref idc -----------------------------*/
    ps_nal_prms->i4_nal_ref_idc = ih264d_get_bits_h264(&s_stream_ctxt, 2);

    /*----------------- Read NAL type -------------------------------*/
    ps_nal_prms->i4_nal_unit_type = ih264d_get_bits_h264(&s_stream_ctxt, 5);
    if(ps_nal_prms->i4_nal_unit_type > CODED_SLICE_EXTENSION_NAL)
    {
        *pu4_err_code = (UWORD32) NAL_CORRUPT_DATA;
        return;
    }
    if(ACCESS_UNIT_DELIMITER_RBSP == ps_nal_prms->i4_nal_unit_type)
    {
        ps_nal_prms->i4_derived_nal_type = NON_VCL_NAL;
        return;
    }

    /* set idr pic flag */
    if(IDR_SLICE_NAL == ps_nal_prms->i4_nal_unit_type)
    {
        ps_nal_prms->i4_idr_pic_flag = SVCD_TRUE;
    }
    else
    {
        ps_nal_prms->i4_idr_pic_flag = SVCD_FALSE;
    }

    /*----------------- Read SVC extension NAL header ---------------*/
    if(CODED_SLICE_EXTENSION_NAL == ps_nal_prms->i4_nal_unit_type ||
       PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type)
    {
        WORD32 i4_svc_extension_flag, i4_idr_flag;

        /* check the size of the buffer */
        if(s_stream_ctxt.u4_max_ofst < 32)
        {
            *pu4_err_code = (UWORD32) NAL_INSUFFICIENT_DATA;
            return;
        }

        i4_svc_extension_flag = ih264d_get_bit_h264(&s_stream_ctxt);
        UNUSED(i4_svc_extension_flag);

        i4_idr_flag = ih264d_get_bit_h264(&s_stream_ctxt);

        /* Set idr pic flag based on idr flag */
        if(1 == i4_idr_flag)
        {
            ps_nal_prms->i4_idr_pic_flag = SVCD_TRUE;
        }
        else
        {
            ps_nal_prms->i4_idr_pic_flag = SVCD_FALSE;
        }

        /* parse priorit id */
        ps_nal_prms->i4_priority_id = ih264d_get_bits_h264(&s_stream_ctxt, 6);

        /* parse the no inter layer prediction flag */
        ps_nal_prms->i4_no_int_lyr_pred = ih264d_get_bit_h264(&s_stream_ctxt);

        /* parse dependency id */
        ps_nal_prms->i4_dependency_id = ih264d_get_bits_h264(&s_stream_ctxt, 3);

        /* parse quality id */
        ps_nal_prms->i4_quality_id = ih264d_get_bits_h264(&s_stream_ctxt, 4);

        if((ps_nal_prms->i4_quality_id > 0) || (ps_nal_prms->i4_dependency_id > 2))
        {
            *pu4_err_code = (UWORD32) NAL_CORRUPT_DATA;
            return;
        }
        /* parse temporal id */
        ps_nal_prms->i4_temporal_id = ih264d_get_bits_h264(&s_stream_ctxt, 3);

        /* parse use ref base pic flag */
        ps_nal_prms->i4_use_ref_base_pic_flag = ih264d_get_bit_h264(&s_stream_ctxt);

        if(0 != ps_nal_prms->i4_use_ref_base_pic_flag)
        {
            *pu4_err_code = (UWORD32) NAL_CORRUPT_DATA;
            return;
        }
        /* parse discrad flag */
        ps_nal_prms->i4_discard_flag = ih264d_get_bit_h264(&s_stream_ctxt);

        /* parse the reserved bits */
        ih264d_get_bits_h264(&s_stream_ctxt, 3);
    }

    /* update NAL hedaer length in bytes */
    ps_nal_prms->i4_nal_header_len = s_stream_ctxt.u4_ofst >> 3;

    /*************************************************************************/
    /* PREFIX NAL UNIT ASSOCIATION WITH ASSOCIATED NAL UNIT                  */
    /*************************************************************************/

    /* if current NAL is not a AVC NAL unit then */
    /* discard the prefix NAL unit if present    */
    if(CODED_SLICE_EXTENSION_NAL == ps_nal_prms->i4_nal_unit_type)
    {
        isvcd_nal_buf_reset(ps_prefix_nal_buf);
    }

    if(SVCD_TRUE == ps_prefix_nal_buf->i4_valid_flag)
    {
        /* Copy the required parameters from the prefix NAL unit */
        ps_nal_prms->i4_dependency_id = ps_prefix_nal_prms->i4_dependency_id;
        ps_nal_prms->i4_quality_id = ps_prefix_nal_prms->i4_quality_id;
        ps_nal_prms->i4_priority_id = ps_prefix_nal_prms->i4_priority_id;
        ps_nal_prms->i4_temporal_id = ps_prefix_nal_prms->i4_temporal_id;
        ps_nal_prms->i4_no_int_lyr_pred = ps_prefix_nal_prms->i4_no_int_lyr_pred;
        ps_nal_prms->i4_use_ref_base_pic_flag = ps_prefix_nal_prms->i4_use_ref_base_pic_flag;
        ps_nal_prms->i4_discard_flag = ps_prefix_nal_prms->i4_discard_flag;
    }

    /*-----------------------------------------------------------------------*/
    /* Set the derived NAL unit type and also update the DQID for VCL NAL    */
    /*  units                                                                */
    /*-----------------------------------------------------------------------*/
    if(CODED_SLICE_EXTENSION_NAL == ps_nal_prms->i4_nal_unit_type ||
       SLICE_NAL == ps_nal_prms->i4_nal_unit_type ||
       IDR_SLICE_NAL == ps_nal_prms->i4_nal_unit_type ||
       PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type)
    {
        ps_nal_prms->i4_derived_nal_type = VCL_NAL;

        /* calculate the DQID and modified DQID */
        ps_nal_prms->i4_dqid = (ps_nal_prms->i4_dependency_id << 4) + ps_nal_prms->i4_quality_id;
    }
    else
    {
        ps_nal_prms->i4_derived_nal_type = NON_VCL_NAL;
    }
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_parse_part_slice_hdr                                */
/*                                                                           */
/*  Description   : This routine parses the slice till POC parameters        */
/*                                                                           */
/*  Inputs        : 1. Pointer to input bitstream                            */
/*                  2. Temporary input buffer                                */
/*                  3. PPS start buffer                                      */
/*                  4. SPS start buffer                                      */
/*                  5. Pointer to NAL paramter structure                     */
/*                  6. Place holder for error code                           */
/*  Globals       : None                                                     */
/*  Processing    : Parses the slice header                                  */
/*                                                                           */
/*  Outputs       : Updated NAL prms structure                               */
/*                  Updated error code                                       */
/*  Returns       : status                                                   */
/*                                                                           */
/*  Issues        : Does not support interlaced content                      */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 09 2021   Vijay           Draft                                */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_parse_part_slice_hdr(UWORD8 *pu1_input_buf, WORD32 i4_input_buf_size,
                                  UWORD8 *pu1_temp_buf, void *pv_sps, void *pv_pps,
                                  nal_prms_t *ps_nal_prms, UWORD32 *pu4_err_code,
                                  WORD32 *pi4_sps_pps_status)
{
    UWORD32 u4_slice_type;
    dec_seq_params_t *ps_sps = (dec_seq_params_t *) pv_sps;
    dec_pic_params_t *ps_pps = (dec_pic_params_t *) pv_pps;
    dec_bit_stream_t s_stream_ctxt = {0};
    dec_bit_stream_t *ps_stream_ctxt;
    UWORD32 *pu4_bitstrm_buf;
    UWORD32 *pu4_bitstrm_ofst;

    *pi4_sps_pps_status = NAL_CORRUPT_DATA;
    /* Perform the emulation prevention and byte swap */
    {
        emulation_prevent_ctxt_t s_emulation_ctxt = {0};
        WORD32 i4_size, i4_temp;

        isvcd_reset_emulation_ctxt((void *) &s_emulation_ctxt);
        i4_size = MIN(i4_input_buf_size, HEADER_BUFFER_LEN_BEFORE_EP);

        isvcd_nal_byte_swap_emulation((UWORD32 *) pu1_temp_buf, (UWORD32 *) &i4_temp, pu1_input_buf,
                                      (UWORD32) i4_size, NUM_OF_ZERO_BYTES_BEFORE_START_CODE,
                                      &s_emulation_ctxt);

        /* Initialize the stream context structure */
        s_stream_ctxt.pu4_buffer = (UWORD32 *) pu1_temp_buf;
        s_stream_ctxt.u4_ofst = 0;
        s_stream_ctxt.u4_max_ofst = (i4_size << 3);
    }

    ps_stream_ctxt = &s_stream_ctxt;

    /* Parse the first mb address in slice */
    pu4_bitstrm_buf = ps_stream_ctxt->pu4_buffer;
    pu4_bitstrm_ofst = &ps_stream_ctxt->u4_ofst;
    ps_nal_prms->u4_first_mb_addr = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf);
    if(ps_nal_prms->u4_first_mb_addr >= (MAX_MBS_LEVEL_51))
    {
        return ERROR_CORRUPTED_SLICE;
    }
    /* Parse slice type */
    u4_slice_type = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf);

    if(u4_slice_type > 9) return ERROR_INV_SLC_TYPE_T;

    /* Check the validity of slice prms */
    switch(u4_slice_type)
    {
        case 0:
        case 5:
            u4_slice_type = P_SLICE;
            /* P slice */
            break;
        case 1:
        case 6:
            u4_slice_type = B_SLICE;
            /* B slice */
            break;
        case 2:
        case 7:
            /* I slice */
            u4_slice_type = I_SLICE;
            break;
        default:
            break;
    }

    /* Parse the pps id */
    ps_nal_prms->u1_pps_id = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf);
    if(ps_nal_prms->u1_pps_id & MASK_ERR_PIC_SET_ID) return ERROR_INV_SLICE_HDR_T;

    /* validate pps id */
    ps_pps += ps_nal_prms->u1_pps_id;
    if(0 == ps_pps->u1_is_valid)
    {
        return NOT_OK;
    }
    /* Derive sps id */
    ps_sps = ps_pps->ps_sps;

    ps_nal_prms->u1_sps_id = ps_sps->u1_seq_parameter_set_id;
    if(CODED_SLICE_EXTENSION_NAL == ps_nal_prms->i4_nal_unit_type)
    {
        ps_sps += MAX_NUM_SEQ_PARAMS;
        ps_nal_prms->u1_sps_id = ps_sps->u1_seq_parameter_set_id;
        ps_nal_prms->u1_sps_id += MAX_NUM_SEQ_PARAMS;
    }

    if(NULL == ps_sps)
    {
        return NOT_OK;
    }
    if(FALSE == ps_sps->u1_is_valid)
    {
        return ERROR_INV_SLICE_HDR_T;
    }
    if(ps_nal_prms->u4_first_mb_addr > (ps_sps->u2_frm_ht_in_mbs * ps_sps->u2_frm_wd_in_mbs))
    {
        return ERROR_CORRUPTED_SLICE;
    }
    *pi4_sps_pps_status = 0;

    /* Parse frame number */
    ps_nal_prms->u2_frm_num = ih264d_get_bits_h264(ps_stream_ctxt, ps_sps->u1_bits_in_frm_num);

    /* IDR picture number */
    if(SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag)
    {
        ps_nal_prms->i4_idr_pic_num = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf);

        if(ps_nal_prms->i4_idr_pic_num > 65535) return ERROR_INV_SLICE_HDR_T;
    }

    /* Poc lsb */
    if(0 == ps_sps->u1_pic_order_cnt_type)
    {
        ps_nal_prms->i4_poc_lsb =
            ih264d_get_bits_h264(ps_stream_ctxt, ps_sps->u1_log2_max_pic_order_cnt_lsb_minus);

        if(ps_nal_prms->i4_poc_lsb < 0 ||
           ps_nal_prms->i4_poc_lsb >= ps_sps->i4_max_pic_order_cntLsb)
            return ERROR_INV_SLICE_HDR_T;
        if(SVCD_TRUE == ps_pps->u1_pic_order_present_flag)
        {
            ps_nal_prms->i4_delta_poc_bot = ih264d_sev(pu4_bitstrm_ofst, pu4_bitstrm_buf);
        }
    }
    else if((1 == ps_sps->u1_pic_order_cnt_type) && (!ps_sps->u1_delta_pic_order_always_zero_flag))
    {
        ps_nal_prms->ai4_delta_poc[0] = ih264d_sev(pu4_bitstrm_ofst, pu4_bitstrm_buf);

        if(SVCD_TRUE == ps_pps->u1_pic_order_present_flag)
        {
            ps_nal_prms->ai4_delta_poc[1] = ih264d_sev(pu4_bitstrm_ofst, pu4_bitstrm_buf);
        }
    }

    *pu4_err_code = 0;
    return (OK);
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_get_int_tgt_lyr_attr                                */
/*                                                                           */
/*  Description   : This routine returns the target layer attributes         */
/*                  (dependency id, temporal id and quality id)              */
/*                                                                           */
/*  Inputs        : 1. Application attributes                                */
/*                  2. Internal attributes (input and output)                */
/*                  3. Nal prms structure                                    */
/*  Globals       : None                                                     */
/*  Processing    :                                                          */
/*                                                                           */
/*  Outputs       : Updated internal target layer attributes                 */
/*  Returns       : status                                                   */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*                                                                           */
/*         DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
/*         06 09 2021   Vijay           Draft                                */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_get_int_tgt_lyr_attr(target_lyr_attr_t *ps_app_attr, target_lyr_attr_t *ps_int_attr,
                                  nal_prms_t *ps_nal_prms)
{
    WORD32 i4_dep_id;
    WORD32 i4_quality_id;
    WORD32 i4_temp_id;
    WORD32 i4_prior_id;

    /* sanity checks */
    if((NULL == ps_app_attr) || (NULL == ps_int_attr) || (NULL == ps_nal_prms))
    {
        return NOT_OK;
    }

    i4_dep_id = ps_int_attr->i4_dependency_id;
    i4_quality_id = ps_int_attr->i4_quality_id;
    i4_temp_id = ps_int_attr->i4_temporal_id;
    i4_prior_id = ps_int_attr->i4_priority_id;

    /* check for idr pic flag                                  */
    /* dependency & temporal id is updated only for IDR picture */
    if(SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag)
    {
        if(ps_int_attr->i4_dependency_id < ps_app_attr->i4_dependency_id)
        {
            /* update the internal attributes only if             */
            /* current dep_id -1 == highest dep id decoded so far */
            /* and quality id is equal to 0                       */
            if((ps_nal_prms->i4_dependency_id - 1 == ps_int_attr->i4_dependency_id) &&
               (0 == ps_nal_prms->i4_quality_id))
            {
                /* Set revised target dependency id */
                i4_dep_id = ps_nal_prms->i4_dependency_id;
                i4_temp_id = ps_app_attr->i4_temporal_id;
                i4_prior_id = ps_app_attr->i4_priority_id;
            }
        }
        else
        {
            /* cases when the curr dep is greater than or equal to app dep */
            i4_dep_id = ps_app_attr->i4_dependency_id;
            i4_temp_id = ps_app_attr->i4_temporal_id;
            i4_prior_id = ps_app_attr->i4_priority_id;
        }
    }

    /* Set quality id */
    if(i4_dep_id == ps_app_attr->i4_dependency_id)
    {
        i4_quality_id = ps_app_attr->i4_quality_id;
    }
    else
    {
        i4_quality_id = MAX_QUALITY_ID;
    }

    /* Update the internal attributes */
    ps_int_attr->i4_dependency_id = i4_dep_id;
    ps_int_attr->i4_quality_id = i4_quality_id;
    ps_int_attr->i4_temporal_id = i4_temp_id;
    ps_int_attr->i4_priority_id = i4_prior_id;

    return (OK);
}

/*****************************************************************************/
/*                                                                           */
/*  Function Name : isvcd_discard_nal                                         */
/*                                                                           */
/*  Description   : Determines whether current NAL unit has to be discarded  */
/*                  or not                                                   */
/*                                                                           */
/*  Inputs        : pv_nal_prms - Pointer to NAL header prms                 */
/*                      structure                                            */
/*                  pv_app_lyr_attr - Pointer to application target layer    */
/*                      attributes  structure                                */
/*                  pv_app_lyr_attr - Pointer to internal target layer       */
/*                      attributes  structure                                */
/*                  i4_update_flag - This flag indicates whether the internal*/
/*                      target attrbutes should be updated or not            */
/*  Globals       : None                                                     */
/*                                                                           */
/*  Processing    : None                                                     */
/*                                                                           */
/*  Outputs       : None                                                     */
/*                                                                           */
/*  Returns       : None                                                     */
/*                                                                           */
/*  Issues        : None                                                     */
/*                                                                           */
/*  Revision History:                                                        */
/*          DD MM YYYY   Author(s)       Changes                             */
/*          06 09 2021   Vijay           Draft                               */
/*                                                                           */
/*****************************************************************************/
WORD32 isvcd_discard_nal(void *pv_nal_prms, void *pv_app_attr, void *pv_int_attr,
                         WORD32 i4_update_flag)
{
    WORD32 i4_discard_nal_flag;
    nal_prms_t *ps_nal_prms;
    target_lyr_attr_t *ps_app_attr;
    target_lyr_attr_t *ps_int_attr;
    WORD32 i4_status;

    ps_nal_prms = (nal_prms_t *) pv_nal_prms;
    ps_app_attr = (target_lyr_attr_t *) pv_app_attr;
    ps_int_attr = (target_lyr_attr_t *) pv_int_attr;

    /* Get the updated target layer attributes */
    if(SVCD_TRUE == i4_update_flag)
    {
        i4_status = isvcd_get_int_tgt_lyr_attr(ps_app_attr, ps_int_attr, ps_nal_prms);
        if(OK != i4_status)
        {
            return NOT_OK;
        }
    }

    i4_discard_nal_flag = SVCD_FALSE;

    if(VCL_NAL == ps_nal_prms->i4_derived_nal_type)
    {
        /*-------------------------------------------------------------------*/
        /*!Discard VCL NAL if any of following is true                       */
        /*! - Dependency id is greater than target dependency id             */
        /*! - Dependency id is equal to target dependency id but quality id  */
        /*!   is greater than target quality id                              */
        /*! - priority id is greater than target priority id                 */
        /*! - Temporal id is greater than target temporal id                 */
        /*! - If dependency id is greater than a NAL unit for which discard  */
        /*!   flag of the NAL header is set                                  */
        /*-------------------------------------------------------------------*/
        if(PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type)
        {
            if(ps_nal_prms->i4_dependency_id > ps_int_attr->i4_dependency_id)
            {
                i4_discard_nal_flag = SVCD_TRUE;
            }

            if(ps_nal_prms->i4_dependency_id == ps_int_attr->i4_dependency_id &&
               ps_nal_prms->i4_quality_id > ps_int_attr->i4_quality_id)
            {
                i4_discard_nal_flag = SVCD_TRUE;
            }

            if(ps_nal_prms->i4_temporal_id > ps_int_attr->i4_temporal_id)
            {
                i4_discard_nal_flag = SVCD_TRUE;
            }

            if(ps_nal_prms->i4_priority_id > ps_int_attr->i4_priority_id)
            {
                i4_discard_nal_flag = SVCD_TRUE;
            }
        }
        else
        {
            if(0 == ps_int_attr->i4_quality_id && 0 == ps_int_attr->i4_dependency_id)
            {
                i4_discard_nal_flag = SVCD_TRUE;
            }
        }
    }

    return (i4_discard_nal_flag);
}
