videoeditorengine/avcedit/src/slice.cpp
changeset 0 951a5db380a0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videoeditorengine/avcedit/src/slice.cpp	Fri Jan 29 14:08:33 2010 +0200
@@ -0,0 +1,1124 @@
+/*
+* Copyright (c) 2010 Ixonos Plc.
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - Initial contribution
+*
+* Contributors:
+* Ixonos Plc
+*
+* Description:
+*
+*/
+
+
+#include <string.h>
+#include "globals.h"
+#include "bitbuffer.h"
+#include "vld.h"
+#include "macroblock.h"
+#include "parameterset.h"
+#include "framebuffer.h"
+#include "dpb.h"
+#include "slice.h"
+#include "sequence.h"
+
+
+#define MIN_ALPHA_BETA_OFFSET   -6
+#define MAX_ALPHA_BETA_OFFSET   6
+
+/*
+ * AVC syntax functions as specified in specification
+ */
+
+
+/*
+ * Static functions
+ */
+
+static int getRefPicListReorderingCmds(slice_s *slice, unsigned int numRefFrames,
+                                       bitbuffer_s *bitbuf);
+
+static int getDecRefPicMarkingCmds(slice_s *slice, unsigned int numRefFrames,
+                                   bitbuffer_s *bitbuf);
+
+static int refPicListReordering(slice_s *slice, dpb_s *dpb,
+                                 frmBuf_s *refPicList[], int numRefPicActive,
+                                 sliceRefPicListReorderCmd_s reorderCmdList[]);
+
+
+
+/*
+ * AVC syntax functions as specified in specification
+ */
+
+/* Return fixed length code */
+static int u_n(bitbuffer_s *bitbuf, int len, unsigned int *val)
+{
+  *val = vldGetFLC(bitbuf, len);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return SLICE_ERROR;
+
+  return SLICE_OK;
+}
+
+/* Return unsigned UVLC code */
+static int ue_v(bitbuffer_s *bitbuf, unsigned int *val, unsigned int maxVal)
+{
+  *val = vldGetUVLC(bitbuf);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return SLICE_ERROR;
+
+  if (*val > maxVal)
+    return SLICE_ERR_ILLEGAL_VALUE;
+
+  return SLICE_OK;
+}
+
+/* Return signed UVLC code */
+static int se_v(bitbuffer_s *bitbuf, int *val, int minVal, int maxVal)
+{
+  *val = vldGetSignedUVLC(bitbuf);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return SLICE_ERROR;
+
+  if (*val < minVal || *val > maxVal)
+    return SLICE_ERR_ILLEGAL_VALUE;
+
+  return SLICE_OK;
+}
+
+/* Return long signed UVLC code */
+static int se_v_long(bitbuffer_s *bitbuf, int32 *val)
+{
+  *val = vldGetSignedUVLClong(bitbuf);
+
+  if (bibGetStatus(bitbuf) < 0)
+    return SLICE_ERROR;
+
+  return SLICE_OK;
+}
+
+
+/*
+ *
+ * sliceOpen:
+ *
+ * Parameters:
+ *
+ * Function:
+ *      Allocate and initialize a slice.
+ *
+ * Returns:
+ *      Pointer to slice
+ *
+ */
+slice_s *sliceOpen()
+{
+  slice_s *slice;
+
+  slice = (slice_s *)User::Alloc(sizeof(slice_s));
+
+  if (slice != NULL)
+    memset(slice, 0, sizeof(slice_s));
+
+  return slice;
+}
+
+
+/*
+ *
+ * sliceClose:
+ *
+ * Parameters:
+ *      slice                 Slice object
+ *
+ * Function:
+ *      Deallocate slice
+ *
+ * Returns:
+ *      Nothing
+ *
+ */
+void sliceClose(slice_s *slice)
+{
+  User::Free(slice);
+}
+
+
+/*
+ * getRefPicListReorderingCmds:
+ *
+ * Parameters:
+ *     slice               Slice object
+ *     bitbuf              Bitbuffer object
+ *     numRefFrames        Number of reference frames in used
+ *
+ * Function:
+ *     Parse and store the ref pic reordering commands
+ *
+ * Return:
+ *     The number of bits being parsed
+ */
+static int getRefPicListReorderingCmds(slice_s *slice, unsigned int numRefFrames,
+                                       bitbuffer_s *bitbuf)
+{
+  int i;
+  unsigned int reordering_of_pic_nums_idc;
+  int retCode;
+
+  if (!IS_SLICE_I(slice->slice_type)) {
+
+    if ((retCode = u_n(bitbuf, 1, &slice->ref_pic_list_reordering_flag0)) < 0)
+      return retCode;
+
+    if (slice->ref_pic_list_reordering_flag0) {
+
+      i = 0;
+      do {
+        /* Get command */
+        if ((retCode = ue_v(bitbuf, &reordering_of_pic_nums_idc, 3)) < 0)
+          return retCode;
+
+        slice->reorderCmdList[i].reordering_of_pic_nums_idc = reordering_of_pic_nums_idc;
+
+        /* Get command parameters */
+        if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) {
+          unsigned int maxDiff = slice->maxFrameNum/2-1;
+          if (reordering_of_pic_nums_idc == 1)
+            maxDiff = maxDiff - 1;
+          if ((retCode = ue_v(bitbuf, &slice->reorderCmdList[i].abs_diff_pic_num_minus1, maxDiff)) < 0)
+            return retCode;
+        }
+        else if (reordering_of_pic_nums_idc == 2) {
+          /* longTermPicNum be in the range of 0 to num_ref_frames, inclusive. */
+          if ((retCode = ue_v(bitbuf, &slice->reorderCmdList[i].long_term_pic_num, numRefFrames)) < 0)
+            return retCode;
+        }
+
+        i++;
+      } while (reordering_of_pic_nums_idc != 3 && i < MAX_NUM_OF_REORDER_CMDS);
+    }
+  }
+
+  return SLICE_OK;
+}
+
+
+/*
+ * getDecRefPicMarkingCmds:
+ *
+ * Parameters:
+ *     slice               Slice object
+ *     bitbuf              Bitbuffer object
+ *     numRefFrames        Number of reference frames in used
+ *
+ * Function:
+ *     Parse and store the MMCO commands
+ *
+ * Return:
+ *     The number of bits being parsed
+ */
+static int getDecRefPicMarkingCmds(slice_s *slice, unsigned int numRefFrames,
+                                   bitbuffer_s *bitbuf)
+{
+  int i;
+  unsigned int mmco;
+  int retCode;
+
+  /* MMCO commands can exist only in slice header of a reference picture */
+  if (slice->nalRefIdc != 0) {
+    if (slice->isIDR) {
+      if ((retCode = u_n(bitbuf, 1, &slice->no_output_of_prior_pics_flag)) < 0)
+        return retCode;
+      if ((retCode = u_n(bitbuf, 1, &slice->long_term_reference_flag)) < 0)
+        return retCode;
+    }
+    else {
+      if ((retCode = u_n(bitbuf, 1, &slice->adaptive_ref_pic_marking_mode_flag)) < 0)
+        return retCode;
+
+      if (slice->adaptive_ref_pic_marking_mode_flag) {
+
+        i = 0;
+        do {
+          /* Get MMCO command */
+          if ((retCode = ue_v(bitbuf, &mmco, 6)) < 0)
+            return retCode;
+
+          slice->mmcoCmdList[i].memory_management_control_operation = mmco;
+
+          /* Get command parameter (if any) */
+          if (mmco == 1 || mmco == 3) {
+            if ((retCode = ue_v(bitbuf, &slice->mmcoCmdList[i].difference_of_pic_nums_minus1, 65535)) < 0)
+              return retCode;
+          }
+          if (mmco == 2) {
+            if ((retCode = ue_v(bitbuf, &slice->mmcoCmdList[i].long_term_pic_num, numRefFrames)) < 0)
+              return retCode;
+          }
+          if (mmco == 3 || mmco == 6) {
+            if ((retCode = ue_v(bitbuf, &slice->mmcoCmdList[i].long_term_frame_idx, numRefFrames)) < 0)
+              return retCode;
+          }
+          if (mmco == 4) {
+            if ((retCode = ue_v(bitbuf, &slice->mmcoCmdList[i].max_long_term_frame_idx_plus1, numRefFrames)) < 0)
+              return retCode;
+          }
+          if (mmco == 5) {
+            slice->picHasMMCO5 = 1;
+          }
+
+          i++;
+        } while (mmco != 0 && i < MAX_NUM_OF_MMCO_OPS);
+      }
+    }
+  }
+  else
+    slice->adaptive_ref_pic_marking_mode_flag = 0;
+
+  return 1;
+}
+
+
+/*
+ * sliceInitRefPicList:
+ *
+ * Parameters:
+ *     dpb                  DPB buffer
+ *     refPicList           Reference picture list (output)
+ *
+ * Fucntion:
+ *     Initialize reference picture list.
+ *
+ * Return:
+ *     Number of reference frames in the list
+ */
+int sliceInitRefPicList(dpb_s *dpb, frmBuf_s *refPicList[])
+{
+  int numRef, numShort;
+  frmBuf_s *refTmp;
+  int i, j;
+
+  /*
+   * Select the reference pictures from the DPB
+   */
+  j = 0;
+  /* Put short term pictures first in the list */
+  for (i = 0; i < dpb->fullness; i++) {
+    if (dpb->buffers[i]->refType == FRM_SHORT_TERM_PIC) 
+      refPicList[j++] = dpb->buffers[i];
+  }
+  numShort = j;
+  /* Put long term pictures after the short term pictures */
+  for (i = 0; i < dpb->fullness; i++) {
+    if (dpb->buffers[i]->refType == FRM_LONG_TERM_PIC) 
+      refPicList[j++] = dpb->buffers[i];
+  }
+  numRef = j;
+  /* numLong = numRef - numShort; */
+
+  /*
+   * Initialisation process for reference picture lists
+   */
+  /* Sort short term pictures in the order of descending picNum */
+  for (i = 0; i < numShort; i++) {
+    for (j = i+1; j < numShort; j++) {
+      if (refPicList[i]->picNum < refPicList[j]->picNum) {
+        /* exchange refPicList[i] and refPicList[j] */
+        refTmp = refPicList[i];
+        refPicList[i] = refPicList[j];
+        refPicList[j] = refTmp;
+      }
+    }
+  }
+  /* Sort long term pictures in the order of ascending longTermPicNum */
+  for (i = numShort; i < numRef; i++) {
+    for (j = i+1; j < numRef; j++) {
+      if (refPicList[i]->longTermPicNum > refPicList[j]->longTermPicNum) {
+        /* exchange refPicList[i] and refPicList[j] */
+        refTmp = refPicList[i];
+        refPicList[i] = refPicList[j];
+        refPicList[j] = refTmp;
+      }
+    }
+  }
+
+  return numRef;
+}
+
+
+/*
+ * sliceFixRefPicList:
+ *
+ * Parameters:
+ *     dpb                  DPB buffer
+ *     refPicList           Reference picture list (output)
+ *     numRefPicActive      Number of active reference frames
+ *     numExistingRefFrames Number of reference frames in refPicList
+ *
+ * Fucntion:
+ *     If numExistingRefFrames < numRefPicActive, try to fill up the
+ *     reference frame list
+ *
+ * Return:
+ *     0 for no pictures exist in reference frame list
+ *     1 for pictures exist in reference frame list
+ */
+int sliceFixRefPicList(dpb_s *dpb, frmBuf_s *refPicList[],
+                       int numRefPicActive, int numExistingRefFrames,
+                       int width, int height)
+{
+  int i;
+
+  if (numExistingRefFrames == 0) {
+    /* Try to find any picture in DPB, even non-reference frame */
+    for (i = 0; i < dpb->size; i++) {
+      if (dpb->buffers[i] != NULL && dpb->buffers[i]->width == width && dpb->buffers[i]->height == height)
+        break;
+    }
+
+    if (i < dpb->size) {
+      refPicList[0] = dpb->buffers[i];
+      numExistingRefFrames = 1;
+    }
+    else
+      return 0;
+  }
+
+  /* Duplicate last extry of the reference frame list so that list becomes full */
+  for (i = numExistingRefFrames; i < numRefPicActive; i++)
+    refPicList[i] = refPicList[numExistingRefFrames-1];
+
+  return 1;
+}
+
+/*
+ * refPicListReordering:
+ *
+ * Parameters:
+ *     slice                Current slice object
+ *     dpb                  DPB buffer
+ *     refPicList           Reference picture list (modified by this function)
+ *     numRefPicActive      Number of active reference frames
+ *     reorderCmdList       Reordering command list
+ *
+ * Fucntion:
+ *     Reorder the reference picture list for current slice
+ *
+ * Return:
+ *     SLICE_OK for no error and negative value for error
+ */
+static int refPicListReordering(slice_s *slice, dpb_s *dpb,
+                                frmBuf_s *refPicList[], int numRefPicActive,
+                                sliceRefPicListReorderCmd_s reorderCmdList[])
+{
+  int i;
+  int reordering_of_pic_nums_idc, longTermPicNum;
+  int32 absDiffPicNum;
+  int refIdx;
+  int32 currPicNum, picNumPred, picNumNoWrap;
+  int32 maxPicNum, picNum;
+  int cmdNum;
+  int cIdx, nIdx;
+
+  /*
+   * 3. Reordering process for reference picture list
+   */
+
+  maxPicNum = slice->maxFrameNum;   /* for frame coding only */
+  currPicNum = slice->frame_num;
+  picNumPred = currPicNum;
+  refIdx = 0;
+  cmdNum = 0;
+
+  do {
+    reordering_of_pic_nums_idc = reorderCmdList[cmdNum].reordering_of_pic_nums_idc;
+
+    if (reordering_of_pic_nums_idc == 0 || reordering_of_pic_nums_idc == 1) {
+
+      /*
+       * reorder short-term ref pic  -subclause 8.2.4.3.1
+       */
+
+      absDiffPicNum = reorderCmdList[cmdNum].abs_diff_pic_num_minus1 + 1;
+
+      /* Derive picNumNoWrap */
+      if (reordering_of_pic_nums_idc == 0) {
+        if (picNumPred - absDiffPicNum < 0)
+          picNumNoWrap = picNumPred - absDiffPicNum + maxPicNum;
+        else
+          picNumNoWrap = picNumPred - absDiffPicNum;
+      }
+      else { /* reordering_of_pic_nums_idc == 1 */
+        if (picNumPred + absDiffPicNum >= maxPicNum) 
+          picNumNoWrap = picNumPred + absDiffPicNum - maxPicNum;
+        else
+          picNumNoWrap = picNumPred + absDiffPicNum;
+      }
+
+      /* Derive picNum */
+      if (picNumNoWrap > currPicNum)
+        picNum = picNumNoWrap - maxPicNum;
+      else
+        picNum = picNumNoWrap;
+
+      /* Find short term picture with picture number picNum */
+      for (i = 0; i < dpb->fullness; i++) {
+        if (!dpb->buffers[i]->nonExisting &&
+            dpb->buffers[i]->refType == FRM_SHORT_TERM_PIC &&
+            dpb->buffers[i]->picNum == picNum)
+          break;
+      }
+
+      /* If picNum was not found */
+      if (i == dpb->fullness) {
+        PRINT((_L("The short term ref pic(%d) is not found!\n"), picNum));
+        return SLICE_ERR_ILLEGAL_VALUE;
+      }
+
+      /* Shift remaining pictures later in the list */
+      for (cIdx = numRefPicActive; cIdx > refIdx; cIdx--)
+        refPicList[cIdx] = refPicList[cIdx - 1];
+
+      /* Place picture with number picNum into the index position refIdx */
+      refPicList[refIdx++] = dpb->buffers[i];
+
+      /* Remove duplicate of the inserted picture */
+      nIdx = refIdx;
+      for (cIdx = refIdx; cIdx <= numRefPicActive; cIdx++)
+        if (refPicList[cIdx]->refType == FRM_LONG_TERM_PIC || refPicList[cIdx]->picNum != picNum)
+          refPicList[nIdx++] = refPicList[cIdx];
+
+      picNumPred = picNumNoWrap;
+    }
+
+    else if (reordering_of_pic_nums_idc == 2) {
+
+      /*
+       * reorder long-term ref pic  -subclause 8.2.4.3.2
+       */
+
+      /* Get long-term picture number */
+      longTermPicNum = reorderCmdList[cmdNum].long_term_pic_num;
+
+      /* Find long-term picture with picture number longTermPicNum */
+      for (i = 0; i < dpb->fullness; i++)
+        if (dpb->buffers[i]->refType == FRM_LONG_TERM_PIC &&
+            dpb->buffers[i]->longTermPicNum == longTermPicNum)
+          break;
+
+      if (i == dpb->fullness) {
+        // something wrong !
+        PRINT((_L("The long term ref pic(%d) is not found!\n"), longTermPicNum));
+        return SLICE_ERR_ILLEGAL_VALUE;
+      }
+
+      /* Shift remaining pictures later in the list */
+      for (cIdx = numRefPicActive; cIdx > refIdx; cIdx--)
+        refPicList[cIdx] = refPicList[cIdx - 1];
+
+      /* Place picture with number longTermPicNum into the index position refIdx */
+      refPicList[refIdx++] = dpb->buffers[i];
+
+      /* Remove duplicate of the inserted picture */
+      nIdx = refIdx;
+      for (cIdx = refIdx; cIdx <= numRefPicActive; cIdx++)
+        if (refPicList[cIdx]->refType == FRM_SHORT_TERM_PIC ||
+            refPicList[cIdx]->longTermPicNum != longTermPicNum)
+        {
+          refPicList[nIdx++] = refPicList[cIdx];
+        }
+    }
+
+    cmdNum++;
+
+  } while (reordering_of_pic_nums_idc != 3 && cmdNum < MAX_NUM_OF_REORDER_CMDS);
+
+
+  refPicList[numRefPicActive] = 0;
+
+  return SLICE_OK;
+}
+
+
+// sliceParseMacroblocks
+// Parses the macroblocks one by one in the input slice. 
+TInt sliceParseMacroblocks(slice_s *slice, frmBuf_s *recoBuf, dpb_s *dpb,
+                           pic_parameter_set_s *pps,
+                           mbAttributes_s *mbData, TInt sliceID,
+                           bitbuffer_s *bitbuf,
+                           TBool aBitShiftInSlice)
+{
+  	frmBuf_s *refPicList0[DPB_MAX_SIZE+1];
+  	macroblock_s mb;
+  	TInt numRefFrames;
+  	TInt numExistingRefFrames;
+//  	TInt refFramesExist;
+  	TInt mbIdxY;
+  	TInt mbIdxX;
+  	TInt mbksPerLine;
+  	TInt mbksPerCol;
+  	TInt picSizeInMbs;
+  	TInt currMbAddr;
+  	TInt sliceGroupNum;
+  	void *stream;
+  	TInt retCode;
+
+  	// Choose number of reference frames and build reference picture list 
+  	numRefFrames   = 0;
+//  	refFramesExist = 0;
+  	if (!IS_SLICE_I(slice->slice_type)) 
+  	{	
+    	if (slice->num_ref_idx_active_override_flag)
+      		numRefFrames = slice->num_ref_idx_l0_active_minus1 + 1;
+    	else
+      		numRefFrames = pps->num_ref_idx_l0_active_minus1 + 1;
+
+    	numExistingRefFrames = sliceInitRefPicList(dpb, refPicList0);
+
+    	if (numExistingRefFrames < numRefFrames) 
+    	{
+//      		refFramesExist = sliceFixRefPicList(dpb, refPicList0, numRefFrames, numExistingRefFrames,
+//            	                                recoBuf->width, recoBuf->height);
+    	}
+    	else
+//      		refFramesExist = 1;
+
+    	if (slice->ref_pic_list_reordering_flag0 && numExistingRefFrames > 0) 
+    	{
+      		retCode = refPicListReordering(slice, dpb, refPicList0, numRefFrames, slice->reorderCmdList);
+      		
+      		if (retCode < 0)
+        		return retCode;
+    	}
+  	}
+
+  	mbksPerLine = recoBuf->width/MBK_SIZE;
+  	mbksPerCol  = recoBuf->height/MBK_SIZE;
+  	picSizeInMbs = mbksPerLine*mbksPerCol;
+
+  	currMbAddr = slice->first_mb_in_slice;
+  	sliceGroupNum = sliceID & 0xF;
+
+  	mbIdxY = currMbAddr / mbksPerLine;
+  	mbIdxX = currMbAddr - mbIdxY*mbksPerLine;
+
+  	mbkSetInitialQP(&mb, slice->qp, pps->chroma_qp_index_offset);
+
+  	stream = bitbuf;
+
+  	// Loop until all macroblocks in current slice have been decoded 
+  	// If there has been a bitshift in the slice, we must go through 
+  	// the macroblocks to see if any PCM coded MB are used.
+  	if(aBitShiftInSlice)
+  	{
+  	
+  		do 
+  		{
+
+    		// Store slice ID for current macroblock 
+    		mbData->sliceMap[currMbAddr] = sliceID;
+
+    		// Store loopfilter mode 
+    		mbData->filterModeTab[currMbAddr] = (int8) slice->disable_deblocking_filter_idc;
+    		mbData->alphaOffset[currMbAddr]   = (int8) (slice->slice_alpha_c0_offset_div2*2);
+    		mbData->betaOffset[currMbAddr]    = (int8) (slice->slice_beta_offset_div2*2);
+
+    		retCode = mbkParse(&mb, numRefFrames,
+            		           mbData, recoBuf->width, 
+                    		   slice->slice_type, pps->constrained_intra_pred_flag,
+                       		   pps->chroma_qp_index_offset,
+		                       mbIdxX, mbIdxY, stream, slice->bitOffset);
+
+			if (retCode == MBK_PCM_FOUND)
+			{
+				// We can stop parsing this slice
+				// Check later if this is the case also if we have slices in more than one NAL (is it even possible?)!!!
+				return SLICE_OK;
+			}
+	
+    		if (retCode < 0)
+      			return SLICE_ERROR;
+
+      		// If end of slice data has been reached and there are no 
+      		// skipped macroblocks left, stop decoding slice.         
+      		if (!bibMoreRbspData(bitbuf) && mb.numSkipped <= 0)
+        		break;
+
+    		// Find next mb address in the current slice group 
+    		do 
+    		{
+      			// Next mb address 
+      			currMbAddr++;
+
+      			// If end of frame was reached, stop search 
+      			if (currMbAddr == picSizeInMbs)
+        			break;
+
+      			// Update mb location 
+      			mbIdxX++;
+      			if (mbIdxX == mbksPerLine) 
+      			{
+        			mbIdxX = 0;
+        			mbIdxY++;
+      			}
+
+    		} while ((mbData->sliceMap[currMbAddr] & 0xF) != sliceGroupNum);
+
+    	// If end of frame was reached, stop decoding slice 
+  		} while (currMbAddr < picSizeInMbs);
+  	}
+
+  	return SLICE_OK;
+}
+
+
+// EncodeUnsignedNBits
+// Encodes the input aValue to the bit buffer with aLength bits.
+void EncodeUnsignedNBits(bitbuffer_s *aBitBuffer, TUint aValue, TUint aLength)
+{
+	TUint tempValue;
+	TInt i;
+	TUint8 byteValue;
+	 
+	if(aBitBuffer->bitpos == 0)
+	{
+		// Get the next byte
+		aBitBuffer->currentBits = aBitBuffer->data[aBitBuffer->bytePos];
+		aBitBuffer->bytePos++;
+		aBitBuffer->bitpos = 8;
+	}
+		
+	// Write aValue bit by bit to the bit buffer
+	for (i=aLength-1; i>=0; i--)
+	{
+		// Get the ith bit from aValue
+		tempValue = (aValue & (1 << i)) >> i;
+		
+		// Zero out the bitpos bit
+		byteValue = aBitBuffer->data[aBitBuffer->bytePos-1] & ~(1<<(aBitBuffer->bitpos-1));
+		byteValue |= tempValue << (aBitBuffer->bitpos-1);
+		
+		aBitBuffer->data[aBitBuffer->bytePos-1] = byteValue;
+		aBitBuffer->bitpos--;
+		
+		if(aBitBuffer->bitpos == 0)
+		{
+			// Get the next byte
+			aBitBuffer->currentBits = aBitBuffer->data[aBitBuffer->bytePos];
+
+			aBitBuffer->bytePos++;
+			aBitBuffer->bitpos = 8;
+		}
+	}
+	
+	// Make sure the bit buffer currentBits is up-to-date
+	aBitBuffer->currentBits = aBitBuffer->data[aBitBuffer->bytePos-1];
+}
+
+
+// ParseSliceHeader
+// Parses the input slice header. PPS Id, frame numbering and POC LSB are modified if required.
+TInt ParseSliceHeader(slice_s *slice, seq_parameter_set_s *spsList[],
+                      pic_parameter_set_s *ppsList[], bitbuffer_s *bitbuf, 
+                      TUint* aFrameNumber, TUint aFrameFromEncoder)
+{
+  	seq_parameter_set_s *sps;
+  	pic_parameter_set_s *pps;
+  	TUint picSizeInMapUnits;
+  	TUint temp, temp2;
+  	TInt sliceQp, len1;
+  	TInt retCode;
+  	TInt shiftedBits = 0;
+
+
+  	slice->picHasMMCO5 = 0;
+  
+  	// Initialize the bit offset to zero
+  	slice->bitOffset = 0;
+
+  	// First macroblock in slice 
+  	if ((retCode = ue_v(bitbuf, &slice->first_mb_in_slice, 65535)) < 0)
+    	return retCode;
+
+  	// Slice type 
+  	if ((retCode = ue_v(bitbuf, &slice->slice_type, SLICE_MAX)) < 0)
+    	return retCode;
+
+  	// PPS id 
+  	if ((retCode = ue_v(bitbuf, &slice->pic_parameter_set_id, PS_MAX_NUM_OF_PPS-1)) < 0)
+    	return retCode;
+  
+  	pps = ppsList[slice->pic_parameter_set_id];
+
+  	if (pps == NULL) 
+  	{
+    	PRINT((_L("Error: referring to non-existing PPS.\n")));     
+    		return SLICE_ERR_NON_EXISTING_PPS;
+  	}
+
+	syncBitBufferBitpos(bitbuf);
+	
+  	// If the index has been changed the new index must be coded instead of 
+  	// the old one to the slice header
+  	if (pps->indexChanged)
+  	{
+  		// We have to encode the new PPS Id to the bitbuffer
+  		TUint oldPPSId = slice->pic_parameter_set_id;
+  		TUint newPPSId;
+  	
+  		if ( aFrameFromEncoder )
+  			newPPSId = pps->encPPSId;
+  		else
+  			newPPSId = pps->origPPSId;
+  	
+		TUint trailingBits = GetNumTrailingBits(bitbuf);
+		TInt diff = 0;
+	
+		TUint oldIdLength = ReturnUnsignedExpGolombCodeLength(oldPPSId);
+		TUint newIdLength = ReturnUnsignedExpGolombCodeLength(newPPSId);
+	
+		// Signal that the slice data has been modified
+		slice->sliceDataModified = 1;    
+    
+		// Get the new pps
+		pps = ppsList[newPPSId];
+		
+		if(trailingBits > 8)
+		{
+			trailingBits = 8;
+		}
+		
+		if ( oldIdLength == newIdLength )	
+		{
+			// Just encode the new Id on top of the old Id
+			bitbuf->bitpos += oldIdLength;
+			
+			if(bitbuf->bitpos > 8)
+			{	
+				// Go to the right byte and bit position
+				bitbuf->bytePos -= bitbuf->bitpos / 8;
+				bitbuf->bitpos = bitbuf->bitpos % 8;
+			}
+			
+			EncodeUnsignedExpGolombCode(bitbuf, newPPSId);
+		}
+		else if ( oldIdLength < newIdLength )
+		{
+			diff = newIdLength - oldIdLength;
+		
+			// Positive bit offset indicates bit-wise shift to right
+			slice->bitOffset = (diff % 8);
+		
+			ShiftBufferRight(bitbuf, diff, trailingBits, oldIdLength);
+		
+			// After shifting, encode the new value to the bit buffer
+			EncodeUnsignedExpGolombCode(bitbuf, newPPSId);
+		}
+		else
+		{
+			// New id's length is smaller than old id's length
+			diff = oldIdLength - newIdLength;
+	
+			// Negative bit offset indicates bit-wise shift to left
+			slice->bitOffset = -(diff % 8);
+		
+			ShiftBufferLeft(bitbuf, diff, oldIdLength);
+		
+			// After shifting, encode the new value to the bit buffer
+			EncodeUnsignedExpGolombCode(bitbuf, newPPSId);
+		}
+	
+		shiftedBits = diff;
+  	}
+
+  	sps = spsList[pps->seq_parameter_set_id];
+  	
+  	if (sps == NULL) 
+  	{
+    	PRINT((_L("Error: referring to non-existing SPS.\n")));     
+    	return SLICE_ERR_NON_EXISTING_SPS;
+  	}
+
+  	picSizeInMapUnits = (sps->pic_width_in_mbs_minus1+1) * (sps->pic_height_in_map_units_minus1+1);
+
+  	if (slice->first_mb_in_slice >= picSizeInMapUnits)
+    	return SLICE_ERR_ILLEGAL_VALUE;
+
+  	// Maximum frame number 
+  	slice->maxFrameNum = (TUint)1 << (sps->log2_max_frame_num_minus4+4);
+  
+  	// IDR type NAL unit shall have frame number as zero
+	if ( slice->nalType == NAL_TYPE_CODED_SLICE_IDR )
+	{
+		// Reset frame number for an IDR slice
+	 	*aFrameNumber = 0;	
+	}
+	else if ( *aFrameNumber == (slice->maxFrameNum - 1 ) )
+	{
+		// Reset frame number if maximum frame number has been reached
+	 	*aFrameNumber = 0;	
+	}
+	else if( !slice->first_mb_in_slice )
+	{
+	    (*aFrameNumber)++;	// Increment frame number only if this is the first mb in slice
+	}
+	
+
+  	if (sps->maxFrameNumChanged)
+  	{
+  		// Frame number field size
+  		TUint oldFrameNum;
+  		TUint newFrameNum = sps->log2_max_frame_num_minus4+4;
+  	
+  		if ( aFrameFromEncoder )
+  			oldFrameNum = sps->encMaxFrameNum+4;
+  		else
+  			oldFrameNum = sps->origMaxFrameNum+4;
+  	
+		TUint trailingBits = GetNumTrailingBits(bitbuf);
+		TInt diff = 0;
+	
+		// Signal that the slice data has been modified
+		slice->sliceDataModified = 1;    
+    
+		if(trailingBits > 8)
+		{
+			trailingBits = 8;
+		}
+		
+		// If the size of the frame number field has changed then shift bits in the buffer
+		if ( oldFrameNum < newFrameNum )
+		{
+			diff = newFrameNum - oldFrameNum;
+		
+			// Positive bit offset indicates bit-wise shift to right
+			slice->bitOffset += (diff % 8);
+		
+			ShiftBufferRight(bitbuf, diff, trailingBits, 0);
+		}
+		else if ( oldFrameNum > newFrameNum )
+		{
+			// New id's length is smaller than old id's length
+			diff = oldFrameNum - newFrameNum;
+	
+			// Negative bit offset indicates bit-wise shift to left
+			slice->bitOffset -= (diff % 8);
+		
+			ShiftBufferLeft(bitbuf, diff, 0);
+		}
+	
+		shiftedBits += diff;
+  	}
+  
+  	// Encode the new frame number here
+  	EncodeUnsignedNBits(bitbuf, *aFrameNumber, sps->log2_max_frame_num_minus4+4);
+  
+  	slice->frame_num = *aFrameNumber;
+
+  	// IDR picture 
+  	if (slice->isIDR) 
+  	{
+    	if ((retCode = ue_v(bitbuf, &slice->idr_pic_id, 65535)) < 0)
+      		return retCode;
+  	}
+
+	syncBitBufferBitpos(bitbuf);
+	
+  	// POC parameters 
+	if (sps->pic_order_cnt_type == 0) 
+  	{
+	  	if (sps->maxPOCNumChanged)
+  		{
+  			// POC lsb number 
+  			TUint oldPOCNum;
+  			TUint newPOCNum = sps->log2_max_pic_order_cnt_lsb_minus4+4;
+  	
+  			if ( aFrameFromEncoder )
+  				oldPOCNum = sps->encMaxPOCNum+4;
+  			else
+  				oldPOCNum = sps->origMaxPOCNum+4;
+  	
+			TUint trailingBits = GetNumTrailingBits(bitbuf);
+			TInt diff = 0;
+	
+			// Signal that the slice data has been modified
+			slice->sliceDataModified = 1;    
+    
+			if (trailingBits > 8)
+			{
+				trailingBits = 8;
+			}
+		
+			// If the size of the POC lsb field has changed then shift bits in the buffer
+			if ( oldPOCNum < newPOCNum )
+			{	
+				diff = newPOCNum - oldPOCNum;
+		
+				// Positive bit offset indicates bit-wise shift to right
+				slice->bitOffset += (diff % 8);
+		
+				ShiftBufferRight(bitbuf, diff, trailingBits, 0);
+
+			}
+			else if ( oldPOCNum > newPOCNum )
+			{
+				// New id's length is smaller than old id's length
+				diff = oldPOCNum - newPOCNum;
+	
+				// Negative bit offset indicates bit-wise shift to left
+				slice->bitOffset -= (diff % 8);
+		
+				ShiftBufferLeft(bitbuf, diff, 0);
+			
+			}
+	
+			shiftedBits += diff;
+  		}
+  
+	  	// For now encode the POC as the frame number
+  		EncodeUnsignedNBits(bitbuf, *aFrameNumber, sps->log2_max_pic_order_cnt_lsb_minus4+4);
+  
+   		slice->delta_pic_order_cnt_bottom = 0;
+    	
+    	if (pps->pic_order_present_flag) 
+    	{ //  && !field_pic_flag 
+      		if ((retCode = se_v_long(bitbuf, &slice->delta_pic_order_cnt_bottom)) < 0)
+        		return retCode;
+    	}
+  	}
+  	else if (sps->pic_order_cnt_type == 1) 
+  	{
+    	slice->delta_pic_order_cnt_0 = 0;
+    	slice->delta_pic_order_cnt_1 = 0;
+    	// Read delta_pic_order_cnt[ 0 ] and delta_pic_order_cnt[ 1 ]
+    	if (!sps->delta_pic_order_always_zero_flag) 
+    	{
+      		// delta_pic_order_cnt[ 0 ] 
+      		if ((retCode = se_v_long(bitbuf, &slice->delta_pic_order_cnt_0)) < 0)
+        		return retCode;
+      		if (pps->pic_order_present_flag) 
+      		{ //  delta_pic_order_cnt[ 1 ] 
+        		if ((retCode = se_v_long(bitbuf, &slice->delta_pic_order_cnt_1)) < 0)
+          			return retCode;
+      		}
+    	}
+  	}
+
+	// If we don't have to do any bit shifting (left or right) with the slice header, 
+	// we can just stop parsing the header and return.
+	if (shiftedBits == 0)
+	{
+		return SLICE_STOP_PARSING;
+	}
+	
+  	// Redundant picture count
+  	if (pps->redundant_pic_cnt_present_flag) 
+  	{
+    	if ((retCode = ue_v(bitbuf, &slice->redundant_pic_cnt, 127)) < 0)
+      		return retCode;
+  	}
+  	else
+    	slice->redundant_pic_cnt = 0;
+
+  	// Reference picture management 
+  	if (IS_SLICE_P(slice->slice_type)) 
+  	{
+    	if ((retCode = u_n(bitbuf, 1, &slice->num_ref_idx_active_override_flag)) < 0)
+      		return retCode;
+    	if (slice->num_ref_idx_active_override_flag) 
+    	{
+      		if ((retCode = ue_v(bitbuf, &slice->num_ref_idx_l0_active_minus1, DPB_MAX_SIZE-1)) < 0)
+        		return retCode;
+    	}
+  	}
+
+  	// Reordering the reference picture list 
+  	retCode = getRefPicListReorderingCmds(slice, sps->num_ref_frames, bitbuf);
+
+	if (retCode < 0)
+    	return retCode;
+
+  	// Read the MMCO commands, but not do the operations until all the slices in current picture are decoded 
+  	if (slice->nalRefIdc) 
+  	{
+    	retCode = getDecRefPicMarkingCmds(slice, sps->num_ref_frames, bitbuf);
+    	if (retCode < 0)
+      		return retCode;
+  	}
+
+  	// Slice quant 
+  	if ((retCode = se_v(bitbuf, &slice->slice_qp_delta, -MAX_QP, MAX_QP)) < 0)
+    	return retCode;
+
+  	sliceQp = pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta;
+  	if (sliceQp < MIN_QP || sliceQp > MAX_QP) 
+  	{
+    	PRINT((_L("Error: illegal slice quant.\n")));     
+    	return SLICE_ERR_ILLEGAL_VALUE;
+  	}
+  	
+  	slice->qp = sliceQp;
+
+  	// Deblocking filter 
+  	slice->disable_deblocking_filter_idc = 0;
+  	slice->slice_alpha_c0_offset_div2    = 0;
+  	slice->slice_beta_offset_div2        = 0;
+
+  	if (pps->deblocking_filter_parameters_present_flag == 1) 
+  	{
+
+    	if ((retCode = ue_v(bitbuf, &slice->disable_deblocking_filter_idc, 2)) < 0)
+      		return retCode;
+
+    	if (slice->disable_deblocking_filter_idc != 1) 
+    	{
+      		if ((retCode = se_v(bitbuf, &slice->slice_alpha_c0_offset_div2, MIN_ALPHA_BETA_OFFSET, MAX_ALPHA_BETA_OFFSET)) < 0)
+        		return retCode;
+      		if ((retCode = se_v(bitbuf, &slice->slice_beta_offset_div2, MIN_ALPHA_BETA_OFFSET, MAX_ALPHA_BETA_OFFSET)) < 0)
+        		return retCode;
+    	}
+  	}
+
+  	// Read slice_group_change_cycle 
+  	if (pps->num_slice_groups_minus1 > 0 && pps->slice_group_map_type >= 3 &&
+        pps->slice_group_map_type <= 5)
+  	{
+    	// len = Ceil( Log2( PicSizeInMapUnits / SliceGroupChangeRate + 1 ) ) 
+	    // PicSizeInMapUnits / SliceGroupChangeRate 
+    	temp = picSizeInMapUnits / (pps->slice_group_change_rate_minus1+1);
+
+    	// Calculate Log2 
+    	temp2 = (temp + 1) >> 1;
+    	for (len1 = 0; len1 < 16 && temp2 != 0; len1++)
+      		temp2 >>= 1;
+
+    	// Calculate Ceil 
+    	if ( (((unsigned)1) << len1) < (temp + 1) )
+      		len1++;
+
+    	if ((retCode = u_n(bitbuf, len1, &slice->slice_group_change_cycle)) < 0)
+      		return retCode;
+
+    	// Ceil( PicSizeInMapUnits/SliceGroupChangeRate ) 
+    	if (temp * (pps->slice_group_change_rate_minus1+1) != picSizeInMapUnits)
+      		temp++;
+
+    	// The value of slice_group_change_cycle shall be in the range of  
+    	// 0 to Ceil( PicSizeInMapUnits/SliceGroupChangeRate ), inclusive. 
+    	if (slice->slice_group_change_cycle > temp)
+      		return SLICE_ERR_ILLEGAL_VALUE;
+  	}
+
+  	return SLICE_OK;
+}
+