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 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); }