diff options
Diffstat (limited to 'media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c')
-rwxr-xr-x | media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c new file mode 100755 index 0000000..c288d4b --- /dev/null +++ b/media/libstagefright/codecs/on2/h264dec/source/h264bsd_slice_data.c @@ -0,0 +1,354 @@ +/* + * 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 + h264bsdDecodeSliceData + SetMbParams + h264bsdMarkSliceCorrupted + +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 1. Include headers +------------------------------------------------------------------------------*/ + +#include "h264bsd_slice_data.h" +#include "h264bsd_util.h" +#include "h264bsd_vlc.h" + +/*------------------------------------------------------------------------------ + 2. External compiler flags +-------------------------------------------------------------------------------- + +-------------------------------------------------------------------------------- + 3. Module defines +------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ + 4. Local function prototypes +------------------------------------------------------------------------------*/ + +static void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId, + i32 chromaQpIndexOffset); + +/*------------------------------------------------------------------------------ + + 5.1 Function name: h264bsdDecodeSliceData + + Functional description: + Decode one slice. Function decodes stream data, i.e. macroblocks + and possible skip_run fields. h264bsdDecodeMacroblock function is + called to handle all other macroblock related processing. + Macroblock to slice group mapping is considered when next + macroblock to process is determined (h264bsdNextMbAddress function) + map + + Inputs: + pStrmData pointer to stream data structure + pStorage pointer to storage structure + currImage pointer to current processed picture, needed for + intra prediction of the macroblocks + pSliceHeader pointer to slice header of the current slice + + Outputs: + currImage processed macroblocks are written to current image + pStorage mbStorage structure of each processed macroblock + is updated here + + Returns: + HANTRO_OK success + HANTRO_NOK invalid stream data + +------------------------------------------------------------------------------*/ + +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; + H264SwDecMemset(&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); + +} + +/*------------------------------------------------------------------------------ + + 5.2 Function: SetMbParams + + Functional description: + Set macroblock parameters that remain constant for this slice + + Inputs: + pSlice pointer to current slice header + sliceId id of the current slice + chromaQpIndexOffset + + Outputs: + pMb pointer to macroblock structure which is updated + + Returns: + none + +------------------------------------------------------------------------------*/ + +void SetMbParams(mbStorage_t *pMb, sliceHeader_t *pSlice, u32 sliceId, + i32 chromaQpIndexOffset) +{ + +/* Variables */ + u32 tmp1; + i32 tmp2, tmp3; + +/* Code */ + + tmp1 = pSlice->disableDeblockingFilterIdc; + tmp2 = pSlice->sliceAlphaC0Offset; + tmp3 = pSlice->sliceBetaOffset; + pMb->sliceId = sliceId; + pMb->disableDeblockingFilterIdc = tmp1; + pMb->filterOffsetA = tmp2; + pMb->filterOffsetB = tmp3; + pMb->chromaQpIndexOffset = chromaQpIndexOffset; + +} + +/*------------------------------------------------------------------------------ + + 5.3 Function name: h264bsdMarkSliceCorrupted + + Functional description: + Mark macroblocks of the slice corrupted. If lastMbAddr in the slice + storage is set -> picWidhtInMbs (or at least 10) macroblocks back + from the lastMbAddr are marked corrupted. However, if lastMbAddr + is not set -> all macroblocks of the slice are marked. + + Inputs: + pStorage pointer to storage structure + firstMbInSlice address of the first macroblock in the slice, this + identifies the slice to be marked corrupted + + Outputs: + pStorage mbStorage for the corrupted macroblocks updated + + Returns: + none + +------------------------------------------------------------------------------*/ + +void h264bsdMarkSliceCorrupted(storage_t *pStorage, u32 firstMbInSlice) +{ + +/* Variables */ + + u32 tmp, i; + u32 sliceId; + u32 currMbAddr; + +/* Code */ + + ASSERT(pStorage); + ASSERT(firstMbInSlice < pStorage->picSizeInMbs); + + currMbAddr = firstMbInSlice; + + sliceId = pStorage->slice->sliceId; + + /* DecodeSliceData sets lastMbAddr for I slices -> if it was set, go back + * MAX(picWidthInMbs, 10) macroblocks and start marking from there */ + if (pStorage->slice->lastMbAddr) + { + ASSERT(pStorage->mb[pStorage->slice->lastMbAddr].sliceId == sliceId); + i = pStorage->slice->lastMbAddr - 1; + tmp = 0; + while (i > currMbAddr) + { + if (pStorage->mb[i].sliceId == sliceId) + { + tmp++; + if (tmp >= MAX(pStorage->activeSps->picWidthInMbs, 10)) + break; + } + i--; + } + currMbAddr = i; + } + + do + { + + if ( (pStorage->mb[currMbAddr].sliceId == sliceId) && + (pStorage->mb[currMbAddr].decoded) ) + { + pStorage->mb[currMbAddr].decoded--; + } + else + { + break; + } + + currMbAddr = h264bsdNextMbAddress(pStorage->sliceGroupMap, + pStorage->picSizeInMbs, currMbAddr); + + } while (currMbAddr); + +} + |