/* * 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 h264bsdDecodeVuiParameters DecodeHrdParameters ------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------ 1. Include headers ------------------------------------------------------------------------------*/ #include "h264bsd_vui.h" #include "basetype.h" #include "h264bsd_vlc.h" #include "h264bsd_stream.h" #include "h264bsd_util.h" /*------------------------------------------------------------------------------ 2. External compiler flags -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- 3. Module defines ------------------------------------------------------------------------------*/ #define MAX_DPB_SIZE 16 #define MAX_BR 240000 /* for level 5.1 */ #define MAX_CPB 240000 /* for level 5.1 */ /*------------------------------------------------------------------------------ 4. Local function prototypes ------------------------------------------------------------------------------*/ static u32 DecodeHrdParameters( strmData_t *pStrmData, hrdParameters_t *pHrdParameters); /*------------------------------------------------------------------------------ Function: h264bsdDecodeVuiParameters Functional description: Decode VUI parameters from the stream. See standard for details. Inputs: pStrmData pointer to stream data structure Outputs: pVuiParameters decoded information is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data or end of stream ------------------------------------------------------------------------------*/ u32 h264bsdDecodeVuiParameters(strmData_t *pStrmData, vuiParameters_t *pVuiParameters) { /* Variables */ u32 tmp; /* Code */ ASSERT(pStrmData); ASSERT(pVuiParameters); H264SwDecMemset(pVuiParameters, 0, sizeof(vuiParameters_t)); tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->aspectRatioPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->aspectRatioPresentFlag) { tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->aspectRatioIdc = tmp; if (pVuiParameters->aspectRatioIdc == ASPECT_RATIO_EXTENDED_SAR) { tmp = h264bsdGetBits(pStrmData, 16); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->sarWidth = tmp; tmp = h264bsdGetBits(pStrmData, 16); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->sarHeight = tmp; } } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->overscanInfoPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->overscanInfoPresentFlag) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->overscanAppropriateFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->videoSignalTypePresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->videoSignalTypePresentFlag) { tmp = h264bsdGetBits(pStrmData, 3); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->videoFormat = tmp; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->videoFullRangeFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->colourDescriptionPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->colourDescriptionPresentFlag) { tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->colourPrimaries = tmp; tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->transferCharacteristics = tmp; tmp = h264bsdGetBits(pStrmData, 8); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->matrixCoefficients = tmp; } else { pVuiParameters->colourPrimaries = 2; pVuiParameters->transferCharacteristics = 2; pVuiParameters->matrixCoefficients = 2; } } else { pVuiParameters->videoFormat = 5; pVuiParameters->colourPrimaries = 2; pVuiParameters->transferCharacteristics = 2; pVuiParameters->matrixCoefficients = 2; } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->chromaLocInfoPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->chromaLocInfoPresentFlag) { tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->chromaSampleLocTypeTopField); if (tmp != HANTRO_OK) return(tmp); if (pVuiParameters->chromaSampleLocTypeTopField > 5) return(HANTRO_NOK); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->chromaSampleLocTypeBottomField); if (tmp != HANTRO_OK) return(tmp); if (pVuiParameters->chromaSampleLocTypeBottomField > 5) return(HANTRO_NOK); } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->timingInfoPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->timingInfoPresentFlag) { tmp = h264bsdShowBits32(pStrmData); if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM) return(HANTRO_NOK); if (tmp == 0) return(HANTRO_NOK); pVuiParameters->numUnitsInTick = tmp; tmp = h264bsdShowBits32(pStrmData); if (h264bsdFlushBits(pStrmData, 32) == END_OF_STREAM) return(HANTRO_NOK); if (tmp == 0) return(HANTRO_NOK); pVuiParameters->timeScale = tmp; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->fixedFrameRateFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->nalHrdParametersPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->nalHrdParametersPresentFlag) { tmp = DecodeHrdParameters(pStrmData, &pVuiParameters->nalHrdParameters); if (tmp != HANTRO_OK) return(tmp); } else { pVuiParameters->nalHrdParameters.cpbCnt = 1; /* MaxBR and MaxCPB should be the values correspondig to the levelIdc * in the SPS containing these VUI parameters. However, these values * are not used anywhere and maximum for any level will be used here */ pVuiParameters->nalHrdParameters.bitRateValue[0] = 1200 * MAX_BR + 1; pVuiParameters->nalHrdParameters.cpbSizeValue[0] = 1200 * MAX_CPB + 1; pVuiParameters->nalHrdParameters.initialCpbRemovalDelayLength = 24; pVuiParameters->nalHrdParameters.cpbRemovalDelayLength = 24; pVuiParameters->nalHrdParameters.dpbOutputDelayLength = 24; pVuiParameters->nalHrdParameters.timeOffsetLength = 24; } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->vclHrdParametersPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->vclHrdParametersPresentFlag) { tmp = DecodeHrdParameters(pStrmData, &pVuiParameters->vclHrdParameters); if (tmp != HANTRO_OK) return(tmp); } else { pVuiParameters->vclHrdParameters.cpbCnt = 1; /* MaxBR and MaxCPB should be the values correspondig to the levelIdc * in the SPS containing these VUI parameters. However, these values * are not used anywhere and maximum for any level will be used here */ pVuiParameters->vclHrdParameters.bitRateValue[0] = 1000 * MAX_BR + 1; pVuiParameters->vclHrdParameters.cpbSizeValue[0] = 1000 * MAX_CPB + 1; pVuiParameters->vclHrdParameters.initialCpbRemovalDelayLength = 24; pVuiParameters->vclHrdParameters.cpbRemovalDelayLength = 24; pVuiParameters->vclHrdParameters.dpbOutputDelayLength = 24; pVuiParameters->vclHrdParameters.timeOffsetLength = 24; } if (pVuiParameters->nalHrdParametersPresentFlag || pVuiParameters->vclHrdParametersPresentFlag) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->lowDelayHrdFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; } tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->picStructPresentFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->bitstreamRestrictionFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; if (pVuiParameters->bitstreamRestrictionFlag) { tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pVuiParameters->motionVectorsOverPicBoundariesFlag = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->maxBytesPerPicDenom); if (tmp != HANTRO_OK) return(tmp); if (pVuiParameters->maxBytesPerPicDenom > 16) return(HANTRO_NOK); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->maxBitsPerMbDenom); if (tmp != HANTRO_OK) return(tmp); if (pVuiParameters->maxBitsPerMbDenom > 16) return(HANTRO_NOK); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->log2MaxMvLengthHorizontal); if (tmp != HANTRO_OK) return(tmp); if (pVuiParameters->log2MaxMvLengthHorizontal > 16) return(HANTRO_NOK); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->log2MaxMvLengthVertical); if (tmp != HANTRO_OK) return(tmp); if (pVuiParameters->log2MaxMvLengthVertical > 16) return(HANTRO_NOK); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->numReorderFrames); if (tmp != HANTRO_OK) return(tmp); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pVuiParameters->maxDecFrameBuffering); if (tmp != HANTRO_OK) return(tmp); } else { pVuiParameters->motionVectorsOverPicBoundariesFlag = HANTRO_TRUE; pVuiParameters->maxBytesPerPicDenom = 2; pVuiParameters->maxBitsPerMbDenom = 1; pVuiParameters->log2MaxMvLengthHorizontal = 16; pVuiParameters->log2MaxMvLengthVertical = 16; pVuiParameters->numReorderFrames = MAX_DPB_SIZE; pVuiParameters->maxDecFrameBuffering = MAX_DPB_SIZE; } return(HANTRO_OK); } /*------------------------------------------------------------------------------ Function: DecodeHrdParameters Functional description: Decode HRD parameters from the stream. See standard for details. Inputs: pStrmData pointer to stream data structure Outputs: pHrdParameters decoded information is stored here Returns: HANTRO_OK success HANTRO_NOK invalid stream data ------------------------------------------------------------------------------*/ static u32 DecodeHrdParameters( strmData_t *pStrmData, hrdParameters_t *pHrdParameters) { /* Variables */ u32 tmp, i; /* Code */ ASSERT(pStrmData); ASSERT(pHrdParameters); tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pHrdParameters->cpbCnt); if (tmp != HANTRO_OK) return(tmp); /* cpbCount = cpb_cnt_minus1 + 1 */ pHrdParameters->cpbCnt++; if (pHrdParameters->cpbCnt > MAX_CPB_CNT) return(HANTRO_NOK); tmp = h264bsdGetBits(pStrmData, 4); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pHrdParameters->bitRateScale = tmp; tmp = h264bsdGetBits(pStrmData, 4); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pHrdParameters->cpbSizeScale = tmp; for (i = 0; i < pHrdParameters->cpbCnt; i++) { /* bit_rate_value_minus1 in the range [0, 2^32 - 2] */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pHrdParameters->bitRateValue[i]); if (tmp != HANTRO_OK) return(tmp); if (pHrdParameters->bitRateValue[i] > 4294967294U) return(HANTRO_NOK); pHrdParameters->bitRateValue[i]++; /* this may result in overflow, but this value is not used for * anything */ pHrdParameters->bitRateValue[i] *= 1 << (6 + pHrdParameters->bitRateScale); /* cpb_size_value_minus1 in the range [0, 2^32 - 2] */ tmp = h264bsdDecodeExpGolombUnsigned(pStrmData, &pHrdParameters->cpbSizeValue[i]); if (tmp != HANTRO_OK) return(tmp); if (pHrdParameters->cpbSizeValue[i] > 4294967294U) return(HANTRO_NOK); pHrdParameters->cpbSizeValue[i]++; /* this may result in overflow, but this value is not used for * anything */ pHrdParameters->cpbSizeValue[i] *= 1 << (4 + pHrdParameters->cpbSizeScale); tmp = h264bsdGetBits(pStrmData, 1); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pHrdParameters->cbrFlag[i] = (tmp == 1) ? HANTRO_TRUE : HANTRO_FALSE; } tmp = h264bsdGetBits(pStrmData, 5); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pHrdParameters->initialCpbRemovalDelayLength = tmp + 1; tmp = h264bsdGetBits(pStrmData, 5); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pHrdParameters->cpbRemovalDelayLength = tmp + 1; tmp = h264bsdGetBits(pStrmData, 5); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pHrdParameters->dpbOutputDelayLength = tmp + 1; tmp = h264bsdGetBits(pStrmData, 5); if (tmp == END_OF_STREAM) return(HANTRO_NOK); pHrdParameters->timeOffsetLength = tmp; return(HANTRO_OK); }