2434 lines
112 KiB
C
2434 lines
112 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_parse.c
|
||
|
|
*
|
||
|
|
* \brief
|
||
|
|
* Contains routines that resample for SVC resampling
|
||
|
|
*
|
||
|
|
* Detailed_description
|
||
|
|
*
|
||
|
|
* \date
|
||
|
|
*
|
||
|
|
*
|
||
|
|
* \author : Kishore
|
||
|
|
**************************************************************************
|
||
|
|
*/
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* 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 "ih264d_debug.h"
|
||
|
|
#include "ih264_debug.h"
|
||
|
|
#include "ih264d_inter_pred.h"
|
||
|
|
#include "isvcd_structs.h"
|
||
|
|
#include "ih264d_nal.h"
|
||
|
|
#include "ih264d_error_handler.h"
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/*Extern Variable Declarations */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* Global Variable Definitions */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* Static Global Variable Definitions */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* Static function Definitions */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_get_nal_buf */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine returns the NAL buffer structure to use for */
|
||
|
|
/* current NAL unit. This will also perform the initializa -*/
|
||
|
|
/* tion of the structure */
|
||
|
|
/* Inputs : 1. NAL parse structure */
|
||
|
|
/* 2. Place holder for nal buffer structure */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : If current NAL unit prefix NAL unit then */
|
||
|
|
/* - Resets the prefix nal buffer structure */
|
||
|
|
/* - Assigns the buffer pointer */
|
||
|
|
/* Otherwise */
|
||
|
|
/* - Assigns the buffer pointer */
|
||
|
|
/* Outputs : - Updated NAL buffer strcuture */
|
||
|
|
/* - Updates the place holder with correct NAL buffer */
|
||
|
|
/* structure */
|
||
|
|
/* Returns : None */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
void isvcd_get_nal_buf(nal_parse_ctxt_t *ps_nal_parse_ctxt, nal_buf_t **pps_nal_buf)
|
||
|
|
{
|
||
|
|
nal_prms_t *ps_nal_prms;
|
||
|
|
nal_buf_t *ps_nal_buf;
|
||
|
|
|
||
|
|
ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
|
||
|
|
|
||
|
|
/* Get the NAL buffer structure */
|
||
|
|
if(PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type)
|
||
|
|
{
|
||
|
|
ps_nal_buf = &ps_nal_parse_ctxt->s_prefix_nal_buf;
|
||
|
|
|
||
|
|
/* Note: This reset will cause a prefix NAL unit */
|
||
|
|
/* which is followed by another prefix NAL unit */
|
||
|
|
/* to be ignored by the module. This is indeed */
|
||
|
|
/* a desired behaviour */
|
||
|
|
isvcd_nal_buf_reset(ps_nal_buf);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_nal_buf = &ps_nal_parse_ctxt->s_nal_buf;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Initialize the buffer structure */
|
||
|
|
ps_nal_buf->i4_valid_flag = SVCD_TRUE;
|
||
|
|
if(VCL_NAL == ps_nal_prms->i4_derived_nal_type)
|
||
|
|
{
|
||
|
|
ps_nal_buf->pu1_buf = ps_nal_parse_ctxt->pu1_vcl_nal_buf;
|
||
|
|
}
|
||
|
|
else if(NON_VCL_NAL == ps_nal_prms->i4_derived_nal_type)
|
||
|
|
{
|
||
|
|
ps_nal_buf->pu1_buf = ps_nal_parse_ctxt->pu1_non_vcl_nal_buf;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_nal_buf->pu1_buf = NULL;
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
*pps_nal_buf = ps_nal_buf;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_dqid_ctxt_reset */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine resets the DQID context. This routine shall */
|
||
|
|
/* be invoked once in a picture */
|
||
|
|
/* */
|
||
|
|
/* Inputs : DQID context structure */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : Invalidates all the DQID nodes */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updated DQID context */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_dqid_ctxt_reset(dqid_ctxt_t *ps_dqid_ctxt)
|
||
|
|
{
|
||
|
|
WORD32 i4_lyr_idx;
|
||
|
|
WORD32 i4_max_num_lyrs;
|
||
|
|
dqid_node_t *ps_dqid_node;
|
||
|
|
|
||
|
|
/* sanity checks */
|
||
|
|
if(NULL == ps_dqid_ctxt)
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_max_num_lyrs = ps_dqid_ctxt->i4_max_num_lyrs;
|
||
|
|
ps_dqid_node = ps_dqid_ctxt->ps_dqid_node;
|
||
|
|
|
||
|
|
/* Loop over all the layers */
|
||
|
|
for(i4_lyr_idx = 0; i4_lyr_idx < i4_max_num_lyrs; i4_lyr_idx++)
|
||
|
|
{
|
||
|
|
/* Reset the valid flag */
|
||
|
|
ps_dqid_node->u1_valid_flag = SVCD_FALSE;
|
||
|
|
|
||
|
|
/* Loop updates */
|
||
|
|
ps_dqid_node += 1;
|
||
|
|
} /* loop over all the layers */
|
||
|
|
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_get_dqid_node */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine gets a DQID node corresponding to a DQID */
|
||
|
|
/* */
|
||
|
|
/* Inputs : 1. DQID context */
|
||
|
|
/* 2. DQID */
|
||
|
|
/* 3. Place holder for DQID node (output) */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : It performs the following */
|
||
|
|
/* - Searches for all elements untill it gets element having*/
|
||
|
|
/* DQID equal to input DQID. */
|
||
|
|
/* - If not found it finds a free (un-occupied) node */
|
||
|
|
/* */
|
||
|
|
/* Outputs : 1. Updated DQID node */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_get_dqid_node(dqid_ctxt_t *ps_dqid_ctxt, UWORD8 u1_dqid, dqid_node_t **pps_dqid_node)
|
||
|
|
{
|
||
|
|
WORD32 i4_lyr_idx;
|
||
|
|
WORD32 i4_max_num_lyrs;
|
||
|
|
dqid_node_t *ps_dqid_node;
|
||
|
|
dqid_node_t *ps_rqrd_dqid_node;
|
||
|
|
|
||
|
|
/* sanity checks */
|
||
|
|
if((NULL == ps_dqid_ctxt) || (NULL == pps_dqid_node))
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_max_num_lyrs = ps_dqid_ctxt->i4_max_num_lyrs;
|
||
|
|
ps_dqid_node = ps_dqid_ctxt->ps_dqid_node;
|
||
|
|
|
||
|
|
/*Initialization */
|
||
|
|
ps_rqrd_dqid_node = NULL;
|
||
|
|
|
||
|
|
/* Loop over all the buffer nodes */
|
||
|
|
for(i4_lyr_idx = 0; i4_lyr_idx < i4_max_num_lyrs; i4_lyr_idx++)
|
||
|
|
{
|
||
|
|
if((SVCD_TRUE == ps_dqid_node->u1_valid_flag) && (u1_dqid == ps_dqid_node->u1_dqid))
|
||
|
|
{
|
||
|
|
ps_rqrd_dqid_node = ps_dqid_node;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
/* Loop updates */
|
||
|
|
ps_dqid_node += 1;
|
||
|
|
} /* Loop over all the buffer nodes */
|
||
|
|
|
||
|
|
if(NULL == ps_rqrd_dqid_node)
|
||
|
|
{
|
||
|
|
/* If vcl node is not allocated for the requested DQID then allocate buffer */
|
||
|
|
ps_dqid_node = ps_dqid_ctxt->ps_dqid_node;
|
||
|
|
for(i4_lyr_idx = 0; i4_lyr_idx < i4_max_num_lyrs; i4_lyr_idx++)
|
||
|
|
{
|
||
|
|
if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
/* Loop updates */
|
||
|
|
ps_dqid_node += 1;
|
||
|
|
} /* Loop over all the nodes */
|
||
|
|
/* Update the node structure */
|
||
|
|
ps_rqrd_dqid_node = ps_dqid_node;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* sanity checks */
|
||
|
|
if(NULL == ps_rqrd_dqid_node)
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
*pps_dqid_node = ps_rqrd_dqid_node;
|
||
|
|
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_nal_reset_ctxt */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine performs NAL unit level initialization */
|
||
|
|
/* This routine shall be called before parsing a NAL unit */
|
||
|
|
/* */
|
||
|
|
/* Inputs : 1. NAL parse context structure */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : This does initializaiton of NAL unit level tracking */
|
||
|
|
/* varaibles */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updated context structure */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_nal_reset_ctxt(nal_parse_ctxt_t *ps_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
nal_unit_t *ps_nal_unit;
|
||
|
|
|
||
|
|
if(NULL == ps_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Reset the NAL boundary detetction */
|
||
|
|
ps_nal_parse_ctxt->i4_find_nal_state = NAL_START;
|
||
|
|
ps_nal_parse_ctxt->i4_zero_byte_cnt = 0;
|
||
|
|
ps_nal_unit = ps_nal_parse_ctxt->pv_nal_unit;
|
||
|
|
ps_nal_unit->i4_num_bufs = 0;
|
||
|
|
|
||
|
|
/*Reset emulation prevention */
|
||
|
|
isvcd_reset_emulation_ctxt(&ps_nal_parse_ctxt->s_emulation_ctxt);
|
||
|
|
|
||
|
|
/*Reset the NAL header prms */
|
||
|
|
isvcd_set_default_nal_prms(&ps_nal_parse_ctxt->s_nal_prms);
|
||
|
|
|
||
|
|
/* Reset other NAL level tracking variables */
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_FALSE;
|
||
|
|
|
||
|
|
/*Reset NAL buffer structure*/
|
||
|
|
isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_nal_buf);
|
||
|
|
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_pic_reset_ctxt */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine performs the picture level initialization. */
|
||
|
|
/* This routine shall be called before parsing a access unit*/
|
||
|
|
/* */
|
||
|
|
/* Inputs : pv_nal_parse_ctxt - Pointer to context structure */
|
||
|
|
/* */
|
||
|
|
/* Globals : None */
|
||
|
|
/* */
|
||
|
|
/* Processing : 1. Resets the varaibles */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updated context structure */
|
||
|
|
/* */
|
||
|
|
/* Returns : none */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* DD MM YYYY Author(s) Changes */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
void isvcd_pic_reset_ctxt(nal_parse_ctxt_t *ps_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
WORD32 i4_status;
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Reset NAL boundary detetction logic */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
i4_status = isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
|
||
|
|
UNUSED(i4_status);
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Reset picture boundary detctetion logic */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au = SVCD_TRUE;
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Reset VCL and non VCL NAL buffer tracking variables */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
ps_nal_parse_ctxt->pu1_non_vcl_nal_buf = ps_nal_parse_ctxt->pv_non_vcl_nal_buf;
|
||
|
|
ps_nal_parse_ctxt->pu1_vcl_nal_buf = ps_nal_parse_ctxt->pv_vcl_nal_buf;
|
||
|
|
|
||
|
|
/* reset the bytes left to buffer size */
|
||
|
|
ps_nal_parse_ctxt->u4_bytes_left_vcl = MAX_VCL_NAL_BUFF_SIZE;
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt->u4_bytes_left_non_vcl = MAX_NON_VCL_NAL_BUFF_SIZE;
|
||
|
|
|
||
|
|
/* Offset the buffer to start of vcl data */
|
||
|
|
UPDATE_NAL_BUF_PTR(&ps_nal_parse_ctxt->pu1_non_vcl_nal_buf, NON_VCL_NAL,
|
||
|
|
&ps_nal_parse_ctxt->u4_bytes_left_non_vcl);
|
||
|
|
|
||
|
|
UPDATE_NAL_BUF_PTR(&ps_nal_parse_ctxt->pu1_vcl_nal_buf, VCL_NAL,
|
||
|
|
&ps_nal_parse_ctxt->u4_bytes_left_vcl);
|
||
|
|
|
||
|
|
/* Reset previous field */
|
||
|
|
ps_nal_parse_ctxt->ps_prev_non_vcl_buf = NULL;
|
||
|
|
ps_nal_parse_ctxt->i4_idr_pic_err_flag = 0;
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Reset other NAL related tracking variables */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
ps_nal_parse_ctxt->i4_num_non_vcl_nals = 0;
|
||
|
|
|
||
|
|
/* Reset the vcl nal node buffer context */
|
||
|
|
i4_status = isvcd_dqid_ctxt_reset(&ps_nal_parse_ctxt->s_dqid_ctxt);
|
||
|
|
|
||
|
|
/* Reset target layer update flag */
|
||
|
|
ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_get_nal_prms */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine will update the nal prms */
|
||
|
|
/* Inputs : 1. Start of bitstream buffer containing NAL header */
|
||
|
|
/* 2. Size of the buffer */
|
||
|
|
/* 3. NAL prms structure */
|
||
|
|
/* 4. Place holder for error code */
|
||
|
|
/* 5. Place holder for nal discard flag */
|
||
|
|
/* 6. NAL parse context structure */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : 1. Parses the NAL header */
|
||
|
|
/* 2. Sets the discard flag */
|
||
|
|
/* 3. If NAL is not discarded and nal is VCL NAL unit then */
|
||
|
|
/* decodes the slice prms (prefix nal units are excluded)*/
|
||
|
|
/* Outputs : Updated NAL prms structure */
|
||
|
|
/* Updated NAL discrd flag */
|
||
|
|
/* Updates the error code if encountered with error */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_get_nal_prms(UWORD8 *pu1_buf, WORD32 i4_buf_size, nal_prms_t *ps_nal_prms,
|
||
|
|
nal_prms_t *ps_prefix_nal_prms, nal_buf_t *ps_prefix_nal_buf,
|
||
|
|
UWORD32 *pu4_err_code, WORD32 *pi4_sps_pps_status,
|
||
|
|
WORD32 *pi4_nal_discard_flag, nal_parse_ctxt_t *ps_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
UWORD8 *pu1_input_buf;
|
||
|
|
WORD32 i4_status;
|
||
|
|
dec_seq_params_t *ps_sps;
|
||
|
|
dec_pic_params_t *ps_pps;
|
||
|
|
|
||
|
|
ps_sps = ps_nal_parse_ctxt->pv_seq_prms;
|
||
|
|
ps_pps = ps_nal_parse_ctxt->pv_pic_prms;
|
||
|
|
|
||
|
|
*pu4_err_code = 0;
|
||
|
|
*pi4_sps_pps_status = NAL_CORRUPT_DATA;
|
||
|
|
|
||
|
|
/* Decode the NAL header */
|
||
|
|
isvcd_dec_nal_hdr(pu1_buf, i4_buf_size, ps_nal_parse_ctxt->pv_nal_header_buf, ps_nal_prms,
|
||
|
|
ps_prefix_nal_buf, ps_prefix_nal_prms, pu4_err_code);
|
||
|
|
|
||
|
|
/* If encountered with error return fail */
|
||
|
|
if(0 != *pu4_err_code)
|
||
|
|
{
|
||
|
|
return (NOT_OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(ACCESS_UNIT_DELIMITER_RBSP == ps_nal_prms->i4_nal_unit_type)
|
||
|
|
{
|
||
|
|
*pi4_nal_discard_flag = 1;
|
||
|
|
return OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Set the discard flag */
|
||
|
|
*pi4_nal_discard_flag = isvcd_discard_nal(
|
||
|
|
(void *) ps_nal_prms, (void *) &ps_nal_parse_ctxt->s_app_attr,
|
||
|
|
(void *) &ps_nal_parse_ctxt->s_int_attr, ps_nal_parse_ctxt->i4_tgt_lyr_update);
|
||
|
|
|
||
|
|
/* Parse the slice header if all the following */
|
||
|
|
/* conditions are true */
|
||
|
|
/* 1. NAL is a VCL NAL unit */
|
||
|
|
/* 2. NAL is not a prefix NAL unit */
|
||
|
|
/* 3. NAL is not discarded */
|
||
|
|
if((NON_VCL_NAL == ps_nal_prms->i4_derived_nal_type) ||
|
||
|
|
(PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type) || (SVCD_TRUE == *pi4_nal_discard_flag))
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
pu1_input_buf = pu1_buf;
|
||
|
|
pu1_input_buf += ps_nal_prms->i4_nal_header_len;
|
||
|
|
i4_buf_size -= ps_nal_prms->i4_nal_header_len;
|
||
|
|
|
||
|
|
i4_status =
|
||
|
|
isvcd_parse_part_slice_hdr(pu1_input_buf, i4_buf_size, ps_nal_parse_ctxt->pv_nal_header_buf,
|
||
|
|
ps_sps, ps_pps, ps_nal_prms, pu4_err_code, pi4_sps_pps_status);
|
||
|
|
|
||
|
|
return (i4_status);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_compare_nal_prms */
|
||
|
|
/* */
|
||
|
|
/* Description : Detects the picture boundary for annex B based input */
|
||
|
|
/* bitstream */
|
||
|
|
/* */
|
||
|
|
/* Inputs : 1. Pointer to NAL prms */
|
||
|
|
/* 2. Pass (first pass or second pass (verification) */
|
||
|
|
/* 3. Place holder for picture boundary type */
|
||
|
|
/* 4. Place holder for picture boundary status */
|
||
|
|
/* 4. pointer to bitstream extract context structure */
|
||
|
|
/* Globals : */
|
||
|
|
/* Processing : Detects the picture bounadry as described in G.7.4.1.2.4 */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Detects the picture boundary */
|
||
|
|
/* Updates the first NAL in AU field */
|
||
|
|
/* Updates the picture boundary type if picture boundary is */
|
||
|
|
/* detetcetd otherwise it's value shall be ignored */
|
||
|
|
/* Updates the picture boundary status with either */
|
||
|
|
/* PIC_BOUNDARY_TRUE if picture boundary is detetcted or */
|
||
|
|
/* PIC_BOUNDARY_FALSE otherwise */
|
||
|
|
/* Updates the error code */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_compare_nal_prms(nal_prms_t *ps_nal_prms, WORD32 i4_pass, WORD32 i4_prev_dqid,
|
||
|
|
WORD32 *pi4_pic_bound_type, WORD32 *pi4_pic_bound_status,
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
dqid_node_t *ps_dqid_node;
|
||
|
|
vcl_node_t *ps_vcl_node;
|
||
|
|
WORD32 i4_status;
|
||
|
|
|
||
|
|
/* If DQID is lesser than the DQID of the previous */
|
||
|
|
/* NAL then declare the picture boundary */
|
||
|
|
*pi4_pic_bound_type = PIC_BOUND_DQID;
|
||
|
|
if(i4_prev_dqid > ps_nal_prms->i4_dqid)
|
||
|
|
{
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_TRUE;
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Perform the picture boundary detection only for */
|
||
|
|
/* the layers with quality id equal to 0 */
|
||
|
|
if((FIRST_PASS == i4_pass) && (0 != (ps_nal_prms->i4_dqid & 0x0F)))
|
||
|
|
{
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Get the DQID node */
|
||
|
|
i4_status =
|
||
|
|
isvcd_get_dqid_node(&ps_nal_parse_ctxt->s_dqid_ctxt, (UWORD8) i4_prev_dqid, &ps_dqid_node);
|
||
|
|
if((OK != i4_status) || (NULL == ps_dqid_node))
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
/* If the current slice is first slice in the layer */
|
||
|
|
/* then do not compare */
|
||
|
|
if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
|
||
|
|
{
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
*pi4_pic_bound_type = PIC_BOUND_SLICE_PRMS;
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_TRUE;
|
||
|
|
ps_vcl_node = ps_dqid_node->ps_vcl_node;
|
||
|
|
|
||
|
|
/* Compare NAL ref idc */
|
||
|
|
{
|
||
|
|
WORD32 i4_prev_ref_pic_flag;
|
||
|
|
WORD32 i4_cur_ref_pic_flag;
|
||
|
|
|
||
|
|
i4_prev_ref_pic_flag = (0 != ps_vcl_node->i4_nal_ref_idc);
|
||
|
|
i4_cur_ref_pic_flag = (0 != ps_nal_prms->i4_nal_ref_idc);
|
||
|
|
|
||
|
|
if(i4_prev_ref_pic_flag != i4_cur_ref_pic_flag)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare IDR picture flag */
|
||
|
|
if(ps_vcl_node->i4_idr_pic_flag != ps_nal_prms->i4_idr_pic_flag)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare PPS id */
|
||
|
|
if(ps_vcl_node->u1_pps_id != ps_nal_prms->u1_pps_id)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare idr pic num */
|
||
|
|
if((SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag) &&
|
||
|
|
(ps_vcl_node->i4_idr_pic_num != ps_nal_prms->i4_idr_pic_num))
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare frame number */
|
||
|
|
if(ps_vcl_node->u2_frm_num != ps_nal_prms->u2_frm_num)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare poc lsb */
|
||
|
|
if(ps_dqid_node->i4_poc_lsb != ps_nal_prms->i4_poc_lsb)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare delta poc bottom */
|
||
|
|
if(ps_dqid_node->i4_delta_poc_bot != ps_nal_prms->i4_delta_poc_bot)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare delta poc [0] */
|
||
|
|
if(ps_dqid_node->ai4_delta_poc[0] != ps_nal_prms->ai4_delta_poc[0])
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Compare delta poc [0] */
|
||
|
|
if(ps_dqid_node->ai4_delta_poc[1] != ps_nal_prms->ai4_delta_poc[1])
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_detetct_pic_boundary_annex_b */
|
||
|
|
/* */
|
||
|
|
/* Description : Detects the picture boundary for annex B based input */
|
||
|
|
/* bitstream */
|
||
|
|
/* */
|
||
|
|
/* */
|
||
|
|
/* Inputs : 1. Pointer to NAL prms */
|
||
|
|
/* 2. Input bitstream structure */
|
||
|
|
/* 3. Current position of the bitstream pointer */
|
||
|
|
/* 4. Place holder for picture boundary status */
|
||
|
|
/* 5. pointer to bitstream extract context structure */
|
||
|
|
/* Globals : */
|
||
|
|
/* Processing : It does the following */
|
||
|
|
/* 1. Look for next NAL. */
|
||
|
|
/* If not found then declare picture boundary */
|
||
|
|
/* Otherwsie goto next step */
|
||
|
|
/* 2. Parse the NAL header */
|
||
|
|
/* If encountered with error then declare picture */
|
||
|
|
/* boundary */
|
||
|
|
/* Otherwise goto next step */
|
||
|
|
/* 3. If picture boundary type is */
|
||
|
|
/* DQID change and DQID is not equal previous DQID then */
|
||
|
|
/* declare picture boundary. Otherwise, the comapre the */
|
||
|
|
/* rest of parameters. If during comparison, if there is*/
|
||
|
|
/* 4. If picture boundary type is */
|
||
|
|
/* SLICE PRMS CHANGE and Dependency id is not equal then*/
|
||
|
|
/* declare picture boundary. Otherwise compre rest of */
|
||
|
|
/* parameters and goto step 5 */
|
||
|
|
/* 5. If during comparison, if there is */
|
||
|
|
/* * an error - then declare picture boundary */
|
||
|
|
/* * Otherwsie if picture boundary is not detetcted */
|
||
|
|
/* then discard the second slice and proceed. */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Detects the picture boundary */
|
||
|
|
/* Updates the first NAL in AU field */
|
||
|
|
/* Updates the picture boundary type if picture boundary is */
|
||
|
|
/* detetcetd otherwise it's value shall be ignored */
|
||
|
|
/* Updates the error code */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_detect_pic_boundary_annex_b(nal_prms_t *ps_nal_prms, UWORD8 *pu1_stream_buffer,
|
||
|
|
WORD32 i4_cur_pos, WORD32 *pi4_pic_bound_status,
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt,
|
||
|
|
UWORD32 *pu4_num_bytes)
|
||
|
|
{
|
||
|
|
UWORD32 u4_err_code;
|
||
|
|
WORD32 i4_zero_cnt;
|
||
|
|
WORD32 i4_status;
|
||
|
|
nal_prms_t s_nal_prms = {0};
|
||
|
|
nal_prms_t s_prefix_nal_prms = {0};
|
||
|
|
nal_buf_t s_prefix_nal_buf = {0};
|
||
|
|
WORD32 i4_pic_bound_type;
|
||
|
|
WORD32 i4_pic_bound_status;
|
||
|
|
UWORD8 *pu1_buf;
|
||
|
|
WORD32 i4_buf_size;
|
||
|
|
WORD32 i4_more_data_flag;
|
||
|
|
WORD32 i4_new_lyr_flag;
|
||
|
|
WORD32 i4_prev_dqid;
|
||
|
|
WORD32 i4_nal_discard_flag;
|
||
|
|
|
||
|
|
/* Initializations */
|
||
|
|
i4_zero_cnt = 0;
|
||
|
|
s_prefix_nal_buf.i4_valid_flag = SVCD_FALSE;
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
|
||
|
|
i4_new_lyr_flag = SVCD_TRUE;
|
||
|
|
|
||
|
|
/* Get the previous layer's DQID */
|
||
|
|
if(SVCD_TRUE == ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
|
||
|
|
ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au = SVCD_FALSE;
|
||
|
|
}
|
||
|
|
i4_prev_dqid = ps_nal_parse_ctxt->i4_prev_dq_id;
|
||
|
|
ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
|
||
|
|
|
||
|
|
/* Detect the picture boundary */
|
||
|
|
if(ps_nal_prms->i4_dqid <= i4_prev_dqid)
|
||
|
|
{
|
||
|
|
i4_status =
|
||
|
|
isvcd_compare_nal_prms(ps_nal_prms, FIRST_PASS, i4_prev_dqid, &i4_pic_bound_type,
|
||
|
|
&i4_pic_bound_status, ps_nal_parse_ctxt);
|
||
|
|
if(OK != i4_status)
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
i4_new_lyr_flag = SVCD_FALSE;
|
||
|
|
|
||
|
|
/* Check whether the picture boundary is detected */
|
||
|
|
/* or not */
|
||
|
|
if(PIC_BOUNDARY_FALSE == i4_pic_bound_status)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Otherwise look for next nal and compare again */
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
do
|
||
|
|
{
|
||
|
|
WORD32 i4_sps_pps_corrupt_status;
|
||
|
|
WORD32 i4_tgt_lyr_bckup;
|
||
|
|
/* If following conditions are true then there */
|
||
|
|
/* is no data left to decode next NAL and hence*/
|
||
|
|
/* no further processing is required */
|
||
|
|
if((NAL_END != ps_nal_parse_ctxt->i4_find_nal_state) ||
|
||
|
|
((WORD64) i4_cur_pos >= (WORD64) *pu4_num_bytes))
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Otherwise fill the parameters */
|
||
|
|
pu1_buf = pu1_stream_buffer;
|
||
|
|
pu1_buf += i4_cur_pos;
|
||
|
|
i4_buf_size = *pu4_num_bytes - i4_cur_pos;
|
||
|
|
|
||
|
|
/* Get the NAL prms. This involves the following things*/
|
||
|
|
/* 1. Decode the NAL header */
|
||
|
|
/* 2. Set the discard flag */
|
||
|
|
/* 3. Decode the slice header if needed */
|
||
|
|
isvcd_set_default_nal_prms(&s_nal_prms);
|
||
|
|
|
||
|
|
/* take a back up of tgt lyr update flag */
|
||
|
|
i4_tgt_lyr_bckup = ps_nal_parse_ctxt->i4_tgt_lyr_update;
|
||
|
|
|
||
|
|
/* the tgt attributes should not be updaetd while pic boundary det*/
|
||
|
|
ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_FALSE;
|
||
|
|
|
||
|
|
i4_status = isvcd_get_nal_prms(pu1_buf, i4_buf_size, &s_nal_prms, &s_prefix_nal_prms,
|
||
|
|
&s_prefix_nal_buf, &u4_err_code, &i4_sps_pps_corrupt_status,
|
||
|
|
&i4_nal_discard_flag, ps_nal_parse_ctxt);
|
||
|
|
/* restore back the tgt lyr update flag */
|
||
|
|
ps_nal_parse_ctxt->i4_tgt_lyr_update = i4_tgt_lyr_bckup;
|
||
|
|
/* If the error code by the nal prms decoder then declare*/
|
||
|
|
/* picture boundary */
|
||
|
|
if(0 != u4_err_code)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_more_data_flag = SVCD_FALSE;
|
||
|
|
|
||
|
|
/* If prefix NAL unit comes then save the nal prms*/
|
||
|
|
if(PREFIX_UNIT_NAL == s_nal_prms.i4_nal_unit_type)
|
||
|
|
{
|
||
|
|
UWORD32 u4_bytes_consumed;
|
||
|
|
WORD32 i4_status;
|
||
|
|
|
||
|
|
/* If prefix NAL is not discarded then set the varaibles */
|
||
|
|
/* appropriatly */
|
||
|
|
if(SVCD_FALSE == i4_nal_discard_flag)
|
||
|
|
{
|
||
|
|
s_prefix_nal_buf.i4_valid_flag = SVCD_TRUE;
|
||
|
|
memcpy(&s_prefix_nal_prms, &s_nal_prms, sizeof(nal_prms_t));
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Go to next start code */
|
||
|
|
i4_zero_cnt = 0;
|
||
|
|
u4_bytes_consumed = 0;
|
||
|
|
i4_status = isvcd_nal_find_start_code(pu1_stream_buffer, i4_cur_pos, *pu4_num_bytes,
|
||
|
|
&i4_zero_cnt, &u4_bytes_consumed);
|
||
|
|
/* If associated NAL unit is not present then */
|
||
|
|
if(SC_FOUND != i4_status)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
i4_cur_pos += u4_bytes_consumed;
|
||
|
|
i4_more_data_flag = SVCD_TRUE;
|
||
|
|
}
|
||
|
|
} while(SVCD_TRUE == i4_more_data_flag);
|
||
|
|
|
||
|
|
/* Do further picture boundary detection only for */
|
||
|
|
/* VCL NAL unit (excliding prefix NAL unit) */
|
||
|
|
if((NON_VCL_NAL == s_nal_prms.i4_derived_nal_type) ||
|
||
|
|
(PREFIX_UNIT_NAL == s_nal_prms.i4_nal_unit_type) || (SVCD_TRUE == i4_nal_discard_flag))
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
if(SVCD_FALSE == i4_new_lyr_flag)
|
||
|
|
{
|
||
|
|
if(PIC_BOUND_DQID == i4_pic_bound_type)
|
||
|
|
{
|
||
|
|
/* If picture boundary was detetcted based on change*/
|
||
|
|
/* in DQID then declare picture boundary if DQID of the third slice is different */
|
||
|
|
if(i4_prev_dqid != s_nal_prms.i4_dqid)
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* If picture boundary was detetcted based on change in DQID */
|
||
|
|
/* then declare picture boundary if dependency id of third slice is different */
|
||
|
|
if(PIC_BOUND_SLICE_PRMS != i4_pic_bound_type)
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
if((i4_prev_dqid & 0xF) != (s_nal_prms.i4_dqid & 0xF))
|
||
|
|
{
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
isvcd_compare_nal_prms(&s_nal_prms, SECOND_PASS, i4_prev_dqid, &i4_pic_bound_type,
|
||
|
|
&i4_pic_bound_status, ps_nal_parse_ctxt);
|
||
|
|
*pi4_pic_bound_status = i4_pic_bound_status;
|
||
|
|
|
||
|
|
if(PIC_BOUNDARY_FALSE == i4_pic_bound_status)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_prev_dq_id = i4_prev_dqid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if(SVCD_TRUE != i4_new_lyr_flag)
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
/* The NAL header is not corrupted only if any of the following conditions are true */
|
||
|
|
/* 1. The DQID of the first slice differs with DQID of the third slice */
|
||
|
|
/* 2. Picture boundary is detected between first slice and third slice */
|
||
|
|
if(i4_prev_dqid == s_nal_prms.i4_dqid)
|
||
|
|
{
|
||
|
|
isvcd_compare_nal_prms(&s_nal_prms, SECOND_PASS, i4_prev_dqid, &i4_pic_bound_type,
|
||
|
|
&i4_pic_bound_status, ps_nal_parse_ctxt);
|
||
|
|
/* NAL header is corrupted and hence correct it */
|
||
|
|
if(PIC_BOUNDARY_FALSE == i4_pic_bound_status)
|
||
|
|
{
|
||
|
|
ps_nal_prms->i4_dqid = s_nal_prms.i4_dqid;
|
||
|
|
ps_nal_prms->i4_dependency_id = s_nal_prms.i4_dependency_id;
|
||
|
|
ps_nal_prms->i4_quality_id = s_nal_prms.i4_quality_id;
|
||
|
|
ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
*pi4_pic_bound_status = PIC_BOUNDARY_FALSE;
|
||
|
|
}
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_insert_vcl_node */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine inserts a DQID layer into DQID list */
|
||
|
|
/* (this will add a VCL NAL node into VCL NAL structure */
|
||
|
|
/* */
|
||
|
|
/* Inputs : 1. vcl nal structure */
|
||
|
|
/* 2. VCL node to be inserted */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updated vcl nal structure */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_insert_vcl_node(vcl_nal_t *ps_vcl_nal, vcl_node_t *ps_vcl_node)
|
||
|
|
{
|
||
|
|
vcl_node_t *ps_bot_node;
|
||
|
|
vcl_node_t *ps_top_node;
|
||
|
|
vcl_node_t *ps_node;
|
||
|
|
WORD32 i4_rqrd_dqid;
|
||
|
|
|
||
|
|
/* sanity checks */
|
||
|
|
if((NULL == ps_vcl_nal) || (NULL == ps_vcl_node))
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_rqrd_dqid = (ps_vcl_node->i4_dependency_id << 4);
|
||
|
|
i4_rqrd_dqid += ps_vcl_node->i4_quality_id;
|
||
|
|
ps_node = ps_vcl_nal->ps_bot_node;
|
||
|
|
|
||
|
|
/* Search for node which has a DQID which is */
|
||
|
|
/* lesser than taht of the node to inserted */
|
||
|
|
while(NULL != ps_node)
|
||
|
|
{
|
||
|
|
WORD32 i4_dqid;
|
||
|
|
|
||
|
|
i4_dqid = (ps_node->i4_dependency_id << 4);
|
||
|
|
i4_dqid += ps_node->i4_quality_id;
|
||
|
|
|
||
|
|
/* If we get a DQID which is greater than*/
|
||
|
|
/* the DQID of the node to be inserted */
|
||
|
|
/* then break out of the loop and update */
|
||
|
|
if(i4_dqid > i4_rqrd_dqid)
|
||
|
|
{
|
||
|
|
ps_bot_node = ps_node->ps_bot_node;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
ps_node = ps_node->ps_top_node;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If none of the nodes in the list have DQId */
|
||
|
|
/* greater than the node to be inserted then */
|
||
|
|
/* bottom node will be top most node */
|
||
|
|
if(NULL == ps_node)
|
||
|
|
{
|
||
|
|
ps_bot_node = ps_vcl_nal->ps_top_node;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Insert the node into DQID list */
|
||
|
|
if(NULL != ps_bot_node)
|
||
|
|
{
|
||
|
|
ps_top_node = ps_bot_node->ps_top_node;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_top_node = ps_vcl_nal->ps_bot_node;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Join previous node and specified node */
|
||
|
|
if(NULL != ps_bot_node)
|
||
|
|
{
|
||
|
|
ps_bot_node->ps_top_node = ps_vcl_node;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_vcl_nal->ps_bot_node = ps_vcl_node;
|
||
|
|
}
|
||
|
|
ps_vcl_node->ps_bot_node = ps_bot_node;
|
||
|
|
|
||
|
|
/* Join next node and specified node */
|
||
|
|
if(NULL != ps_top_node)
|
||
|
|
{
|
||
|
|
ps_top_node->ps_bot_node = ps_vcl_node;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_vcl_nal->ps_top_node = ps_vcl_node;
|
||
|
|
}
|
||
|
|
ps_vcl_node->ps_top_node = ps_top_node;
|
||
|
|
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_update_nal_ctxt */
|
||
|
|
/* */
|
||
|
|
/* Description : Updates the vcl nal or non vcl structures. */
|
||
|
|
/* */
|
||
|
|
/* Inputs : ps_nal_parse_ctxt - Bitstream extract context structure */
|
||
|
|
/* vcl nal structure pointer */
|
||
|
|
/* NON vcl nal structure */
|
||
|
|
/* */
|
||
|
|
/* Globals : None */
|
||
|
|
/* */
|
||
|
|
/* Processing : If VCL NAL then adds a node to DQID list */
|
||
|
|
/* otherwise adds information to non vcl structure */
|
||
|
|
/* */
|
||
|
|
/* Outputs : None */
|
||
|
|
/* */
|
||
|
|
/* Returns : None */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* DD MM YYYY Author(s) Changes */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
void isvcd_update_nal_ctxt(nal_parse_ctxt_t *ps_nal_parse_ctxt, vcl_nal_t *ps_vcl_nal,
|
||
|
|
non_vcl_nal_t *ps_non_vcl_nal)
|
||
|
|
{
|
||
|
|
/*! If current NAL is VCL NAL then
|
||
|
|
- Insert a VCL node into DQID list if neccessery
|
||
|
|
- update the information part of NAL unit */
|
||
|
|
/*! Otherwise, populate the buffer parameters into non vcl output
|
||
|
|
structure */
|
||
|
|
nal_prms_t *ps_nal_prms;
|
||
|
|
nal_buf_t *ps_nal_buf, *ps_prefix_nal_buf;
|
||
|
|
|
||
|
|
ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
|
||
|
|
ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
|
||
|
|
ps_nal_buf = &ps_nal_parse_ctxt->s_nal_buf;
|
||
|
|
ps_prefix_nal_buf = &ps_nal_parse_ctxt->s_prefix_nal_buf;
|
||
|
|
|
||
|
|
/* If prefix NAL unit then */
|
||
|
|
/* - calculate the SODB length */
|
||
|
|
if(PREFIX_UNIT_NAL == ps_nal_prms->i4_nal_unit_type)
|
||
|
|
{
|
||
|
|
/* Since we consume the zeroes in start code also */
|
||
|
|
/* size has to reduced */
|
||
|
|
if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
|
||
|
|
{
|
||
|
|
ps_prefix_nal_buf->i4_buf_size -= 2;
|
||
|
|
}
|
||
|
|
|
||
|
|
ps_prefix_nal_buf->u4_max_bits =
|
||
|
|
isvcd_nal_rbsp_to_sodb(ps_prefix_nal_buf->pu1_buf, ps_prefix_nal_buf->i4_buf_size, 0);
|
||
|
|
memcpy(&ps_nal_parse_ctxt->s_prefix_nal_prms, &ps_nal_parse_ctxt->s_nal_prms,
|
||
|
|
sizeof(nal_prms_t));
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
|
||
|
|
{
|
||
|
|
/* Since we consume the zeroes in start code also */
|
||
|
|
/* size has to reduced */
|
||
|
|
if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
|
||
|
|
{
|
||
|
|
ps_nal_buf->i4_buf_size -= 2;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if(VCL_NAL == ps_nal_prms->i4_derived_nal_type)
|
||
|
|
{
|
||
|
|
dqid_node_t *ps_dqid_node;
|
||
|
|
vcl_node_t *ps_node;
|
||
|
|
WORD32 i4_status;
|
||
|
|
dec_pic_params_t *ps_pps;
|
||
|
|
dec_seq_params_t *ps_sps;
|
||
|
|
vcl_buf_hdr_t *ps_vcl_hdr;
|
||
|
|
vcl_buf_hdr_t *ps_prev_vcl_hdr;
|
||
|
|
WORD32 i4_slice_offset;
|
||
|
|
|
||
|
|
ps_sps = ps_nal_parse_ctxt->pv_seq_prms;
|
||
|
|
ps_sps += ps_nal_prms->u1_sps_id;
|
||
|
|
ps_pps = ps_nal_parse_ctxt->pv_pic_prms;
|
||
|
|
ps_pps += ps_nal_prms->u1_pps_id;
|
||
|
|
|
||
|
|
/* Get the VCL NAL node */
|
||
|
|
i4_status = isvcd_get_dqid_node(&ps_nal_parse_ctxt->s_dqid_ctxt,
|
||
|
|
(UWORD8) ps_nal_parse_ctxt->i4_prev_dq_id, &ps_dqid_node);
|
||
|
|
|
||
|
|
ps_node = ps_dqid_node->ps_vcl_node;
|
||
|
|
|
||
|
|
if(NULL == ps_node)
|
||
|
|
{
|
||
|
|
/* no active node has been acquired */
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
/* The DQID list updation should happen only once in a */
|
||
|
|
/* layer. Hence a flag used to determine whether the */
|
||
|
|
/* layer is already initialized or not. */
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
|
||
|
|
{
|
||
|
|
/* Update the DQID node */
|
||
|
|
ps_dqid_node->u1_valid_flag = SVCD_TRUE;
|
||
|
|
ps_dqid_node->u1_dqid = (ps_nal_prms->i4_dependency_id << 4);
|
||
|
|
ps_dqid_node->u1_dqid += ps_nal_prms->i4_quality_id;
|
||
|
|
ps_dqid_node->i4_poc_lsb = ps_nal_prms->i4_poc_lsb;
|
||
|
|
ps_dqid_node->i4_delta_poc_bot = ps_nal_prms->i4_delta_poc_bot;
|
||
|
|
ps_dqid_node->ai4_delta_poc[0] = ps_nal_prms->ai4_delta_poc[0];
|
||
|
|
ps_dqid_node->ai4_delta_poc[1] = ps_nal_prms->ai4_delta_poc[1];
|
||
|
|
|
||
|
|
/* Update the VCL node */
|
||
|
|
ps_node->i4_quality_id = ps_nal_prms->i4_quality_id;
|
||
|
|
ps_node->i4_dependency_id = ps_nal_prms->i4_dependency_id;
|
||
|
|
ps_node->i4_temporal_id = ps_nal_prms->i4_temporal_id;
|
||
|
|
ps_node->i4_priority_id = ps_nal_prms->i4_priority_id;
|
||
|
|
ps_node->i4_idr_pic_flag = ps_nal_prms->i4_idr_pic_flag;
|
||
|
|
ps_node->i4_nal_ref_idc = ps_nal_prms->i4_nal_ref_idc;
|
||
|
|
ps_node->i4_nal_unit_type = ps_nal_prms->i4_nal_unit_type;
|
||
|
|
ps_node->i4_use_ref_base = ps_nal_prms->i4_use_ref_base_pic_flag;
|
||
|
|
ps_node->i4_nal_ref_idc = ps_nal_prms->i4_nal_ref_idc;
|
||
|
|
ps_node->u1_sps_id = ps_nal_prms->u1_sps_id;
|
||
|
|
ps_node->u1_pps_id = ps_nal_prms->u1_pps_id;
|
||
|
|
ps_node->u2_frm_num = ps_nal_prms->u2_frm_num;
|
||
|
|
ps_node->i4_idr_pic_num = ps_nal_prms->i4_idr_pic_num;
|
||
|
|
ps_node->i4_num_slices = 0;
|
||
|
|
ps_node->u1_acc_no_int_pred = 1;
|
||
|
|
if(0 == ps_sps->u1_pic_order_cnt_type)
|
||
|
|
{
|
||
|
|
ps_node->i4_poc_syntax = ps_nal_prms->i4_poc_lsb;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_node->i4_poc_syntax = ps_nal_prms->ai4_delta_poc[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Insert the node into DQID list */
|
||
|
|
i4_status = isvcd_insert_vcl_node(ps_vcl_nal, ps_node);
|
||
|
|
if(OK != i4_status)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Reset the previous field */
|
||
|
|
ps_nal_parse_ctxt->ps_prev_vcl_buf = NULL;
|
||
|
|
ps_node->ps_first_vcl_nal = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Update accumulated no inter layer prediction */
|
||
|
|
ps_node->u1_acc_no_int_pred &= (UWORD8) ps_nal_prms->i4_no_int_lyr_pred;
|
||
|
|
|
||
|
|
/****************** Fill VCL BUF header ************/
|
||
|
|
|
||
|
|
/* If prefix NAL unit is present then update */
|
||
|
|
/* the following */
|
||
|
|
/* - Start of buffer header will be present in*/
|
||
|
|
/* before the start of prefix NAL unit's SODB*/
|
||
|
|
/* data. */
|
||
|
|
/* Note: If memeory left for buffer header */
|
||
|
|
/* of the prefix NAL unit will have junk */
|
||
|
|
/* values */
|
||
|
|
|
||
|
|
if(NULL == ps_nal_buf->pu1_buf)
|
||
|
|
{
|
||
|
|
/* no nal needs to be added into the list hence return */
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_vcl_hdr = (vcl_buf_hdr_t *) (ps_nal_buf->pu1_buf - GET_NAL_BUF_INC(VCL_NAL));
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_slice_offset = 0;
|
||
|
|
if(SVCD_TRUE == ps_prefix_nal_buf->i4_valid_flag)
|
||
|
|
{
|
||
|
|
ps_vcl_hdr = (vcl_buf_hdr_t *) (ps_prefix_nal_buf->pu1_buf - GET_NAL_BUF_INC(VCL_NAL));
|
||
|
|
i4_slice_offset = ps_nal_buf->pu1_buf - ps_prefix_nal_buf->pu1_buf;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Update the next field of the previous nal */
|
||
|
|
/* unit or if it is the first NAL then update */
|
||
|
|
/* VCL node information */
|
||
|
|
ps_prev_vcl_hdr = ps_nal_parse_ctxt->ps_prev_vcl_buf;
|
||
|
|
if(NULL != ps_prev_vcl_hdr)
|
||
|
|
{
|
||
|
|
ps_prev_vcl_hdr->ps_next = ps_vcl_hdr;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_node->ps_first_vcl_nal = ps_vcl_hdr;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Fill the VCL buffer header */
|
||
|
|
ps_vcl_hdr->ps_next = NULL;
|
||
|
|
ps_vcl_hdr->i4_no_int_lyr_pred = ps_nal_prms->i4_no_int_lyr_pred;
|
||
|
|
ps_vcl_hdr->i4_first_mb_addr = ps_nal_prms->u4_first_mb_addr;
|
||
|
|
ps_vcl_hdr->u4_prefix_nal_bits = ps_prefix_nal_buf->u4_max_bits;
|
||
|
|
ps_vcl_hdr->i4_slice_offset = 0;
|
||
|
|
ps_vcl_hdr->i4_buf_offset = GET_NAL_BUF_INC(VCL_NAL);
|
||
|
|
ps_vcl_hdr->i4_slice_offset = i4_slice_offset;
|
||
|
|
|
||
|
|
/* Determine max num bits */
|
||
|
|
ps_nal_buf->u4_max_bits = isvcd_nal_rbsp_to_sodb(
|
||
|
|
ps_nal_buf->pu1_buf, ps_nal_buf->i4_buf_size, ps_pps->u1_entropy_coding_mode);
|
||
|
|
ps_vcl_hdr->u4_max_bits = ps_nal_buf->u4_max_bits;
|
||
|
|
|
||
|
|
/* Updates */
|
||
|
|
ps_nal_parse_ctxt->ps_prev_vcl_buf = ps_vcl_hdr;
|
||
|
|
ps_node->i4_num_slices += 1;
|
||
|
|
}
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/* If start of NAL and if its a NON VCL NAL then update the */
|
||
|
|
/* start address of the NON VCL NAL */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
else
|
||
|
|
{
|
||
|
|
non_vcl_buf_hdr_t *ps_non_vcl_buf_hdr;
|
||
|
|
non_vcl_buf_hdr_t *ps_prev_non_vcl_buf_hdr;
|
||
|
|
|
||
|
|
ps_non_vcl_buf_hdr =
|
||
|
|
(non_vcl_buf_hdr_t *) (ps_nal_buf->pu1_buf - GET_NAL_BUF_INC(NON_VCL_NAL));
|
||
|
|
|
||
|
|
/* Update NON VCL structure */
|
||
|
|
ps_non_vcl_buf_hdr->i4_nal_unit_type = ps_nal_prms->i4_nal_unit_type;
|
||
|
|
ps_non_vcl_buf_hdr->ps_next = NULL;
|
||
|
|
ps_non_vcl_buf_hdr->i4_buf_offset = GET_NAL_BUF_INC(NON_VCL_NAL);
|
||
|
|
ps_non_vcl_buf_hdr->i4_buf_size = ps_nal_buf->i4_buf_size;
|
||
|
|
|
||
|
|
/* Update the next field and first non vcl fields of */
|
||
|
|
/* non vcl buffer header structure and non vcl */
|
||
|
|
/* structure respectively */
|
||
|
|
ps_prev_non_vcl_buf_hdr = ps_nal_parse_ctxt->ps_prev_non_vcl_buf;
|
||
|
|
if(NULL != ps_prev_non_vcl_buf_hdr)
|
||
|
|
{
|
||
|
|
ps_prev_non_vcl_buf_hdr->ps_next = ps_non_vcl_buf_hdr;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_non_vcl_nal->ps_first_non_vcl_nal = ps_non_vcl_buf_hdr;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Updates */
|
||
|
|
ps_nal_parse_ctxt->i4_num_non_vcl_nals += 1;
|
||
|
|
ps_non_vcl_nal->i4_num_non_vcl_nals = ps_nal_parse_ctxt->i4_num_non_vcl_nals;
|
||
|
|
ps_nal_parse_ctxt->ps_prev_non_vcl_buf = ps_non_vcl_buf_hdr;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_idr_err_hdlr */
|
||
|
|
/* */
|
||
|
|
/* Description : This routine shall be invoked to handle a case when a */
|
||
|
|
/* slice is an IDR picture and it is referring to corrupted */
|
||
|
|
/* SPS or PPS */
|
||
|
|
/* */
|
||
|
|
/* Inputs : 1. VCL NAL structure */
|
||
|
|
/* 2. NAL paramters */
|
||
|
|
/* 3. NAL parse context structure */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : It will set the highest available dependency id below the*/
|
||
|
|
/* current dependency id as the target layer. Also sets the */
|
||
|
|
/* update target layer flag to FALSE as target layer need not*/
|
||
|
|
/* adopt to the application's target layer in the current */
|
||
|
|
/* picture */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updated vcl nal structure */
|
||
|
|
/* Updated internal target layer attributes */
|
||
|
|
/* Updated target layer update flag */
|
||
|
|
/* Returns : status */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_idr_err_hdlr(vcl_nal_t *ps_vcl_nal, nal_prms_t *ps_nal_prms,
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
vcl_node_t *ps_vcl_node;
|
||
|
|
target_lyr_attr_t *ps_int_attr;
|
||
|
|
|
||
|
|
/* sanity checks */
|
||
|
|
if((NULL == ps_vcl_nal) || (NULL == ps_nal_prms) || (NULL == ps_nal_parse_ctxt))
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
UNUSED(ps_nal_prms);
|
||
|
|
|
||
|
|
/* Initializations */
|
||
|
|
ps_vcl_node = ps_vcl_nal->ps_top_node;
|
||
|
|
ps_int_attr = &ps_nal_parse_ctxt->s_int_attr;
|
||
|
|
|
||
|
|
/* the highest node present in the depedency list will be */
|
||
|
|
/* considered as targte layer and appropriate params will be used */
|
||
|
|
|
||
|
|
/* If not found then delete all the layers in the AU */
|
||
|
|
if(NULL == ps_vcl_node)
|
||
|
|
{
|
||
|
|
ps_int_attr->i4_dependency_id = -1;
|
||
|
|
ps_int_attr->i4_quality_id = MAX_QUALITY_ID;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* Set the target layer */
|
||
|
|
ps_int_attr->i4_dependency_id = ps_vcl_node->i4_dependency_id;
|
||
|
|
ps_int_attr->i4_quality_id = ps_vcl_node->i4_quality_id;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name :svcd_refine_dqid_list */
|
||
|
|
/* */
|
||
|
|
/* Description : Inserts the dummy nodes for each dependency id which */
|
||
|
|
/* have not come in the bitstream */
|
||
|
|
/* */
|
||
|
|
/* Inputs :VCL NAL structure */
|
||
|
|
/* NAL parse context structure */
|
||
|
|
/* Globals : None */
|
||
|
|
/* Processing : For each dependency id till the target dependency id */
|
||
|
|
/* - If layer already exists (came in the bitstream) then */
|
||
|
|
/* do nothing */
|
||
|
|
/* - Otherwsie insert a dummy node */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updated VCL NAL structure */
|
||
|
|
/* Returns : None */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
WORD32 isvcd_refine_dqid_list(vcl_nal_t *ps_vcl_nal, nal_parse_ctxt_t *ps_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
vcl_node_t *ps_node;
|
||
|
|
target_lyr_attr_t *ps_int_attr;
|
||
|
|
dqid_ctxt_t *ps_dqid_ctxt;
|
||
|
|
UWORD8 u1_dep_id;
|
||
|
|
WORD32 i4_status;
|
||
|
|
WORD32 i4_dep_id;
|
||
|
|
|
||
|
|
ps_int_attr = &ps_nal_parse_ctxt->s_int_attr;
|
||
|
|
ps_dqid_ctxt = &ps_nal_parse_ctxt->s_dqid_ctxt;
|
||
|
|
i4_dep_id = -1;
|
||
|
|
|
||
|
|
for(u1_dep_id = 0; u1_dep_id <= ps_int_attr->i4_dependency_id; u1_dep_id++)
|
||
|
|
{
|
||
|
|
dqid_node_t *ps_dqid_node;
|
||
|
|
|
||
|
|
/* Get a DQID node */
|
||
|
|
i4_status = isvcd_get_dqid_node(ps_dqid_ctxt, (UWORD8) (u1_dep_id << 4), &ps_dqid_node);
|
||
|
|
if(OK != i4_status)
|
||
|
|
{
|
||
|
|
return NOT_OK;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If node does not exist already then insert a dummy node */
|
||
|
|
if(SVCD_FALSE == ps_dqid_node->u1_valid_flag)
|
||
|
|
{
|
||
|
|
if(1 == ps_nal_parse_ctxt->i4_idr_pic_err_flag)
|
||
|
|
{
|
||
|
|
ps_int_attr->i4_dependency_id = i4_dep_id;
|
||
|
|
ps_int_attr->i4_quality_id = MAX_QUALITY_ID;
|
||
|
|
|
||
|
|
/* remove all the nodes from dependency list */
|
||
|
|
/* which are at higher dependency than the */
|
||
|
|
/* value set in init attributes */
|
||
|
|
while(NULL != ps_vcl_nal->ps_top_node)
|
||
|
|
{
|
||
|
|
/* if higher dependency */
|
||
|
|
if(ps_vcl_nal->ps_top_node->i4_dependency_id > i4_dep_id)
|
||
|
|
{
|
||
|
|
ps_vcl_nal->ps_top_node = ps_vcl_nal->ps_top_node->ps_bot_node;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* if no node exists in the dependency list */
|
||
|
|
if(NULL == ps_vcl_nal->ps_top_node)
|
||
|
|
{
|
||
|
|
ps_vcl_nal->ps_bot_node = NULL;
|
||
|
|
}
|
||
|
|
else if(ps_vcl_nal->ps_top_node == ps_vcl_nal->ps_bot_node)
|
||
|
|
{
|
||
|
|
/* if a single node exists */
|
||
|
|
ps_vcl_nal->ps_top_node->ps_bot_node = NULL;
|
||
|
|
ps_vcl_nal->ps_bot_node->ps_top_node = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
return (NOT_OK);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_dqid_node->u1_valid_flag = SVCD_TRUE;
|
||
|
|
ps_dqid_node->u1_dqid = (u1_dep_id << 4);
|
||
|
|
|
||
|
|
/* Fill VCL node information */
|
||
|
|
ps_node = ps_dqid_node->ps_vcl_node;
|
||
|
|
ps_node->i4_dependency_id = u1_dep_id;
|
||
|
|
ps_node->i4_quality_id = 0;
|
||
|
|
ps_node->ps_first_vcl_nal = NULL;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Insert node into DQID list */
|
||
|
|
i4_status = isvcd_insert_vcl_node(ps_vcl_nal, ps_node);
|
||
|
|
if(OK != i4_status)
|
||
|
|
{
|
||
|
|
return (NOT_OK);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_dep_id++;
|
||
|
|
} /* End of loop over all the dependency id */
|
||
|
|
return (OK);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_nal_parse_set_target_attr */
|
||
|
|
/* */
|
||
|
|
/* Description : Sets the target layer attributes */
|
||
|
|
/* */
|
||
|
|
/* Inputs : i4_target_quality_id - Target layer quality id */
|
||
|
|
/* i4_target_dependency_id - Target layer dependency id */
|
||
|
|
/* i4_target_temporal_id - Target layer temporal id */
|
||
|
|
/* i4_target_priority_id - Target layer priority id */
|
||
|
|
/* pv_nal_parse_ctxt - Pointer module handle */
|
||
|
|
/* */
|
||
|
|
/* 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_nal_parse_set_target_attr(WORD32 i4_target_quality_id, WORD32 i4_target_dependency_id,
|
||
|
|
WORD32 i4_target_temporal_id, WORD32 i4_target_priority_id,
|
||
|
|
void *pv_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt;
|
||
|
|
target_lyr_attr_t *ps_app_attr;
|
||
|
|
|
||
|
|
if((i4_target_quality_id > MAX_QUALITY_ID) || (i4_target_dependency_id > MAX_DEPENDENCY_ID))
|
||
|
|
{
|
||
|
|
return IV_FAIL;
|
||
|
|
}
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
|
||
|
|
ps_app_attr = &ps_nal_parse_ctxt->s_app_attr;
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Register the target information into context structure */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
ps_app_attr->i4_quality_id = i4_target_quality_id;
|
||
|
|
ps_app_attr->i4_dependency_id = i4_target_dependency_id;
|
||
|
|
ps_app_attr->i4_temporal_id = i4_target_temporal_id;
|
||
|
|
ps_app_attr->i4_priority_id = i4_target_priority_id;
|
||
|
|
return IV_SUCCESS;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_nal_parse_reset_ctxt */
|
||
|
|
/* */
|
||
|
|
/* Description : Initializes the bitstream extraction module. Should be */
|
||
|
|
/* called once in a sequence */
|
||
|
|
/* */
|
||
|
|
/* Inputs : i4_input_bitstream_mode - Input bitstream mode RFC or */
|
||
|
|
/* Annex B */
|
||
|
|
/* i4_input_mode - Input mode - Full input mode or partial */
|
||
|
|
/* input mode */
|
||
|
|
/* pv_nal_parse_ctxt - Module handle */
|
||
|
|
/* */
|
||
|
|
/* 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_nal_parse_reset_ctxt(WORD32 i4_input_bitstream_mode, WORD32 i4_input_mode,
|
||
|
|
void *pv_nal_parse_ctxt)
|
||
|
|
{
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
|
||
|
|
UNUSED(i4_input_mode);
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Set the input bitstream mode of context structure */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
switch(i4_input_bitstream_mode)
|
||
|
|
{
|
||
|
|
case ANNEX_B:
|
||
|
|
case NON_ANNEX_B:
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt->i4_input_bitstream_mode = i4_input_bitstream_mode;
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Perform the picture level initialization */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
isvcd_pic_reset_ctxt(pv_nal_parse_ctxt);
|
||
|
|
|
||
|
|
/* Reset the prefix nal unit buffer structure */
|
||
|
|
isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_prefix_nal_buf);
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/*! Reset other varaibles */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
ps_nal_parse_ctxt->i4_dec_frst_sc_flag = SVCD_TRUE;
|
||
|
|
ps_nal_parse_ctxt->i4_eos_flag = SVCD_FALSE;
|
||
|
|
ps_nal_parse_ctxt->u1_pic_boundary_aud_flag = 0;
|
||
|
|
ps_nal_parse_ctxt->u4_bytes_left = 0;
|
||
|
|
|
||
|
|
/* Reset target layer attributes */
|
||
|
|
{
|
||
|
|
target_lyr_attr_t *ps_app_attr;
|
||
|
|
target_lyr_attr_t *ps_int_attr;
|
||
|
|
|
||
|
|
ps_app_attr = &ps_nal_parse_ctxt->s_app_attr;
|
||
|
|
ps_int_attr = &ps_nal_parse_ctxt->s_int_attr;
|
||
|
|
|
||
|
|
ps_app_attr->i4_dependency_id = MAX_DEPENDENCY_ID;
|
||
|
|
ps_app_attr->i4_quality_id = MAX_QUALITY_ID;
|
||
|
|
ps_app_attr->i4_temporal_id = MAX_TEMPORAL_ID;
|
||
|
|
ps_app_attr->i4_priority_id = MAX_PRIORITY_ID;
|
||
|
|
|
||
|
|
ps_int_attr->i4_dependency_id = -1;
|
||
|
|
ps_int_attr->i4_quality_id = MAX_QUALITY_ID;
|
||
|
|
ps_int_attr->i4_temporal_id = 0;
|
||
|
|
ps_int_attr->i4_priority_id = MAX_PRIORITY_ID;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_nal_parse_partial_signal_eos */
|
||
|
|
/* */
|
||
|
|
/* Description : Does processing when end of stream occurs for partial */
|
||
|
|
/* input mode of operation. */
|
||
|
|
/* */
|
||
|
|
/* Inputs : pv_nal_parse_ctxt - bitstream extract context structure */
|
||
|
|
/* pv_out_vcl_nal - vcl nal structure */
|
||
|
|
/* pv_out_non_vcl_nal - non vcl nal structure */
|
||
|
|
/* */
|
||
|
|
/* Globals : None */
|
||
|
|
/* */
|
||
|
|
/* Processing : None */
|
||
|
|
/* */
|
||
|
|
/* Outputs : None */
|
||
|
|
/* */
|
||
|
|
/* Returns : Picture boundary detetcted or not */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* DD MM YYYY Author(s) Changes */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
WORD32 isvcd_nal_parse_partial_signal_eos(void *pv_nal_parse_ctxt, void *pv_out_vcl_nal,
|
||
|
|
void *pv_out_non_vcl_nal)
|
||
|
|
{
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt;
|
||
|
|
vcl_nal_t *ps_vcl_nal;
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
|
||
|
|
ps_vcl_nal = (vcl_nal_t *) pv_out_vcl_nal;
|
||
|
|
|
||
|
|
/* for RFC mode */
|
||
|
|
if(NON_ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
|
||
|
|
{
|
||
|
|
/* Reset the end of stream flag so that in */
|
||
|
|
ps_nal_parse_ctxt->i4_eos_flag = SVCD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
if(1 == ps_nal_parse_ctxt->u1_pic_boundary_aud_flag)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_eos_flag = SVCD_TRUE;
|
||
|
|
}
|
||
|
|
/* Update VCL node if it is first call in the */
|
||
|
|
/* flush mode */
|
||
|
|
if(SVCD_FALSE == ps_nal_parse_ctxt->i4_eos_flag)
|
||
|
|
{
|
||
|
|
WORD32 i4_status;
|
||
|
|
|
||
|
|
/* Update the unfinished NAL into VCL node if */
|
||
|
|
/* all the following conditions are true */
|
||
|
|
/* 1. We have not found the start code and */
|
||
|
|
/* NAL boundary is not detected yet */
|
||
|
|
/* 2. NAL is not discarded */
|
||
|
|
if((FIND_NAL_END == ps_nal_parse_ctxt->i4_find_nal_state) &&
|
||
|
|
(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag))
|
||
|
|
{
|
||
|
|
isvcd_update_nal_ctxt(ps_nal_parse_ctxt, pv_out_vcl_nal, pv_out_non_vcl_nal);
|
||
|
|
}
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt->i4_idr_pic_err_flag = 0;
|
||
|
|
/* Refine based on the no inter layer pred flag*/
|
||
|
|
i4_status = isvcd_refine_dqid_list(ps_vcl_nal, ps_nal_parse_ctxt);
|
||
|
|
|
||
|
|
if(!(OK == i4_status))
|
||
|
|
{
|
||
|
|
return i4_status;
|
||
|
|
}
|
||
|
|
UNUSED(i4_status);
|
||
|
|
|
||
|
|
/* Reset the context structure variables */
|
||
|
|
isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
|
||
|
|
/* Reset the end of stream flag so that in */
|
||
|
|
/* the next flush call the above steps need */
|
||
|
|
/* not be performed */
|
||
|
|
ps_nal_parse_ctxt->i4_eos_flag = SVCD_TRUE;
|
||
|
|
|
||
|
|
return (PIC_BOUNDARY_TRUE);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
return (FLUSH_DECODED_PICTURE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_nal_parse_pic_bound_proc */
|
||
|
|
/* */
|
||
|
|
/* Description : Function does the picture end processign and resets */
|
||
|
|
/* */
|
||
|
|
/* */
|
||
|
|
/* Inputs : ps_nal_parse_ctxt, ps_vcl_nal */
|
||
|
|
/* Globals : none */
|
||
|
|
/* Processing : DQid list refiniment and resets */
|
||
|
|
/* */
|
||
|
|
/* Outputs : none */
|
||
|
|
/* Returns : none */
|
||
|
|
/* */
|
||
|
|
/* Issues : none */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* */
|
||
|
|
/* DD MM YYYY Author(s) Changes (Describe the changes made) */
|
||
|
|
/* 06 09 2021 vijayakumar creation */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
void isvcd_nal_parse_pic_bound_proc(nal_parse_ctxt_t *ps_nal_parse_ctxt, vcl_nal_t *ps_vcl_nal,
|
||
|
|
nal_prms_t *ps_nal_prms)
|
||
|
|
{
|
||
|
|
WORD32 i4_status;
|
||
|
|
|
||
|
|
i4_status = isvcd_refine_dqid_list(ps_vcl_nal, ps_nal_parse_ctxt);
|
||
|
|
|
||
|
|
/* in case of IDR pictures if the node */
|
||
|
|
/* which has to be added into dependency */
|
||
|
|
/* list is not valied then the layer below */
|
||
|
|
/* that node is set as target layer */
|
||
|
|
|
||
|
|
if(NOT_OK == i4_status)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
|
||
|
|
ps_vcl_nal->i1_nal_ref_id_next = -1;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
/* update the next access unit params */
|
||
|
|
/* will be used by lower level decoder*/
|
||
|
|
/* for concealment of frame number */
|
||
|
|
/* applicable for single layer cases */
|
||
|
|
ps_vcl_nal->i1_nal_ref_id_next = ps_nal_prms->i4_nal_ref_idc;
|
||
|
|
|
||
|
|
ps_vcl_nal->u2_frm_num_next = ps_nal_prms->u2_frm_num;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* -------- reset few variables in context structure ----*/
|
||
|
|
isvcd_pic_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
}
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_nal_parse_vcl_nal_partial */
|
||
|
|
/* */
|
||
|
|
/* Description : None */
|
||
|
|
/* */
|
||
|
|
/* Inputs : pv_nal_parse_ctxt - bitstream extract ctxt */
|
||
|
|
/* structure */
|
||
|
|
/* pv_input_bitstream_ctxt - bitstream context */
|
||
|
|
/* pv_out_non_vcl_nal - non vcl nal structure (output) */
|
||
|
|
/* pv_out_vcl_nal - vcl nal structure (output) */
|
||
|
|
/* pu4_bytes_consumed - bytes consumed variable(output) */
|
||
|
|
/* pi4_num_packets_consumed - packets consumed (output/RFC) */
|
||
|
|
/* */
|
||
|
|
/* Globals : None */
|
||
|
|
/* */
|
||
|
|
/* Processing : None */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updates bytes consumed variable, packets consumed, */
|
||
|
|
/* output structures (vcl nal , non vcl nal) */
|
||
|
|
/* */
|
||
|
|
/* Returns : If picture bounadry is detetcted then PIC_BOUNDARY_TRUE */
|
||
|
|
/* otherwise PIC_BOUNDARY_FALSE */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* DD MM YYYY Author(s) Changes */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
WORD32 isvcd_nal_parse_vcl_nal_partial(void *pv_nal_parse_ctxt, UWORD8 *pu1_stream_buffer,
|
||
|
|
void *pv_out_non_vcl_nal, void *pv_out_vcl_nal,
|
||
|
|
UWORD32 *pu4_bytes_consumed, UWORD32 *pu4_num_bytes)
|
||
|
|
{
|
||
|
|
/*! - Search for the NAL boundary
|
||
|
|
- If NAL boundary is not found and bytes consumed is lesser than
|
||
|
|
minimum buffer size then break out of the loop
|
||
|
|
- if it is start of NAL then read the NAL header
|
||
|
|
- If it is a VCL NAL then invoke picture boundary detection logic and
|
||
|
|
picture boundary is detected then break out of the loop without
|
||
|
|
updating the bytes consumed variable
|
||
|
|
- NAL discard logic determines whther the current NAL has to be
|
||
|
|
discarded or not
|
||
|
|
- If NAL is not discarded then populate the vcl or non vcl output
|
||
|
|
structures
|
||
|
|
*/
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt;
|
||
|
|
vcl_nal_t *ps_vcl_nal;
|
||
|
|
non_vcl_nal_t *ps_non_vcl_nal;
|
||
|
|
nal_unit_t *ps_nal_unit;
|
||
|
|
WORD32 i4_nal_start_flag, i4_cur_pos, i4_status;
|
||
|
|
WORD32 i4_nal_header_len, i4_more_data_flag;
|
||
|
|
UWORD32 u4_bytes_consumed_temp = 0;
|
||
|
|
UWORD8 **ppu1_out_buf;
|
||
|
|
nal_prms_t *ps_nal_prms;
|
||
|
|
WORD32 i4_pic_bound_status;
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
|
||
|
|
ps_vcl_nal = (vcl_nal_t *) pv_out_vcl_nal;
|
||
|
|
ps_non_vcl_nal = (non_vcl_nal_t *) pv_out_non_vcl_nal;
|
||
|
|
ps_nal_unit = (nal_unit_t *) ps_nal_parse_ctxt->pv_nal_unit;
|
||
|
|
ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
|
||
|
|
|
||
|
|
/* Initialization */
|
||
|
|
i4_cur_pos = 0;
|
||
|
|
*pu4_bytes_consumed = 0;
|
||
|
|
i4_nal_header_len = 0;
|
||
|
|
i4_nal_start_flag = SVCD_FALSE;
|
||
|
|
i4_more_data_flag = SVCD_TRUE;
|
||
|
|
i4_pic_bound_status = PIC_BOUNDARY_FALSE;
|
||
|
|
|
||
|
|
ps_non_vcl_nal->i4_num_non_vcl_nals = ps_nal_parse_ctxt->i4_num_non_vcl_nals;
|
||
|
|
|
||
|
|
/* Since we do not perform the picture boundary detection */
|
||
|
|
/* on the prefix NAL unit, the current picture's prefix */
|
||
|
|
/* NAL unit will be at the bottom of the buffer. Hence */
|
||
|
|
/* it should be copied to top of the buffer */
|
||
|
|
if(SVCD_TRUE == ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au)
|
||
|
|
{
|
||
|
|
nal_buf_t *ps_prefix_nal_buf;
|
||
|
|
|
||
|
|
ps_prefix_nal_buf = &ps_nal_parse_ctxt->s_prefix_nal_buf;
|
||
|
|
if(SVCD_TRUE == ps_prefix_nal_buf->i4_valid_flag)
|
||
|
|
{
|
||
|
|
WORD32 i4_buf_size;
|
||
|
|
UWORD8 *pu1_vcl_nal;
|
||
|
|
|
||
|
|
if(ps_prefix_nal_buf->i4_buf_size > 0)
|
||
|
|
{
|
||
|
|
i4_buf_size = ps_prefix_nal_buf->i4_buf_size;
|
||
|
|
i4_buf_size = UP_ALIGN_8(i4_buf_size + BUFFER_ALIGN_4);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
i4_buf_size = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
pu1_vcl_nal = ps_nal_parse_ctxt->pu1_vcl_nal_buf + i4_buf_size;
|
||
|
|
|
||
|
|
memmove(ps_nal_parse_ctxt->pu1_vcl_nal_buf, ps_prefix_nal_buf->pu1_buf, i4_buf_size);
|
||
|
|
ps_prefix_nal_buf->pu1_buf = ps_nal_parse_ctxt->pu1_vcl_nal_buf;
|
||
|
|
ps_nal_parse_ctxt->pu1_vcl_nal_buf = pu1_vcl_nal;
|
||
|
|
|
||
|
|
/* subtract the buffer size left */
|
||
|
|
ps_nal_parse_ctxt->u4_bytes_left_vcl -= i4_buf_size;
|
||
|
|
}
|
||
|
|
/* Reset the top and bottom node */
|
||
|
|
ps_vcl_nal->ps_top_node = NULL;
|
||
|
|
ps_vcl_nal->ps_bot_node = NULL;
|
||
|
|
ps_vcl_nal->i1_nal_ref_id_next = -1;
|
||
|
|
ps_vcl_nal->u2_frm_num_next = 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If number of bytes left in the previous process call */
|
||
|
|
/* is is greater or equal to number of bytes in input */
|
||
|
|
/* buffer of the current process call then declare that */
|
||
|
|
/* end of bitstream has occurred and consume the bytes */
|
||
|
|
/* but do not decode */
|
||
|
|
if(ps_nal_parse_ctxt->u4_bytes_left >= (UWORD32) *pu4_num_bytes)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
|
||
|
|
*pu4_bytes_consumed = *pu4_num_bytes;
|
||
|
|
|
||
|
|
i4_status =
|
||
|
|
isvcd_nal_parse_partial_signal_eos(ps_nal_parse_ctxt, ps_vcl_nal, ps_non_vcl_nal);
|
||
|
|
/* set the next AU params to default values */
|
||
|
|
ps_vcl_nal->i1_nal_ref_id_next = -1;
|
||
|
|
ps_vcl_nal->u2_frm_num_next = 0;
|
||
|
|
|
||
|
|
return (i4_status);
|
||
|
|
}
|
||
|
|
ps_nal_parse_ctxt->u4_bytes_left = 0;
|
||
|
|
|
||
|
|
/*************************************************************************/
|
||
|
|
/* LOOP OVER NALs */
|
||
|
|
/*************************************************************************/
|
||
|
|
do
|
||
|
|
{
|
||
|
|
nal_buf_t *ps_nal_buf;
|
||
|
|
UWORD32 *pu4_bytes_left;
|
||
|
|
|
||
|
|
/* Find NAL boundary */
|
||
|
|
if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
|
||
|
|
{
|
||
|
|
i4_nal_start_flag = isvcd_get_annex_b_nal_unit(
|
||
|
|
pu1_stream_buffer, i4_cur_pos, *pu4_num_bytes,
|
||
|
|
&ps_nal_parse_ctxt->i4_find_nal_state, &ps_nal_parse_ctxt->i4_zero_byte_cnt,
|
||
|
|
&u4_bytes_consumed_temp, ps_nal_parse_ctxt->pv_nal_unit, &i4_more_data_flag);
|
||
|
|
|
||
|
|
i4_cur_pos += u4_bytes_consumed_temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*********************************************************************/
|
||
|
|
/* READ NAL HEADER AND NAL DISCARD LOGIC */
|
||
|
|
/*********************************************************************/
|
||
|
|
|
||
|
|
/* If it is the start of NAL header perform the following */
|
||
|
|
/* 1. Decode NAL header */
|
||
|
|
/* 2. Determine whether the NAL has to be discarded or not*/
|
||
|
|
/* 3. Detect the picture boundary */
|
||
|
|
if(SVCD_TRUE == i4_nal_start_flag)
|
||
|
|
{
|
||
|
|
UWORD32 u4_err_code;
|
||
|
|
WORD32 i4_sps_pps_corrupt_status;
|
||
|
|
WORD32 i4_internal_dep_id_prev;
|
||
|
|
|
||
|
|
/* Get the NAL prms. This involves the following things*/
|
||
|
|
/* 1. Decode the NAL header */
|
||
|
|
/* 2. Set the discard flag */
|
||
|
|
/* 3. Decode the slice header if needed */
|
||
|
|
|
||
|
|
/* get the dependency id at which the NAl parse is currently */
|
||
|
|
/* present */
|
||
|
|
i4_internal_dep_id_prev = ps_nal_parse_ctxt->s_int_attr.i4_dependency_id;
|
||
|
|
|
||
|
|
i4_status = isvcd_get_nal_prms(
|
||
|
|
ps_nal_unit->pu1_bufs, ps_nal_unit->i4_buf_sizes, ps_nal_prms,
|
||
|
|
&ps_nal_parse_ctxt->s_prefix_nal_prms, &ps_nal_parse_ctxt->s_prefix_nal_buf,
|
||
|
|
&u4_err_code, &i4_sps_pps_corrupt_status, &ps_nal_parse_ctxt->i4_discard_nal_flag,
|
||
|
|
ps_nal_parse_ctxt);
|
||
|
|
|
||
|
|
if(NON_ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If the error code returned by the "picture boundary" */
|
||
|
|
/* detetction is */
|
||
|
|
/* 1. Insufficient bitstream size: then store the bytes */
|
||
|
|
/* left and break out of the loop */
|
||
|
|
/* 2. Corrupted slice: then discard the slice */
|
||
|
|
if((NAL_INSUFFICIENT_DATA == (WORD32) u4_err_code) &&
|
||
|
|
(NAL_END != ps_nal_parse_ctxt->i4_find_nal_state))
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->u4_bytes_left = *pu4_num_bytes - *pu4_bytes_consumed;
|
||
|
|
|
||
|
|
/* Reset the NAL level tracking variables */
|
||
|
|
isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
else if(0 != u4_err_code)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
|
||
|
|
|
||
|
|
if(SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag)
|
||
|
|
{
|
||
|
|
/* IDR Error handler is called */
|
||
|
|
/* only if for a given layer the NAL */
|
||
|
|
/* haeder and partial slice decode */
|
||
|
|
/* routine comes out as no SPS PPS */
|
||
|
|
/* error. But for Lowest layer in */
|
||
|
|
/* access unit it is doen always */
|
||
|
|
if(i4_internal_dep_id_prev != ps_nal_parse_ctxt->s_int_attr.i4_dependency_id)
|
||
|
|
{
|
||
|
|
/* if the target depedency id has been */
|
||
|
|
/* changed while decoding currnet NAL */
|
||
|
|
|
||
|
|
if((0 != i4_sps_pps_corrupt_status) ||
|
||
|
|
(-1 == ps_nal_parse_ctxt->i4_prev_dq_id))
|
||
|
|
{
|
||
|
|
i4_status =
|
||
|
|
isvcd_idr_err_hdlr(ps_vcl_nal, ps_nal_prms, ps_nal_parse_ctxt);
|
||
|
|
if(OK != i4_status)
|
||
|
|
{
|
||
|
|
return i4_status;
|
||
|
|
}
|
||
|
|
UNUSED(i4_status);
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_FALSE;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
if(0 == ps_nal_prms->i4_quality_id)
|
||
|
|
{
|
||
|
|
/* over write the frame number */
|
||
|
|
ps_nal_parse_ctxt->s_nal_prms.u2_frm_num = 0;
|
||
|
|
|
||
|
|
/* Get the previous layer's DQID */
|
||
|
|
if(ps_nal_parse_ctxt->i4_prev_dq_id < ps_nal_prms->i4_dqid)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_prev_dq_id = ps_nal_prms->i4_dqid;
|
||
|
|
ps_nal_parse_ctxt->i4_is_frst_vcl_nal_in_au = SVCD_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* update the nal context with the nal */
|
||
|
|
/* header params */
|
||
|
|
isvcd_update_nal_ctxt(ps_nal_parse_ctxt, ps_vcl_nal,
|
||
|
|
ps_non_vcl_nal);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Populate the derived nal type into bitstream extract*/
|
||
|
|
/* context structure */
|
||
|
|
i4_nal_header_len = ps_nal_prms->i4_nal_header_len;
|
||
|
|
ps_nal_parse_ctxt->i4_nal_type = ps_nal_prms->i4_derived_nal_type;
|
||
|
|
|
||
|
|
/* get the accumulated idr pic error flag */
|
||
|
|
ps_nal_parse_ctxt->i4_idr_pic_err_flag |=
|
||
|
|
((SVCD_TRUE == ps_nal_prms->i4_idr_pic_flag) &&
|
||
|
|
(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag) &&
|
||
|
|
(i4_internal_dep_id_prev != ps_nal_parse_ctxt->s_int_attr.i4_dependency_id));
|
||
|
|
|
||
|
|
if(ACCESS_UNIT_DELIMITER_RBSP == ps_nal_prms->i4_nal_unit_type)
|
||
|
|
{
|
||
|
|
i4_pic_bound_status = PIC_BOUNDARY_TRUE;
|
||
|
|
ps_nal_parse_ctxt->u1_pic_boundary_aud_flag = 1;
|
||
|
|
/* If picture boundary is detected then come out of */
|
||
|
|
/* the loop */
|
||
|
|
if(PIC_BOUNDARY_TRUE == i4_pic_bound_status)
|
||
|
|
{
|
||
|
|
isvcd_nal_parse_pic_bound_proc(ps_nal_parse_ctxt, ps_vcl_nal, ps_nal_prms);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
/* Perform the picture boundary detetction if all the */
|
||
|
|
/* following conditions are TRUE */
|
||
|
|
/* 1. VCL NAL */
|
||
|
|
/* 2. Not a prefix NAL */
|
||
|
|
/* 3. Not a discardable NAL */
|
||
|
|
if((VCL_NAL == ps_nal_prms->i4_derived_nal_type) &&
|
||
|
|
(PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type) &&
|
||
|
|
(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag))
|
||
|
|
{
|
||
|
|
if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->u1_pic_boundary_aud_flag = 0;
|
||
|
|
|
||
|
|
i4_status = isvcd_detect_pic_boundary_annex_b(ps_nal_prms, pu1_stream_buffer,
|
||
|
|
i4_cur_pos, &i4_pic_bound_status,
|
||
|
|
ps_nal_parse_ctxt, pu4_num_bytes);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If picture boundary is detected then come out of */
|
||
|
|
/* the loop */
|
||
|
|
if(PIC_BOUNDARY_TRUE == i4_pic_bound_status)
|
||
|
|
{
|
||
|
|
isvcd_nal_parse_pic_bound_proc(ps_nal_parse_ctxt, ps_vcl_nal, ps_nal_prms);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
|
||
|
|
{
|
||
|
|
/* Set the active NAL buffer structure and initialize */
|
||
|
|
/* the nal buffer structure */
|
||
|
|
isvcd_get_nal_buf(ps_nal_parse_ctxt, &ps_nal_buf);
|
||
|
|
ps_nal_parse_ctxt->ps_nal_buf = ps_nal_buf;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->ps_nal_buf = NULL;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
/* In RFC based bitstreams, this is a dummy update (in this mode, the*/
|
||
|
|
/* bytes consumed updation is done by picture boundary dectection */
|
||
|
|
/* But for Annex B based streams this is valid update */
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
*pu4_bytes_consumed += u4_bytes_consumed_temp;
|
||
|
|
|
||
|
|
/*********************************************************************/
|
||
|
|
/* EMULATION PREVENTION AND BYTE SWAPPING */
|
||
|
|
/*********************************************************************/
|
||
|
|
|
||
|
|
/* Determine output buffer */
|
||
|
|
ps_nal_buf = ps_nal_parse_ctxt->ps_nal_buf;
|
||
|
|
|
||
|
|
if(VCL_NAL == ps_nal_parse_ctxt->i4_nal_type)
|
||
|
|
{
|
||
|
|
ppu1_out_buf = &ps_nal_parse_ctxt->pu1_vcl_nal_buf;
|
||
|
|
pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_vcl;
|
||
|
|
if(*pu4_bytes_left < (MAX_VCL_NAL_BUFF_SIZE * 0.05))
|
||
|
|
{
|
||
|
|
return (VCL_NAL_FOUND_FALSE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ppu1_out_buf = &ps_nal_parse_ctxt->pu1_non_vcl_nal_buf;
|
||
|
|
pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_non_vcl;
|
||
|
|
if(*pu4_bytes_left < (MAX_NON_VCL_NAL_BUFF_SIZE * 0.05))
|
||
|
|
{
|
||
|
|
return (VCL_NAL_FOUND_FALSE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* if 0 bytes left then discard the current NAL */
|
||
|
|
if(0 >= (WORD32) *pu4_bytes_left)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Perform the emulation prevention and byte swap */
|
||
|
|
if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
|
||
|
|
{
|
||
|
|
UWORD32 u4_output_bytes, u4_buf_inc;
|
||
|
|
|
||
|
|
/* Do emulation prevention and byte swapping on all the packets */
|
||
|
|
/* of RFC or current partial or full Annex B NAL unit */
|
||
|
|
{
|
||
|
|
UWORD32 u4_buf_size;
|
||
|
|
|
||
|
|
/* clip the size before emulation prevention */
|
||
|
|
u4_buf_size = (UWORD32) CLIP3(0, (WORD32) *pu4_bytes_left,
|
||
|
|
(ps_nal_unit->i4_buf_sizes - i4_nal_header_len));
|
||
|
|
|
||
|
|
u4_buf_inc = isvcd_nal_byte_swap_emulation(
|
||
|
|
(UWORD32 *) *ppu1_out_buf, &u4_output_bytes,
|
||
|
|
ps_nal_unit->pu1_bufs + i4_nal_header_len, u4_buf_size,
|
||
|
|
NUM_OF_ZERO_BYTES_BEFORE_START_CODE, &ps_nal_parse_ctxt->s_emulation_ctxt);
|
||
|
|
|
||
|
|
i4_nal_header_len = 0;
|
||
|
|
u4_buf_inc = UP_ALIGN_8(u4_buf_inc);
|
||
|
|
*ppu1_out_buf += u4_buf_inc;
|
||
|
|
*pu4_bytes_left -= u4_buf_inc;
|
||
|
|
ps_nal_buf->i4_buf_size += u4_output_bytes;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*********************************************************************/
|
||
|
|
/* UPDATE VARIABLES */
|
||
|
|
/*********************************************************************/
|
||
|
|
if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
|
||
|
|
{
|
||
|
|
if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
|
||
|
|
{
|
||
|
|
/* This fucntions updates output nal ctxt - vcl nal structure*/
|
||
|
|
/* and non vcl nal structure depending upon the current NAL */
|
||
|
|
/* type. */
|
||
|
|
/* This will only update parameters which are available at */
|
||
|
|
/* end of NAL unit like nal unit's total size */
|
||
|
|
isvcd_update_nal_ctxt(ps_nal_parse_ctxt, ps_vcl_nal, ps_non_vcl_nal);
|
||
|
|
|
||
|
|
UPDATE_NAL_BUF_PTR(ppu1_out_buf, ps_nal_prms->i4_derived_nal_type, pu4_bytes_left);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If the prefix NAL unit is not immediatly followed by */
|
||
|
|
/* a AVC NAL unit it shall be discarded and hence reset */
|
||
|
|
/* is done */
|
||
|
|
/* Also if prefix NAL unit is discarded then we should */
|
||
|
|
/* not associate the prefix NAL unit with AVC NAL unit */
|
||
|
|
/* and hence a reset is required */
|
||
|
|
if((PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type) ||
|
||
|
|
(SVCD_TRUE == ps_nal_parse_ctxt->i4_discard_nal_flag))
|
||
|
|
{
|
||
|
|
isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_prefix_nal_buf);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Reset the nal level tracking variables */
|
||
|
|
isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*------------- while loop ends here --------------------------------*/
|
||
|
|
} while(SVCD_TRUE == i4_more_data_flag);
|
||
|
|
|
||
|
|
return (i4_pic_bound_status);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*****************************************************************************/
|
||
|
|
/* */
|
||
|
|
/* Function Name : isvcd_nal_parse_non_vcl_nal */
|
||
|
|
/* */
|
||
|
|
/* Description : None */
|
||
|
|
/* */
|
||
|
|
/* Inputs : pv_nal_parse_ctxt - bitstream extract ctxt */
|
||
|
|
/* structure */
|
||
|
|
/* pv_input_bitstream_ctxt - bitstream context */
|
||
|
|
/* pv_out_non_vcl_nal - non vcl nal structure (output) */
|
||
|
|
/* pu4_bytes_consumed - bytes consumed variable(output) */
|
||
|
|
/* pi4_num_packets_consumed - packets consumed (output/RFC) */
|
||
|
|
/* */
|
||
|
|
/* Globals : None */
|
||
|
|
/* */
|
||
|
|
/* Processing : None */
|
||
|
|
/* */
|
||
|
|
/* Outputs : Updates bytes consumed variable, packets consumed, */
|
||
|
|
/* output structures (non vcl nal) */
|
||
|
|
/* */
|
||
|
|
/* Returns : If vcl nal is found then VCL_NAL_FOUND_TRUE otherwise */
|
||
|
|
/* VCL_NAL_FOUND_FALSE */
|
||
|
|
/* */
|
||
|
|
/* Issues : None */
|
||
|
|
/* */
|
||
|
|
/* Revision History: */
|
||
|
|
/* DD MM YYYY Author(s) Changes */
|
||
|
|
/* 06 09 2021 Vijay Draft */
|
||
|
|
/* */
|
||
|
|
/*****************************************************************************/
|
||
|
|
|
||
|
|
WORD32 isvcd_nal_parse_non_vcl_nal(void *pv_nal_parse_ctxt, UWORD8 *pu1_stream_buffer,
|
||
|
|
void *pv_out_non_vcl_nal, UWORD32 *pu4_bytes_consumed,
|
||
|
|
UWORD32 *pu4_num_bytes)
|
||
|
|
{
|
||
|
|
/*! - Search for the NAL boundary
|
||
|
|
- If NAL boundary is not found and bytes consumed is lesser than
|
||
|
|
minimum buffer size then break out of the loop
|
||
|
|
- if it is start of NAL then read the NAL header
|
||
|
|
- If it is a VCL NAL then return from this fucntion saying that
|
||
|
|
VCL NAL found
|
||
|
|
- NAL discard logic determines whther the current NAL has to be
|
||
|
|
discarded or not
|
||
|
|
- If NAL is not discarded then populate the vcl or non vcl output
|
||
|
|
structures
|
||
|
|
*/
|
||
|
|
|
||
|
|
nal_parse_ctxt_t *ps_nal_parse_ctxt;
|
||
|
|
non_vcl_nal_t *ps_non_vcl_nal;
|
||
|
|
nal_unit_t *ps_nal_unit;
|
||
|
|
WORD32 i4_nal_start_flag, i4_cur_pos, i4_status;
|
||
|
|
WORD32 i4_nal_header_len, i4_more_data_flag;
|
||
|
|
UWORD32 u4_bytes_consumed_temp = 0;
|
||
|
|
UWORD8 **ppu1_out_buf;
|
||
|
|
nal_prms_t *ps_nal_prms;
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt = (nal_parse_ctxt_t *) pv_nal_parse_ctxt;
|
||
|
|
ps_non_vcl_nal = (non_vcl_nal_t *) pv_out_non_vcl_nal;
|
||
|
|
ps_nal_unit = (nal_unit_t *) ps_nal_parse_ctxt->pv_nal_unit;
|
||
|
|
ps_nal_prms = &ps_nal_parse_ctxt->s_nal_prms;
|
||
|
|
|
||
|
|
/* Initialization */
|
||
|
|
i4_cur_pos = 0;
|
||
|
|
*pu4_bytes_consumed = 0;
|
||
|
|
i4_nal_header_len = 0;
|
||
|
|
i4_nal_start_flag = SVCD_FALSE;
|
||
|
|
i4_more_data_flag = SVCD_TRUE;
|
||
|
|
i4_status = PIC_BOUNDARY_FALSE;
|
||
|
|
|
||
|
|
/* reset the target layer update flag */
|
||
|
|
ps_nal_parse_ctxt->i4_tgt_lyr_update = SVCD_FALSE;
|
||
|
|
/*************************************************************************/
|
||
|
|
/* SEARCHING FOR THE START OF BITSTREAM */
|
||
|
|
/*************************************************************************/
|
||
|
|
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
/* For Annex B based bitstreams the first start code has to decoded */
|
||
|
|
/* The first start code can come after multiple process call also. This */
|
||
|
|
/* has to be carefully handled */
|
||
|
|
/*-----------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode &&
|
||
|
|
SVCD_TRUE == ps_nal_parse_ctxt->i4_dec_frst_sc_flag)
|
||
|
|
{
|
||
|
|
WORD32 i4_status;
|
||
|
|
|
||
|
|
i4_status =
|
||
|
|
isvcd_get_first_start_code(pu1_stream_buffer, pu4_bytes_consumed, pu4_num_bytes);
|
||
|
|
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
/* If start code found then proceed with bitstream extraction */
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
|
||
|
|
if(i4_status == SC_NOT_FOUND)
|
||
|
|
{
|
||
|
|
return (VCL_NAL_FOUND_FALSE);
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_cur_pos = *pu4_bytes_consumed;
|
||
|
|
ps_nal_parse_ctxt->i4_dec_frst_sc_flag = SVCD_FALSE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If number of bytes left in the previous process call */
|
||
|
|
/* is is greater or equal to number of bytes in input */
|
||
|
|
/* buffer of the current process call then declare that */
|
||
|
|
/* end of bitstream has occurred and consume the bytes */
|
||
|
|
/* but do not decode */
|
||
|
|
if(ps_nal_parse_ctxt->u4_bytes_left >= (UWORD32) *pu4_num_bytes)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
|
||
|
|
*pu4_bytes_consumed = *pu4_num_bytes;
|
||
|
|
|
||
|
|
i4_status = isvcd_nal_parse_partial_signal_eos(ps_nal_parse_ctxt, NULL, ps_non_vcl_nal);
|
||
|
|
return (i4_status);
|
||
|
|
}
|
||
|
|
|
||
|
|
do
|
||
|
|
{
|
||
|
|
nal_buf_t *ps_nal_buf;
|
||
|
|
UWORD32 *pu4_bytes_left;
|
||
|
|
|
||
|
|
/*********************************************************************/
|
||
|
|
/* NAL BOUNDARY DETECTION */
|
||
|
|
/*********************************************************************/
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
/* Detect NAL boundary */
|
||
|
|
/* After return, this NAL boundary detetction logic might be in */
|
||
|
|
/* one of following states: */
|
||
|
|
/* - NAL_START */
|
||
|
|
/* - FIND_NAL_END */
|
||
|
|
/* - NAL_END */
|
||
|
|
/*-------------------------------------------------------------------*/
|
||
|
|
if(ANNEX_B == ps_nal_parse_ctxt->i4_input_bitstream_mode)
|
||
|
|
{
|
||
|
|
i4_nal_start_flag = isvcd_get_annex_b_nal_unit(
|
||
|
|
pu1_stream_buffer, i4_cur_pos, *pu4_num_bytes,
|
||
|
|
&ps_nal_parse_ctxt->i4_find_nal_state, &ps_nal_parse_ctxt->i4_zero_byte_cnt,
|
||
|
|
&u4_bytes_consumed_temp, ps_nal_parse_ctxt->pv_nal_unit, &i4_more_data_flag);
|
||
|
|
|
||
|
|
i4_cur_pos += u4_bytes_consumed_temp;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If current NAL unit is start of new NAL unit then parse the NAL
|
||
|
|
header. If the current NAL unit type is VCL NAL then return from
|
||
|
|
this function. otherwise apply NAL discard logic and discard the
|
||
|
|
NAL if discard NAL flag is true */
|
||
|
|
|
||
|
|
if(SVCD_TRUE == i4_nal_start_flag)
|
||
|
|
{
|
||
|
|
UWORD32 u4_err_code;
|
||
|
|
WORD32 i4_sps_pps_corrupt_status;
|
||
|
|
|
||
|
|
/* Get the NAL prms. This involves the following things*/
|
||
|
|
/* 1. Decode the NAL header */
|
||
|
|
/* 2. Set the discard flag */
|
||
|
|
/* 3. Decode the slice header if needed */
|
||
|
|
isvcd_get_nal_prms(ps_nal_unit->pu1_bufs, ps_nal_unit->i4_buf_sizes, ps_nal_prms,
|
||
|
|
&ps_nal_parse_ctxt->s_prefix_nal_prms,
|
||
|
|
&ps_nal_parse_ctxt->s_prefix_nal_buf, &u4_err_code,
|
||
|
|
&i4_sps_pps_corrupt_status, &ps_nal_parse_ctxt->i4_discard_nal_flag,
|
||
|
|
ps_nal_parse_ctxt);
|
||
|
|
/* If the error code returned by the "picture boundary" */
|
||
|
|
/* detetction is */
|
||
|
|
/* 1. Insufficient bitstream size: then store the bytes */
|
||
|
|
/* left and break out of the loop */
|
||
|
|
/* 2. Corrupted slice: then discard the slice */
|
||
|
|
if((NAL_INSUFFICIENT_DATA == (WORD32) u4_err_code) &&
|
||
|
|
(NAL_END != ps_nal_parse_ctxt->i4_find_nal_state))
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->u4_bytes_left = *pu4_num_bytes - *pu4_bytes_consumed;
|
||
|
|
|
||
|
|
/* Reset the NAL level tracking variables */
|
||
|
|
isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
else if(0 != u4_err_code)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Populate other paramters based on the nal prms */
|
||
|
|
ps_nal_parse_ctxt->i4_nal_type = ps_nal_prms->i4_derived_nal_type;
|
||
|
|
i4_nal_header_len = ps_nal_prms->i4_nal_header_len;
|
||
|
|
|
||
|
|
/* If derived NAL unit is VCL_NAL then return from this function */
|
||
|
|
if(VCL_NAL == ps_nal_prms->i4_derived_nal_type &&
|
||
|
|
PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type)
|
||
|
|
{
|
||
|
|
isvcd_pic_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
|
||
|
|
return (VCL_NAL_FOUND_TRUE);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Set the active NAL buffer structure and initialize */
|
||
|
|
/* the nal buffer structure */
|
||
|
|
isvcd_get_nal_buf(ps_nal_parse_ctxt, &ps_nal_buf);
|
||
|
|
|
||
|
|
ps_nal_parse_ctxt->ps_nal_buf = ps_nal_buf;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Update the bytes consumed variable */
|
||
|
|
|
||
|
|
*pu4_bytes_consumed += u4_bytes_consumed_temp;
|
||
|
|
|
||
|
|
ps_nal_buf = ps_nal_parse_ctxt->ps_nal_buf;
|
||
|
|
if(VCL_NAL == ps_nal_parse_ctxt->i4_nal_type)
|
||
|
|
{
|
||
|
|
ppu1_out_buf = &ps_nal_parse_ctxt->pu1_vcl_nal_buf;
|
||
|
|
pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_vcl;
|
||
|
|
if(*pu4_bytes_left < (MAX_VCL_NAL_BUFF_SIZE * 0.05))
|
||
|
|
{
|
||
|
|
return (VCL_NAL_FOUND_FALSE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
ppu1_out_buf = &ps_nal_parse_ctxt->pu1_non_vcl_nal_buf;
|
||
|
|
pu4_bytes_left = &ps_nal_parse_ctxt->u4_bytes_left_non_vcl;
|
||
|
|
if(*pu4_bytes_left < (MAX_NON_VCL_NAL_BUFF_SIZE * 0.05))
|
||
|
|
{
|
||
|
|
return (VCL_NAL_FOUND_FALSE);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/* if 0 bytes left then discard the current NAL */
|
||
|
|
if(0 >= (WORD32) *pu4_bytes_left)
|
||
|
|
{
|
||
|
|
ps_nal_parse_ctxt->i4_discard_nal_flag = SVCD_TRUE;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If NAL is not discarded then :
|
||
|
|
1) Perform emulation prevention and byte swapping on the RBSP data
|
||
|
|
2) Update the NAL unit ctxt:
|
||
|
|
a) If VCL NAL then update DQID list
|
||
|
|
b) If NON VCL NAL then update the non vcl output structure */
|
||
|
|
|
||
|
|
if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
|
||
|
|
{
|
||
|
|
UWORD32 u4_output_bytes, u4_buf_inc;
|
||
|
|
|
||
|
|
{
|
||
|
|
UWORD32 u4_buf_size;
|
||
|
|
|
||
|
|
/* clip the size before emulation prevention */
|
||
|
|
u4_buf_size = (UWORD32) CLIP3(0, (WORD32) *pu4_bytes_left,
|
||
|
|
(ps_nal_unit->i4_buf_sizes - i4_nal_header_len));
|
||
|
|
|
||
|
|
u4_buf_inc = isvcd_nal_byte_swap_emulation(
|
||
|
|
(UWORD32 *) *ppu1_out_buf, &u4_output_bytes,
|
||
|
|
ps_nal_unit->pu1_bufs + i4_nal_header_len, u4_buf_size,
|
||
|
|
NUM_OF_ZERO_BYTES_BEFORE_START_CODE, &ps_nal_parse_ctxt->s_emulation_ctxt);
|
||
|
|
i4_nal_header_len = 0;
|
||
|
|
|
||
|
|
u4_buf_inc = UP_ALIGN_8(u4_buf_inc);
|
||
|
|
*ppu1_out_buf += u4_buf_inc;
|
||
|
|
*pu4_bytes_left -= u4_buf_inc;
|
||
|
|
ps_nal_buf->i4_buf_size += u4_output_bytes;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*********************************************************************/
|
||
|
|
/* UPDATE VARIABLES */
|
||
|
|
/*********************************************************************/
|
||
|
|
|
||
|
|
if(NAL_END == ps_nal_parse_ctxt->i4_find_nal_state)
|
||
|
|
{
|
||
|
|
/*---------------------------------------------------------------*/
|
||
|
|
/* - Update the total bits in the NAL. While doing so bits */
|
||
|
|
/* calculated so far should be converted to SODB length */
|
||
|
|
/*---------------------------------------------------------------*/
|
||
|
|
if(SVCD_FALSE == ps_nal_parse_ctxt->i4_discard_nal_flag)
|
||
|
|
{
|
||
|
|
isvcd_update_nal_ctxt(ps_nal_parse_ctxt, NULL, ps_non_vcl_nal);
|
||
|
|
|
||
|
|
UPDATE_NAL_BUF_PTR(ppu1_out_buf, ps_nal_prms->i4_derived_nal_type, pu4_bytes_left);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* If the prefix NAL unit is not immediatly followed by */
|
||
|
|
/* a AVC NAL unit it shall be discarded and hence reset */
|
||
|
|
/* is done */
|
||
|
|
/* Also if prefix NAL unit is discarded then we should */
|
||
|
|
/* not associate the prefix NAL unit with AVC NAL unit */
|
||
|
|
/* and hence a reset is required */
|
||
|
|
if((PREFIX_UNIT_NAL != ps_nal_prms->i4_nal_unit_type) ||
|
||
|
|
(SVCD_TRUE == ps_nal_parse_ctxt->i4_discard_nal_flag))
|
||
|
|
{
|
||
|
|
isvcd_nal_buf_reset(&ps_nal_parse_ctxt->s_prefix_nal_buf);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Reset NAL level tracking variables */
|
||
|
|
isvcd_nal_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
}
|
||
|
|
|
||
|
|
i4_nal_header_len = 0;
|
||
|
|
/*------------- while loop ends here --------------------------------*/
|
||
|
|
} while(SVCD_TRUE == i4_more_data_flag);
|
||
|
|
|
||
|
|
if(i4_more_data_flag == 0)
|
||
|
|
{
|
||
|
|
isvcd_pic_reset_ctxt(ps_nal_parse_ctxt);
|
||
|
|
return (VCL_NAL_FOUND_TRUE);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (VCL_NAL_FOUND_FALSE);
|
||
|
|
}
|