static u32 DecodeBufferingPeriod( strmData_t *pStrmData, seiBufferingPeriod_t *pBufferingPeriod, u32 cpbCnt, u32 initialCpbRemovalDelayLength, u32 nalHrdBpPresentFlag, u32 vclHrdBpPresentFlag) { /* Variables */ u32 tmp, i; /* Code */ ASSERT(pStrmData); ASSERT(pBufferingPeriod); ASSERT(cpbCnt); ASSERT(initialCpbRemovalDelayLength); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pBufferingPeriod->seqParameterSetId); if (tmp != HANTRO_OK) return(tmp); if (pBufferingPeriod->seqParameterSetId > 31) return(HANTRO_NOK); if (nalHrdBpPresentFlag) { for (i = 0; i < cpbCnt; i++) { tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (tmp == 0) return(HANTRO_NOK); pBufferingPeriod->initialCpbRemovalDelay[i] = tmp; tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pBufferingPeriod->initialCpbRemovalDelayOffset[i] = tmp; } } if (vclHrdBpPresentFlag) { for (i = 0; i < cpbCnt; i++) { tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pBufferingPeriod->initialCpbRemovalDelay[i] = tmp; tmp = h264bsdGetBits(pStrmData, initialCpbRemovalDelayLength); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pBufferingPeriod->initialCpbRemovalDelayOffset[i] = tmp; } } return(HANTRO_OK); }
u32 h264bsdDecodeSliceData(strmData_t *pStrmData, storage_t *pStorage, image_t *currImage, sliceHeader_t *pSliceHeader) { /* Variables */ u8 mbData[384 + 15 + 32]; u8 *data; u32 tmp; u32 skipRun; u32 prevSkipped; u32 currMbAddr; u32 moreMbs; u32 mbCount; i32 qpY; macroblockLayer_t *mbLayer; /* Code */ ASSERT(pStrmData); ASSERT(pSliceHeader); ASSERT(pStorage); ASSERT(pSliceHeader->firstMbInSlice < pStorage->picSizeInMbs); /* ensure 16-byte alignment */ data = (u8*)ALIGN(mbData, 16); mbLayer = pStorage->mbLayer; currMbAddr = pSliceHeader->firstMbInSlice; skipRun = 0; prevSkipped = HANTRO_FALSE; /* increment slice index, will be one for decoding of the first slice of * the picture */ pStorage->slice->sliceId++; /* lastMbAddr stores address of the macroblock that was last successfully * decoded, needed for error handling */ pStorage->slice->lastMbAddr = 0; mbCount = 0; /* initial quantization parameter for the slice is obtained as the sum of * initial QP for the picture and sliceQpDelta for the current slice */ qpY = (i32)pStorage->activePps->picInitQp + pSliceHeader->sliceQpDelta; do { /* primary picture and already decoded macroblock -> error */ if (!pSliceHeader->redundantPicCnt && pStorage->mb[currMbAddr].decoded) { EPRINT("Primary and already decoded"); return(HANTRO_NOK); } SetMbParams(pStorage->mb + currMbAddr, pSliceHeader, pStorage->slice->sliceId, pStorage->activePps->chromaQpIndexOffset); if (!IS_I_SLICE(pSliceHeader->sliceType)) { if (!prevSkipped) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &skipRun); if (tmp != HANTRO_OK) return(tmp); /* skip_run shall be less than or equal to number of * macroblocks left */ if (skipRun > (pStorage->picSizeInMbs - currMbAddr)) { EPRINT("skip_run"); return(HANTRO_NOK); } if (skipRun) { prevSkipped = HANTRO_TRUE; memset(&mbLayer->mbPred, 0, sizeof(mbPred_t)); /* mark current macroblock skipped */ mbLayer->mbType = P_Skip; } } } if (skipRun) { DEBUG(("Skipping macroblock %d\n", currMbAddr)); skipRun--; } else { prevSkipped = HANTRO_FALSE; tmp = h264bsdDecodeMacroblockLayer(pStrmData, mbLayer, pStorage->mb + currMbAddr, pSliceHeader->sliceType, pSliceHeader->numRefIdxL0Active); if (tmp != HANTRO_OK) { EPRINT("macroblock_layer"); return(tmp); } } tmp = h264bsdDecodeMacroblock(pStorage->mb + currMbAddr, mbLayer, currImage, pStorage->dpb, &qpY, currMbAddr, pStorage->activePps->constrainedIntraPredFlag, data); if (tmp != HANTRO_OK) { EPRINT("MACRO_BLOCK"); return(tmp); } /* increment macroblock count only for macroblocks that were decoded * for the first time (redundant slices) */ if (pStorage->mb[currMbAddr].decoded == 1) mbCount++; /* keep on processing as long as there is stream data left or * processing of macroblocks to be skipped based on the last skipRun is * not finished */ moreMbs = (h264bsdMoreRbspData(pStrmData) || skipRun) ? HANTRO_TRUE : HANTRO_FALSE; /* lastMbAddr is only updated for intra slices (all macroblocks of * inter slices will be lost in case of an error) */ if (IS_I_SLICE(pSliceHeader->sliceType)) pStorage->slice->lastMbAddr = currMbAddr; currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap, pStorage->picSizeInMbs, currMbAddr); /* data left in the buffer but no more macroblocks for current slice * group -> error */ if (moreMbs && !currMbAddr) { EPRINT("Next mb address"); return(HANTRO_NOK); } } while (moreMbs); if ((pStorage->slice->numDecodedMbs + mbCount) > pStorage->picSizeInMbs) { EPRINT("Num decoded mbs"); return(HANTRO_NOK); } pStorage->slice->numDecodedMbs += mbCount; return(HANTRO_OK); }
u32 DecodeMvcExtension(strmData_t *pStrmData, seqParamSet_t *pSeqParamSet) { /* Variables */ u32 tmp, i, j, k; u32 value, tmpCount, tmpCount1, tmpCount2; hrdParameters_t hrdParams; /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSeqParamSet->mvc.numViews = value + 1; if (pSeqParamSet->mvc.numViews > MAX_NUM_VIEWS) return(HANTRO_NOK); /* view_id */ for (i = 0; i < pSeqParamSet->mvc.numViews; i++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (i < MAX_NUM_VIEWS) pSeqParamSet->mvc.viewId[i] = value; } for (i = 1; i < pSeqParamSet->mvc.numViews; i++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.numAnchorRefsL0[i] = value;*/ tmpCount = value; for (j = 0; j < tmpCount; j++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.anchorRefL0[i][j] = value;*/ } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.numNonAnchorRefsL0[i] = value;*/ tmpCount = value; for (j = 0; j < tmpCount; j++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.nonAnchorRefL0[i][j] = value;*/ } } for (i = 1; i < pSeqParamSet->mvc.numViews; i++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.numAnchorRefsL1[i] = value;*/ tmpCount = value; for (j = 0; j < tmpCount; j++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.anchorRefL1[i][j] = value;*/ } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.numNonAnchorRefsL1[i] = value;*/ tmpCount = value; for (j = 0; j < tmpCount; j++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /*pSeqParamSet->mvc.nonAnchorRefL1[i][j] = value;*/ } } /* num_level_values_signalled_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); tmpCount = value + 1; for (i = 0; i < tmpCount; i++) { /* level_idc */ tmp = h264bsdGetBits(pStrmData, 8); /* num_applicable_ops_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); tmpCount1 = value + 1; for (j = 0; j < tmpCount1; j++) { /* applicable_op_temporal_id */ tmp = h264bsdGetBits(pStrmData, 3); /* applicable_op_num_target_views_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); tmpCount2 = value + 1; for (k = 0; k < tmpCount2; k++) { /* applicable_op_target_view_id */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); } /* applicable_op_num_views_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); } } /* mvc_vui_parameters_present_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == 1) { /* vui_mvc_num_ops_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); tmpCount = value + 1; for (i = 0; i < tmpCount; i++) { /* vui_mvc_temporal_id */ tmp = h264bsdGetBits(pStrmData, 3); /* vui_mvc_num_target_output_views_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); tmpCount1 = value + 1; for (k = 0; k < tmpCount1; k++) { /* vui_mvc_view_id */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); } /* vui_mvc_timing_info_present_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == 1) { /* vui_mvc_num_units_in_tick */ tmp = h264bsdShowBits(pStrmData,32); if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM) return(END_OF_STREAM); /* vui_mvc_time_scale */ tmp = h264bsdShowBits(pStrmData,32); if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM) return(END_OF_STREAM); /* vui_mvc_fixed_frame_rate_flag */ tmp = h264bsdGetBits(pStrmData, 1); } j = 0; /* vui_mvc_nal_hrd_parameters_present_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == 1) { j = 1; tmp = h264bsdDecodeHrdParameters(pStrmData, &hrdParams); } /* vui_mvc_vcl_hrd_parameters_present_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == 1) { j = 1; tmp = h264bsdDecodeHrdParameters(pStrmData, &hrdParams); } if (j) { /* vui_mvc_low_delay_hrd_flag */ tmp = h264bsdGetBits(pStrmData, 1); } /* vui_mvc_pic_struct_present_flag */ tmp = h264bsdGetBits(pStrmData, 1); } } return(HANTRO_OK); }
/*------------------------------------------------------------------------------ Function: h264bsdFixFrameNum Functional description: Fix frame numbers in slice headers of current frame. This implements SW workaround for hardware fault (bit 12 of frameNum field shall be 0 to not break inter prediction). Inputs: Outputs: Returns: ------------------------------------------------------------------------------*/ u32 h264bsdFixFrameNum(u8 *pStream, u32 strmLen, u32 frameNum, u32 maxFrameNum, u32 *skippedBytes) { #define BIT 12 u8 *p, *pEnd; u32 value, tmp, first = 1; strmData_t strmData; u32 frameNumLen = 0; u32 bitPos; u32 loop = 0; *skippedBytes = 0; if (!(frameNum & (1 << BIT))) return 0; /* log2(maxFrameNum) -> num bits to represent frame_num */ while(maxFrameNum >> frameNumLen) frameNumLen++; frameNumLen--; ASSERT(frameNumLen > BIT); p = pStream; pEnd = p + strmLen; if (p[0] == 0 && p[1] == 0 && p[2] <= 1) { /* skip prefix */ while (*p++ == 0); *skippedBytes = p - pStream; /* if e.g. prefix NAL unit in the beginning of current stream * buffer -> loop to find slice header to fix the frame num */ loop = 1; } while (1) { tmp = (*p++) & 0x1F; /* nal unit type */ if (tmp == NAL_CODED_SLICE || tmp == NAL_CODED_SLICE_IDR || tmp == NAL_CODED_SLICE_EXT) { /* skip nal unit header extension */ if (tmp == NAL_CODED_SLICE_EXT) p += 3; if (p >= pEnd) return 0; strmData.pStrmBuffStart = p; strmData.pStrmCurrPos = strmData.pStrmBuffStart; strmData.bitPosInWord = 0; strmData.strmBuffReadBits = 0; strmData.strmBuffSize = pEnd - p; /* first_mb_in_slice */ tmp = h264bsdDecodeExpGolombUnsigned(&strmData, &value); if(tmp != HANTRO_OK) return 0; /* start of frame */ if (value == 0 && !first) return 0; /* skip slice_type */ tmp = h264bsdDecodeExpGolombUnsigned(&strmData, &value); if(tmp != HANTRO_OK) return 0; /* skip pic_parameter_set_id */ tmp = h264bsdDecodeExpGolombUnsigned(&strmData, &value); if(tmp != HANTRO_OK) return 0; /* frame_num */ tmp = h264bsdShowBits(&strmData, frameNumLen); if(tmp != frameNum) return 0; bitPos = strmData.bitPosInWord + frameNumLen - 1 - BIT; p = (u8*)strmData.pStrmCurrPos + bitPos/8; bitPos &= 0x7; /* reset bit */ *p &= ~(0x80 >> bitPos); /* if loop is set -> stream contains start code prefixes and * nal unit mode needs to be forced */ return (loop ? 1 : 0); } /* h264bsdFindNextStartCode starts with one byte offset -> compensate */ if (loop) { p = (u8*)h264bsdFindNextStartCode(p, pEnd - p); if (p == NULL) return 0; } else break; }; return 0; #undef BIT }
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); } }
u32 h264bsdDecodeSeqParamSet(strmData_t *pStrmData, seqParamSet_t *pSeqParamSet, u32 mvcFlag) { /* Variables */ u32 tmp, i, value; /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); (void)DWLmemset(pSeqParamSet, 0, sizeof(seqParamSet_t)); /* profile_idc */ tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (tmp != 66) { DEBUG_PRINT(("NOT BASELINE PROFILE %d\n", tmp)); } #ifdef ASIC_TRACE_SUPPORT if (tmp==66) trace_h264DecodingTools.profileType.baseline = 1; if (tmp==77) trace_h264DecodingTools.profileType.main = 1; if (tmp == 100) trace_h264DecodingTools.profileType.high = 1; #endif pSeqParamSet->profileIdc = tmp; /* constrained_set0_flag */ tmp = h264bsdGetBits(pStrmData, 1); pSeqParamSet->constrained_set0_flag = tmp; /* constrained_set1_flag */ tmp = h264bsdGetBits(pStrmData, 1); pSeqParamSet->constrained_set1_flag = tmp; /* constrained_set2_flag */ tmp = h264bsdGetBits(pStrmData, 1); pSeqParamSet->constrained_set2_flag = tmp; /* constrained_set3_flag */ tmp = h264bsdGetBits(pStrmData, 1); pSeqParamSet->constrained_set3_flag = tmp; if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* reserved_zero_4bits, values of these bits shall be ignored */ tmp = h264bsdGetBits(pStrmData, 4); if (tmp == END_OF_STREAM) { ERROR_PRINT("reserved_zero_4bits"); return(HANTRO_NOK); } tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) { ERROR_PRINT("level_idc"); return(HANTRO_NOK); } pSeqParamSet->levelIdc = tmp; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->seqParameterSetId); if (tmp != HANTRO_OK) return(tmp); if (pSeqParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS) { ERROR_PRINT("seq_param_set_id"); return(HANTRO_NOK); } if( pSeqParamSet->profileIdc >= 100 ) { /* chroma_format_idc */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if( tmp > 1 ) return(HANTRO_NOK); pSeqParamSet->chromaFormatIdc = value; if (pSeqParamSet->chromaFormatIdc == 0) pSeqParamSet->monoChrome = 1; /* residual_colour_transform_flag (skipped) */ /* bit_depth_luma_minus8 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* bit_depth_chroma_minus8 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); /* qpprime_y_zero_transform_bypass_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* seq_scaling_matrix_present_flag */ tmp = h264bsdGetBits(pStrmData, 1); #ifdef ASIC_TRACE_SUPPORT if (tmp) trace_h264DecodingTools.scalingMatrixPresentType.seq = 1; #endif if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->scalingMatrixPresentFlag = tmp; if (tmp) { for (i = 0; i < 8; i++) { tmp = h264bsdGetBits(pStrmData, 1); pSeqParamSet->scalingListPresent[i] = tmp; if (tmp) { ScalingList(pSeqParamSet->scalingList, pStrmData, i); } else FallbackScaling(pSeqParamSet->scalingList, i); } } } else { pSeqParamSet->chromaFormatIdc = 1; /* 4:2:0 */ pSeqParamSet->scalingMatrixPresentFlag = 0; } /* log2_max_frame_num_minus4 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) { ERROR_PRINT("log2_max_frame_num_minus4"); return(tmp); } if (value > 12) { ERROR_PRINT("log2_max_frame_num_minus4"); return(HANTRO_NOK); } /* maxFrameNum = 2^(log2_max_frame_num_minus4 + 4) */ pSeqParamSet->maxFrameNum = 1 << (value+4); /* valid POC types are 0, 1 and 2 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) { ERROR_PRINT("pic_order_cnt_type"); return(tmp); } if (value > 2) { ERROR_PRINT("pic_order_cnt_type"); return(HANTRO_NOK); } pSeqParamSet->picOrderCntType = value; if (pSeqParamSet->picOrderCntType == 0) { /* log2_max_pic_order_cnt_lsb_minus4 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value > 12) { ERROR_PRINT("log2_max_pic_order_cnt_lsb_minus4"); return(HANTRO_NOK); } /* maxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4) */ pSeqParamSet->maxPicOrderCntLsb = 1 << (value+4); } else if (pSeqParamSet->picOrderCntType == 1) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->deltaPicOrderAlwaysZeroFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdDecodeExpGolombSigned(pStrmData, &pSeqParamSet->offsetForNonRefPic); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombSigned(pStrmData, &pSeqParamSet->offsetForTopToBottomField); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->numRefFramesInPicOrderCntCycle); if (tmp != HANTRO_OK) return(tmp); if (pSeqParamSet->numRefFramesInPicOrderCntCycle > 255) { ERROR_PRINT("num_ref_frames_in_pic_order_cnt_cycle"); return(HANTRO_NOK); } if (pSeqParamSet->numRefFramesInPicOrderCntCycle) { /* NOTE: This has to be freed somewhere! */ ALLOCATE(pSeqParamSet->offsetForRefFrame, pSeqParamSet->numRefFramesInPicOrderCntCycle, i32); if (pSeqParamSet->offsetForRefFrame == NULL) return(MEMORY_ALLOCATION_ERROR); for (i = 0; i < pSeqParamSet->numRefFramesInPicOrderCntCycle; i++) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, pSeqParamSet->offsetForRefFrame + i); if (tmp != HANTRO_OK) return(tmp); } } else { pSeqParamSet->offsetForRefFrame = NULL; } } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->numRefFrames); if (tmp != HANTRO_OK) return(tmp); if (pSeqParamSet->numRefFrames > MAX_NUM_REF_PICS || /* max num ref frames in mvc stereo high profile is actually 8, but * here we just check that it is less than 15 (base 15 used for * inter view reference picture) */ (mvcFlag && (pSeqParamSet->numRefFrames > 15))) { ERROR_PRINT("num_ref_frames"); return(HANTRO_NOK); } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->gapsInFrameNumValueAllowedFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSeqParamSet->picWidthInMbs = value + 1; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSeqParamSet->picHeightInMbs = value + 1; /* frame_mbs_only_flag, shall be 1 for baseline profile */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->frameMbsOnlyFlag = tmp; if (!pSeqParamSet->frameMbsOnlyFlag) { pSeqParamSet->mbAdaptiveFrameFieldFlag = h264bsdGetBits(pStrmData, 1); pSeqParamSet->picHeightInMbs *= 2; } /* direct_8x8_inference_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->direct8x8InferenceFlag = tmp; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->frameCroppingFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; #ifdef ASIC_TRACE_SUPPORT if (tmp) trace_h264DecodingTools.imageCropping = 1; #endif if (pSeqParamSet->frameCroppingFlag) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropLeftOffset); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropRightOffset); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropTopOffset); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropBottomOffset); if (tmp != HANTRO_OK) return(tmp); /* check that frame cropping params are valid, parameters shall * specify non-negative area within the original picture */ if ( ( (i32)pSeqParamSet->frameCropLeftOffset > ( 8 * (i32)pSeqParamSet->picWidthInMbs - ((i32)pSeqParamSet->frameCropRightOffset + 1) ) ) || ( (i32)pSeqParamSet->frameCropTopOffset > ( 8 * (i32)pSeqParamSet->picHeightInMbs - ((i32)pSeqParamSet->frameCropBottomOffset + 1) ) ) ) { ERROR_PRINT("frame_cropping"); return(HANTRO_NOK); } } /* check that image dimensions and levelIdc match */ tmp = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs; value = GetDpbSize(tmp, pSeqParamSet->levelIdc); if (value == INVALID_DPB_SIZE || pSeqParamSet->numRefFrames > value) { DEBUG_PRINT(("WARNING! Invalid DPB size based on SPS Level!\n")); DEBUG_PRINT(("WARNING! Using num_ref_frames =%d for DPB size!\n", pSeqParamSet->numRefFrames)); /* set maxDpbSize to 1 if numRefFrames is zero */ value = pSeqParamSet->numRefFrames ? pSeqParamSet->numRefFrames : 1; } pSeqParamSet->maxDpbSize = value; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->vuiParametersPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; /* VUI */ if (pSeqParamSet->vuiParametersPresentFlag) { ALLOCATE(pSeqParamSet->vuiParameters, 1, vuiParameters_t); if (pSeqParamSet->vuiParameters == NULL) return(MEMORY_ALLOCATION_ERROR); tmp = h264bsdDecodeVuiParameters(pStrmData, pSeqParamSet->vuiParameters); if (tmp == END_OF_STREAM) { pSeqParamSet->vuiParameters->bitstreamRestrictionFlag |= 1; pSeqParamSet->vuiParameters->maxDecFrameBuffering = pSeqParamSet->maxDpbSize; } else if (tmp != HANTRO_OK) return(tmp); /* check numReorderFrames and maxDecFrameBuffering */ if (pSeqParamSet->vuiParameters->bitstreamRestrictionFlag) { if (pSeqParamSet->vuiParameters->numReorderFrames > pSeqParamSet->vuiParameters->maxDecFrameBuffering || pSeqParamSet->vuiParameters->maxDecFrameBuffering < pSeqParamSet->numRefFrames || pSeqParamSet->vuiParameters->maxDecFrameBuffering > pSeqParamSet->maxDpbSize) { ERROR_PRINT("Not valid vuiParameters->bitstreamRestriction"); return(HANTRO_NOK); } /* standard says that "the sequence shall not require a DPB with * size of more than max(1, maxDecFrameBuffering) */ pSeqParamSet->maxDpbSize = MAX(1, pSeqParamSet->vuiParameters->maxDecFrameBuffering); } } if (mvcFlag) { if (pSeqParamSet->profileIdc == 118 || pSeqParamSet->profileIdc == 128) { /* bit_equal_to_one */ tmp = h264bsdGetBits(pStrmData, 1); tmp = DecodeMvcExtension(pStrmData, pSeqParamSet); if (tmp != HANTRO_OK) return tmp; } /* additional_extension2_flag, shall be zero */ tmp = h264bsdGetBits(pStrmData, 1); /* TODO: skip rest of the stuff if equal to 1 */ } tmp = h264bsdRbspTrailingBits(pStrmData); /* ignore possible errors in trailing bits of parameters sets */ return(HANTRO_OK); }
u32 h264bsdDecodePicParamSet(strmData_t *pStrmData, picParamSet_t *pPicParamSet) { /* Variables */ u32 tmp, i, value; i32 itmp; /* Code */ ASSERT(pStrmData); ASSERT(pPicParamSet); H264SwDecMemset(pPicParamSet, 0, sizeof(picParamSet_t)); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pPicParamSet->picParameterSetId); if (tmp != HANTRO_OK) return(tmp); if (pPicParamSet->picParameterSetId >= MAX_NUM_PIC_PARAM_SETS) { EPRINT("pic_parameter_set_id"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pPicParamSet->seqParameterSetId); if (tmp != HANTRO_OK) return(tmp); if (pPicParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS) { EPRINT("seq_param_set_id"); return(HANTRO_NOK); } /* entropy_coding_mode_flag, shall be 0 for baseline profile */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp) { EPRINT("entropy_coding_mode_flag"); return(HANTRO_NOK); } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pPicParamSet->picOrderPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; /* num_slice_groups_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pPicParamSet->numSliceGroups = value + 1; if (pPicParamSet->numSliceGroups > MAX_NUM_SLICE_GROUPS) { EPRINT("num_slice_groups_minus1"); return(HANTRO_NOK); } /* decode slice group mapping information if more than one slice groups */ if (pPicParamSet->numSliceGroups > 1) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pPicParamSet->sliceGroupMapType); if (tmp != HANTRO_OK) return(tmp); if (pPicParamSet->sliceGroupMapType > 6) { EPRINT("slice_group_map_type"); return(HANTRO_NOK); } if (pPicParamSet->sliceGroupMapType == 0) { ALLOCATE(pPicParamSet->runLength, pPicParamSet->numSliceGroups, u32); if (pPicParamSet->runLength == NULL) return(MEMORY_ALLOCATION_ERROR); for (i = 0; i < pPicParamSet->numSliceGroups; i++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pPicParamSet->runLength[i] = value+1; /* param values checked in CheckPps() */ } } else if (pPicParamSet->sliceGroupMapType == 2) { ALLOCATE(pPicParamSet->topLeft, pPicParamSet->numSliceGroups - 1, u32); ALLOCATE(pPicParamSet->bottomRight, pPicParamSet->numSliceGroups - 1, u32); if (pPicParamSet->topLeft == NULL || pPicParamSet->bottomRight == NULL) return(MEMORY_ALLOCATION_ERROR); for (i = 0; i < pPicParamSet->numSliceGroups - 1; i++) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pPicParamSet->topLeft[i] = value; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pPicParamSet->bottomRight[i] = value; /* param values checked in CheckPps() */ } } else if ( (pPicParamSet->sliceGroupMapType == 3) || (pPicParamSet->sliceGroupMapType == 4) || (pPicParamSet->sliceGroupMapType == 5) ) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pPicParamSet->sliceGroupChangeDirectionFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pPicParamSet->sliceGroupChangeRate = value + 1; /* param value checked in CheckPps() */ } else if (pPicParamSet->sliceGroupMapType == 6) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pPicParamSet->picSizeInMapUnits = value + 1; ALLOCATE(pPicParamSet->sliceGroupId, pPicParamSet->picSizeInMapUnits, u32); if (pPicParamSet->sliceGroupId == NULL) return(MEMORY_ALLOCATION_ERROR); /* determine number of bits needed to represent range * [0, numSliceGroups) */ tmp = CeilLog2NumSliceGroups[pPicParamSet->numSliceGroups-1]; for (i = 0; i < pPicParamSet->picSizeInMapUnits; i++) { pPicParamSet->sliceGroupId[i] = h264bsdGetBits(pStrmData, tmp); if ( pPicParamSet->sliceGroupId[i] >= pPicParamSet->numSliceGroups ) { EPRINT("slice_group_id"); return(HANTRO_NOK); } } } } /* num_ref_idx_l0_active_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value > 31) { EPRINT("num_ref_idx_l0_active_minus1"); return(HANTRO_NOK); } pPicParamSet->numRefIdxL0Active = value + 1; /* num_ref_idx_l1_active_minus1 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value > 31) { EPRINT("num_ref_idx_l1_active_minus1"); return(HANTRO_NOK); } /* weighted_pred_flag, this shall be 0 for baseline profile */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp) { EPRINT("weighted_pred_flag"); return(HANTRO_NOK); } /* weighted_bipred_idc */ tmp = h264bsdGetBits(pStrmData, 2); if (tmp > 2) { EPRINT("weighted_bipred_idc"); return(HANTRO_NOK); } /* pic_init_qp_minus26 */ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); if ((itmp < -26) || (itmp > 25)) { EPRINT("pic_init_qp_minus26"); return(HANTRO_NOK); } pPicParamSet->picInitQp = (u32)(itmp + 26); /* pic_init_qs_minus26 */ tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); if ((itmp < -26) || (itmp > 25)) { EPRINT("pic_init_qs_minus26"); return(HANTRO_NOK); } tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); if ((itmp < -12) || (itmp > 12)) { EPRINT("chroma_qp_index_offset"); return(HANTRO_NOK); } pPicParamSet->chromaQpIndexOffset = itmp; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pPicParamSet->deblockingFilterControlPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pPicParamSet->constrainedIntraPredFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pPicParamSet->redundantPicCntPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdRbspTrailingBits(pStrmData); /* ignore possible errors in trailing bits of parameters sets */ return(HANTRO_OK); }
u32 DecodeMbPred(strmData_t *pStrmData, mbPred_t *pMbPred, mbType_e mbType, u32 numRefIdxActive) { /* Variables */ u32 tmp, i, j, value; i32 itmp; /* Code */ ASSERT(pStrmData); ASSERT(pMbPred); switch (h264bsdMbPartPredMode(mbType)) { case PRED_MODE_INTER: /* PRED_MODE_INTER */ if (numRefIdxActive > 1) { for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++) { tmp = h264bsdDecodeExpGolombTruncated(pStrmData, &value, (u32)(numRefIdxActive > 2)); if (tmp != HANTRO_OK || value >= numRefIdxActive) return(HANTRO_NOK); pMbPred->refIdxL0[j] = value; } } for (i = h264bsdNumMbPart(mbType), j = 0; i--; j++) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pMbPred->mvdL0[j].hor = (i16)itmp; tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK) return(tmp); pMbPred->mvdL0[j].ver = (i16)itmp; } break; case PRED_MODE_INTRA4x4: for (itmp = 0, i = 0; itmp < 2; itmp++) { value = h264bsdShowBits32(pStrmData); tmp = 0; for (j = 8; j--; i++) { pMbPred->prevIntra4x4PredModeFlag[i] = value & 0x80000000 ? HANTRO_TRUE : HANTRO_FALSE; value <<= 1; if (!pMbPred->prevIntra4x4PredModeFlag[i]) { pMbPred->remIntra4x4PredMode[i] = value>>29; value <<= 3; tmp++; } } if (h264bsdFlushBits(pStrmData, 8 + 3*tmp) == END_OF_STREAM) return(HANTRO_NOK); } /* fall-through */ case PRED_MODE_INTRA16x16: tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK || value > 3) return(HANTRO_NOK); pMbPred->intraChromaPredMode = value; break; }
u32 h264bsdDecodeMacroblockLayer(strmData_t *pStrmData, macroblockLayer_t *pMbLayer, mbStorage_t *pMb, u32 sliceType, u32 numRefIdxActive) { /* Variables */ u32 tmp, i, value; i32 itmp; mbPartPredMode_e partMode; /* Code */ ASSERT(pStrmData); ASSERT(pMbLayer); #ifdef H264DEC_NEON h264bsdClearMbLayer(pMbLayer, ((sizeof(macroblockLayer_t) + 63) & ~0x3F)); #else H264SwDecMemset(pMbLayer, 0, sizeof(macroblockLayer_t)); #endif tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (IS_I_SLICE(sliceType)) { if ((value + 6) > 31 || tmp != HANTRO_OK) return(HANTRO_NOK); pMbLayer->mbType = (mbType_e)(value + 6); } else { if ((value + 1) > 31 || tmp != HANTRO_OK) return(HANTRO_NOK); pMbLayer->mbType = (mbType_e)(value + 1); } if (pMbLayer->mbType == I_PCM) { i32 *level; while( !h264bsdIsByteAligned(pStrmData) ) { /* pcm_alignment_zero_bit */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp) return(HANTRO_NOK); } level = pMbLayer->residual.level[0]; for (i = 0; i < 384; i++) { value = h264bsdGetBits(pStrmData, 8); if (value == END_OF_STREAM) return(HANTRO_NOK); *level++ = (i32)value; } } else { partMode = h264bsdMbPartPredMode(pMbLayer->mbType); if ( (partMode == PRED_MODE_INTER) && (h264bsdNumMbPart(pMbLayer->mbType) == 4) ) { tmp = DecodeSubMbPred(pStrmData, &pMbLayer->subMbPred, pMbLayer->mbType, numRefIdxActive); } else { tmp = DecodeMbPred(pStrmData, &pMbLayer->mbPred, pMbLayer->mbType, numRefIdxActive); } if (tmp != HANTRO_OK) return(tmp); if (partMode != PRED_MODE_INTRA16x16) { tmp = h264bsdDecodeExpGolombMapped(pStrmData, &value, (u32)(partMode == PRED_MODE_INTRA4x4)); if (tmp != HANTRO_OK) return(tmp); pMbLayer->codedBlockPattern = value; } else { pMbLayer->codedBlockPattern = CbpIntra16x16(pMbLayer->mbType); } if ( pMbLayer->codedBlockPattern || (partMode == PRED_MODE_INTRA16x16) ) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if (tmp != HANTRO_OK || (itmp < -26) || (itmp > 25) ) return(HANTRO_NOK); pMbLayer->mbQpDelta = itmp; tmp = DecodeResidual(pStrmData, &pMbLayer->residual, pMb, pMbLayer->mbType, pMbLayer->codedBlockPattern); pStrmData->strmBuffReadBits = (u32)(pStrmData->pStrmCurrPos - pStrmData->pStrmBuffStart) * 8 + pStrmData->bitPosInWord; if (tmp != HANTRO_OK) return(tmp); } } return(HANTRO_OK); }
u32 h264bsdDecodeSeqParamSet(strmData_t *pStrmData, seqParamSet_t *pSeqParamSet) { /* Variables */ u32 tmp, i, value; /* Code */ ASSERT(pStrmData); ASSERT(pSeqParamSet); memset(pSeqParamSet, 0, sizeof(seqParamSet_t)); /* profile_idc */ tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (tmp != 66) { DEBUG(("NOT BASELINE PROFILE %d\n", tmp)); } pSeqParamSet->profileIdc = tmp; /* constrained_set0_flag */ tmp = h264bsdGetBits(pStrmData, 1); /* constrained_set1_flag */ tmp = h264bsdGetBits(pStrmData, 1); /* constrained_set2_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); /* reserved_zero_5bits, values of these bits shall be ignored */ tmp = h264bsdGetBits(pStrmData, 5); if (tmp == END_OF_STREAM) return(HANTRO_NOK); tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->levelIdc = tmp; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->seqParameterSetId); if (tmp != HANTRO_OK) return(tmp); if (pSeqParamSet->seqParameterSetId >= MAX_NUM_SEQ_PARAM_SETS) { EPRINT("seq_param_set_id"); return(HANTRO_NOK); } /* log2_max_frame_num_minus4 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value > 12) { EPRINT("log2_max_frame_num_minus4"); return(HANTRO_NOK); } /* maxFrameNum = 2^(log2_max_frame_num_minus4 + 4) */ pSeqParamSet->maxFrameNum = 1 << (value+4); /* valid POC types are 0, 1 and 2 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value > 2) { EPRINT("pic_order_cnt_type"); return(HANTRO_NOK); } pSeqParamSet->picOrderCntType = value; if (pSeqParamSet->picOrderCntType == 0) { /* log2_max_pic_order_cnt_lsb_minus4 */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); if (value > 12) { EPRINT("log2_max_pic_order_cnt_lsb_minus4"); return(HANTRO_NOK); } /* maxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4) */ pSeqParamSet->maxPicOrderCntLsb = 1 << (value+4); } else if (pSeqParamSet->picOrderCntType == 1) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->deltaPicOrderAlwaysZeroFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdDecodeExpGolombSigned(pStrmData, &pSeqParamSet->offsetForNonRefPic); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombSigned(pStrmData, &pSeqParamSet->offsetForTopToBottomField); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->numRefFramesInPicOrderCntCycle); if (tmp != HANTRO_OK) return(tmp); if (pSeqParamSet->numRefFramesInPicOrderCntCycle > 255) { EPRINT("num_ref_frames_in_pic_order_cnt_cycle"); return(HANTRO_NOK); } if (pSeqParamSet->numRefFramesInPicOrderCntCycle) { /* NOTE: This has to be freed somewhere! */ ALLOCATE(pSeqParamSet->offsetForRefFrame, pSeqParamSet->numRefFramesInPicOrderCntCycle, i32); if (pSeqParamSet->offsetForRefFrame == NULL) return(MEMORY_ALLOCATION_ERROR); for (i = 0; i < pSeqParamSet->numRefFramesInPicOrderCntCycle; i++) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, pSeqParamSet->offsetForRefFrame + i); if (tmp != HANTRO_OK) return(tmp); } } else { pSeqParamSet->offsetForRefFrame = NULL; } } tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->numRefFrames); if (tmp != HANTRO_OK) return(tmp); if (pSeqParamSet->numRefFrames > MAX_NUM_REF_PICS) { EPRINT("num_ref_frames"); return(HANTRO_NOK); } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->gapsInFrameNumValueAllowedFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSeqParamSet->picWidthInMbs = value + 1; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if (tmp != HANTRO_OK) return(tmp); pSeqParamSet->picHeightInMbs = value + 1; /* frame_mbs_only_flag, shall be 1 for baseline profile */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); if (!tmp) { EPRINT("frame_mbs_only_flag"); return(HANTRO_NOK); } /* direct_8x8_inference_flag */ tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->frameCroppingFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pSeqParamSet->frameCroppingFlag) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropLeftOffset); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropRightOffset); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropTopOffset); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pSeqParamSet->frameCropBottomOffset); if (tmp != HANTRO_OK) return(tmp); /* check that frame cropping params are valid, parameters shall * specify non-negative area within the original picture */ if ( ( (i32)pSeqParamSet->frameCropLeftOffset > ( 8 * (i32)pSeqParamSet->picWidthInMbs - ((i32)pSeqParamSet->frameCropRightOffset + 1) ) ) || ( (i32)pSeqParamSet->frameCropTopOffset > ( 8 * (i32)pSeqParamSet->picHeightInMbs - ((i32)pSeqParamSet->frameCropBottomOffset + 1) ) ) ) { EPRINT("frame_cropping"); return(HANTRO_NOK); } } /* check that image dimensions and levelIdc match */ tmp = pSeqParamSet->picWidthInMbs * pSeqParamSet->picHeightInMbs; value = GetDpbSize(tmp, pSeqParamSet->levelIdc); if (value == INVALID_DPB_SIZE || pSeqParamSet->numRefFrames > value) { DEBUG(("WARNING! Invalid DPB size based on SPS Level!\n")); DEBUG(("WARNING! Using num_ref_frames =%d for DPB size!\n", pSeqParamSet->numRefFrames)); value = pSeqParamSet->numRefFrames; } pSeqParamSet->maxDpbSize = value; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pSeqParamSet->vuiParametersPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; /* VUI */ if (pSeqParamSet->vuiParametersPresentFlag) { ALLOCATE(pSeqParamSet->vuiParameters, 1, vuiParameters_t); if (pSeqParamSet->vuiParameters == NULL) return(MEMORY_ALLOCATION_ERROR); tmp = h264bsdDecodeVuiParameters(pStrmData, pSeqParamSet->vuiParameters); if (tmp != HANTRO_OK) return(tmp); /* check numReorderFrames and maxDecFrameBuffering */ if (pSeqParamSet->vuiParameters->bitstreamRestrictionFlag) { if (pSeqParamSet->vuiParameters->numReorderFrames > pSeqParamSet->vuiParameters->maxDecFrameBuffering || pSeqParamSet->vuiParameters->maxDecFrameBuffering < pSeqParamSet->numRefFrames || pSeqParamSet->vuiParameters->maxDecFrameBuffering > pSeqParamSet->maxDpbSize) { return(HANTRO_NOK); } /* standard says that "the sequence shall not require a DPB with * size of more than max(1, maxDecFrameBuffering) */ pSeqParamSet->maxDpbSize = MAX(1, pSeqParamSet->vuiParameters->maxDecFrameBuffering); } } tmp = h264bsdRbspTrailingBits(pStrmData); /* ignore possible errors in trailing bits of parameters sets */ return(HANTRO_OK); }
u32 h264bsdDecodeMacroblockLayerCavlc(strmData_t * pStrmData, macroblockLayer_t * pMbLayer, mbStorage_t * pMb, const sliceHeader_t * pSliceHdr ) { /* Variables */ u32 tmp, i, value; i32 itmp; mbPartPredMode_e partMode; /* Code */ ASSERT(pStrmData); ASSERT(pMbLayer); (void)DWLmemset(pMbLayer->residual.totalCoeff, 0, 24); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &value); if(IS_I_SLICE(pSliceHdr->sliceType)) { if((value + 6) > 31 || tmp != HANTRO_OK) return (HANTRO_NOK); pMbLayer->mbType = (mbType_e) (value + 6); } else { if((value + 1) > 31 || tmp != HANTRO_OK) return (HANTRO_NOK); pMbLayer->mbType = (mbType_e) (value + 1); } if(pMbLayer->mbType == I_PCM) { u8 *level; while(!h264bsdIsByteAligned(pStrmData)) { /* pcm_alignment_zero_bit */ tmp = h264bsdGetBits(pStrmData, 1); if(tmp) return (HANTRO_NOK); } level = (u8 *) pMbLayer->residual.rlc; for(i = 384; i > 0; i--) { value = h264bsdGetBits(pStrmData, 8); if(value == END_OF_STREAM) return (HANTRO_NOK); *level++ = (u8) value; } } else { partMode = h264bsdMbPartPredMode(pMbLayer->mbType); if((partMode == PRED_MODE_INTER) && (h264bsdNumMbPart(pMbLayer->mbType) == 4)) { tmp = DecodeSubMbPred(pStrmData, &pMbLayer->subMbPred, pMbLayer->mbType, pSliceHdr->numRefIdxL0Active, pMb ); } else { tmp = DecodeMbPred(pStrmData, &pMbLayer->mbPred, pMbLayer->mbType, pSliceHdr->numRefIdxL0Active, pMb ); } if(tmp != HANTRO_OK) return (tmp); if(partMode != PRED_MODE_INTRA16x16) { tmp = h264bsdDecodeExpGolombMapped(pStrmData, &value, (u32) (partMode == PRED_MODE_INTRA4x4)); if(tmp != HANTRO_OK) return (tmp); pMbLayer->codedBlockPattern = value; } else { pMbLayer->codedBlockPattern = CbpIntra16x16(pMbLayer->mbType); } if(pMbLayer->codedBlockPattern || (partMode == PRED_MODE_INTRA16x16)) { tmp = h264bsdDecodeExpGolombSigned(pStrmData, &itmp); if(tmp != HANTRO_OK || (u32) (itmp + 26) > 51U /*(itmp >= -26) || (itmp < 26) */ ) return (HANTRO_NOK); pMbLayer->mbQpDelta = itmp; tmp = DecodeResidual(pStrmData, pMbLayer, pMb); if(tmp != HANTRO_OK) return (tmp); } } return (HANTRO_OK); }