1257 lines
59 KiB
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);
|
||
|
|
}
|