/H264Dec/source/h264bsd_dpb.c
http://github.com/mbebenita/Broadway · C · 1584 lines · 761 code · 267 blank · 556 comment · 178 complexity · 46ab8f2eaf94c6b0f5abbca9b757bc77 MD5 · raw file
- /*
- * 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
- ComparePictures
- h264bsdReorderRefPicList
- Mmcop1
- Mmcop2
- Mmcop3
- Mmcop4
- Mmcop5
- Mmcop6
- h264bsdMarkDecRefPic
- h264bsdGetRefPicData
- h264bsdAllocateDpbImage
- SlidingWindowRefPicMarking
- h264bsdInitDpb
- h264bsdResetDpb
- h264bsdInitRefPicList
- FindDpbPic
- SetPicNums
- h264bsdCheckGapsInFrameNum
- FindSmallestPicOrderCnt
- OutputPicture
- h264bsdDpbOutputPicture
- h264bsdFlushDpb
- h264bsdFreeDpb
- ------------------------------------------------------------------------------*/
- /*------------------------------------------------------------------------------
- 1. Include headers
- ------------------------------------------------------------------------------*/
- #include "h264bsd_cfg.h"
- #include "h264bsd_dpb.h"
- #include "h264bsd_slice_header.h"
- #include "h264bsd_image.h"
- #include "h264bsd_util.h"
- #include "basetype.h"
- /*------------------------------------------------------------------------------
- 2. External compiler flags
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- 3. Module defines
- ------------------------------------------------------------------------------*/
- /* macros to determine picture status. Note that IS_SHORT_TERM macro returns
- * true also for non-existing pictures because non-existing pictures are
- * regarded short term pictures according to H.264 standard */
- #define IS_REFERENCE(a) ((a).status)
- #define IS_EXISTING(a) ((a).status > NON_EXISTING)
- #define IS_SHORT_TERM(a) \
- ((a).status == NON_EXISTING || (a).status == SHORT_TERM)
- #define IS_LONG_TERM(a) ((a).status == LONG_TERM)
- /* macro to set a picture unused for reference */
- #define SET_UNUSED(a) (a).status = UNUSED;
- #define MAX_NUM_REF_IDX_L0_ACTIVE 16
- /*------------------------------------------------------------------------------
- 4. Local function prototypes
- ------------------------------------------------------------------------------*/
- static i32 ComparePictures(const void *ptr1, const void *ptr2);
- static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums);
- static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum);
- static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
- u32 longTermFrameIdx);
- static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx);
- static u32 Mmcop5(dpbStorage_t *dpb);
- static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
- u32 longTermFrameIdx);
- static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb);
- static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm);
- static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum);
- static dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb);
- static u32 OutputPicture(dpbStorage_t *dpb);
- static void ShellSort(dpbPicture_t *pPic, u32 num);
- /*------------------------------------------------------------------------------
- Function: ComparePictures
- Functional description:
- Function to compare dpb pictures, used by the ShellSort() function.
- Order of the pictures after sorting shall be as follows:
- 1) short term reference pictures starting with the largest
- picNum
- 2) long term reference pictures starting with the smallest
- longTermPicNum
- 3) pictures unused for reference but needed for display
- 4) other pictures
- Returns:
- -1 pic 1 is greater than pic 2
- 0 equal from comparison point of view
- 1 pic 2 is greater then pic 1
- ------------------------------------------------------------------------------*/
- static i32 ComparePictures(const void *ptr1, const void *ptr2)
- {
- /* Variables */
- dpbPicture_t *pic1, *pic2;
- /* Code */
- ASSERT(ptr1);
- ASSERT(ptr2);
- pic1 = (dpbPicture_t*)ptr1;
- pic2 = (dpbPicture_t*)ptr2;
- /* both are non-reference pictures, check if needed for display */
- if (!IS_REFERENCE(*pic1) && !IS_REFERENCE(*pic2))
- {
- if (pic1->toBeDisplayed && !pic2->toBeDisplayed)
- return(-1);
- else if (!pic1->toBeDisplayed && pic2->toBeDisplayed)
- return(1);
- else
- return(0);
- }
- /* only pic 1 needed for reference -> greater */
- else if (!IS_REFERENCE(*pic2))
- return(-1);
- /* only pic 2 needed for reference -> greater */
- else if (!IS_REFERENCE(*pic1))
- return(1);
- /* both are short term reference pictures -> check picNum */
- else if (IS_SHORT_TERM(*pic1) && IS_SHORT_TERM(*pic2))
- {
- if (pic1->picNum > pic2->picNum)
- return(-1);
- else if (pic1->picNum < pic2->picNum)
- return(1);
- else
- return(0);
- }
- /* only pic 1 is short term -> greater */
- else if (IS_SHORT_TERM(*pic1))
- return(-1);
- /* only pic 2 is short term -> greater */
- else if (IS_SHORT_TERM(*pic2))
- return(1);
- /* both are long term reference pictures -> check picNum (contains the
- * longTermPicNum */
- else
- {
- if (pic1->picNum > pic2->picNum)
- return(1);
- else if (pic1->picNum < pic2->picNum)
- return(-1);
- else
- return(0);
- }
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdReorderRefPicList
- Functional description:
- Function to perform reference picture list reordering based on
- reordering commands received in the slice header. See details
- of the process in the H.264 standard.
- Inputs:
- dpb pointer to dpb storage structure
- order pointer to reordering commands
- currFrameNum current frame number
- numRefIdxActive number of active reference indices for current
- picture
- Outputs:
- dpb 'list' field of the structure reordered
- Returns:
- HANTRO_OK success
- HANTRO_NOK if non-existing pictures referred to in the
- reordering commands
- ------------------------------------------------------------------------------*/
- u32 h264bsdReorderRefPicList(
- dpbStorage_t *dpb,
- refPicListReordering_t *order,
- u32 currFrameNum,
- u32 numRefIdxActive)
- {
- /* Variables */
- u32 i, j, k, picNumPred, refIdx;
- i32 picNum, picNumNoWrap, index;
- u32 isShortTerm;
- /* Code */
- ASSERT(order);
- ASSERT(currFrameNum <= dpb->maxFrameNum);
- ASSERT(numRefIdxActive <= MAX_NUM_REF_IDX_L0_ACTIVE);
- /* set dpb picture numbers for sorting */
- SetPicNums(dpb, currFrameNum);
- if (!order->refPicListReorderingFlagL0)
- return(HANTRO_OK);
- refIdx = 0;
- picNumPred = currFrameNum;
- i = 0;
- while (order->command[i].reorderingOfPicNumsIdc < 3)
- {
- /* short term */
- if (order->command[i].reorderingOfPicNumsIdc < 2)
- {
- if (order->command[i].reorderingOfPicNumsIdc == 0)
- {
- picNumNoWrap =
- (i32)picNumPred - (i32)order->command[i].absDiffPicNum;
- if (picNumNoWrap < 0)
- picNumNoWrap += (i32)dpb->maxFrameNum;
- }
- else
- {
- picNumNoWrap =
- (i32)(picNumPred + order->command[i].absDiffPicNum);
- if (picNumNoWrap >= (i32)dpb->maxFrameNum)
- picNumNoWrap -= (i32)dpb->maxFrameNum;
- }
- picNumPred = (u32)picNumNoWrap;
- picNum = picNumNoWrap;
- if ((u32)picNumNoWrap > currFrameNum)
- picNum -= (i32)dpb->maxFrameNum;
- isShortTerm = HANTRO_TRUE;
- }
- /* long term */
- else
- {
- picNum = (i32)order->command[i].longTermPicNum;
- isShortTerm = HANTRO_FALSE;
- }
- /* find corresponding picture from dpb */
- index = FindDpbPic(dpb, picNum, isShortTerm);
- if (index < 0 || !IS_EXISTING(dpb->buffer[index]))
- return(HANTRO_NOK);
- /* shift pictures */
- for (j = numRefIdxActive; j > refIdx; j--)
- dpb->list[j] = dpb->list[j-1];
- /* put picture into the list */
- dpb->list[refIdx++] = &dpb->buffer[index];
- /* remove later references to the same picture */
- for (j = k = refIdx; j <= numRefIdxActive; j++)
- if(dpb->list[j] != &dpb->buffer[index])
- dpb->list[k++] = dpb->list[j];
- i++;
- }
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: Mmcop1
- Functional description:
- Function to mark a short-term reference picture unused for
- reference, memory_management_control_operation equal to 1
- Returns:
- HANTRO_OK success
- HANTRO_NOK failure, picture does not exist in the buffer
- ------------------------------------------------------------------------------*/
- static u32 Mmcop1(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums)
- {
- /* Variables */
- i32 index, picNum;
- /* Code */
- ASSERT(currPicNum < dpb->maxFrameNum);
- picNum = (i32)currPicNum - (i32)differenceOfPicNums;
- index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
- if (index < 0)
- return(HANTRO_NOK);
- SET_UNUSED(dpb->buffer[index]);
- dpb->numRefFrames--;
- if (!dpb->buffer[index].toBeDisplayed)
- dpb->fullness--;
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: Mmcop2
- Functional description:
- Function to mark a long-term reference picture unused for
- reference, memory_management_control_operation equal to 2
- Returns:
- HANTRO_OK success
- HANTRO_NOK failure, picture does not exist in the buffer
- ------------------------------------------------------------------------------*/
- static u32 Mmcop2(dpbStorage_t *dpb, u32 longTermPicNum)
- {
- /* Variables */
- i32 index;
- /* Code */
- index = FindDpbPic(dpb, (i32)longTermPicNum, HANTRO_FALSE);
- if (index < 0)
- return(HANTRO_NOK);
- SET_UNUSED(dpb->buffer[index]);
- dpb->numRefFrames--;
- if (!dpb->buffer[index].toBeDisplayed)
- dpb->fullness--;
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: Mmcop3
- Functional description:
- Function to assing a longTermFrameIdx to a short-term reference
- frame (i.e. to change it to a long-term reference picture),
- memory_management_control_operation equal to 3
- Returns:
- HANTRO_OK success
- HANTRO_NOK failure, short-term picture does not exist in the
- buffer or is a non-existing picture, or invalid
- longTermFrameIdx given
- ------------------------------------------------------------------------------*/
- static u32 Mmcop3(dpbStorage_t *dpb, u32 currPicNum, u32 differenceOfPicNums,
- u32 longTermFrameIdx)
- {
- /* Variables */
- i32 index, picNum;
- u32 i;
- /* Code */
- ASSERT(dpb);
- ASSERT(currPicNum < dpb->maxFrameNum);
- if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
- (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
- return(HANTRO_NOK);
- /* check if a long term picture with the same longTermFrameIdx already
- * exist and remove it if necessary */
- for (i = 0; i < dpb->maxRefFrames; i++)
- if (IS_LONG_TERM(dpb->buffer[i]) &&
- (u32)dpb->buffer[i].picNum == longTermFrameIdx)
- {
- SET_UNUSED(dpb->buffer[i]);
- dpb->numRefFrames--;
- if (!dpb->buffer[i].toBeDisplayed)
- dpb->fullness--;
- break;
- }
- picNum = (i32)currPicNum - (i32)differenceOfPicNums;
- index = FindDpbPic(dpb, picNum, HANTRO_TRUE);
- if (index < 0)
- return(HANTRO_NOK);
- if (!IS_EXISTING(dpb->buffer[index]))
- return(HANTRO_NOK);
- dpb->buffer[index].status = LONG_TERM;
- dpb->buffer[index].picNum = (i32)longTermFrameIdx;
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: Mmcop4
- Functional description:
- Function to set maxLongTermFrameIdx,
- memory_management_control_operation equal to 4
- Returns:
- HANTRO_OK success
- ------------------------------------------------------------------------------*/
- static u32 Mmcop4(dpbStorage_t *dpb, u32 maxLongTermFrameIdx)
- {
- /* Variables */
- u32 i;
- /* Code */
- dpb->maxLongTermFrameIdx = maxLongTermFrameIdx;
- for (i = 0; i < dpb->maxRefFrames; i++)
- if (IS_LONG_TERM(dpb->buffer[i]) &&
- ( ((u32)dpb->buffer[i].picNum > maxLongTermFrameIdx) ||
- (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ) )
- {
- SET_UNUSED(dpb->buffer[i]);
- dpb->numRefFrames--;
- if (!dpb->buffer[i].toBeDisplayed)
- dpb->fullness--;
- }
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: Mmcop5
- Functional description:
- Function to mark all reference pictures unused for reference and
- set maxLongTermFrameIdx to NO_LONG_TERM_FRAME_INDICES,
- memory_management_control_operation equal to 5. Function flushes
- the buffer and places all pictures that are needed for display into
- the output buffer.
- Returns:
- HANTRO_OK success
- ------------------------------------------------------------------------------*/
- static u32 Mmcop5(dpbStorage_t *dpb)
- {
- /* Variables */
- u32 i;
- /* Code */
- for (i = 0; i < 16; i++)
- {
- if (IS_REFERENCE(dpb->buffer[i]))
- {
- SET_UNUSED(dpb->buffer[i]);
- if (!dpb->buffer[i].toBeDisplayed)
- dpb->fullness--;
- }
- }
- /* output all pictures */
- while (OutputPicture(dpb) == HANTRO_OK)
- ;
- dpb->numRefFrames = 0;
- dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
- dpb->prevRefFrameNum = 0;
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: Mmcop6
- Functional description:
- Function to assign longTermFrameIdx to the current picture,
- memory_management_control_operation equal to 6
- Returns:
- HANTRO_OK success
- HANTRO_NOK invalid longTermFrameIdx or no room for current
- picture in the buffer
- ------------------------------------------------------------------------------*/
- static u32 Mmcop6(dpbStorage_t *dpb, u32 frameNum, i32 picOrderCnt,
- u32 longTermFrameIdx)
- {
- /* Variables */
- u32 i;
- /* Code */
- ASSERT(frameNum < dpb->maxFrameNum);
- if ( (dpb->maxLongTermFrameIdx == NO_LONG_TERM_FRAME_INDICES) ||
- (longTermFrameIdx > dpb->maxLongTermFrameIdx) )
- return(HANTRO_NOK);
- /* check if a long term picture with the same longTermFrameIdx already
- * exist and remove it if necessary */
- for (i = 0; i < dpb->maxRefFrames; i++)
- if (IS_LONG_TERM(dpb->buffer[i]) &&
- (u32)dpb->buffer[i].picNum == longTermFrameIdx)
- {
- SET_UNUSED(dpb->buffer[i]);
- dpb->numRefFrames--;
- if (!dpb->buffer[i].toBeDisplayed)
- dpb->fullness--;
- break;
- }
- if (dpb->numRefFrames < dpb->maxRefFrames)
- {
- dpb->currentOut->frameNum = frameNum;
- dpb->currentOut->picNum = (i32)longTermFrameIdx;
- dpb->currentOut->picOrderCnt = picOrderCnt;
- dpb->currentOut->status = LONG_TERM;
- if (dpb->noReordering)
- dpb->currentOut->toBeDisplayed = HANTRO_FALSE;
- else
- dpb->currentOut->toBeDisplayed = HANTRO_TRUE;
- dpb->numRefFrames++;
- dpb->fullness++;
- return(HANTRO_OK);
- }
- /* if there is no room, return an error */
- else
- return(HANTRO_NOK);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdMarkDecRefPic
- Functional description:
- Function to perform reference picture marking process. This
- function should be called both for reference and non-reference
- pictures. Non-reference pictures shall have mark pointer set to
- NULL.
- Inputs:
- dpb pointer to the DPB data structure
- mark pointer to reference picture marking commands
- image pointer to current picture to be placed in the buffer
- frameNum frame number of the current picture
- picOrderCnt picture order count for the current picture
- isIdr flag to indicate if the current picture is an
- IDR picture
- currentPicId identifier for the current picture, from the
- application, stored along with the picture
- numErrMbs number of concealed macroblocks in the current
- picture, stored along with the picture
- Outputs:
- dpb 'buffer' modified, possible output frames placed into
- 'outBuf'
- Returns:
- HANTRO_OK success
- HANTRO_NOK failure
- ------------------------------------------------------------------------------*/
- u32 h264bsdMarkDecRefPic(
- dpbStorage_t *dpb,
- decRefPicMarking_t *mark,
- image_t *image,
- u32 frameNum,
- i32 picOrderCnt,
- u32 isIdr,
- u32 currentPicId,
- u32 numErrMbs)
- {
- /* Variables */
- u32 i, status;
- u32 markedAsLongTerm;
- u32 toBeDisplayed;
- /* Code */
- ASSERT(dpb);
- ASSERT(mark || !isIdr);
- ASSERT(!isIdr || (frameNum == 0 && picOrderCnt == 0));
- ASSERT(frameNum < dpb->maxFrameNum);
- if (image->data != dpb->currentOut->data)
- {
- EPRINT("TRYING TO MARK NON-ALLOCATED IMAGE");
- return(HANTRO_NOK);
- }
- dpb->lastContainsMmco5 = HANTRO_FALSE;
- status = HANTRO_OK;
- toBeDisplayed = dpb->noReordering ? HANTRO_FALSE : HANTRO_TRUE;
- /* non-reference picture, stored for display reordering purposes */
- if (mark == NULL)
- {
- dpb->currentOut->status = UNUSED;
- dpb->currentOut->frameNum = frameNum;
- dpb->currentOut->picNum = (i32)frameNum;
- dpb->currentOut->picOrderCnt = picOrderCnt;
- dpb->currentOut->toBeDisplayed = toBeDisplayed;
- if (!dpb->noReordering)
- dpb->fullness++;
- }
- /* IDR picture */
- else if (isIdr)
- {
- /* h264bsdCheckGapsInFrameNum not called for IDR pictures -> have to
- * reset numOut and outIndex here */
- dpb->numOut = dpb->outIndex = 0;
- /* flush the buffer */
- Mmcop5(dpb);
- /* if noOutputOfPriorPicsFlag was set -> the pictures preceding the
- * IDR picture shall not be output -> set output buffer empty */
- if (mark->noOutputOfPriorPicsFlag || dpb->noReordering)
- {
- dpb->numOut = 0;
- dpb->outIndex = 0;
- }
- if (mark->longTermReferenceFlag)
- {
- dpb->currentOut->status = LONG_TERM;
- dpb->maxLongTermFrameIdx = 0;
- }
- else
- {
- dpb->currentOut->status = SHORT_TERM;
- dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
- }
- dpb->currentOut->frameNum = 0;
- dpb->currentOut->picNum = 0;
- dpb->currentOut->picOrderCnt = 0;
- dpb->currentOut->toBeDisplayed = toBeDisplayed;
- dpb->fullness = 1;
- dpb->numRefFrames = 1;
- }
- /* reference picture */
- else
- {
- markedAsLongTerm = HANTRO_FALSE;
- if (mark->adaptiveRefPicMarkingModeFlag)
- {
- i = 0;
- while (mark->operation[i].memoryManagementControlOperation)
- {
- switch (mark->operation[i].memoryManagementControlOperation)
- {
- case 1:
- status = Mmcop1(
- dpb,
- frameNum,
- mark->operation[i].differenceOfPicNums);
- break;
- case 2:
- status = Mmcop2(dpb, mark->operation[i].longTermPicNum);
- break;
- case 3:
- status = Mmcop3(
- dpb,
- frameNum,
- mark->operation[i].differenceOfPicNums,
- mark->operation[i].longTermFrameIdx);
- break;
- case 4:
- status = Mmcop4(
- dpb,
- mark->operation[i].maxLongTermFrameIdx);
- break;
- case 5:
- status = Mmcop5(dpb);
- dpb->lastContainsMmco5 = HANTRO_TRUE;
- frameNum = 0;
- break;
- case 6:
- status = Mmcop6(
- dpb,
- frameNum,
- picOrderCnt,
- mark->operation[i].longTermFrameIdx);
- if (status == HANTRO_OK)
- markedAsLongTerm = HANTRO_TRUE;
- break;
- default: /* invalid memory management control operation */
- status = HANTRO_NOK;
- break;
- }
- if (status != HANTRO_OK)
- {
- break;
- }
- i++;
- }
- }
- else
- {
- status = SlidingWindowRefPicMarking(dpb);
- }
- /* if current picture was not marked as long-term reference by
- * memory management control operation 6 -> mark current as short
- * term and insert it into dpb (if there is room) */
- if (!markedAsLongTerm)
- {
- if (dpb->numRefFrames < dpb->maxRefFrames)
- {
- dpb->currentOut->frameNum = frameNum;
- dpb->currentOut->picNum = (i32)frameNum;
- dpb->currentOut->picOrderCnt = picOrderCnt;
- dpb->currentOut->status = SHORT_TERM;
- dpb->currentOut->toBeDisplayed = toBeDisplayed;
- dpb->fullness++;
- dpb->numRefFrames++;
- }
- /* no room */
- else
- {
- status = HANTRO_NOK;
- }
- }
- }
- dpb->currentOut->isIdr = isIdr;
- dpb->currentOut->picId = currentPicId;
- dpb->currentOut->numErrMbs = numErrMbs;
- /* dpb was initialized to not to reorder the pictures -> output current
- * picture immediately */
- if (dpb->noReordering)
- {
- ASSERT(dpb->numOut == 0);
- ASSERT(dpb->outIndex == 0);
- dpb->outBuf[dpb->numOut].data = dpb->currentOut->data;
- dpb->outBuf[dpb->numOut].isIdr = dpb->currentOut->isIdr;
- dpb->outBuf[dpb->numOut].picId = dpb->currentOut->picId;
- dpb->outBuf[dpb->numOut].numErrMbs = dpb->currentOut->numErrMbs;
- dpb->numOut++;
- }
- else
- {
- /* output pictures if buffer full */
- while (dpb->fullness > dpb->dpbSize)
- {
- i = OutputPicture(dpb);
- ASSERT(i == HANTRO_OK);
- }
- }
- /* sort dpb */
- ShellSort(dpb->buffer, dpb->dpbSize+1);
- return(status);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdGetRefPicData
- Functional description:
- Function to get reference picture data from the reference picture
- list
- Returns:
- pointer to desired reference picture data
- NULL if invalid index or non-existing picture referred
- ------------------------------------------------------------------------------*/
- u8* h264bsdGetRefPicData(dpbStorage_t *dpb, u32 index)
- {
- /* Variables */
- /* Code */
- if(index > 16 || dpb->list[index] == NULL)
- return(NULL);
- else if(!IS_EXISTING(*dpb->list[index]))
- return(NULL);
- else
- return(dpb->list[index]->data);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdAllocateDpbImage
- Functional description:
- function to allocate memory for a image. This function does not
- really allocate any memory but reserves one of the buffer
- positions for decoding of current picture
- Returns:
- pointer to memory area for the image
- ------------------------------------------------------------------------------*/
- u8* h264bsdAllocateDpbImage(dpbStorage_t *dpb)
- {
- /* Variables */
- /* Code */
- ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
- !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
- ASSERT(dpb->fullness <= dpb->dpbSize);
- dpb->currentOut = dpb->buffer + dpb->dpbSize;
- return(dpb->currentOut->data);
- }
- /*------------------------------------------------------------------------------
- Function: SlidingWindowRefPicMarking
- Functional description:
- Function to perform sliding window refence picture marking process.
- Outputs:
- HANTRO_OK success
- HANTRO_NOK failure, no short-term reference frame found that
- could be marked unused
- ------------------------------------------------------------------------------*/
- static u32 SlidingWindowRefPicMarking(dpbStorage_t *dpb)
- {
- /* Variables */
- i32 index, picNum;
- u32 i;
- /* Code */
- if (dpb->numRefFrames < dpb->maxRefFrames)
- {
- return(HANTRO_OK);
- }
- else
- {
- index = -1;
- picNum = 0;
- /* find the oldest short term picture */
- for (i = 0; i < dpb->numRefFrames; i++)
- if (IS_SHORT_TERM(dpb->buffer[i]))
- if (dpb->buffer[i].picNum < picNum || index == -1)
- {
- index = (i32)i;
- picNum = dpb->buffer[i].picNum;
- }
- if (index >= 0)
- {
- SET_UNUSED(dpb->buffer[index]);
- dpb->numRefFrames--;
- if (!dpb->buffer[index].toBeDisplayed)
- dpb->fullness--;
- return(HANTRO_OK);
- }
- }
- return(HANTRO_NOK);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdInitDpb
- Functional description:
- Function to initialize DPB. Reserves memories for the buffer,
- reference picture list and output buffer. dpbSize indicates
- the maximum DPB size indicated by the levelIdc in the stream.
- If noReordering flag is FALSE the DPB stores dpbSize pictures
- for display reordering purposes. On the other hand, if the
- flag is TRUE the DPB only stores maxRefFrames reference pictures
- and outputs all the pictures immediately.
- Inputs:
- picSizeInMbs picture size in macroblocks
- dpbSize size of the DPB (number of pictures)
- maxRefFrames max number of reference frames
- maxFrameNum max frame number
- noReordering flag to indicate that DPB does not have to
- prepare to reorder frames for display
- Outputs:
- dpb pointer to dpb data storage
- Returns:
- HANTRO_OK success
- MEMORY_ALLOCATION_ERROR if memory allocation failed
- ------------------------------------------------------------------------------*/
- u32 h264bsdInitDpb(
- dpbStorage_t *dpb,
- u32 picSizeInMbs,
- u32 dpbSize,
- u32 maxRefFrames,
- u32 maxFrameNum,
- u32 noReordering)
- {
- /* Variables */
- u32 i;
- /* Code */
- ASSERT(picSizeInMbs);
- ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
- ASSERT(maxRefFrames <= dpbSize);
- ASSERT(maxFrameNum);
- ASSERT(dpbSize);
- dpb->maxLongTermFrameIdx = NO_LONG_TERM_FRAME_INDICES;
- dpb->maxRefFrames = MAX(maxRefFrames, 1);
- if (noReordering)
- dpb->dpbSize = dpb->maxRefFrames;
- else
- dpb->dpbSize = dpbSize;
- dpb->maxFrameNum = maxFrameNum;
- dpb->noReordering = noReordering;
- dpb->fullness = 0;
- dpb->numRefFrames = 0;
- dpb->prevRefFrameNum = 0;
- ALLOCATE(dpb->buffer, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t);
- if (dpb->buffer == NULL)
- return(MEMORY_ALLOCATION_ERROR);
- H264SwDecMemset(dpb->buffer, 0,
- (MAX_NUM_REF_IDX_L0_ACTIVE + 1)*sizeof(dpbPicture_t));
- for (i = 0; i < dpb->dpbSize + 1; i++)
- {
- /* Allocate needed amount of memory, which is:
- * image size + 32 + 15, where 32 cames from the fact that in ARM OpenMax
- * DL implementation Functions may read beyond the end of an array,
- * by a maximum of 32 bytes. And +15 cames for the need to align memory
- * to 16-byte boundary */
- ALLOCATE(dpb->buffer[i].pAllocatedData, (picSizeInMbs*384 + 32+15), u8);
- if (dpb->buffer[i].pAllocatedData == NULL)
- return(MEMORY_ALLOCATION_ERROR);
- dpb->buffer[i].data = ALIGN(dpb->buffer[i].pAllocatedData, 16);
- }
- ALLOCATE(dpb->list, MAX_NUM_REF_IDX_L0_ACTIVE + 1, dpbPicture_t*);
- ALLOCATE(dpb->outBuf, dpb->dpbSize+1, dpbOutPicture_t);
- if (dpb->list == NULL || dpb->outBuf == NULL)
- return(MEMORY_ALLOCATION_ERROR);
- H264SwDecMemset(dpb->list, 0,
- ((MAX_NUM_REF_IDX_L0_ACTIVE + 1) * sizeof(dpbPicture_t*)) );
- dpb->numOut = dpb->outIndex = 0;
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdResetDpb
- Functional description:
- Function to reset DPB. This function should be called when an IDR
- slice (other than the first) activates new sequence parameter set.
- Function calls h264bsdFreeDpb to free old allocated memories and
- h264bsdInitDpb to re-initialize the DPB. Same inputs, outputs and
- returns as for h264bsdInitDpb.
- ------------------------------------------------------------------------------*/
- u32 h264bsdResetDpb(
- dpbStorage_t *dpb,
- u32 picSizeInMbs,
- u32 dpbSize,
- u32 maxRefFrames,
- u32 maxFrameNum,
- u32 noReordering)
- {
- /* Code */
- ASSERT(picSizeInMbs);
- ASSERT(maxRefFrames <= MAX_NUM_REF_PICS);
- ASSERT(maxRefFrames <= dpbSize);
- ASSERT(maxFrameNum);
- ASSERT(dpbSize);
- h264bsdFreeDpb(dpb);
- return h264bsdInitDpb(dpb, picSizeInMbs, dpbSize, maxRefFrames,
- maxFrameNum, noReordering);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdInitRefPicList
- Functional description:
- Function to initialize reference picture list. Function just
- sets pointers in the list according to pictures in the buffer.
- The buffer is assumed to contain pictures sorted according to
- what the H.264 standard says about initial reference picture list.
- Inputs:
- dpb pointer to dpb data structure
- Outputs:
- dpb 'list' field initialized
- Returns:
- none
- ------------------------------------------------------------------------------*/
- void h264bsdInitRefPicList(dpbStorage_t *dpb)
- {
- /* Variables */
- u32 i;
- /* Code */
- for (i = 0; i < dpb->numRefFrames; i++)
- dpb->list[i] = &dpb->buffer[i];
- }
- /*------------------------------------------------------------------------------
- Function: FindDpbPic
- Functional description:
- Function to find a reference picture from the buffer. The picture
- to be found is identified by picNum and isShortTerm flag.
- Returns:
- index of the picture in the buffer
- -1 if the specified picture was not found in the buffer
- ------------------------------------------------------------------------------*/
- static i32 FindDpbPic(dpbStorage_t *dpb, i32 picNum, u32 isShortTerm)
- {
- /* Variables */
- u32 i = 0;
- u32 found = HANTRO_FALSE;
- /* Code */
- if (isShortTerm)
- {
- while (i < dpb->maxRefFrames && !found)
- {
- if (IS_SHORT_TERM(dpb->buffer[i]) &&
- dpb->buffer[i].picNum == picNum)
- found = HANTRO_TRUE;
- else
- i++;
- }
- }
- else
- {
- ASSERT(picNum >= 0);
- while (i < dpb->maxRefFrames && !found)
- {
- if (IS_LONG_TERM(dpb->buffer[i]) &&
- dpb->buffer[i].picNum == picNum)
- found = HANTRO_TRUE;
- else
- i++;
- }
- }
- if (found)
- return((i32)i);
- else
- return(-1);
- }
- /*------------------------------------------------------------------------------
- Function: SetPicNums
- Functional description:
- Function to set picNum values for short-term pictures in the
- buffer. Numbering of pictures is based on frame numbers and as
- frame numbers are modulo maxFrameNum -> frame numbers of older
- pictures in the buffer may be bigger than the currFrameNum.
- picNums will be set so that current frame has the largest picNum
- and all the short-term frames in the buffer will get smaller picNum
- representing their "distance" from the current frame. This
- function kind of maps the modulo arithmetic back to normal.
- ------------------------------------------------------------------------------*/
- static void SetPicNums(dpbStorage_t *dpb, u32 currFrameNum)
- {
- /* Variables */
- u32 i;
- i32 frameNumWrap;
- /* Code */
- ASSERT(dpb);
- ASSERT(currFrameNum < dpb->maxFrameNum);
- for (i = 0; i < dpb->numRefFrames; i++)
- if (IS_SHORT_TERM(dpb->buffer[i]))
- {
- if (dpb->buffer[i].frameNum > currFrameNum)
- frameNumWrap =
- (i32)dpb->buffer[i].frameNum - (i32)dpb->maxFrameNum;
- else
- frameNumWrap = (i32)dpb->buffer[i].frameNum;
- dpb->buffer[i].picNum = frameNumWrap;
- }
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdCheckGapsInFrameNum
- Functional description:
- Function to check gaps in frame_num and generate non-existing
- (short term) reference pictures if necessary. This function should
- be called only for non-IDR pictures.
- Inputs:
- dpb pointer to dpb data structure
- frameNum frame number of the current picture
- isRefPic flag to indicate if current picture is a reference or
- non-reference picture
- gapsAllowed Flag which indicates active SPS stance on whether
- to allow gaps
- Outputs:
- dpb 'buffer' possibly modified by inserting non-existing
- pictures with sliding window marking process
- Returns:
- HANTRO_OK success
- HANTRO_NOK error in sliding window reference picture marking or
- frameNum equal to previous reference frame used for
- a reference picture
- ------------------------------------------------------------------------------*/
- u32 h264bsdCheckGapsInFrameNum(dpbStorage_t *dpb, u32 frameNum, u32 isRefPic,
- u32 gapsAllowed)
- {
- /* Variables */
- u32 unUsedShortTermFrameNum;
- u8 *tmp;
- /* Code */
- ASSERT(dpb);
- ASSERT(dpb->fullness <= dpb->dpbSize);
- ASSERT(frameNum < dpb->maxFrameNum);
- dpb->numOut = 0;
- dpb->outIndex = 0;
- if(!gapsAllowed)
- return(HANTRO_OK);
- if ( (frameNum != dpb->prevRefFrameNum) &&
- (frameNum != ((dpb->prevRefFrameNum + 1) % dpb->maxFrameNum)))
- {
- unUsedShortTermFrameNum = (dpb->prevRefFrameNum + 1) % dpb->maxFrameNum;
- /* store data pointer of last buffer position to be used as next
- * "allocated" data pointer if last buffer position after this process
- * contains data pointer located in outBuf (buffer placed in the output
- * shall not be overwritten by the current picture) */
- tmp = dpb->buffer[dpb->dpbSize].data;
- do
- {
- SetPicNums(dpb, unUsedShortTermFrameNum);
- if (SlidingWindowRefPicMarking(dpb) != HANTRO_OK)
- {
- return(HANTRO_NOK);
- }
- /* output pictures if buffer full */
- while (dpb->fullness >= dpb->dpbSize)
- {
- #ifdef _ASSERT_USED
- ASSERT(!dpb->noReordering);
- ASSERT(OutputPicture(dpb) == HANTRO_OK);
- #else
- OutputPicture(dpb);
- #endif
- }
- /* add to end of list */
- ASSERT( !dpb->buffer[dpb->dpbSize].toBeDisplayed &&
- !IS_REFERENCE(dpb->buffer[dpb->dpbSize]) );
- dpb->buffer[dpb->dpbSize].status = NON_EXISTING;
- dpb->buffer[dpb->dpbSize].frameNum = unUsedShortTermFrameNum;
- dpb->buffer[dpb->dpbSize].picNum = (i32)unUsedShortTermFrameNum;
- dpb->buffer[dpb->dpbSize].picOrderCnt = 0;
- dpb->buffer[dpb->dpbSize].toBeDisplayed = HANTRO_FALSE;
- dpb->fullness++;
- dpb->numRefFrames++;
- /* sort the buffer */
- ShellSort(dpb->buffer, dpb->dpbSize+1);
- unUsedShortTermFrameNum = (unUsedShortTermFrameNum + 1) %
- dpb->maxFrameNum;
- } while (unUsedShortTermFrameNum != frameNum);
- /* pictures placed in output buffer -> check that 'data' in
- * buffer position dpbSize is not in the output buffer (this will be
- * "allocated" by h264bsdAllocateDpbImage). If it is -> exchange data
- * pointer with the one stored in the beginning */
- if (dpb->numOut)
- {
- u32 i;
- for (i = 0; i < dpb->numOut; i++)
- {
- if (dpb->outBuf[i].data == dpb->buffer[dpb->dpbSize].data)
- {
- /* find buffer position containing data pointer stored in
- * tmp */
- for (i = 0; i < dpb->dpbSize; i++)
- {
- if (dpb->buffer[i].data == tmp)
- {
- dpb->buffer[i].data =
- dpb->buffer[dpb->dpbSize].data;
- dpb->buffer[dpb->dpbSize].data = tmp;
- break;
- }
- }
- ASSERT(i < dpb->dpbSize);
- break;
- }
- }
- }
- }
- /* frameNum for reference pictures shall not be the same as for previous
- * reference picture, otherwise accesses to pictures in the buffer cannot
- * be solved unambiguously */
- else if (isRefPic && frameNum == dpb->prevRefFrameNum)
- {
- return(HANTRO_NOK);
- }
- /* save current frame_num in prevRefFrameNum. For non-reference frame
- * prevFrameNum is set to frame number of last non-existing frame above */
- if (isRefPic)
- dpb->prevRefFrameNum = frameNum;
- else if (frameNum != dpb->prevRefFrameNum)
- {
- dpb->prevRefFrameNum =
- (frameNum + dpb->maxFrameNum - 1) % dpb->maxFrameNum;
- }
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: FindSmallestPicOrderCnt
- Functional description:
- Function to find picture with smallest picture order count. This
- will be the next picture in display order.
- Returns:
- pointer to the picture, NULL if no pictures to be displayed
- ------------------------------------------------------------------------------*/
- dpbPicture_t* FindSmallestPicOrderCnt(dpbStorage_t *dpb)
- {
- /* Variables */
- u32 i;
- i32 picOrderCnt;
- dpbPicture_t *tmp;
- /* Code */
- ASSERT(dpb);
- picOrderCnt = 0x7FFFFFFF;
- tmp = NULL;
- for (i = 0; i <= dpb->dpbSize; i++)
- {
- if (dpb->buffer[i].toBeDisplayed &&
- (dpb->buffer[i].picOrderCnt < picOrderCnt))
- {
- tmp = dpb->buffer + i;
- picOrderCnt = dpb->buffer[i].picOrderCnt;
- }
- }
- return(tmp);
- }
- /*------------------------------------------------------------------------------
- Function: OutputPicture
- Functional description:
- Function to put next display order picture into the output buffer.
- Returns:
- HANTRO_OK success
- HANTRO_NOK no pictures to display
- ------------------------------------------------------------------------------*/
- u32 OutputPicture(dpbStorage_t *dpb)
- {
- /* Variables */
- dpbPicture_t *tmp;
- /* Code */
- ASSERT(dpb);
- if (dpb->noReordering)
- return(HANTRO_NOK);
- tmp = FindSmallestPicOrderCnt(dpb);
- /* no pictures to be displayed */
- if (tmp == NULL)
- return(HANTRO_NOK);
- dpb->outBuf[dpb->numOut].data = tmp->data;
- dpb->outBuf[dpb->numOut].isIdr = tmp->isIdr;
- dpb->outBuf[dpb->numOut].picId = tmp->picId;
- dpb->outBuf[dpb->numOut].numErrMbs = tmp->numErrMbs;
- dpb->numOut++;
- tmp->toBeDisplayed = HANTRO_FALSE;
- if (!IS_REFERENCE(*tmp))
- {
- dpb->fullness--;
- }
- return(HANTRO_OK);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdDpbOutputPicture
- Functional description:
- Function to get next display order picture from the output buffer.
- Return:
- pointer to output picture structure, NULL if no pictures to
- display
- ------------------------------------------------------------------------------*/
- dpbOutPicture_t* h264bsdDpbOutputPicture(dpbStorage_t *dpb)
- {
- /* Variables */
- /* Code */
- ASSERT(dpb);
- if (dpb->outIndex < dpb->numOut)
- return(dpb->outBuf + dpb->outIndex++);
- else
- return(NULL);
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdFlushDpb
- Functional description:
- Function to flush the DPB. Function puts all pictures needed for
- display into the output buffer. This function shall be called in
- the end of the stream to obtain pictures buffered for display
- re-ordering purposes.
- ------------------------------------------------------------------------------*/
- void h264bsdFlushDpb(dpbStorage_t *dpb)
- {
- /* don't do anything if buffer not reserved */
- if (dpb->buffer)
- {
- dpb->flushed = 1;
- /* output all pictures */
- while (OutputPicture(dpb) == HANTRO_OK)
- ;
- }
- }
- /*------------------------------------------------------------------------------
- Function: h264bsdFreeDpb
- Functional description:
- Function to free memories reserved for the DPB.
- ------------------------------------------------------------------------------*/
- void h264bsdFreeDpb(dpbStorage_t *dpb)
- {
- /* Variables */
- u32 i;
- /* Code */
- ASSERT(dpb);
- if (dpb->buffer)
- {
- for (i = 0; i < dpb->dpbSize+1; i++)
- {
- FREE(dpb->buffer[i].pAllocatedData);
- }
- }
- FREE(dpb->buffer);
- FREE(dpb->list);
- FREE(dpb->outBuf);
- }
- /*------------------------------------------------------------------------------
- Function: ShellSort
- Functional description:
- Sort pictures in the buffer. Function implements Shell's method,
- i.e. diminishing increment sort. See e.g. "Numerical Recipes in C"
- for more information.
- ------------------------------------------------------------------------------*/
- static void ShellSort(dpbPicture_t *pPic, u32 num)
- {
- u32 i, j;
- u32 step;
- dpbPicture_t tmpPic;
- step = 7;
- while (step)
- {
- for (i = step; i < num; i++)
- {
- tmpPic = pPic[i];
- j = i;
- while (j >= step && ComparePictures(pPic + j - step, &tmpPic) > 0)
- {
- pPic[j] = pPic[j-step];
- j -= step;
- }
- pPic[j] = tmpPic;
- }
- step >>= 1;
- }
- }