/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /*------------------------------------------------------------------------------ Table of contents 1. Include headers 2. External compiler flags 3. Module defines 4. Local function prototypes 5. Functions h264bsdDecodeSliceHeader NumSliceGroupChangeCycleBits RefPicListReordering DecRefPicMarking CheckPpsId CheckFrameNum CheckIdrPicId CheckPicOrderCntLsb CheckDeltaPicOrderCntBottom CheckDeltaPicOrderCnt CheckRedundantPicCnt ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 1. Include headers ------------------------------------------------------------------------------*/ #include "h264bsd_slice_header.h" #include "h264bsd_util.h" #include "h264bsd_vlc.h" #include "h264bsd_nal_unit.h" #include "h264bsd_dpb.h" #define UNUSED(x) (void)(x) /*------------------------------------------------------------------------------ 2. External compiler flags -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 3. Module defines ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 4. Local function prototypes ------------------------------------------------------------------------------*/ static u32 RefPicListReordering(strmData_t *, refPicListReordering_t *, u32, u32); static u32 NumSliceGroupChangeCycleBits(u32 picSizeInMbs, u32 sliceGroupChangeRate); static u32 DecRefPicMarking(strmData_t *pStrmData, decRefPicMarking_t *pDecRefPicMarking, nalUnitType_e nalUnitType, u32 numRefFrames); /*------------------------------------------------------------------------------ Function name: h264bsdDecodeSliceHeader Functional description: Decode slice header data from the stream. Inputs: pStrmData pointer to stream data structure pSeqParamSet pointer to active sequence parameter set pPicParamSet pointer to active picture parameter set pNalUnit pointer to current NAL unit structure Outputs: pSliceHeader decoded data is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data or end of stream ------------------------------------------------------------------------------*/ u32 h264bsdDecodeSliceHeader(strmData_t *pStrmData, sliceHeader_t *pSliceHeader, seqParamSet_t *pSeqParamSet, picParamSet_t *pPicParamSet, nalUnit_t *pNalUnit) { /* Variables */ u32 tmp, i, value; i32 itmp; u32 picSizeInMbs; /* Code */ ASSERT(pStrmData); ASSERT(pSliceHeader); ASSERT(pSeqParamSet); ASSERT(pPicParamSet); ASSERT( pNalUnit->nalUnitType == NAL_CODED_SLICE || pNalUnit->nalUnitType == NAL_CODED_SLICE_IDR ); H264SwDecMemset(pSliceHeader, 0, sizeof(sliceHeader_t)); picSizeInMbs = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->firstMbInSlice = value; if (value >= picSizeInMbs) { EPRINT("first_mb_in_slice"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->sliceType = value; /* slice type has to be either I or P slice. P slice is not allowed when * current NAL unit is an IDR NAL unit or num_ref_frames is 0 */ if ( !IS_I_SLICE(pSliceHeader->sliceType) && ( !IS_P_SLICE(pSliceHeader->sliceType) || IS_IDR_NAL_UNIT(pNalUnit) || !pSeqParamSet->numRefFrames ) ) { EPRINT("slice_type"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->picParameterSetId = value; if (pSliceHeader->picParameterSetId != pPicParamSet->picParameterSetId) { EPRINT("pic_parameter_set_id"); return(HANTRO_NOK); } /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (pSeqParamSet->maxFrameNum >> i) i++; i--; tmp = h264bsdGetBits(pStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (IS_IDR_NAL_UNIT(pNalUnit) && tmp != 0) { EPRINT("frame_num"); return(HANTRO_NOK); } pSliceHeader->frameNum = tmp; if (IS_IDR_NAL_UNIT(pNalUnit)) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->idrPicId = value; if (value > 65535) { EPRINT("idr_pic_id"); return(HANTRO_NOK); } } if (pSeqParamSet->picOrderCntType == 0) { /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ i = 0; while (pSeqParamSet->maxPicOrderCntLsb >> i) i++; i--; tmp = h264bsdGetBits(pStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSliceHeader->picOrderCntLsb = tmp; if (pPicParamSet->picOrderPresentFlag) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->deltaPicOrderCntBottom = itmp; } /* check that picOrderCnt for IDR picture will be zero. See * DecodePicOrderCnt function to understand the logic here */ if ( IS_IDR_NAL_UNIT(pNalUnit) && ( (pSliceHeader->picOrderCntLsb > pSeqParamSet->maxPicOrderCntLsb/2) || MIN((i32)pSliceHeader->picOrderCntLsb, (i32)pSliceHeader->picOrderCntLsb + pSliceHeader->deltaPicOrderCntBottom) != 0 ) ) { return(HANTRO_NOK); } } if ( (pSeqParamSet->picOrderCntType == 1) && !pSeqParamSet->deltaPicOrderAlwaysZeroFlag ) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->deltaPicOrderCnt[0] = itmp; if (pPicParamSet->picOrderPresentFlag) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->deltaPicOrderCnt[1] = itmp; } /* check that picOrderCnt for IDR picture will be zero. See * DecodePicOrderCnt function to understand the logic here */ if ( IS_IDR_NAL_UNIT(pNalUnit) && MIN(pSliceHeader->deltaPicOrderCnt[0], pSliceHeader->deltaPicOrderCnt[0] + pSeqParamSet->offsetForTopToBottomField + pSliceHeader->deltaPicOrderCnt[1]) != 0) { return(HANTRO_NOK); } } if (pPicParamSet->redundantPicCntPresentFlag) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->redundantPicCnt = value; if (value > 127) { EPRINT("redundant_pic_cnt"); return(HANTRO_NOK); } } if (IS_P_SLICE(pSliceHeader->sliceType)) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSliceHeader->numRefIdxActiveOverrideFlag = tmp; if (pSliceHeader->numRefIdxActiveOverrideFlag) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value > 15) { EPRINT("num_ref_idx_l0_active_minus1"); return(HANTRO_NOK); } pSliceHeader->numRefIdxL0Active = value + 1; } /* set numRefIdxL0Active from pic param set */ else { /* if value (minus1) in picture parameter set exceeds 15 it should * have been overridden here */ if (pPicParamSet->numRefIdxL0Active > 16) { EPRINT("num_ref_idx_active_override_flag"); return(HANTRO_NOK); } pSliceHeader->numRefIdxL0Active = pPicParamSet->numRefIdxL0Active; } } if (IS_P_SLICE(pSliceHeader->sliceType)) { tmp = RefPicListReordering(pStrmData, &pSliceHeader->refPicListReordering, pSliceHeader->numRefIdxL0Active, pSeqParamSet->maxFrameNum); if (tmp != HANTRO_OK) return(tmp); } if (pNalUnit->nalRefIdc != 0) { tmp = DecRefPicMarking(pStrmData, &pSliceHeader->decRefPicMarking, pNalUnit->nalUnitType, pSeqParamSet->numRefFrames); if (tmp != HANTRO_OK) return(tmp); } /* decode sliceQpDelta and check that initial QP for the slice will be on * the range [0, 51] */ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->sliceQpDelta = itmp; itmp += (i32)pPicParamSet->picInitQp; if ( (itmp < 0) || (itmp > 51) ) { EPRINT("slice_qp_delta"); return(HANTRO_NOK); } if (pPicParamSet->deblockingFilterControlPresentFlag) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSliceHeader->disableDeblockingFilterIdc = value; if (pSliceHeader->disableDeblockingFilterIdc > 2) { EPRINT("disable_deblocking_filter_idc"); return(HANTRO_NOK); } if (pSliceHeader->disableDeblockingFilterIdc != 1) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); if ( (itmp < -6) || (itmp > 6) ) { EPRINT("slice_alpha_c0_offset_div2"); return(HANTRO_NOK); } pSliceHeader->sliceAlphaC0Offset = itmp * 2; tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); if ( (itmp < -6) || (itmp > 6) ) { EPRINT("slice_beta_offset_div2"); return(HANTRO_NOK); } pSliceHeader->sliceBetaOffset = itmp * 2; } } if ( (pPicParamSet->numSliceGroups > 1) && (pPicParamSet->sliceGroupMapType >= 3) && (pPicParamSet->sliceGroupMapType <= 5) ) { /* set tmp to number of bits used to represent slice_group_change_cycle * in the stream */ tmp = NumSliceGroupChangeCycleBits(picSizeInMbs, pPicParamSet->sliceGroupChangeRate); value = h264bsdGetBits(pStrmData, tmp); if (value == END_OF_STREAM) return(HANTRO_NOK); pSliceHeader->sliceGroupChangeCycle = value; /* corresponds to tmp = Ceil(picSizeInMbs / sliceGroupChangeRate) */ tmp = (picSizeInMbs + pPicParamSet->sliceGroupChangeRate - 1) / pPicParamSet->sliceGroupChangeRate; if (pSliceHeader->sliceGroupChangeCycle > tmp) { EPRINT("slice_group_change_cycle"); return(HANTRO_NOK); } } return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: NumSliceGroupChangeCycleBits Functional description: Determine number of bits needed to represent slice_group_change_cycle in the stream. The standard states that slice_group_change_cycle is represented by Ceil( Log2( (picSizeInMbs / sliceGroupChangeRate) + 1) ) bits. Division "/" in the equation is non-truncating division. Inputs: picSizeInMbs picture size in macroblocks sliceGroupChangeRate Outputs: none Returns: number of bits needed ------------------------------------------------------------------------------*/ u32 NumSliceGroupChangeCycleBits(u32 picSizeInMbs, u32 sliceGroupChangeRate) { /* Variables */ u32 tmp,numBits,mask; /* Code */ ASSERT(picSizeInMbs); ASSERT(sliceGroupChangeRate); ASSERT(sliceGroupChangeRate <= picSizeInMbs); /* compute (picSizeInMbs / sliceGroupChangeRate + 1), rounded up */ if (picSizeInMbs % sliceGroupChangeRate) tmp = 2 + picSizeInMbs/sliceGroupChangeRate; else tmp = 1 + picSizeInMbs/sliceGroupChangeRate; numBits = 0; mask = ~0U; /* set numBits to position of right-most non-zero bit */ while (tmp & (mask<<++numBits)) ; numBits--; /* add one more bit if value greater than 2^numBits */ if (tmp & ((1<refPicListReorderingFlagL0 = tmp; if (pRefPicListReordering->refPicListReorderingFlagL0) { i = 0; do { if (i > numRefIdxActive) { EPRINT("Too many reordering commands"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &command); if (tmp != HANTRO_OK) return(tmp); if (command > 3) { EPRINT("reordering_of_pic_nums_idc"); return(HANTRO_NOK); } pRefPicListReordering->command[i].reorderingOfPicNumsIdc = command; if ((command == 0) || (command == 1)) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value >= maxPicNum) { EPRINT("abs_diff_pic_num_minus1"); return(HANTRO_NOK); } pRefPicListReordering->command[i].absDiffPicNum = value + 1; } else if (command == 2) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pRefPicListReordering->command[i].longTermPicNum = value; } i++; } while (command != 3); /* there shall be at least one reordering command if * refPicListReorderingFlagL0 was set */ if (i == 1) { EPRINT("ref_pic_list_reordering"); return(HANTRO_NOK); } } return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: DecRefPicMarking Functional description: Decode decoded reference picture marking syntax elements from the stream. Inputs: pStrmData pointer to stream data structure nalUnitType type of the current NAL unit numRefFrames max number of reference frames from the active SPS Outputs: pDecRefPicMarking decoded data is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 DecRefPicMarking(strmData_t *pStrmData, decRefPicMarking_t *pDecRefPicMarking, nalUnitType_e nalUnitType, u32 numRefFrames) { /* Variables */ u32 tmp, value; u32 i; u32 operation; /* variables for error checking purposes, store number of memory * management operations of certain type */ u32 num4 = 0, num5 = 0, num6 = 0, num1to3 = 0; /* Code */ ASSERT( nalUnitType == NAL_CODED_SLICE_IDR || nalUnitType == NAL_CODED_SLICE || nalUnitType == NAL_SEI ); if (nalUnitType == NAL_CODED_SLICE_IDR) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pDecRefPicMarking->noOutputOfPriorPicsFlag = tmp; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pDecRefPicMarking->longTermReferenceFlag = tmp; if (!numRefFrames && pDecRefPicMarking->longTermReferenceFlag) { EPRINT("long_term_reference_flag"); return(HANTRO_NOK); } } else { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pDecRefPicMarking->adaptiveRefPicMarkingModeFlag = tmp; if (pDecRefPicMarking->adaptiveRefPicMarkingModeFlag) { i = 0; do { /* see explanation of the MAX_NUM_MMC_OPERATIONS in * slice_header.h */ if (i > (2 * numRefFrames + 2)) { EPRINT("Too many management operations"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &operation); if (tmp != HANTRO_OK) return(tmp); if (operation > 6) { EPRINT("memory_management_control_operation"); return(HANTRO_NOK); } pDecRefPicMarking->operation[i]. memoryManagementControlOperation = operation; if ((operation == 1) || (operation == 3)) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pDecRefPicMarking->operation[i].differenceOfPicNums = value + 1; } if (operation == 2) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pDecRefPicMarking->operation[i].longTermPicNum = value; } if ((operation == 3) || (operation == 6)) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pDecRefPicMarking->operation[i].longTermFrameIdx = value; } if (operation == 4) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* value shall be in range [0, numRefFrames] */ if (value > numRefFrames) { EPRINT("max_long_term_frame_idx_plus1"); return(HANTRO_NOK); } if (value == 0) { pDecRefPicMarking->operation[i]. maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES; } else { pDecRefPicMarking->operation[i]. maxLongTermFrameIdx = value - 1; } num4++; } if (operation == 5) { num5++; } if (operation && operation <= 3) num1to3++; if (operation == 6) num6++; i++; } while (operation != 0); /* error checking */ if (num4 > 1 || num5 > 1 || num6 > 1 || (num1to3 && num5)) return(HANTRO_NOK); } } return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function name: h264bsdCheckPpsId Functional description: Peek value of pic_parameter_set_id from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure Outputs: picParamSetId value is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 h264bsdCheckPpsId(strmData_t *pStrmData, u32 *picParamSetId) { /* Variables */ u32 tmp, value; strmData_t tmpStrmData[1]; /* Code */ ASSERT(pStrmData); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value >= MAX_NUM_PIC_PARAM_SETS) return(HANTRO_NOK); *picParamSetId = value; return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdCheckFrameNum Functional description: Peek value of frame_num from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure maxFrameNum Outputs: frameNum value is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 h264bsdCheckFrameNum( strmData_t *pStrmData, u32 maxFrameNum, u32 *frameNum) { /* Variables */ u32 tmp, value, i; strmData_t tmpStrmData[1]; /* Code */ ASSERT(pStrmData); ASSERT(maxFrameNum); ASSERT(frameNum); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* skip first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (maxFrameNum >> i) i++; i--; /* frame_num */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); *frameNum = tmp; return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdCheckIdrPicId Functional description: Peek value of idr_pic_id from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure maxFrameNum max frame number from active SPS nalUnitType type of the current NAL unit Outputs: idrPicId value is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 h264bsdCheckIdrPicId( strmData_t *pStrmData, u32 maxFrameNum, nalUnitType_e nalUnitType, u32 *idrPicId) { /* Variables */ u32 tmp, value, i; strmData_t tmpStrmData[1]; /* Code */ ASSERT(pStrmData); ASSERT(maxFrameNum); ASSERT(idrPicId); /* nalUnitType must be equal to 5 because otherwise idrPicId is not * present */ if (nalUnitType != NAL_CODED_SLICE_IDR) return(HANTRO_NOK); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* skip first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (maxFrameNum >> i) i++; i--; /* skip frame_num */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* idr_pic_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, idrPicId); if (tmp != HANTRO_OK) return(tmp); return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdCheckPicOrderCntLsb Functional description: Peek value of pic_order_cnt_lsb from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure pSeqParamSet pointer to active SPS nalUnitType type of the current NAL unit Outputs: picOrderCntLsb value is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 h264bsdCheckPicOrderCntLsb( strmData_t *pStrmData, seqParamSet_t *pSeqParamSet, nalUnitType_e nalUnitType, u32 *picOrderCntLsb) { /* Variables */ u32 tmp, value, i; strmData_t tmpStrmData[1]; /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); ASSERT(picOrderCntLsb); /* picOrderCntType must be equal to 0 */ ASSERT(pSeqParamSet->picOrderCntType == 0); ASSERT(pSeqParamSet->maxFrameNum); ASSERT(pSeqParamSet->maxPicOrderCntLsb); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* skip first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (pSeqParamSet->maxFrameNum >> i) i++; i--; /* skip frame_num */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* skip idr_pic_id when necessary */ if (nalUnitType == NAL_CODED_SLICE_IDR) { tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); } /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ i = 0; while (pSeqParamSet->maxPicOrderCntLsb >> i) i++; i--; /* pic_order_cnt_lsb */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); *picOrderCntLsb = tmp; return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdCheckDeltaPicOrderCntBottom Functional description: Peek value of delta_pic_order_cnt_bottom from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure pSeqParamSet pointer to active SPS nalUnitType type of the current NAL unit Outputs: deltaPicOrderCntBottom value is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 h264bsdCheckDeltaPicOrderCntBottom( strmData_t *pStrmData, seqParamSet_t *pSeqParamSet, nalUnitType_e nalUnitType, i32 *deltaPicOrderCntBottom) { /* Variables */ u32 tmp, value, i; strmData_t tmpStrmData[1]; /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); ASSERT(deltaPicOrderCntBottom); /* picOrderCntType must be equal to 0 and picOrderPresentFlag must be TRUE * */ ASSERT(pSeqParamSet->picOrderCntType == 0); ASSERT(pSeqParamSet->maxFrameNum); ASSERT(pSeqParamSet->maxPicOrderCntLsb); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* skip first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (pSeqParamSet->maxFrameNum >> i) i++; i--; /* skip frame_num */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* skip idr_pic_id when necessary */ if (nalUnitType == NAL_CODED_SLICE_IDR) { tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); } /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ i = 0; while (pSeqParamSet->maxPicOrderCntLsb >> i) i++; i--; /* skip pic_order_cnt_lsb */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* delta_pic_order_cnt_bottom */ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, deltaPicOrderCntBottom); if (tmp != HANTRO_OK) return(tmp); return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdCheckDeltaPicOrderCnt Functional description: Peek values delta_pic_order_cnt[0] and delta_pic_order_cnt[1] from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure pSeqParamSet pointer to active SPS nalUnitType type of the current NAL unit picOrderPresentFlag flag indicating if delta_pic_order_cnt[1] is present in the stream Outputs: deltaPicOrderCnt values are stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 h264bsdCheckDeltaPicOrderCnt( strmData_t *pStrmData, seqParamSet_t *pSeqParamSet, nalUnitType_e nalUnitType, u32 picOrderPresentFlag, i32 *deltaPicOrderCnt) { /* Variables */ u32 tmp, value, i; strmData_t tmpStrmData[1]; /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); ASSERT(deltaPicOrderCnt); /* picOrderCntType must be equal to 1 and deltaPicOrderAlwaysZeroFlag must * be FALSE */ ASSERT(pSeqParamSet->picOrderCntType == 1); ASSERT(!pSeqParamSet->deltaPicOrderAlwaysZeroFlag); ASSERT(pSeqParamSet->maxFrameNum); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* skip first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (pSeqParamSet->maxFrameNum >> i) i++; i--; /* skip frame_num */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* skip idr_pic_id when necessary */ if (nalUnitType == NAL_CODED_SLICE_IDR) { tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); } /* delta_pic_order_cnt[0] */ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &deltaPicOrderCnt[0]); if (tmp != HANTRO_OK) return(tmp); /* delta_pic_order_cnt[1] if present */ if (picOrderPresentFlag) { tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &deltaPicOrderCnt[1]); if (tmp != HANTRO_OK) return(tmp); } return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdCheckRedundantPicCnt Functional description: Peek value of redundant_pic_cnt from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure pSeqParamSet pointer to active SPS pPicParamSet pointer to active PPS nalUnitType type of the current NAL unit Outputs: redundantPicCnt value is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ u32 h264bsdCheckRedundantPicCnt( strmData_t *pStrmData, seqParamSet_t *pSeqParamSet, picParamSet_t *pPicParamSet, nalUnitType_e nalUnitType, u32 *redundantPicCnt) { /* Variables */ u32 tmp, value, i; i32 ivalue; strmData_t tmpStrmData[1]; /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); ASSERT(pPicParamSet); ASSERT(redundantPicCnt); /* redundant_pic_cnt_flag must be TRUE */ ASSERT(pPicParamSet->redundantPicCntPresentFlag); ASSERT(pSeqParamSet->maxFrameNum); ASSERT(pSeqParamSet->picOrderCntType > 0 || pSeqParamSet->maxPicOrderCntLsb); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* skip first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while (pSeqParamSet->maxFrameNum >> i) i++; i--; /* skip frame_num */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* skip idr_pic_id when necessary */ if (nalUnitType == NAL_CODED_SLICE_IDR) { tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if (tmp != HANTRO_OK) return(tmp); } if (pSeqParamSet->picOrderCntType == 0) { /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ i = 0; while (pSeqParamSet->maxPicOrderCntLsb >> i) i++; i--; /* pic_order_cnt_lsb */ tmp = h264bsdGetBits(tmpStrmData, i); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (pPicParamSet->picOrderPresentFlag) { /* skip delta_pic_order_cnt_bottom */ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); if (tmp != HANTRO_OK) return(tmp); } } if (pSeqParamSet->picOrderCntType == 1 && !pSeqParamSet->deltaPicOrderAlwaysZeroFlag) { /* delta_pic_order_cnt[0] */ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); if (tmp != HANTRO_OK) return(tmp); /* delta_pic_order_cnt[1] if present */ if (pPicParamSet->picOrderPresentFlag) { tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); if (tmp != HANTRO_OK) return(tmp); } } /* redundant_pic_cnt */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, redundantPicCnt); if (tmp != HANTRO_OK) return(tmp); return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: h264bsdCheckPriorPicsFlag Functional description: Peek value of no_output_of_prior_pics_flag from the slice header. Function does not modify current stream positions but copies the stream data structure to tmp structure which is used while accessing stream data. Inputs: pStrmData pointer to stream data structure pSeqParamSet pointer to active SPS pPicParamSet pointer to active PPS nalUnitType type of the current NAL unit Outputs: noOutputOfPriorPicsFlag value is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ /*lint -e715 disable lint info nalUnitType not referenced */ u32 h264bsdCheckPriorPicsFlag(u32 * noOutputOfPriorPicsFlag, const strmData_t * pStrmData, const seqParamSet_t * pSeqParamSet, const picParamSet_t * pPicParamSet, nalUnitType_e nalUnitType) { /* Variables */ u32 tmp, value, i; i32 ivalue; strmData_t tmpStrmData[1]; UNUSED(nalUnitType); /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); ASSERT(pPicParamSet); ASSERT(noOutputOfPriorPicsFlag); /* must be IDR lsice */ ASSERT(nalUnitType == NAL_CODED_SLICE_IDR); /* don't touch original stream position params */ *tmpStrmData = *pStrmData; /* skip first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if(tmp != HANTRO_OK) return (tmp); /* slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if(tmp != HANTRO_OK) return (tmp); /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if(tmp != HANTRO_OK) return (tmp); /* log2(maxFrameNum) -> num bits to represent frame_num */ i = 0; while(pSeqParamSet->maxFrameNum >> i) i++; i--; /* skip frame_num */ tmp = h264bsdGetBits(tmpStrmData, i); if(tmp == END_OF_STREAM) return (HANTRO_NOK); /* skip idr_pic_id */ tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if(tmp != HANTRO_OK) return (tmp); if(pSeqParamSet->picOrderCntType == 0) { /* log2(maxPicOrderCntLsb) -> num bits to represent pic_order_cnt_lsb */ i = 0; while(pSeqParamSet->maxPicOrderCntLsb >> i) i++; i--; /* skip pic_order_cnt_lsb */ tmp = h264bsdGetBits(tmpStrmData, i); if(tmp == END_OF_STREAM) return (HANTRO_NOK); if(pPicParamSet->picOrderPresentFlag) { /* skip delta_pic_order_cnt_bottom */ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); if(tmp != HANTRO_OK) return (tmp); } } if(pSeqParamSet->picOrderCntType == 1 && !pSeqParamSet->deltaPicOrderAlwaysZeroFlag) { /* skip delta_pic_order_cnt[0] */ tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); if(tmp != HANTRO_OK) return (tmp); /* skip delta_pic_order_cnt[1] if present */ if(pPicParamSet->picOrderPresentFlag) { tmp = h264bsdDecodeExpGolombSigned(tmpStrmData, &ivalue); if(tmp != HANTRO_OK) return (tmp); } } /* skip redundant_pic_cnt */ if(pPicParamSet->redundantPicCntPresentFlag) { tmp = h264bsdDecodeExpGolombUnsigned(tmpStrmData, &value); if(tmp != HANTRO_OK) return (tmp); } *noOutputOfPriorPicsFlag = h264bsdGetBits(tmpStrmData, 1); if(*noOutputOfPriorPicsFlag == END_OF_STREAM) return (HANTRO_NOK); return (HANTRO_OK); } /*lint +e715 */