--- /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;
+}
+