aboutsummaryrefslogtreecommitdiff
path: root/Src/h264dec/ldecod/src/erc_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/h264dec/ldecod/src/erc_api.c')
-rw-r--r--Src/h264dec/ldecod/src/erc_api.c371
1 files changed, 371 insertions, 0 deletions
diff --git a/Src/h264dec/ldecod/src/erc_api.c b/Src/h264dec/ldecod/src/erc_api.c
new file mode 100644
index 00000000..48e827a0
--- /dev/null
+++ b/Src/h264dec/ldecod/src/erc_api.c
@@ -0,0 +1,371 @@
+
+/*!
+ *************************************************************************************
+ * \file erc_api.c
+ *
+ * \brief
+ * External (still inside video decoder) interface for error concealment module
+ *
+ * \author
+ * - Ari Hourunranta <ari.hourunranta@nokia.com>
+ * - Viktor Varsa <viktor.varsa@nokia.com>
+ * - Ye-Kui Wang <wyk@ieee.org>
+ *
+ *************************************************************************************
+ */
+
+
+#include "global.h"
+#include "memalloc.h"
+#include "erc_api.h"
+
+/*!
+ ************************************************************************
+ * \brief
+ * Initinize the error concealment module
+ ************************************************************************
+ */
+void ercInit(VideoParameters *p_Vid, int pic_sizex, int pic_sizey, int flag)
+{
+ ercClose(p_Vid, p_Vid->erc_errorVar);
+ p_Vid->erc_object_list = (objectBuffer_t *) calloc((pic_sizex * pic_sizey) >> 6, sizeof(objectBuffer_t));
+ if (p_Vid->erc_object_list == NULL) no_mem_exit("ercInit: erc_object_list");
+
+ // the error concealment instance is allocated
+ p_Vid->erc_errorVar = ercOpen();
+
+ // set error concealment ON
+ ercSetErrorConcealment(p_Vid->erc_errorVar, flag);
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Allocates data structures used in error concealment.
+ *\return
+ * The allocated ercVariables_t is returned.
+ ************************************************************************
+ */
+ercVariables_t *ercOpen( void )
+{
+ ercVariables_t *errorVar = NULL;
+
+ errorVar = (ercVariables_t *)malloc( sizeof(ercVariables_t));
+ if ( errorVar == NULL ) no_mem_exit("ercOpen: errorVar");
+
+ errorVar->nOfMBs = 0;
+ errorVar->segments = NULL;
+ errorVar->currSegment = 0;
+ errorVar->yCondition = NULL;
+ errorVar->uCondition = NULL;
+ errorVar->vCondition = NULL;
+ errorVar->prevFrameYCondition = NULL;
+
+ errorVar->concealment = 1;
+
+ return errorVar;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Resets the variables used in error detection.
+ * Should be called always when starting to decode a new frame.
+ * \param errorVar
+ * Variables for error concealment
+ * \param nOfMBs
+ * Number of macroblocks in a frame
+ * \param numOfSegments
+ * Estimated number of segments (memory reserved)
+ * \param picSizeX
+ * Width of the frame in pixels.
+ ************************************************************************
+ */
+void ercReset( ercVariables_t *errorVar, int nOfMBs, int numOfSegments, int picSizeX )
+{
+ if ( errorVar && errorVar->concealment )
+ {
+ int i = 0;
+
+ // If frame size has been changed
+ if ( nOfMBs != errorVar->nOfMBs && errorVar->yCondition != NULL )
+ {
+ free( errorVar->yCondition );
+ errorVar->yCondition = NULL;
+ free( errorVar->prevFrameYCondition );
+ errorVar->prevFrameYCondition = NULL;
+ free( errorVar->uCondition );
+ errorVar->uCondition = NULL;
+ free( errorVar->vCondition );
+ errorVar->vCondition = NULL;
+ free( errorVar->segments );
+ errorVar->segments = NULL;
+ }
+
+ // If the structures are uninitialized (first frame, or frame size is changed)
+ if ( errorVar->yCondition == NULL )
+ {
+ errorVar->segments = (ercSegment_t *)malloc( numOfSegments*sizeof(ercSegment_t) );
+ if ( errorVar->segments == NULL ) no_mem_exit("ercReset: errorVar->segments");
+ memset( errorVar->segments, 0, numOfSegments*sizeof(ercSegment_t));
+ errorVar->nOfSegments = numOfSegments;
+
+ errorVar->yCondition = (int *)malloc( 4*nOfMBs*sizeof(int) );
+ if ( errorVar->yCondition == NULL ) no_mem_exit("ercReset: errorVar->yCondition");
+ errorVar->prevFrameYCondition = (int *)malloc( 4*nOfMBs*sizeof(int) );
+ if ( errorVar->prevFrameYCondition == NULL ) no_mem_exit("ercReset: errorVar->prevFrameYCondition");
+ errorVar->uCondition = (int *)malloc( nOfMBs*sizeof(int) );
+ if ( errorVar->uCondition == NULL ) no_mem_exit("ercReset: errorVar->uCondition");
+ errorVar->vCondition = (int *)malloc( nOfMBs*sizeof(int) );
+ if ( errorVar->vCondition == NULL ) no_mem_exit("ercReset: errorVar->vCondition");
+ errorVar->nOfMBs = nOfMBs;
+ }
+ else
+ {
+ // Store the yCondition struct of the previous frame
+ int *tmp = errorVar->prevFrameYCondition;
+ errorVar->prevFrameYCondition = errorVar->yCondition;
+ errorVar->yCondition = tmp;
+ }
+
+ // Reset tables and parameters
+ memset( errorVar->yCondition, 0, 4*nOfMBs*sizeof(*errorVar->yCondition));
+ memset( errorVar->uCondition, 0, nOfMBs*sizeof(*errorVar->uCondition));
+ memset( errorVar->vCondition, 0, nOfMBs*sizeof(*errorVar->vCondition));
+
+ if (errorVar->nOfSegments != numOfSegments)
+ {
+ free( errorVar->segments );
+ errorVar->segments = NULL;
+ errorVar->segments = (ercSegment_t *)malloc( numOfSegments*sizeof(ercSegment_t) );
+ if ( errorVar->segments == NULL ) no_mem_exit("ercReset: errorVar->segments");
+ errorVar->nOfSegments = numOfSegments;
+ }
+
+ memset( errorVar->segments, 0, errorVar->nOfSegments*sizeof(ercSegment_t));
+
+ for ( ; i < errorVar->nOfSegments; i++ )
+ {
+ errorVar->segments[i].fCorrupted = 1; //! mark segments as corrupted
+ errorVar->segments[i].startMBPos = 0;
+ errorVar->segments[i].endMBPos = nOfMBs - 1;
+ }
+
+ errorVar->currSegment = 0;
+ errorVar->nOfCorruptedSegments = 0;
+ }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Resets the variables used in error detection.
+ * Should be called always when starting to decode a new frame.
+ * \param p_Vid
+ * VideoParameters variable
+ * \param errorVar
+ * Variables for error concealment
+ ************************************************************************
+ */
+void ercClose(VideoParameters *p_Vid, ercVariables_t *errorVar )
+{
+ if ( errorVar != NULL )
+ {
+ if (errorVar->yCondition != NULL)
+ {
+ free( errorVar->segments );
+ free( errorVar->yCondition );
+ free( errorVar->uCondition );
+ free( errorVar->vCondition );
+ free( errorVar->prevFrameYCondition );
+ }
+ free( errorVar );
+ errorVar = NULL;
+ }
+
+ if ( p_Vid && p_Vid->erc_object_list)
+ {
+ free(p_Vid->erc_object_list);
+ p_Vid->erc_object_list=NULL;
+ }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Sets error concealment ON/OFF. Can be invoked only between frames, not during a frame
+ * \param errorVar
+ * Variables for error concealment
+ * \param value
+ * New value
+ ************************************************************************
+ */
+void ercSetErrorConcealment( ercVariables_t *errorVar, int value )
+{
+ if ( errorVar != NULL )
+ errorVar->concealment = value;
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Creates a new segment in the segment-list, and marks the start MB and bit position.
+ * If the end of the previous segment was not explicitly marked by "ercStopSegment",
+ * also marks the end of the previous segment.
+ * If needed, it reallocates the segment-list for a larger storage place.
+ * \param currMBNum
+ * The MB number where the new slice/segment starts
+ * \param segment
+ * Segment/Slice No. counted by the caller
+ * \param bitPos
+ * Bitstream pointer: number of bits read from the buffer.
+ * \param errorVar
+ * Variables for error detector
+ ************************************************************************
+ */
+void ercStartSegment( int currMBNum, int segment, unsigned int bitPos, ercVariables_t *errorVar )
+{
+ if ( errorVar && errorVar->concealment )
+ {
+ errorVar->currSegmentCorrupted = 0;
+
+ errorVar->segments[ segment ].fCorrupted = 0;
+ errorVar->segments[ segment ].startMBPos = currMBNum;
+ }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Marks the end position of a segment.
+ * \param currMBNum
+ * The last MB number of the previous segment
+ * \param segment
+ * Segment/Slice No. counted by the caller
+ * If (segment<0) the internal segment counter is used.
+ * \param bitPos
+ * Bitstream pointer: number of bits read from the buffer.
+ * \param errorVar
+ * Variables for error detector
+ ************************************************************************
+ */
+void ercStopSegment( int currMBNum, int segment, unsigned int bitPos, ercVariables_t *errorVar )
+{
+ if ( errorVar && errorVar->concealment )
+ {
+ errorVar->segments[ segment ].endMBPos = currMBNum; //! Changed TO 12.11.2001
+ errorVar->currSegment++;
+ }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Marks the current segment (the one which has the "currMBNum" MB in it)
+ * as lost: all the blocks of the MBs in the segment as corrupted.
+ * \param picSizeX
+ * Width of the frame in pixels.
+ * \param errorVar
+ * Variables for error detector
+ ************************************************************************
+ */
+void ercMarkCurrSegmentLost(int picSizeX, ercVariables_t *errorVar )
+{
+ if ( errorVar && errorVar->concealment )
+ {
+ int current_segment = errorVar->currSegment-1, j;
+
+ if (errorVar->currSegmentCorrupted == 0)
+ {
+ errorVar->nOfCorruptedSegments++;
+ errorVar->currSegmentCorrupted = 1;
+ }
+
+ for ( j = errorVar->segments[current_segment].startMBPos; j <= errorVar->segments[current_segment].endMBPos; j++ )
+ {
+ errorVar->yCondition[MBNum2YBlock (j, 0, picSizeX)] = ERC_BLOCK_CORRUPTED;
+ errorVar->yCondition[MBNum2YBlock (j, 1, picSizeX)] = ERC_BLOCK_CORRUPTED;
+ errorVar->yCondition[MBNum2YBlock (j, 2, picSizeX)] = ERC_BLOCK_CORRUPTED;
+ errorVar->yCondition[MBNum2YBlock (j, 3, picSizeX)] = ERC_BLOCK_CORRUPTED;
+ errorVar->uCondition[j] = ERC_BLOCK_CORRUPTED;
+ errorVar->vCondition[j] = ERC_BLOCK_CORRUPTED;
+ }
+ errorVar->segments[current_segment].fCorrupted = 1;
+ }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Marks the current segment (the one which has the "currMBNum" MB in it)
+ * as OK: all the blocks of the MBs in the segment as OK.
+ * \param picSizeX
+ * Width of the frame in pixels.
+ * \param errorVar
+ * Variables for error detector
+ ************************************************************************
+ */
+void ercMarkCurrSegmentOK(int picSizeX, ercVariables_t *errorVar )
+{
+ if ( errorVar && errorVar->concealment )
+ {
+ int current_segment = errorVar->currSegment-1, j;
+
+ // mark all the Blocks belonging to the segment as OK */
+ for ( j = errorVar->segments[current_segment].startMBPos; j <= errorVar->segments[current_segment].endMBPos; j++ )
+ {
+ errorVar->yCondition[MBNum2YBlock (j, 0, picSizeX)] = ERC_BLOCK_OK;
+ errorVar->yCondition[MBNum2YBlock (j, 1, picSizeX)] = ERC_BLOCK_OK;
+ errorVar->yCondition[MBNum2YBlock (j, 2, picSizeX)] = ERC_BLOCK_OK;
+ errorVar->yCondition[MBNum2YBlock (j, 3, picSizeX)] = ERC_BLOCK_OK;
+ errorVar->uCondition[j] = ERC_BLOCK_OK;
+ errorVar->vCondition[j] = ERC_BLOCK_OK;
+ }
+ errorVar->segments[current_segment].fCorrupted = 0;
+ }
+}
+
+/*!
+ ************************************************************************
+ * \brief
+ * Marks the Blocks of the given component (YUV) of the current MB as concealed.
+ * \param currMBNum
+ * Selects the segment where this MB number is in.
+ * \param comp
+ * Component to mark (0:Y, 1:U, 2:V, <0:All)
+ * \param picSizeX
+ * Width of the frame in pixels.
+ * \param errorVar
+ * Variables for error detector
+ ************************************************************************
+ */
+void ercMarkCurrMBConcealed( int currMBNum, int comp, int picSizeX, ercVariables_t *errorVar )
+{
+ int setAll = 0;
+
+ if ( errorVar && errorVar->concealment )
+ {
+ if (comp < 0)
+ {
+ setAll = 1;
+ comp = 0;
+ }
+
+ switch (comp)
+ {
+ case 0:
+ errorVar->yCondition[MBNum2YBlock (currMBNum, 0, picSizeX)] = ERC_BLOCK_CONCEALED;
+ errorVar->yCondition[MBNum2YBlock (currMBNum, 1, picSizeX)] = ERC_BLOCK_CONCEALED;
+ errorVar->yCondition[MBNum2YBlock (currMBNum, 2, picSizeX)] = ERC_BLOCK_CONCEALED;
+ errorVar->yCondition[MBNum2YBlock (currMBNum, 3, picSizeX)] = ERC_BLOCK_CONCEALED;
+ if (!setAll)
+ break;
+ case 1:
+ errorVar->uCondition[currMBNum] = ERC_BLOCK_CONCEALED;
+ if (!setAll)
+ break;
+ case 2:
+ errorVar->vCondition[currMBNum] = ERC_BLOCK_CONCEALED;
+ }
+ }
+}