diff -r 000000000000 -r 951a5db380a0 videoeditorengine/avcedit/src/slice.cpp --- /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 +#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; +} +