unplugged-system/external/libavc/decoder/svc/isvcd_nal.c

1257 lines
59 KiB
C

/******************************************************************************
*
* 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);
}